Skip to content

Commit

Permalink
Update master
Browse files Browse the repository at this point in the history
  • Loading branch information
timja committed Aug 5, 2024
1 parent 12edfe3 commit c8e5bd7
Show file tree
Hide file tree
Showing 52 changed files with 1,165 additions and 587 deletions.
12 changes: 9 additions & 3 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,29 @@ For refactoring and code cleanup changes, exercise the code before and after the

### Proposed changelog entries

- JENKINS-XXXXX, human-readable text
- human-readable text

<!-- Comment:
The changelog entry should be in the imperative mood; e.g., write "do this"/"return that" rather than "does this"/"returns that".
For examples, see: https://www.jenkins.io/changelog/
Remove JENKINS-XXXXX if there is no issue for the pull request.
Do not include the Jira issue in the changelog entry.
Include the Jira issue in the description of the pull request so that the changelog generator can find it and include it in the generated changelog.
You may add multiple changelog entries if applicable by adding a new entry to the list, e.g.
- JENKINS-123456, First changelog entry
- First changelog entry
- Second changelog entry
-->

### Proposed upgrade guidelines

N/A

<!-- Comment:
Leave the proposed upgrade guidelines in the pull request with the "N/A" value if no upgrade guidelines are needed.
The changelog generator relies on the presence of the upgrade guidelines section as part of its data extraction process.
-->

```[tasklist]
### Submitter checklist
- [ ] The Jira issue, if it exists, is well-described.
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/publish-release-artifact.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
wget -q https://get.jenkins.io/${REPO}/${PROJECT_VERSION}/${FILE_NAME}
- name: Upload Release Asset
id: upload-war
uses: softprops/action-gh-release@a74c6b72af54cfa997e81df42d94703d6313a2d0
uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down Expand Up @@ -108,7 +108,7 @@ jobs:
- name: Upload Release Asset
id: upload-deb
if: always()
uses: softprops/action-gh-release@a74c6b72af54cfa997e81df42d94703d6313a2d0
uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down Expand Up @@ -144,7 +144,7 @@ jobs:
- name: Upload Release Asset
id: upload-rpm
if: always()
uses: softprops/action-gh-release@a74c6b72af54cfa997e81df42d94703d6313a2d0
uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down Expand Up @@ -180,7 +180,7 @@ jobs:
- name: Upload Release Asset
id: upload-msi
if: always()
uses: softprops/action-gh-release@a74c6b72af54cfa997e81df42d94703d6313a2d0
uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down Expand Up @@ -216,7 +216,7 @@ jobs:
- name: Upload Release Asset
id: upload-suse-rpm
if: always()
uses: softprops/action-gh-release@a74c6b72af54cfa997e81df42d94703d6313a2d0
uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down
2 changes: 1 addition & 1 deletion ath.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set -o xtrace
cd "$(dirname "$0")"

# https://github.com/jenkinsci/acceptance-test-harness/releases
export ATH_VERSION=5883.vdea_99c1762a_d
export ATH_VERSION=5911.v5f88b_6d0c450

if [[ $# -eq 0 ]]; then
export JDK=17
Expand Down
4 changes: 2 additions & 2 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ THE SOFTWARE.
<properties>
<commons-fileupload2.version>2.0.0-M2</commons-fileupload2.version>
<slf4jVersion>2.0.13</slf4jVersion>
<stapler.version>1881.vd39f3ee5c629</stapler.version>
<stapler.version>1892.v73465f3d074d</stapler.version>
<groovy.version>2.4.21</groovy.version>
</properties>

Expand Down Expand Up @@ -113,7 +113,7 @@ THE SOFTWARE.
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.17.0</version>
<version>1.17.1</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/hudson/ClassicPluginStrategy.java
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ private void fix(Attributes atts, List<PluginWrapper.Dependency> optionalDepende

for (Dependency d : DetachedPluginsUtil.getImpliedDependencies(pluginName, jenkinsVersion)) {
LOGGER.fine(() -> "implied dep " + pluginName + " → " + d.shortName);
pluginManager.considerDetachedPlugin(d.shortName);
pluginManager.considerDetachedPlugin(d.shortName, pluginName);
optionalDependencies.add(d);
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/hudson/PluginManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ public void run(Reactor reactor) throws Exception {
}});
}

void considerDetachedPlugin(String shortName) {
void considerDetachedPlugin(String shortName, String source) {
if (new File(rootDir, shortName + ".jpi").isFile() ||
new File(rootDir, shortName + ".hpi").isFile() ||
new File(rootDir, shortName + ".jpl").isFile() ||
Expand All @@ -627,7 +627,7 @@ void considerDetachedPlugin(String shortName) {
for (String loadedFile : loadPluginsFromWar(getDetachedLocation(), (dir, name) -> normalisePluginName(name).equals(shortName))) {
String loaded = normalisePluginName(loadedFile);
File arc = new File(rootDir, loaded + ".jpi");
LOGGER.info(() -> "Loading a detached plugin as a dependency: " + arc);
LOGGER.info(() -> "Loading a detached plugin " + arc + " as a dependency of " + source);
try {
plugins.add(strategy.createPluginWrapper(arc));
} catch (IOException e) {
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/hudson/lifecycle/ExitLifecycle.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.util.BootFailure;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.model.Jenkins;
Expand Down Expand Up @@ -72,4 +73,9 @@ public void restart() {

System.exit(exitOnRestart);
}

@Override
public void onBootFailure(BootFailure problem) {
restart();
}
}
10 changes: 10 additions & 0 deletions core/src/main/java/hudson/lifecycle/Lifecycle.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import hudson.Util;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import hudson.util.BootFailure;
import hudson.util.JenkinsReloadFailed;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -324,6 +326,14 @@ public boolean supportsDynamicLoad() {
return true;
}

/**
* Called when Jenkins has failed to boot.
* @param problem a boot failure (could be {@link JenkinsReloadFailed})
* @since TODO
*/
public void onBootFailure(BootFailure problem) {
}

@Restricted(NoExternalUse.class)
public static final class PlaceholderLifecycle extends ExitLifecycle {

Expand Down
94 changes: 4 additions & 90 deletions core/src/main/java/hudson/model/AbstractItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

package hudson.model;

import static hudson.model.queue.Executables.getParentOf;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;

import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
Expand All @@ -39,9 +38,6 @@
import hudson.cli.declarative.CLIResolver;
import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SaveableListener;
import hudson.model.queue.SubTask;
import hudson.model.queue.Tasks;
import hudson.model.queue.WorkUnit;
import hudson.security.ACL;
import hudson.security.ACLContext;
import hudson.security.AccessControlled;
Expand All @@ -57,12 +53,8 @@
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -705,11 +697,13 @@ public void delete(StaplerRequest req, StaplerResponse rsp) throws IOException,
*
* <p>
* Any exception indicates the deletion has failed, but {@link AbortException} would prevent the caller
* from showing the stack trace. This
* from showing the stack trace.
* @see ItemDeletion
*/
@Override
public void delete() throws IOException, InterruptedException {
checkPermission(DELETE);
ItemListener.checkBeforeDelete(this);
boolean responsibleForAbortingBuilds = !ItemDeletion.contains(this);
boolean ownsRegistration = ItemDeletion.register(this);
if (!ownsRegistration && ItemDeletion.isRegistered(this)) {
Expand All @@ -719,87 +713,7 @@ public void delete() throws IOException, InterruptedException {
try {
// if a build is in progress. Cancel it.
if (responsibleForAbortingBuilds || ownsRegistration) {
Queue queue = Queue.getInstance();
if (this instanceof Queue.Task) {
// clear any items in the queue so they do not get picked up
queue.cancel((Queue.Task) this);
}
// now cancel any child items - this happens after ItemDeletion registration, so we can use a snapshot
for (Queue.Item i : queue.getItems()) {
Item item = Tasks.getItemOf(i.task);
while (item != null) {
if (item == this) {
if (!queue.cancel(i)) {
LOGGER.warning(() -> "failed to cancel " + i);
}
break;
}
if (item.getParent() instanceof Item) {
item = (Item) item.getParent();
} else {
break;
}
}
}
// interrupt any builds in progress (and this should be a recursive test so that folders do not pay
// the 15 second delay for every child item). This happens after queue cancellation, so will be
// a complete set of builds in flight
Map<Executor, Queue.Executable> buildsInProgress = new LinkedHashMap<>();
for (Computer c : Jenkins.get().getComputers()) {
for (Executor e : c.getAllExecutors()) {
final WorkUnit workUnit = e.getCurrentWorkUnit();
final Queue.Executable executable = workUnit != null ? workUnit.getExecutable() : null;
final SubTask subtask = executable != null ? getParentOf(executable) : null;

if (subtask != null) {
Item item = Tasks.getItemOf(subtask);
while (item != null) {
if (item == this) {
buildsInProgress.put(e, e.getCurrentExecutable());
e.interrupt(Result.ABORTED);
break;
}
if (item.getParent() instanceof Item) {
item = (Item) item.getParent();
} else {
break;
}
}
}
}
}
if (!buildsInProgress.isEmpty()) {
// give them 15 seconds or so to respond to the interrupt
long expiration = System.nanoTime() + TimeUnit.SECONDS.toNanos(15);
// comparison with executor.getCurrentExecutable() == computation currently should always be true
// as we no longer recycle Executors, but safer to future-proof in case we ever revisit recycling
while (!buildsInProgress.isEmpty() && expiration - System.nanoTime() > 0L) {
// we know that ItemDeletion will prevent any new builds in the queue
// ItemDeletion happens-before Queue.cancel so we know that the Queue will stay clear
// Queue.cancel happens-before collecting the buildsInProgress list
// thus buildsInProgress contains the complete set we need to interrupt and wait for
for (Iterator<Map.Entry<Executor, Queue.Executable>> iterator =
buildsInProgress.entrySet().iterator();
iterator.hasNext(); ) {
Map.Entry<Executor, Queue.Executable> entry = iterator.next();
// comparison with executor.getCurrentExecutable() == executable currently should always be
// true as we no longer recycle Executors, but safer to future-proof in case we ever
// revisit recycling.
if (!entry.getKey().isAlive()
|| entry.getValue() != entry.getKey().getCurrentExecutable()) {
iterator.remove();
}
// I don't know why, but we have to keep interrupting
entry.getKey().interrupt(Result.ABORTED);
}
Thread.sleep(50L);
}
if (!buildsInProgress.isEmpty()) {
throw new Failure(Messages.AbstractItem_FailureToStopBuilds(
buildsInProgress.size(), getFullDisplayName()
));
}
}
ItemDeletion.cancelBuildsInProgress(this);
}
if (this instanceof ItemGroup) {
// delete individual items first
Expand Down
1 change: 1 addition & 0 deletions core/src/main/java/hudson/model/AbstractProject.java
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,7 @@ public List<Action> getActions() {
* null if no information is available (for example,
* if no build was done yet.)
*/
@SuppressWarnings("deprecation")
@Override
public Node getLastBuiltOn() {
// where was it built on?
Expand Down
7 changes: 6 additions & 1 deletion core/src/main/java/hudson/model/AdministrativeMonitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,10 @@ public void doDisable(StaplerRequest req, StaplerResponse rsp) throws IOExceptio
* Form UI elements that change system state, e.g. toggling a feature on or off, need to be hidden from users
* lacking Administer permission.
* </p>
* @since 2.233
* @deprecated Callers should use {@link #checkRequiredPermission()} or {@link #hasRequiredPermission()}.
*/
@Deprecated
public Permission getRequiredPermission() {
return Jenkins.ADMINISTER;
}
Expand All @@ -213,6 +216,7 @@ public Permission getRequiredPermission() {
* </p>
* @see #getRequiredPermission()
* @see #hasRequiredPermission()
* @since 2.468
*/
public void checkRequiredPermission() {
Jenkins.get().checkPermission(getRequiredPermission());
Expand All @@ -226,6 +230,7 @@ public void checkRequiredPermission() {
* </p>
* @see #getRequiredPermission()
* @see #checkRequiredPermission()
* @since 2.468
*/
public boolean hasRequiredPermission() {
return Jenkins.get().hasPermission(getRequiredPermission());
Expand All @@ -236,7 +241,7 @@ public boolean hasRequiredPermission() {
*
* @return true if the current user has the minimum required permission to view any administrative monitor.
*
* @since TODO
* @since 2.468
*/
public static boolean hasPermissionToDisplay() {
return Jenkins.get().hasAnyPermission(Jenkins.SYSTEM_READ, Jenkins.MANAGE);
Expand Down
5 changes: 0 additions & 5 deletions core/src/main/java/hudson/model/BuildAuthorizationToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import hudson.security.ACL;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import jenkins.security.ApiTokenProperty;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
Expand Down Expand Up @@ -82,10 +81,6 @@ public static void checkPermission(Job<?, ?> project, BuildAuthorizationToken to
return;
}

if (req.getAttribute(ApiTokenProperty.class.getName()) instanceof User) {
return;
}

rsp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
rsp.addHeader("Allow", "POST");
throw HttpResponses.forwardToView(project, "requirePOST.jelly");
Expand Down
5 changes: 4 additions & 1 deletion core/src/main/java/hudson/model/Descriptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,9 @@ public T newInstance(@Nullable StaplerRequest req, @NonNull JSONObject formData)
return verifyNewInstance(bindJSON(req, clazz, formData, true));
}
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException | RuntimeException e) {
if (e instanceof RuntimeException && e instanceof HttpResponse) {
throw (RuntimeException) e;
}
throw new LinkageError("Failed to instantiate " + clazz + " from " + RedactSecretJsonInErrorMessageSanitizer.INSTANCE.sanitize(formData), e);
}
}
Expand Down Expand Up @@ -674,7 +677,7 @@ public Object instantiate(Class actualType, JSONObject json) {
+ actualType.getName() + " " + json);
}
} catch (Exception x) {
LOGGER.log(Level.WARNING, "falling back to default instantiation " + actualType.getName() + " " + json, x);
LOGGER.log(x instanceof HttpResponse ? Level.FINE : Level.WARNING, "falling back to default instantiation " + actualType.getName() + " " + json, x);
// If nested objects are not using newInstance, bindJSON will wind up throwing the same exception anyway,
// so logging above will result in a duplicated stack trace.
// However if they *are* then this is the only way to find errors in that newInstance.
Expand Down
Loading

0 comments on commit c8e5bd7

Please sign in to comment.