mirror of https://github.com/jenkinsci/jenkins.git
Merge branch 'master' into describable
This commit is contained in:
commit
8ac576e5f8
|
@ -41,7 +41,7 @@ THE SOFTWARE.
|
||||||
<commons-fileupload2.version>2.0.0-M2</commons-fileupload2.version>
|
<commons-fileupload2.version>2.0.0-M2</commons-fileupload2.version>
|
||||||
<groovy.version>2.4.21</groovy.version>
|
<groovy.version>2.4.21</groovy.version>
|
||||||
<jelly.version>1.1-jenkins-20250108</jelly.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>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
|
|
@ -895,37 +895,6 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
|
||||||
@Override
|
@Override
|
||||||
public Object getDynamic(String token, StaplerRequest2 req,
|
public Object getDynamic(String token, StaplerRequest2 req,
|
||||||
StaplerResponse2 rsp) {
|
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 {
|
||||||
// try to interpret the token as build number
|
// try to interpret the token as build number
|
||||||
return getBuildByNumber(Integer.parseInt(token));
|
return getBuildByNumber(Integer.parseInt(token));
|
||||||
|
|
|
@ -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.
|
* @since 1.635.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -281,7 +282,7 @@ public abstract class Node extends AbstractModelObject implements Reconfigurable
|
||||||
try {
|
try {
|
||||||
if (temporaryOfflineCause != cause) {
|
if (temporaryOfflineCause != cause) {
|
||||||
temporaryOfflineCause = cause;
|
temporaryOfflineCause = cause;
|
||||||
save();
|
Jenkins.get().updateNode(this);
|
||||||
}
|
}
|
||||||
if (temporaryOfflineCause != null) {
|
if (temporaryOfflineCause != null) {
|
||||||
Listeners.notify(ComputerListener.class, false, l -> l.onTemporarilyOffline(toComputer(), temporaryOfflineCause));
|
Listeners.notify(ComputerListener.class, false, l -> l.onTemporarilyOffline(toComputer(), temporaryOfflineCause));
|
||||||
|
|
|
@ -248,6 +248,15 @@ public abstract class Slave extends Node implements Serializable {
|
||||||
return launcher == null ? new JNLPLauncher() : launcher;
|
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) {
|
public void setLauncher(ComputerLauncher launcher) {
|
||||||
this.launcher = launcher;
|
this.launcher = launcher;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,6 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
import java.util.concurrent.ConcurrentSkipListMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
@ -203,17 +202,18 @@ public class Nodes implements PersistenceRoot {
|
||||||
* @since 1.634
|
* @since 1.634
|
||||||
*/
|
*/
|
||||||
public boolean updateNode(final @NonNull Node node) throws IOException {
|
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;
|
boolean exists;
|
||||||
try {
|
try {
|
||||||
exists = Queue.withLock(new Callable<>() {
|
exists = Queue.withLock(() -> {
|
||||||
@Override
|
|
||||||
public Boolean call() throws Exception {
|
|
||||||
if (node == nodes.get(node.getNodeName())) {
|
if (node == nodes.get(node.getNodeName())) {
|
||||||
jenkins.trimLabels(node);
|
jenkins.trimLabels(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// should never happen, but if it does let's do the right thing
|
// should never happen, but if it does let's do the right thing
|
||||||
|
@ -225,7 +225,9 @@ public class Nodes implements PersistenceRoot {
|
||||||
if (exists) {
|
if (exists) {
|
||||||
// TODO there is a theoretical race whereby the node instance is updated/removed after lock release
|
// TODO there is a theoretical race whereby the node instance is updated/removed after lock release
|
||||||
node.save();
|
node.save();
|
||||||
// TODO should this fireOnUpdated?
|
if (fireListener) {
|
||||||
|
NodeListener.fireOnUpdated(node, node);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -252,7 +254,7 @@ public class Nodes implements PersistenceRoot {
|
||||||
newOne.onLoad(Nodes.this, newOne.getNodeName());
|
newOne.onLoad(Nodes.this, newOne.getNodeName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
updateNode(newOne);
|
updateNode(newOne, false);
|
||||||
if (!newOne.getNodeName().equals(oldOne.getNodeName())) {
|
if (!newOne.getNodeName().equals(oldOne.getNodeName())) {
|
||||||
LOGGER.fine(() -> "deleting " + new File(getRootDir(), oldOne.getNodeName()));
|
LOGGER.fine(() -> "deleting " + new File(getRootDir(), oldOne.getNodeName()));
|
||||||
Util.deleteRecursive(new File(getRootDir(), oldOne.getNodeName()));
|
Util.deleteRecursive(new File(getRootDir(), oldOne.getNodeName()));
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
"postcss-preset-env": "10.1.5",
|
"postcss-preset-env": "10.1.5",
|
||||||
"postcss-scss": "4.0.9",
|
"postcss-scss": "4.0.9",
|
||||||
"prettier": "3.5.3",
|
"prettier": "3.5.3",
|
||||||
"sass": "1.85.1",
|
"sass": "1.86.0",
|
||||||
"sass-loader": "16.0.5",
|
"sass-loader": "16.0.5",
|
||||||
"style-loader": "4.0.0",
|
"style-loader": "4.0.0",
|
||||||
"stylelint": "16.16.0",
|
"stylelint": "16.16.0",
|
||||||
|
|
4
pom.xml
4
pom.xml
|
@ -73,9 +73,9 @@ THE SOFTWARE.
|
||||||
</issueManagement>
|
</issueManagement>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>2.502</revision>
|
<revision>2.503</revision>
|
||||||
<changelist>-SNAPSHOT</changelist>
|
<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 -->
|
<!-- configuration for patch tracker plugin -->
|
||||||
<project.patchManagement.system>github</project.patchManagement.system>
|
<project.patchManagement.system>github</project.patchManagement.system>
|
||||||
|
|
|
@ -178,7 +178,7 @@ THE SOFTWARE.
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jenkins-ci.main</groupId>
|
<groupId>org.jenkins-ci.main</groupId>
|
||||||
<artifactId>jenkins-test-harness</artifactId>
|
<artifactId>jenkins-test-harness</artifactId>
|
||||||
<version>2414.v185474555e66</version>
|
<version>2418.ve283b_a_b_79e37</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
|
|
|
@ -39,6 +39,7 @@ import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.NonNull;
|
import edu.umd.cs.findbugs.annotations.NonNull;
|
||||||
import hudson.EnvVars;
|
import hudson.EnvVars;
|
||||||
|
import hudson.ExtensionList;
|
||||||
import hudson.FilePath;
|
import hudson.FilePath;
|
||||||
import hudson.model.Node.Mode;
|
import hudson.model.Node.Mode;
|
||||||
import hudson.model.Queue.WaitingItem;
|
import hudson.model.Queue.WaitingItem;
|
||||||
|
@ -61,6 +62,7 @@ import java.util.Collection;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import jenkins.model.Jenkins;
|
import jenkins.model.Jenkins;
|
||||||
|
import jenkins.model.NodeListener;
|
||||||
import jenkins.security.QueueItemAuthenticatorConfiguration;
|
import jenkins.security.QueueItemAuthenticatorConfiguration;
|
||||||
import org.htmlunit.HttpMethod;
|
import org.htmlunit.HttpMethod;
|
||||||
import org.htmlunit.Page;
|
import org.htmlunit.Page;
|
||||||
|
@ -91,6 +93,20 @@ public class NodeTest {
|
||||||
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
|
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
|
@Test
|
||||||
public void testSetTemporaryOfflineCause() throws Exception {
|
public void testSetTemporaryOfflineCause() throws Exception {
|
||||||
Node node = j.createOnlineSlave();
|
Node node = j.createOnlineSlave();
|
||||||
|
@ -98,16 +114,19 @@ public class NodeTest {
|
||||||
project.setAssignedLabel(j.jenkins.getLabel(node.getDisplayName()));
|
project.setAssignedLabel(j.jenkins.getLabel(node.getDisplayName()));
|
||||||
OfflineCause cause = new OfflineCause.ByCLI("message");
|
OfflineCause cause = new OfflineCause.ByCLI("message");
|
||||||
node.setTemporaryOfflineCause(cause);
|
node.setTemporaryOfflineCause(cause);
|
||||||
|
assertThat(NodeListenerImpl.getCount(), is(1));
|
||||||
for (ComputerListener l : ComputerListener.all()) {
|
for (ComputerListener l : ComputerListener.all()) {
|
||||||
l.onOnline(node.toComputer(), TaskListener.NULL);
|
l.onOnline(node.toComputer(), TaskListener.NULL);
|
||||||
}
|
}
|
||||||
assertEquals("Node should have offline cause which was set.", cause, node.toComputer().getOfflineCause());
|
assertEquals("Node should have offline cause which was set.", cause, node.toComputer().getOfflineCause());
|
||||||
OfflineCause cause2 = new OfflineCause.ByCLI("another message");
|
OfflineCause cause2 = new OfflineCause.ByCLI("another message");
|
||||||
node.setTemporaryOfflineCause(cause2);
|
node.setTemporaryOfflineCause(cause2);
|
||||||
|
assertThat(NodeListenerImpl.getCount(), is(2));
|
||||||
assertEquals("Node should have the new offline cause.", cause2, node.toComputer().getOfflineCause());
|
assertEquals("Node should have the new offline cause.", cause2, node.toComputer().getOfflineCause());
|
||||||
// Exists in some plugins
|
// Exists in some plugins
|
||||||
node.toComputer().setTemporarilyOffline(false, new OfflineCause.ByCLI("A third message"));
|
node.toComputer().setTemporarilyOffline(false, new OfflineCause.ByCLI("A third message"));
|
||||||
assertThat(node.getTemporaryOfflineCause(), nullValue());
|
assertThat(node.getTemporaryOfflineCause(), nullValue());
|
||||||
|
assertThat(NodeListenerImpl.getCount(), is(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -49,6 +49,14 @@ public class NodeListenerTest {
|
||||||
verifyNoMoreInteractions(mock);
|
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) {
|
private CLICommandInvoker cli(CLICommand cmd) {
|
||||||
return new CLICommandInvoker(j, cmd);
|
return new CLICommandInvoker(j, cmd);
|
||||||
}
|
}
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -4372,7 +4372,7 @@ __metadata:
|
||||||
postcss-preset-env: "npm:10.1.5"
|
postcss-preset-env: "npm:10.1.5"
|
||||||
postcss-scss: "npm:4.0.9"
|
postcss-scss: "npm:4.0.9"
|
||||||
prettier: "npm:3.5.3"
|
prettier: "npm:3.5.3"
|
||||||
sass: "npm:1.85.1"
|
sass: "npm:1.86.0"
|
||||||
sass-loader: "npm:16.0.5"
|
sass-loader: "npm:16.0.5"
|
||||||
sortablejs: "npm:1.15.6"
|
sortablejs: "npm:1.15.6"
|
||||||
style-loader: "npm:4.0.0"
|
style-loader: "npm:4.0.0"
|
||||||
|
@ -6351,9 +6351,9 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"sass@npm:1.85.1":
|
"sass@npm:1.86.0":
|
||||||
version: 1.85.1
|
version: 1.86.0
|
||||||
resolution: "sass@npm:1.85.1"
|
resolution: "sass@npm:1.86.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@parcel/watcher": "npm:^2.4.1"
|
"@parcel/watcher": "npm:^2.4.1"
|
||||||
chokidar: "npm:^4.0.0"
|
chokidar: "npm:^4.0.0"
|
||||||
|
@ -6364,7 +6364,7 @@ __metadata:
|
||||||
optional: true
|
optional: true
|
||||||
bin:
|
bin:
|
||||||
sass: sass.js
|
sass: sass.js
|
||||||
checksum: 10c0/f843aa1df1dca2f0e9cb2fb247e4939fd514ae4c182cdd1900a0622c0d71b40dfb1c4225f78b78e165a318287ca137ec597695db3e496408bd16a921a2bc2b3f
|
checksum: 10c0/921caea1fd8a450d4a986e5570ce13c4ca7b2a57da390811add3d2087ad8f46f53b34652ddcb237d8bdaad49c560b8d6eee130c733c787d058bc5a71a914c139
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue