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-23786] Permit the Shell plugin to set a build result as unstable via a return code #2563

Merged
merged 4 commits into from
Oct 11, 2016

Conversation

stochmial
Copy link

Continuation of the pull request: #1325

The CommandInterpreter.join(Proc p) method is supposed to be an extension
point to allow an UNSTABLE build result to be set, but it has no access to
the Build object with which to do so.

Add a getBuild() method that returns the build passed to perform(...). A better
API would be a new join(...) with more arguments, but that'd break out of tree
plugins that might already be using this for other purposes.
Currently a shell job has to make a HTTP call back to Jenkins to set
its build result as unstable. This is slow, requires the slave to
have access to the master's HTTP interface, and is fiddly. The
alternative, the TextFinder plugin, is no better.

Instead, allow a job to set the build result to unstable with a
return value.

Adds the Advanced parameter "unstableReturn" which, if non-zero,
is the code the script must return to set the build as unstable.
@@ -73,7 +84,13 @@ public String getDisplayName() {

@Override
public Builder newInstance(StaplerRequest req, JSONObject data) {
return new BatchFile(data.getString("command"));
final String unstableReturnStr = data.getString("unstableReturn");
Copy link
Member

Choose a reason for hiding this comment

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

Why is this even using newInstance? Should just be databinding.

Copy link
Author

Choose a reason for hiding this comment

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

fixed (hopefully) in next commit

@@ -40,10 +40,17 @@
*/
public class BatchFile extends CommandInterpreter {
@DataBoundConstructor
public BatchFile(String command) {
public BatchFile(String command, Integer unstableReturn) {
Copy link
Member

Choose a reason for hiding this comment

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

Use of @DataboundSetter for new arguments would be preferable over adding new constructors.

Copy link
Author

Choose a reason for hiding this comment

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

fixed (hopefully) in next commit

* Useful for {@link #join(Proc p)} for setting build results.
*
* @return The build being run, or null if outside perform(...)
* @since 1.573
Copy link
Member

Choose a reason for hiding this comment

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

Nope.

Copy link
Author

Choose a reason for hiding this comment

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

Refactored

@@ -97,6 +118,7 @@ public boolean perform(AbstractBuild<?,?> build, Launcher launcher, TaskListener
Util.displayIOException(e, listener);
e.printStackTrace(listener.fatalError(Messages.CommandInterpreter_CommandFailed()));
}
this.build = null;
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be in the finally block?

Copy link
Author

Choose a reason for hiding this comment

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

Refactored in next commit

@DataBoundConstructor
public Shell(String command) {
public Shell(String command, Integer unstableReturn) {
Copy link
Member

Choose a reason for hiding this comment

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

See BatchFile.

Copy link
Author

Choose a reason for hiding this comment

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

fixed (hopefully) in next commit

@@ -28,4 +28,10 @@ THE SOFTWARE.
description="${%description(rootURL)}">
<f:textarea name="command" value="${instance.command}" class="fixed-width" />
</f:entry>
<f:advanced>
<f:entry title="errorlevel to set build unstable"
description="${%unstableReturn_description(rootURL)}">
Copy link
Member

Choose a reason for hiding this comment

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

No argument needed as there's no placeholder in the localized string.

Copy link
Author

Choose a reason for hiding this comment

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

added help section and fixed in next commit

@@ -28,4 +28,10 @@ THE SOFTWARE.
description="${%description(rootURL)}">
<f:textarea name="command" value="${instance.command}" class="fixed-width" />
</f:entry>
<f:advanced>
<f:entry title="errorlevel to set build unstable"
Copy link
Member

Choose a reason for hiding this comment

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

Unclear why this isn't just using databinding.

Copy link
Author

Choose a reason for hiding this comment

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

fixed (hopefully) in next commit

<f:advanced>
<f:entry title="errorlevel to set build unstable"
description="${%unstableReturn_description(rootURL)}">
<f:number clazz="positive-number" name="unstableReturn" value="${instance.unstableReturn}" min="1" max="255" step="1" />
Copy link
Member

Choose a reason for hiding this comment

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

Are these min/max values universal?


f.advanced() {

f.entry(title:_("Return code to set build unstable"), description:_("If set, the script return code that will be interpreted as an unstable build result.")) {
Copy link
Member

Choose a reason for hiding this comment

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

Why is this inline, when the BatchFile equivalent is in the view's default locale resource file?

Copy link
Author

Choose a reason for hiding this comment

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

fixed (hopefully) in next commit

f.advanced() {

f.entry(title:_("Return code to set build unstable"), description:_("If set, the script return code that will be interpreted as an unstable build result.")) {
f.number(name: "unstableReturn", value: instance?.unstableReturn, min:1, max:255, step:1)
Copy link
Member

Choose a reason for hiding this comment

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

Where's the 'positive number' part present in BatchFile's form? Not needed? Then why is it present there?

Copy link
Author

Choose a reason for hiding this comment

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

fixed (hopefully) in next commit

@stochmial
Copy link
Author

Hi Daniel, thanks for review. I think the next commit should fix all requests. I'm not sure why one of the tests failed. I don't think the changes are related to this test. I need assistance from someone more experienced to get more understanding.

@daniel-beck
Copy link
Member

@stochmial Legitimate failure. FindBugs complained as follows:

req must be non-null but is marked as nullable [hudson.tasks.BatchFile$DescriptorImpl] At BatchFile.java:[line 97] NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE

public Builder newInstance(StaplerRequest req, JSONObject data) {
return new BatchFile(data.getString("command"));
public Builder newInstance(StaplerRequest req, JSONObject formData) {
return req.bindJSON(BatchFile.class,formData);
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 the FindBugs issue since req is CheckForNull.

Still not clear to me why this is even overridden. Doesn't the default Descriptor#newInstance(…) do the exact same thing?

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

@daniel-beck daniel-beck left a comment

Choose a reason for hiding this comment

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

We're getting really close here. Only few minor issues left IMO.

<div>
If set, the batch errorlevel result that will be interpreted as an unstable build result.
In WinNT4 and beyond, the ERRORLEVEL is stored as a Long - that is, a four byte, signed integer;
yielding maximum and minimum values of 2147483647 and -2147483648, respectively.
Copy link
Member

Choose a reason for hiding this comment

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

Are all of these values actually used?

Copy link
Author

Choose a reason for hiding this comment

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

I tested a simple batch file with a single line: 'exit /b -2147483648' and the errorlevel is set to '-2147483648'. It works on win7, etc. I think it's better not to limit the available range, although hardly used.

@@ -0,0 +1,5 @@
<div>
If set, the batch errorlevel result that will be interpreted as an unstable build result.
In WinNT4 and beyond, the ERRORLEVEL is stored as a Long - that is, a four byte, signed integer;
Copy link
Member

Choose a reason for hiding this comment

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

WinNT4? Why not Windows NT 4? Is that a common identifier of some kind?

Copy link
Author

Choose a reason for hiding this comment

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

I agree this help text should be corrected. Not sure how much detail is needed here. I thought this text to be rather a hint than the complete documentation. How about:

"If set, the batch errorlevel result that will be interpreted as an unstable build result. If the final errorlevel matches the value, the build results will be set to unstable and next steps will be continued. Supported values match the widest errorlevel range for Windows like systems. In Windows NT4 and beyond the ERRORLEVEL is stored as a four byte, signed integer, yielding maximum and minimum values of 2147483647 and -2147483648, respectively. Older versions of Windows use 2 bytes. DOS like systems use single byte, yelding errorlevels between 0-255 ."

@@ -0,0 +1,3 @@
<div>
If set, the shell exit code that will be interpreted as an unstable build result. On Unix-like systems the value between 0-255.
Copy link
Member

Choose a reason for hiding this comment

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

Second sentence missing its verb.

Also, seems overly terse, could use an explanation what this means. E.g. not aborting the build if that's the result, but continuing.

Copy link
Author

Choose a reason for hiding this comment

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

How about:
“If set, the shell exit code that will be interpreted as an unstable build result. If the exit code matches the value, the build results will be set to 'unstable' and next steps will be continued. On Unix-like it is a value between 0-255.”

@@ -64,6 +66,13 @@ public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListene
return perform(build,launcher,(TaskListener)listener);
}

/**
* Allow the user to define a result for "unstable".
Copy link
Member

Choose a reason for hiding this comment

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

Not actually describing what this does.

Missing @since TODO.

@@ -28,4 +28,9 @@ THE SOFTWARE.
description="${%description(rootURL)}">
<f:textarea name="command" value="${instance.command}" class="fixed-width" />
</f:entry>
<f:advanced>
<f:entry title="${%Errorlevel to set build unstable}" field="unstableReturn" >
<f:number name="unstableReturn" value="${instance.unstableReturn}" min="-2147483648" max="2147483647" step="1" />
Copy link
Member

Choose a reason for hiding this comment

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

Why is name needed here, doesn't field take care of this?


f.advanced() {
f.entry(title:_("Exit code to set build unstable"), field: "unstableReturn") {
f.number(clazz:"positive-number", name: "unstableReturn", value: instance?.unstableReturn, min:1, max:255, step:1)
Copy link
Member

Choose a reason for hiding this comment

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

Form validation allows 0...255, while this has the range of 1...255, why?

Copy link
Author

@stochmial stochmial Sep 27, 2016

Choose a reason for hiding this comment

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

There is a general question if we should allow users to define exit code zero as an unstable build? I think better not.

Copy link
Member

Choose a reason for hiding this comment

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

Let's start with 'no' and open up if there's an actual need for it.

/**
* Performs on-the-fly validation of the exit code.
*/
public FormValidation doCheckUnstableReturn(@QueryParameter String value) {
Copy link
Member

Choose a reason for hiding this comment

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

@Restricted(DoNotUse.class) wouldn't be a bad idea.

@daniel-beck
Copy link
Member

I didn't point them out individually, but a whole bunch of @since TODO and @Restricted are missing here.

  • @Restricted for anything not intended for use in plugins, e.g. all doCheck seem like good candidates.
  • @since TODO required for every protected or public field or method newly added, unless @Restricted (in which case it's optional IMO, but we're a bit inconsistent here).

TODO is literal, do not fill in the version you expect this to go in. Better TODO than wrong if nobody catches it.

@stochmial
Copy link
Author

All requests should be corrected.

Copy link
Member

@daniel-beck daniel-beck left a comment

Choose a reason for hiding this comment

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

Minor messaging issues, but otherwise okay 👍

@jenkinsci/code-reviewers Please review.

@@ -81,3 +83,5 @@ Maven.NotMavenDirectory={0} doesn\u2019t look like a Maven directory
Maven.NoExecutable=Couldn\u2019t find any executable in {0}

Shell.DisplayName=Execute shell
Shell.invalid_exit_code_range=Invalid exit code value: {0}. Check help section
Copy link
Member

Choose a reason for hiding this comment

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

Missing trailing period.

Copy link
Author

Choose a reason for hiding this comment

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

I'm not sure, because no messages there have periods in the end.

Copy link
Member

Choose a reason for hiding this comment

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

BatchFile.invalid_exit_code_range has, so one of these is wrong.

Copy link
Author

Choose a reason for hiding this comment

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

Ok, fixed by removing all trailing periods.

@@ -81,3 +83,5 @@ Maven.NotMavenDirectory={0} doesn\u2019t look like a Maven directory
Maven.NoExecutable=Couldn\u2019t find any executable in {0}

Shell.DisplayName=Execute shell
Shell.invalid_exit_code_range=Invalid exit code value: {0}. Check help section
Shell.invalid_exit_code_zero=Exit code zero is not allowed to make build unstable
Copy link
Member

Choose a reason for hiding this comment

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

Form validation does not prevent users from saving the form. I expect the '0' value to actually be saved. So, strongly discouraged, with explanation that it's never going to be successful perhaps?

Copy link
Author

Choose a reason for hiding this comment

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

I changed from error to warning and added explanation in help message.

@stochmial
Copy link
Author

Is there anything else needed to finish this? I.e. sqashing my commits? I would rather leave rigerc commits as they are and squash only mine.

@daniel-beck
Copy link
Member

@stochmial In the current state, I would definitely squash when merging, so to retain @ringerc's commits, that would be useful. But please wait to do that until the reviews are finished.

@oleg-nenashev
Copy link
Member

Noticed that I have not submitted the previous review :( redoing it

@stochmial
Copy link
Author

@oleg: I still don't see your review.

@@ -56,6 +65,20 @@ protected String getFileExtension() {
return ".bat";
}

public final Integer getUnstableReturn() {
Copy link
Member

Choose a reason for hiding this comment

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

Add CheckForNull.
🐜

Copy link
Author

Choose a reason for hiding this comment

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

Done

return FormValidation.warning(hudson.tasks.Messages.BatchFile_invalid_exit_code_zero());
}
if (unstableReturn < Integer.MIN_VALUE || unstableReturn > Integer.MAX_VALUE) {
return FormValidation.error(hudson.tasks.Messages.BatchFile_invalid_exit_code_range(unstableReturn));
Copy link
Member

Choose a reason for hiding this comment

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

Does Batch really support so wide return code range?

Copy link
Author

Choose a reason for hiding this comment

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

I tested a simple batch file with a single line: 'exit /b -2147483648' and the errorlevel is set to '-2147483648'. It works on win7, etc. I think it's better not to limit the available range, although hardly used.

Copy link
Member

Choose a reason for hiding this comment

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

agreed

@@ -94,6 +102,20 @@ protected String getFileExtension() {
return ".sh";
}

public final Integer getUnstableReturn() {
Copy link
Member

Choose a reason for hiding this comment

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

CheckForNull

Copy link
Author

Choose a reason for hiding this comment

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

Done

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.

Test implementation needs fix

}

@Issue("JENKINS-23786")
public void testUnstableReturn() throws Exception {
Copy link
Member

Choose a reason for hiding this comment

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

🐛 No @Test annotation. JUnit 4 is not actually running this test

Copy link
Member

Choose a reason for hiding this comment

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

I would also add "Unix" to the test name

Copy link
Author

Choose a reason for hiding this comment

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

I did.

b = rule.assertBuildStatus(Result.SUCCESS, p.scheduleBuild2(0).get());

/* Creating unstable=0 produces unstable=null */
assertNull( createNewShell("",0).getUnstableReturn() );
Copy link
Member

Choose a reason for hiding this comment

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

Maybe needs splitting to several tests (or needs some comments)

Copy link
Author

Choose a reason for hiding this comment

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

I split and refactored tests.


@Issue("JENKINS-23786")
public void testUnstableReturn() throws Exception {
if(Functions.isWindows())
Copy link
Member

@oleg-nenashev oleg-nenashev Oct 3, 2016

Choose a reason for hiding this comment

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

🐜 Should be assumeThat in order to mark the test as skipped instead of passed.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed

}

@Issue("JENKINS-23786")
public void testUnstableReturn() throws Exception {
Copy link
Member

Choose a reason for hiding this comment

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

Same. Missing Test annotation and no assumeThat()

Copy link
Author

Choose a reason for hiding this comment

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

Done

@@ -28,4 +28,9 @@ THE SOFTWARE.
description="${%description(rootURL)}">
<f:textarea name="command" value="${instance.command}" class="fixed-width" />
</f:entry>
<f:advanced>
<f:entry title="${%Errorlevel to set build unstable}" field="unstableReturn" >
Copy link
Member

Choose a reason for hiding this comment

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

Better to use ERRORLEVEL then

Copy link
Author

Choose a reason for hiding this comment

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

Changed 'Errorlevel' and 'ErrorLevel' to 'ERRORLEVEL' in all messageas.

@oleg-nenashev
Copy link
Member

@stochmial Done, sorry for the delay

@stochmial
Copy link
Author

I refactored tests and verified they are triggered.

@oleg-nenashev oleg-nenashev added the needs-more-reviews Complex change, which would benefit from more eyes label Oct 5, 2016
@oleg-nenashev
Copy link
Member

Looks good to me 👍

@oleg-nenashev
Copy link
Member

@daniel-beck Are you fine with the revised version?

@daniel-beck
Copy link
Member

@oleg-nenashev Code looks good, haven't run it for a while though.

If @stochmial could commit to fixing followup issues during the next few weeks that would be great.

@stochmial
Copy link
Author

I am ready to fix issues. I also added push permissions to all participants

@stochmial
Copy link
Author

I can see all check finished successfully but the status still says 'Some checks haven’t completed yet'. An error in CI process?

@oleg-nenashev
Copy link
Member

I suppose it's just another glitch on the new CI instance.
One of the builds has passed, hence it's ready to go.

Not sure in which weekly release it will land

@oleg-nenashev oleg-nenashev added the ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback label Oct 9, 2016
@oleg-nenashev oleg-nenashev removed the needs-more-reviews Complex change, which would benefit from more eyes label Oct 9, 2016
@oleg-nenashev oleg-nenashev changed the title [WIP] JENKINS-23786: Permit the Shell plugin to set a build result as unstable via a return code - rebased [JENKINS-23786] Permit the Shell plugin to set a build result as unstable via a return code - rebased Oct 10, 2016
@oleg-nenashev oleg-nenashev changed the title [JENKINS-23786] Permit the Shell plugin to set a build result as unstable via a return code - rebased [JENKINS-23786] Permit the Shell plugin to set a build result as unstable via a return code Oct 10, 2016
@oleg-nenashev
Copy link
Member

I would like to squash these 18 commits, but there are two authors => it can be done only manually

@stochmial
Copy link
Author

I squashed my commits

@oleg-nenashev
Copy link
Member

Thanks! Could you also update the commit message? Just to add issue prefix in order to let the SCM <=> JIRA integration to mark the issue properly?

refactor and fix

remove duplication and fix FB errors

fix integration tests

consistency fixes

consistency fixes

changed error message to warning

fix comment and warning message

fix comment

fix junit tests

fix junit tests

fix junit tests

fix junit tests

clean import

a commit to trigger jenkins checks
@stochmial
Copy link
Author

Done

@oleg-nenashev oleg-nenashev merged commit 720b75f into jenkinsci:master Oct 11, 2016
oleg-nenashev added a commit that referenced this pull request Oct 15, 2016
@daniel-beck
Copy link
Member

@oleg-nenashev But… the commit message wasn't updated to be bot compatible?

@oleg-nenashev
Copy link
Member

Haha, my bad since I have not checked the new commit message :(
I'll note it in the ticket

@ringerc
Copy link
Contributor

ringerc commented Oct 18, 2016 via email

@stochmial
Copy link
Author

Thanks all for support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants