-
-
Notifications
You must be signed in to change notification settings - Fork 9k
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-59656] check build id before interrupting from the executors widget #4264
[JENKINS-59656] check build id before interrupting from the executors widget #4264
Conversation
…re it's the intended one
d82340e
to
4bf1620
Compare
023098b
to
bd7858a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…seless now that it's doStopBuild(String) which takes a runExtId parameter
is this still a work in progress? |
Yes, I'm waiting for #4278 to be merged, to shorten the jelly code. |
Now using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, AFAIK queue executables are builds, freestylebuilds, abstractbuilds and workflowruns all inherit from run
https://javadoc.jenkins.io/hudson/model/Queue.Executable.html
I think you need to change the stop button on the build page as well? |
I don't think so. This button already POSTs to the This Of course, we could change |
Updated the PR text, because it was still describing the first version of the changes (with an optional parameter to doStop instead of the new doStopBuild method). |
@@ -110,7 +110,7 @@ THE SOFTWARE. | |||
</st:include> | |||
<td class="pane" align="center" valign="middle"> | |||
<j:if test="${e.hasStopPermission()}"> | |||
<l:stopButton href="${rootURL}/${c.url}${url}/stop" confirm="${%confirm(exe.fullDisplayName)}" alt="${%terminate this build}" /> | |||
<l:stopButton href="${rootURL}/${c.url}${url}/stopBuild?runExtId=${h.urlEncode(exe.externalizableId)}" confirm="${%confirm(exe.fullDisplayName)}" alt="${%terminate this build}" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that h.urlEncode
expects a non null object. But if exe
is not a Run
that method is not defined on the object and I think jelly will then just pass in null
causing a NullPointerException
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I've addressed that in db5d364, by making h.urlEncode
tolerant to null
. It will then return an empty string, which is, I think, more convenient than returning null
for the intended use case (encoding URL query parameters).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, and you're right about jelly passing null
for unknown properties, I tested it to be sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you agree to keep the former behavior if the executable is not a Run
?
Agreed. I was kind of assuming You and @rsandell are absolutely right that the change I propose should not break these cases (by throwing an NPE from the jelly view, or by not interrupting the current executable). |
@thomasgl-orange thanks for your changes! I'm not sure about changing the behaviour in a public method in such an extended class. What do you think about checking in the Jelly file if the externalizableId is null or not and call the proper method depending on that, given you already implemented the two methods (the one receiving the id and the one not receiving it). |
I have the same concern than @varyvol and I think its suggestion makes sense |
@varyvol @fcojfernandez : While I would agree, in general, that changing behavior of an existing public method is not good, I think here we should tolerate it. The Also, the current implementation, when called with a So, my opinion is still that "improving" this method, thus slightly changing its behavior on this corner case, is the way to go. The best alternative being, in my opinion, to add a new |
@thomasgl-orange my concern is because if I make a quick search, I can see uses of that method: https://github.com/search?q=org%3Ajenkinsci+Functions.urlEncode&type=Code At a very first glance, the change does not seem to have a great impact, but maybe it's wort to have a deeper look at those uses. |
The only use from that search I see is https://github.com/jenkinsci/jenkins/blob/96cc9ce0c57fe25e1538c9e8601672eed4b059db/core/src/main/resources/hudson/search/Search/search-failed.jelly and that's in core |
@fcojfernandez @timja : I went through results from https://github.com/search?q=org%3Ajenkinsci+"urlEncode"&type=Code (without "Functions" in the query, because it could hide results in Jelly files), and the two relevant results I find are usages I had introduced in #4278:
(and these ones are alright with the null change)
One more thing, if it counts: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough then!
@thomasgl-orange makes sense, thanks for the explanation and the in-depth verification. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation looks great, thanks a lot!
One minor comment about making the new API public, but it does not block the merge.
* @since TODO | ||
*/ | ||
@RequirePOST | ||
public HttpResponse doStopBuild(@CheckForNull @QueryParameter(fixEmpty = true) String runExtId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it have to be a public API? We could mark it as @Restricted(NoExternalUse.class)
which is a good practice for stapler endpoints IMHO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right, fixed in f01385e.
FYI, to make sure this restriction was alright, I've searched through all existing uses of the original Executor#doStop()
method by plugins in the jenkinsci organisation, in case some would have a reason to be changed to Executor#doStopBuild(String)
instead. But the few call sites I've found are always similar to what is done in AbstractBuild#doStop()
, with Executor#doStop()
being called immediately on an executor which has just been retrieved as the current one for a specific build, so it would be redundant to check it's the "right" one twice.
See JENKINS-59656
The approach I propose here is to add a new
stopBuild
method to the executor API (Executor#doStopBuild(String)
), which takes an identifier for the target build as parameter. It's value (if set) should match the externalizable id of the executor's current executable. If it doesn't match, thestopBuild
request does nothing (similar to the case of the user not having the right permissions). Of course, the executors view adds the right build ids to the target URL of its stop buttons.The behaviour of the existing
stop
API (which takes no parameter) is left unchanged. Usage as an HTTP API method should be avoided (and the one I've substituted is the only one I've found in Jenkins code base), because it's error-prone (it can stop a build which is not the intended one), but I think it's usage as a Java method is still okay (see discussion below about implementation ofAbstractBuild#doStop()
), so I don't think it should be deprecated.Note that I've assumed that a
Queue.Executable
was also always aRun
(on which I could callgetExternalizableId()
). Please let me know if it's not true.Proposed changelog entries
Submitter checklist
Desired reviewers
Maybe @daniel-beck, for the test case? (because it's based on something you wrote in
Security400Test
)