diff --git a/core/src/main/java/hudson/model/Executor.java b/core/src/main/java/hudson/model/Executor.java index f86dbd7c6c0a..6b478adb1056 100644 --- a/core/src/main/java/hudson/model/Executor.java +++ b/core/src/main/java/hudson/model/Executor.java @@ -50,6 +50,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Vector; import java.util.concurrent.Callable; @@ -284,7 +285,14 @@ public void recordCauseOfInterruption(Run build, TaskListener listener) { lock.writeLock().unlock(); } - build.addAction(new InterruptedBuildAction(r)); + InterruptedBuildAction action = build.getAction(InterruptedBuildAction.class); + if (action != null) { + Collection combinedCauses = new LinkedHashSet<>(action.getCauses()); + combinedCauses.addAll(r); + build.replaceAction(new InterruptedBuildAction(combinedCauses)); + } else { + build.addAction(new InterruptedBuildAction(r)); + } for (CauseOfInterruption c : r) c.print(listener); } diff --git a/test/src/test/java/hudson/model/ExecutorTest.java b/test/src/test/java/hudson/model/ExecutorTest.java index 3c76323131ee..fb5f48c67196 100644 --- a/test/src/test/java/hudson/model/ExecutorTest.java +++ b/test/src/test/java/hudson/model/ExecutorTest.java @@ -3,6 +3,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -16,7 +17,9 @@ import hudson.slaves.OfflineCause; import hudson.util.OneShotEvent; import java.io.IOException; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +import jenkins.model.CauseOfInterruption; import jenkins.model.CauseOfInterruption.UserInterruption; import jenkins.model.InterruptedBuildAction; import jenkins.model.Jenkins; @@ -227,4 +230,34 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen } } } + + @Test + public void recordCauseOfInterruption() throws Exception { + FreeStyleProject p = j.createFreeStyleProject(); + p.getBuildersList().add(TestBuilder.of((build, launcher, listener) -> { + Executor exec = build.getExecutor(); + exec.interrupt(Result.NOT_BUILT, new TestCauseOfInterruption("one"), new TestCauseOfInterruption("two")); + exec.recordCauseOfInterruption(build, listener); + exec.interrupt(Result.NOT_BUILT, new TestCauseOfInterruption("three"), new TestCauseOfInterruption("four")); + exec.recordCauseOfInterruption(build, listener); + })); + FreeStyleBuild b = j.buildAndAssertStatus(Result.NOT_BUILT, p); + assertThat(b.getActions(InterruptedBuildAction.class).stream().map(iba -> iba.getCauses().stream().map(CauseOfInterruption::getShortDescription).toList()).toList(), is(List.of(List.of("one", "two", "three", "four")))); + } + + private static final class TestCauseOfInterruption extends CauseOfInterruption { + private final String msg; + + TestCauseOfInterruption(String msg) { + this.msg = msg; + + } + + @Override + public String getShortDescription() { + return msg; + } + } + + }