-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Fix false 'Build Scheduled' notification when parent multibranch is d… #26117
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
Fix false 'Build Scheduled' notification when parent multibranch is d… #26117
Conversation
…isabled When trying to trigger a build of a branch job in a disabled multibranch project, the UI showed 'Build Scheduled' even though the build was not actually scheduled (queue returned null, causing a 302 redirect). Changes: - Updated isBuildable() to check if parent ParameterizedJob is disabled - Changed doBuild() to return 409 CONFLICT when schedule2() returns null - Fixed JavaScript to only treat HTTP 201 as success (not 302 redirects) Fixes issue where disabled multibranch parent allows branch builds to appear scheduled when they are actually rejected.
mawinter69
left a comment
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.
| ItemGroup<? extends Item> parentGroup = ((Job) this).getParent(); | ||
| if (parentGroup instanceof Item) { | ||
| Item parent = (Item) parentGroup; | ||
| if (parent instanceof ParameterizedJob && ((ParameterizedJob) parent).isDisabled()) { |
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.
A MultiBranchProject is not a ParameterizedJob but a ComputedFolder. So this check will never be true.
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 absolutely right, thanks for pointing that out.
A MultiBranchProject (and organization folders) are ComputedFolder implementations, not ParameterizedJobs, so the parent check I added will never be true for multibranch/organization folders and therefore doesn’t actually affect the build button visibility in those cases.
The real functional change in this PR is:
- Returning
409 CONFLICTfromdoBuildwhenschedule2(...).getItem()isnullinstead of redirecting with302, and - Updating the JS to only treat
201as success.
That fixes the incorrect “Build Scheduled” notification when the build is not actually queued.
To keep this PR focused and correct, I’ll remove the ineffective ParameterizedJob parent check from isBuildable() and leave the PR scoped to the response/notification fix. If we also want to hide the build button for branch jobs when the multibranch (or org folder) is disabled, I agree that needs a different approach that works with ComputedFolder and could be handled in a follow‑up change.
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.
Why did you change both files? Wouldn't one of the changes be enough?
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.
@daniel-beck Good question. Either change alone would fix the issue:
- Only Java change: Returning
409 CONFLICTinstead of302would makersp.okfalse, so the JS would show the error message. - Only JS change: Checking
rsp.status === 201would ignore302redirects, so it wouldn't show success incorrectly.
I included both because:
- The Java change uses the correct HTTP status code (
409 CONFLICTfor a rejected build) - The JS change is more precise (only treats actual creation as success)
If you prefer, I can remove one of them. Which would you prefer to keep?
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.
Both changes are unnecessary. The JS change is less likely to impact other code I'd expect, either change is probably ok though.
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.
Agree with Tim. HTTP response codes for this are a whole thing, and we'd just break someone's API use.
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.
Thanks for the feedback. I understand the concern about changing HTTP status codes potentially breaking API clients.
I propose using a custom response header instead, which is already used in Jenkins (e.g., X-Building, X-Jenkins-ValidateButton-Callback).
Proposed approach:
-
Backend: When
schedule2()returns null, keep the 302 redirect (for API compatibility) but add a header:rsp.setHeader("X-Build-Scheduled", "false"); rsp.sendRedirect(".");
When successful, add:
rsp.setHeader("X-Build-Scheduled", "true"); rsp.sendRedirect(SC_CREATED, ...);
-
Frontend: Check the header instead of status code:
const scheduled = rsp.headers.get("X-Build-Scheduled"); if (scheduled === "true") { notificationBar.show(success, notificationBar.SUCCESS); } else { notificationBar.show(failure, notificationBar.ERROR); }
Benefits:
- Maintains API compatibility (keeps 302 redirect)
- Follows existing Jenkins patterns
- Explicit signal for the UI
- No breaking changes
If you prefer, I can keep only the JavaScript change (rsp.status === 201), though it's less precise. What do you think?
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 already have an explicit signal. 201 created that’s all you need
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.
Alternative (more detailed):
Thanks for clarifying. I understand now:
- 201 Created is already the explicit success signal
- The JavaScript change (rsp.status === 201) correctly uses that signal
- The Java change (409 CONFLICT) is unnecessary and could break API clients
I'll revert the Java change back to the original redirect behavior and keep only the JavaScript fix. This addresses the UI notification issue while maintaining API compatibility.
Updating the PR accordingly.
Why? I've shown no previous interest in this issue. |
Reverted the 409 CONFLICT throw back to redirect behavior to maintain API compatibility. The JavaScript change (checking rsp.status === 201) is sufficient to fix the UI notification issue using the existing 201 Created signal.
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, (untested but reviewed code, including in Java not from diff)
|
I built a local copy and confirmed that the "Build Now" button on the job page now reports an error instead of reporting that it scheduled the job. However, when I click the arrow on the folder page that means "Build Now", it still reports that the job was scheduled, even though it was not scheduled. I created the job as a multibranch Pipeline with the GitHub branch source for https://github.com/jenkinsci/implied-labels-plugin use a fine grained access token with read only access to all my public repositories. I disabled the job by appending the "/disable" to the URL of the folder and submitting the page. Is it expected that there is a behavioral difference between those two forms of "Build Now"? Job page
Results from clicking "Build Now"
Folder page
Results from clicking arrow that means "Build Now"
|
|
Job page: job-subpage.jelly line 63 still references the deleted data-callback="lib_hudson_project_configurable_build_now_callback", which causes the error. Line 68 also has href="${url}/build?delay=0sec" instead of href="#", reintroducing the race condition. Folder page: BuildButtonColumn/column.jelly line 48 has href="${href}" set directly. If the onclick handler doesn't attach in time, the browser follows the href as GET, which can show "Build scheduled" even when disabled. Both need the same fix: set href="#" and use a data attribute for the URL. The job page also needs the callback reference removed. Should I apply these fixes? |
|
Ideally on the folder page the button would be removed, when the multibranch project is disabled. But the current APIs don't allow to find this out I think. That is what @LakshyaBagani tried to achieve in the change of the Java file. Might be possible by adding a method |
It seems you're mixing things here with the other PR. The problem @MarkEWaite describes has nothing to do with the race condition |
|
Sorry for the confusion - I mixed up the two PRs. The folder page issue isn't related to race conditions. The issue: the folder page uses BuildButtonColumn/icon.js, which still checks rsp.ok, while the job page uses configurable.js that checks rsp.status === 201. That's why the folder page still shows "Build scheduled" incorrectly. The fix: change icon.js from if (rsp.ok) to if (rsp.status === 201) to match the fix in configurable.js. I understand hiding the button when the multibranch is disabled would require API changes that are out of scope. This change will at least fix the incorrect notification. @mawinter69 Am I thinking in the right direction ? |
Matches the fix in configurable.js to only treat 201 Created as success, preventing false 'Build scheduled' notifications when builds are rejected.
|
I opened #26131 that implements my proposal for the API change. |
MarkEWaite
left a comment
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've confirmed that the additional case that I reported is handled by the pull request. Thanks!
This PR is now ready for merge. We will merge it after approximately 24 hours if there is no negative feedback.
/label ready-for-merge
|
Do we still need this PR? With #26131 the buttons are no longer there when the parent Multibranch or org folder job is disabled. |
I don't think its needed but it may be more correct as fetch will follow redirects and checking for ok isn't enough as that could be a 200 from a redirect. |
Dismissing the request for changes from @mawinter69 because he replied with a "thumbs-up" to the answer from @timja
|
Congratulations on getting your very first Jenkins core pull request merged 🎉🥳 |





Fixes #16678
Description
When trying to trigger a build of a branch job in a disabled multibranch project, the UI incorrectly showed "Build Scheduled" notification even though the build was not actually scheduled. The queue rejected the build (returned null), but the code sent a 302 redirect which the JavaScript treated as success.
Changes
isBuildable()method: Now checks if the parentParameterizedJob(e.g., multibranch project) is disabled before allowing buildsdoBuild(): Changed from returning 302 redirect to throwing 409 CONFLICT whenschedule2()returns nullrsp.ok(which includes 302) to checkingrsp.status === 201specificallyTesting done
Manual testing performed:
Tested on: Jenkins 2.541-SNAPSHOT
Proposed changelog entries
Proposed changelog category
/label bug
Proposed upgrade guidelines
N/A
Submitter checklist
@Restrictedor have@since TODOJavadocs, as appropriate.@Deprecated(since = "TODO")or@Deprecated(forRemoval = true, since = "TODO"), if applicable.evalto ease future introduction of Content Security Policy (CSP) directives (see documentation).Desired reviewers
@timja @mawinter69 @daniel-beck