Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-43900] Update to 2.X parent POM #5

Merged
merged 11 commits into from Oct 4, 2017

Conversation

varyvol
Copy link

@varyvol varyvol commented Apr 27, 2017

JENKINS-43900

  • Update to 2.X parent POM.
  • Bump Jenkins and plugins versions.
  • Fix Findbugs errors.

@reviewbybees @olamy @stephenc @jglick @kwhetstone @andresrc

Copy link
Member

@oleg-nenashev oleg-nenashev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 for getType() check. It is required to ensure it was not a migration logic before decoupling of the plugin

@@ -25,4 +25,16 @@
<Match>
<Class name="~.*\.Messages"/>
</Match>
<Match>
<Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use @SuppressFBWarnings() instead

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed but, out of curiosity, why is that preferable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that you can write a clear justification in every case.

} else {
return new InputStreamReader(getLogInputStream(), getCharset());
}
return new InputStreamReader(getLogInputStream(), getCharset());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it is correct, but OK

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getCharset() is already checking for nullability and returning default charset in that case.

@@ -158,7 +158,7 @@ public String getGroupId() {
*/
@NonNull
public String getType() {
return type == null ? DEFAULT_TYPE : type;
return type;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 I am pretty sure it was a migration logic. Should be replaced by readResolve

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can be missing something, but type is being set in the constructor, where the null check is already done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Object deserialization does not involve the constructor. So, if somebody migrates old data, this field can be probably null

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right so I am reverting this. Thanks @oleg-nenashev

@ghost
Copy link

ghost commented Apr 27, 2017

This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation.

@@ -36,6 +37,7 @@
/**
* @author stephenc
*/
@SuppressFBWarnings(value = "SE_BAD_FIELD")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? This certainly looks like a bug to me. AbstractBuild cannot be serialized. So either make the field transient, or remove implements Serializable if no one is actually serializing it, or explain why this code is not doing what it looks like.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed Serializable as it would not be working up to now.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* @author stephenc
*/
public class DeployEvent implements Serializable {
public class DeployEvent {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a weight-in from the maintainer. The class is definitely not serializable in the current implementation. But removal of the interface breaks binary compatibility.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess nobody was serializing this because there would be issues raised. But a confirmation from the maintainer would be great for sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm in agreement with @oleg-nenashev . Even though removing it is harmless it would break binary compatibility.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@christ66 so then supressing back the Findbugs error?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just remove the interface

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah if it is not actually serializable, then removing the interface does not break anything that was not already broken.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will leave it to @christ66, @stephenc and @olamy since they are the plugin maintainers. There is a way to make the class serializable, but I am not sure it worth effort (though I would really vote for it if I was the maintainer)

@@ -157,6 +158,7 @@ public String getGroupId() {
* @return the type of artifact to match.
*/
@NonNull
@SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE", justification = "Might be null if serialized")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"deserialized", but ok

@varyvol varyvol closed this May 5, 2017
@varyvol varyvol reopened this May 5, 2017
@varyvol
Copy link
Author

varyvol commented May 15, 2017

@olamy @stephenc @christ66 could you please review this?

Copy link
Member

@stephenc stephenc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks ok to me... seems like a lot of fussing over nothing... though I have given up maintaining this plugin as E_TO_MANY_PLUGINS

@varyvol
Copy link
Author

varyvol commented May 25, 2017

@oleg-nenashev @jglick @christ66 @olamy once Stephen has approved this, are you fine with this getting merged?

Copy link
Member

@jglick jglick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect use of Remoting.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* @author stephenc
*/
public class DeployEvent implements Serializable {
public class DeployEvent {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah if it is not actually serializable, then removing the interface does not break anything that was not already broken.

@@ -36,7 +36,7 @@
/**
* Since we allow token expansion, we must provide a default Maven path -- in
* case they are running on a master without any Mavens.
* <p/>
* <p></p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually wrong. Just use

<p>

@@ -232,7 +234,7 @@ public void log(String message) {
throw new DeployException("Deployment hosts of type " + configuration.getClass() + " are unsupported");
}

public static class FingerprintDecorator implements Callable<DeployedApplicationLocation, IOException> {
public static class FingerprintDecorator extends MasterToSlaveCallable<DeployedApplicationLocation, IOException> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think this is true. FingerprintingWrapper has code which apparently calls it from the agent side, if that callable was running remotely. And its body calls Hudson.getInstance() without a null check, confirming that it is intended to be run on the master side. Thus it should be a SlaveToMasterCallable.

But before you make such a change you would need to review its implementation carefully to ensure that no malicious arguments could possibly cause any harm. That seems unlikely, since the agent could pass any md5sum it likes, mangling fingerprints of some unrelated artifact. Which means that really FingerprintDecorator needs to be deleted, and FingerprintingWrapper needs to be reworked so that any information about fingerprints is simply returned, to be handled by its caller (after any necessary sanity checks). That in turn means understanding the call points in the two Engine.process overloads. The one taking FilePath is called from perform in what is clearly a master context (because it is calling build.getWorkspace(), and a Run can only exist on master); thus the other overload must also be called from master. Thus it is the process methods which would need to add suitable DeployedApplicationFingerprintFacets; perhaps FingerprintingWrapper needs to be returning a pair of DeployedApplicationLocation and md5sum.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jglick So let's see if I follow you. You mean that:

  • The engine.process() is executed in master.
  • It calls the wrapper, which is executed in the agent.
  • This one calls the decorator, which is executed in the master.
  • Again in the wrapper, eventually it returns this information to the master.

And you think such "travel" to decorate could be avoided by returning what's necessary in the wrapper and just using it in the process() method. Is that it?

If so, what it's not clear to me is if you think this is something to improve or something that you think that is required. Because if the first one, I would prefer to tackle that in another PR to move this forward and not to increase the size of this one.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that it?

Yes.

if you think this is something to improve or something that you think that is required

I think fixing this is required. Certainly the PR as it currently stands is incorrect. Anyway it should be a pretty small refactoring; I am happy to offer a suggested commit if you are unsure.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last commit should make it. Please let me know if you think something is not appropriate.

@@ -119,7 +119,10 @@ protected boolean knows(@NonNull Class<? extends AbstractProject> jobType) {
*/
@Override
public Run<?, ?> getLastSuccessfulBuild(AbstractProject<?, ?> project) {
return CapabilitiesResolver.getLastDeployableBuild(PromotionProcess.class.cast(project).getRootProject());
if (project != null) {
return CapabilitiesResolver.getLastDeployableBuild(PromotionProcess.class.cast(project).getRootProject());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pointless use of Class.cast (should never be used with a constant receiver). Just

(PromotionProcess) project

Copy link
Member

@jglick jglick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better, thanks!

@stephenc you might want to take a look since this is your code IIRC

@@ -205,6 +206,33 @@ public DeployedApplicationLocation process(File applicationFile, T target) throw
}
}

private DeployedApplicationLocation addToFacects(AbstractMap.SimpleEntry<String, DeployedApplicationLocation> pair) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

}

public static class FingerprintingWrapper extends MasterToSlaveFileCallable<DeployedApplicationLocation> {
public static class FingerprintingWrapper extends MasterToSlaveFileCallable<AbstractMap.SimpleEntry<String, DeployedApplicationLocation>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clearer to use Map.Entry<…> as the declared type

@@ -181,7 +180,8 @@ public boolean perform() throws Throwable {
public DeployedApplicationLocation process(FilePath applicationFile, T target) throws DeployException {
try {
FingerprintingWrapper actor = new FingerprintingWrapper(newDeployActor(target), listener);
return applicationFile.act(actor);
AbstractMap.SimpleEntry<String, DeployedApplicationLocation> pair = applicationFile.act(actor);
return this.addToFacects(pair);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arguably more readable if pair is inlined (so the verbose type need not be mentioned)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely! Changed.


if (!NO_MD5.equals(md5sum)) {
Jenkins j = Jenkins.getInstance();
if (j == null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use getActiveInstance in suitable core versions (later it is back to getInstance)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not available in 1.580.1

if (instance != null) {
return decorator.call();
} else {
Channel current = Channel.current();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any deletion of a call to Channel.current() is a happy day!

} catch (Exception e) {
listener.error("[cloudbees-deployer] Could not record fingerprint association");
// e.printStackTrace(listener.getLogger());
} catch (LinkageError e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very possibly obsolete.

: "Can only have a null Jenkins instance if on the other end of a channel";
return current.call(decorator);
}
return new AbstractMap.SimpleEntry<String, DeployedApplicationLocation>(md5sum, location);
} catch (Exception e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The try-catch could probably be deleted and the caller made to handle any of the usual exceptions, as it probably already is. I suspect this was here in case the callback to master failed, which is now an obsolete condition.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have removed them as they are being captured in the process() method.

@jglick jglick dismissed oleg-nenashev’s stale review June 14, 2017 16:54

Requested change was made AFAICT.

String md5sum = Util.getDigestOf(fis);
return new AbstractMap.SimpleEntry<String, DeployedApplicationLocation>(md5sum, location);
} finally {
IOUtils.closeQuietly(fis);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just

fis.close();

suffices

@varyvol
Copy link
Author

varyvol commented Jun 19, 2017

@oleg-nenashev @stephenc @christ66 any extra comment here?

@@ -232,76 +261,26 @@ public void log(String message) {
throw new DeployException("Deployment hosts of type " + configuration.getClass() + " are unsupported");
}

public static class FingerprintDecorator implements Callable<DeployedApplicationLocation, IOException> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also incompatible

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How so?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allows us to delete this nonsense.

Copy link
Member

@oleg-nenashev oleg-nenashev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not ready to approve it due to the incompatible changes like FingerprintDecorator class removal.

But I leave the decision to maintainers. If the current version gets merged, I just strongly recommend to release it as a new major version (2.0)

@jglick
Copy link
Member

jglick commented Jun 20, 2017

I do not see any incompatibilities here and see no need for a 2.0 version.

Copy link
Member

@stephenc stephenc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems ok, but I haven't looked at this plugin in ages

@@ -157,6 +158,7 @@ public String getGroupId() {
* @return the type of artifact to match.
*/
@NonNull
@SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE", justification = "Might be null if deserialized")
public String getType() {
return type == null ? DEFAULT_TYPE : type;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could remove the fb warning suppression with StringUtils.defaultString(type, DEFAULT_TYPE)

@varyvol
Copy link
Author

varyvol commented Jun 23, 2017

@stephenc thanks.

@olamy @jglick @oleg-nenashev do you think this could be merged (and released) now?

@oleg-nenashev
Copy link
Member

@varyvol You can see my feedback above. If I was the plugin maintainer, then I would request changes. But I am not, hence it's up to its maintainers. @reviewbybees done according to the votes

The ball is on the side of @stephenc and @olamy (according to pom.xml)

@varyvol
Copy link
Author

varyvol commented Jun 23, 2017

@oleg-nenashev why do you think the changes are incompatible? The class is used only internally, and it's behaviour has been maintained.

@oleg-nenashev
Copy link
Member

oleg-nenashev commented Jun 23, 2017

@varyvol

why do you think the changes are incompatible? The class is used only internally, and it's behaviour has been maintained.

FingerprintDecorator class is public. Deletion of public classes is always formally incompatible, because it is not possible to guarantee that nobody uses them (e.g. in custom System Groovy scripts or private-source plugins like CloudBees ones)

@jglick
Copy link
Member

jglick commented Jun 23, 2017

it is not possible to guarantee that nobody uses them

Of course not, but there is no remotely plausible use case for this class outside its plugin.

@varyvol
Copy link
Author

varyvol commented Jun 27, 2017

So is there anything I can do to move this forward?

@jglick
Copy link
Member

jglick commented Jun 28, 2017

I think @stephenc is the maintainer.

@varyvol
Copy link
Author

varyvol commented Jul 10, 2017

@stephenc ping. Could you please review (and merge if appropriate) this?

@oleg-nenashev
Copy link
Member

@reviewbybees done

@jglick
Copy link
Member

jglick commented Oct 4, 2017

@stephenc again

@stephenc stephenc merged commit dda2f2c into jenkinsci:master Oct 4, 2017
@stephenc
Copy link
Member

stephenc commented Oct 4, 2017

@jglick can someone else roll the release or do you need me to?

@daniel-beck
Copy link
Member

Any intentions to release this?

@oleg-nenashev
Copy link
Member

I'd guess it will happen soon after #7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
7 participants