Merge branch 'master' into describable

This commit is contained in:
Vincent Latombe 2025-03-20 15:32:36 +01:00 committed by GitHub
commit 8ac576e5f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 61 additions and 53 deletions

View File

@ -41,7 +41,7 @@ THE SOFTWARE.
<commons-fileupload2.version>2.0.0-M2</commons-fileupload2.version>
<groovy.version>2.4.21</groovy.version>
<jelly.version>1.1-jenkins-20250108</jelly.version>
<stapler.version>1961.vd0a_a_60970a_a_2</stapler.version>
<stapler.version>1962.v928389828d33</stapler.version>
</properties>
<dependencyManagement>

View File

@ -895,37 +895,6 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
@Override
public Object getDynamic(String token, StaplerRequest2 req,
StaplerResponse2 rsp) {
if (Util.isOverridden(Job.class, getClass(), "getDynamic", String.class, StaplerRequest.class, StaplerResponse.class)) {
return getDynamic(token, StaplerRequest.fromStaplerRequest2(req), StaplerResponse.fromStaplerResponse2(rsp));
}
try {
// try to interpret the token as build number
return getBuildByNumber(Integer.parseInt(token));
} catch (NumberFormatException e) {
// try to map that to widgets
for (Widget w : getWidgets()) {
if (w.getUrlName().equals(token))
return w;
}
// is this a permalink?
for (Permalink p : getPermalinks()) {
if (p.getId().equals(token))
return p.resolve(this);
}
return super.getDynamic(token, req, rsp);
}
}
/**
* @deprecated use {@link #getDynamic(String, StaplerRequest2, StaplerResponse2)}
*/
@Deprecated
@Override
public Object getDynamic(String token, StaplerRequest req,
StaplerResponse rsp) {
// Intentionally not factoring this out into a common implementation method because it contains a call to super.
try {
// try to interpret the token as build number
return getBuildByNumber(Integer.parseInt(token));

View File

@ -138,6 +138,7 @@ public abstract class Node extends AbstractModelObject implements Reconfigurable
}
/**
* In most cases, you should not call this method directly, but {@link Jenkins#updateNode(Node)} instead.
* @since 1.635.
*/
@Override
@ -281,7 +282,7 @@ public abstract class Node extends AbstractModelObject implements Reconfigurable
try {
if (temporaryOfflineCause != cause) {
temporaryOfflineCause = cause;
save();
Jenkins.get().updateNode(this);
}
if (temporaryOfflineCause != null) {
Listeners.notify(ComputerListener.class, false, l -> l.onTemporarilyOffline(toComputer(), temporaryOfflineCause));

View File

@ -248,6 +248,15 @@ public abstract class Slave extends Node implements Serializable {
return launcher == null ? new JNLPLauncher() : launcher;
}
/**
* @deprecated In most cases, you should not call this method directly, but {@link Jenkins#updateNode(Node)} instead.
*/
@Override
@Deprecated
public void save() throws IOException {
super.save();
}
public void setLauncher(ComputerLauncher launcher) {
this.launcher = launcher;
}

View File

@ -47,7 +47,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.atomic.AtomicBoolean;
@ -203,17 +202,18 @@ public class Nodes implements PersistenceRoot {
* @since 1.634
*/
public boolean updateNode(final @NonNull Node node) throws IOException {
return updateNode(node, true);
}
private boolean updateNode(final @NonNull Node node, boolean fireListener) throws IOException {
boolean exists;
try {
exists = Queue.withLock(new Callable<>() {
@Override
public Boolean call() throws Exception {
if (node == nodes.get(node.getNodeName())) {
jenkins.trimLabels(node);
return true;
}
return false;
exists = Queue.withLock(() -> {
if (node == nodes.get(node.getNodeName())) {
jenkins.trimLabels(node);
return true;
}
return false;
});
} catch (RuntimeException e) {
// should never happen, but if it does let's do the right thing
@ -225,7 +225,9 @@ public class Nodes implements PersistenceRoot {
if (exists) {
// TODO there is a theoretical race whereby the node instance is updated/removed after lock release
node.save();
// TODO should this fireOnUpdated?
if (fireListener) {
NodeListener.fireOnUpdated(node, node);
}
return true;
}
return false;
@ -252,7 +254,7 @@ public class Nodes implements PersistenceRoot {
newOne.onLoad(Nodes.this, newOne.getNodeName());
}
});
updateNode(newOne);
updateNode(newOne, false);
if (!newOne.getNodeName().equals(oldOne.getNodeName())) {
LOGGER.fine(() -> "deleting " + new File(getRootDir(), oldOne.getNodeName()));
Util.deleteRecursive(new File(getRootDir(), oldOne.getNodeName()));

View File

@ -42,7 +42,7 @@
"postcss-preset-env": "10.1.5",
"postcss-scss": "4.0.9",
"prettier": "3.5.3",
"sass": "1.85.1",
"sass": "1.86.0",
"sass-loader": "16.0.5",
"style-loader": "4.0.0",
"stylelint": "16.16.0",

View File

@ -73,9 +73,9 @@ THE SOFTWARE.
</issueManagement>
<properties>
<revision>2.502</revision>
<revision>2.503</revision>
<changelist>-SNAPSHOT</changelist>
<project.build.outputTimestamp>2025-03-11T13:49:05Z</project.build.outputTimestamp>
<project.build.outputTimestamp>2025-03-18T13:51:20Z</project.build.outputTimestamp>
<!-- configuration for patch tracker plugin -->
<project.patchManagement.system>github</project.patchManagement.system>

View File

@ -178,7 +178,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-test-harness</artifactId>
<version>2414.v185474555e66</version>
<version>2418.ve283b_a_b_79e37</version>
<scope>test</scope>
<exclusions>
<exclusion>

View File

@ -39,6 +39,7 @@ import static org.junit.Assert.fail;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.EnvVars;
import hudson.ExtensionList;
import hudson.FilePath;
import hudson.model.Node.Mode;
import hudson.model.Queue.WaitingItem;
@ -61,6 +62,7 @@ import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.List;
import jenkins.model.Jenkins;
import jenkins.model.NodeListener;
import jenkins.security.QueueItemAuthenticatorConfiguration;
import org.htmlunit.HttpMethod;
import org.htmlunit.Page;
@ -91,6 +93,20 @@ public class NodeTest {
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
}
@TestExtension("testSetTemporaryOfflineCause")
public static class NodeListenerImpl extends NodeListener {
private int count;
public static int getCount() {
return ExtensionList.lookupSingleton(NodeListenerImpl.class).count;
}
@Override
protected void onUpdated(@NonNull Node oldOne, @NonNull Node newOne) {
count++;
}
}
@Test
public void testSetTemporaryOfflineCause() throws Exception {
Node node = j.createOnlineSlave();
@ -98,16 +114,19 @@ public class NodeTest {
project.setAssignedLabel(j.jenkins.getLabel(node.getDisplayName()));
OfflineCause cause = new OfflineCause.ByCLI("message");
node.setTemporaryOfflineCause(cause);
assertThat(NodeListenerImpl.getCount(), is(1));
for (ComputerListener l : ComputerListener.all()) {
l.onOnline(node.toComputer(), TaskListener.NULL);
}
assertEquals("Node should have offline cause which was set.", cause, node.toComputer().getOfflineCause());
OfflineCause cause2 = new OfflineCause.ByCLI("another message");
node.setTemporaryOfflineCause(cause2);
assertThat(NodeListenerImpl.getCount(), is(2));
assertEquals("Node should have the new offline cause.", cause2, node.toComputer().getOfflineCause());
// Exists in some plugins
node.toComputer().setTemporarilyOffline(false, new OfflineCause.ByCLI("A third message"));
assertThat(node.getTemporaryOfflineCause(), nullValue());
assertThat(NodeListenerImpl.getCount(), is(3));
}
@Test

View File

@ -49,6 +49,14 @@ public class NodeListenerTest {
verifyNoMoreInteractions(mock);
}
@Test
public void updateNode() throws Exception {
Node agent = j.createSlave();
agent.setLabelString("some label");
Jenkins.get().updateNode(agent);
verify(mock, times(1)).onUpdated(any(Node.class), any(Node.class));
}
private CLICommandInvoker cli(CLICommand cmd) {
return new CLICommandInvoker(j, cmd);
}

View File

@ -4372,7 +4372,7 @@ __metadata:
postcss-preset-env: "npm:10.1.5"
postcss-scss: "npm:4.0.9"
prettier: "npm:3.5.3"
sass: "npm:1.85.1"
sass: "npm:1.86.0"
sass-loader: "npm:16.0.5"
sortablejs: "npm:1.15.6"
style-loader: "npm:4.0.0"
@ -6351,9 +6351,9 @@ __metadata:
languageName: node
linkType: hard
"sass@npm:1.85.1":
version: 1.85.1
resolution: "sass@npm:1.85.1"
"sass@npm:1.86.0":
version: 1.86.0
resolution: "sass@npm:1.86.0"
dependencies:
"@parcel/watcher": "npm:^2.4.1"
chokidar: "npm:^4.0.0"
@ -6364,7 +6364,7 @@ __metadata:
optional: true
bin:
sass: sass.js
checksum: 10c0/f843aa1df1dca2f0e9cb2fb247e4939fd514ae4c182cdd1900a0622c0d71b40dfb1c4225f78b78e165a318287ca137ec597695db3e496408bd16a921a2bc2b3f
checksum: 10c0/921caea1fd8a450d4a986e5570ce13c4ca7b2a57da390811add3d2087ad8f46f53b34652ddcb237d8bdaad49c560b8d6eee130c733c787d058bc5a71a914c139
languageName: node
linkType: hard