From cd986f1538d04991a51c421ec7c7a281a042e0ff Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Thu, 26 Sep 2024 13:43:08 -0400 Subject: [PATCH 1/3] Add test for deleting a Pipeline job while one of its builds is running only on a OneOffExecutor --- .../plugins/workflow/job/WorkflowJobTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/test/java/org/jenkinsci/plugins/workflow/job/WorkflowJobTest.java b/src/test/java/org/jenkinsci/plugins/workflow/job/WorkflowJobTest.java index 39ff9b44..0d505fb5 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/job/WorkflowJobTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/job/WorkflowJobTest.java @@ -1,6 +1,8 @@ package org.jenkinsci.plugins.workflow.job; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -12,10 +14,14 @@ import org.htmlunit.html.HtmlCheckBoxInput; import org.htmlunit.html.HtmlForm; import hudson.cli.CLICommandInvoker; +import hudson.model.Executor; import hudson.model.Result; import hudson.plugins.git.GitSCM; import hudson.security.WhoAmI; import hudson.triggers.SCMTrigger; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; import jenkins.plugins.git.GitSampleRepoRule; import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition; @@ -25,6 +31,7 @@ import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.RunLoadCounter; + public class WorkflowJobTest { @Rule public JenkinsRule j = new JenkinsRule(); @@ -157,4 +164,38 @@ public void newBuildsShouldNotLoadOld() throws Throwable { }); } + @Test + public void deletionShouldWaitForBuildsToComplete() throws Throwable { + var p = j.createProject(WorkflowJob.class); + p.setDefinition(new CpsFlowDefinition( + "import java.time.Duration\n" + + "import java.time.Instant\n" + + "@NonCPS def tightLoop() {\n" + + " echo 'uninterruptible'\n" + + " def start = Instant.now()\n" + + " while (Duration.between(start, Instant.now()).toSeconds() < 3) {\n" + + " try {\n" + + " Thread.sleep(100)\n" + + " } catch (InterruptedException e) { }\n" + + " }\n" + + "}\n" + + "tightLoop()", false)); + var b = p.scheduleBuild2(0).waitForStart(); + j.waitForMessage("uninterruptible", b); + // The build isn't done and can't be interrupted, so ItemDeletion.cancelBuildsInProgress should have to wait at least 3 seconds for it to complete. + // (but right now it completes immediately) + p.delete(); + // Make sure that the job really has been deleted. + assertThat(j.jenkins.getItemByFullName(p.getFullName()), nullValue()); + // ItemDeletion.cancelBuildsInProgress should guarantee that the queue is empty at this point. + // (but right now test0 #1 will still be running) + var executables = Stream.of(j.jenkins.getComputers()) + .flatMap(c -> c.getAllExecutors().stream()) + .map(Executor::getCurrentExecutable) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + assertThat(executables, empty()); + // (right now we end up waiting 3 seconds here for test0 #1 to complete while shutting down Jenkins) + } + } From 3426a6ac25629e3dba064468f9e3cac9280b0a0c Mon Sep 17 00:00:00 2001 From: Devin Nusbaum Date: Fri, 27 Sep 2024 15:21:18 -0400 Subject: [PATCH 2/3] [JENKINS-73824] Pick up incremental version of core and simplify test --- pom.xml | 19 ++++++++-- .../plugins/workflow/job/WorkflowJobTest.java | 38 ++++++++++--------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/pom.xml b/pom.xml index 680afe1a..fab2141b 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ org.jenkins-ci.plugins plugin - 4.85 + 4.88 org.jenkins-ci.plugins.workflow @@ -63,7 +63,11 @@ 999999-SNAPSHOT - 2.454 + + 2.479-rc35394.6ec50c7e34f9 + + 2289.vfd344a_6d1660 + 3.58 false true 2.26 @@ -73,14 +77,21 @@ io.jenkins.tools.bom - bom-2.452.x - 3023.v02a_987a_b_3ff9 + bom-weekly + 3387.v0f2773fa_3200 import pom + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + provided + io.jenkins.plugins ionicons-api diff --git a/src/test/java/org/jenkinsci/plugins/workflow/job/WorkflowJobTest.java b/src/test/java/org/jenkinsci/plugins/workflow/job/WorkflowJobTest.java index 0d505fb5..0099988b 100644 --- a/src/test/java/org/jenkinsci/plugins/workflow/job/WorkflowJobTest.java +++ b/src/test/java/org/jenkinsci/plugins/workflow/job/WorkflowJobTest.java @@ -20,19 +20,24 @@ import hudson.security.WhoAmI; import hudson.triggers.SCMTrigger; import java.util.Objects; +import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; import jenkins.plugins.git.GitSampleRepoRule; import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; +import org.jvnet.hudson.test.BuildWatcher; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.RunLoadCounter; - public class WorkflowJobTest { + private static final Logger LOGGER = Logger.getLogger(WorkflowJobTest.class.getName()); + + @ClassRule public static BuildWatcher watcher = new BuildWatcher(); @Rule public JenkinsRule j = new JenkinsRule(); @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule(); @@ -164,38 +169,35 @@ public void newBuildsShouldNotLoadOld() throws Throwable { }); } + @Issue("JENKINS-73824") @Test public void deletionShouldWaitForBuildsToComplete() throws Throwable { var p = j.createProject(WorkflowJob.class); p.setDefinition(new CpsFlowDefinition( - "import java.time.Duration\n" + - "import java.time.Instant\n" + - "@NonCPS def tightLoop() {\n" + - " echo 'uninterruptible'\n" + - " def start = Instant.now()\n" + - " while (Duration.between(start, Instant.now()).toSeconds() < 3) {\n" + - " try {\n" + - " Thread.sleep(100)\n" + - " } catch (InterruptedException e) { }\n" + - " }\n" + - "}\n" + - "tightLoop()", false)); + """ + try { + echo 'about to sleep' + sleep 999 + } catch(e) { + echo 'aborting soon' + sleep 3 + } + """, true)); var b = p.scheduleBuild2(0).waitForStart(); - j.waitForMessage("uninterruptible", b); - // The build isn't done and can't be interrupted, so ItemDeletion.cancelBuildsInProgress should have to wait at least 3 seconds for it to complete. - // (but right now it completes immediately) + j.waitForMessage("about to sleep", b); + // The build isn't done and catches the interruption, so ItemDeletion.cancelBuildsInProgress should have to wait at least 3 seconds for it to complete. + LOGGER.info(() -> "Deleting " + p); p.delete(); + LOGGER.info(() -> "Deleted " + p); // Make sure that the job really has been deleted. assertThat(j.jenkins.getItemByFullName(p.getFullName()), nullValue()); // ItemDeletion.cancelBuildsInProgress should guarantee that the queue is empty at this point. - // (but right now test0 #1 will still be running) var executables = Stream.of(j.jenkins.getComputers()) .flatMap(c -> c.getAllExecutors().stream()) .map(Executor::getCurrentExecutable) .filter(Objects::nonNull) .collect(Collectors.toList()); assertThat(executables, empty()); - // (right now we end up waiting 3 seconds here for test0 #1 to complete while shutting down Jenkins) } } From e42df03c82bf167299afb7b5fffa333565d935a7 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Fri, 4 Oct 2024 14:03:49 -0700 Subject: [PATCH 3/3] Update pom.xml --- pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pom.xml b/pom.xml index 87ef7fe4..8719669e 100644 --- a/pom.xml +++ b/pom.xml @@ -82,13 +82,6 @@ - - - jakarta.servlet - jakarta.servlet-api - 5.0.0 - provided - io.jenkins.plugins ionicons-api