From 090bc3951a035bf470f22457282a85ecbdbe6341 Mon Sep 17 00:00:00 2001
From: strangelookingnerd
<49242855+strangelookingnerd@users.noreply.github.com>
Date: Tue, 12 Aug 2025 11:21:42 +0200
Subject: [PATCH 1/4] Migrate tests to JUnit5
* Migrate annotations and imports
* Migrate assertions
* Remove public visibility for test classes and methods
* Minor code cleanup
---
pom.xml | 2 +-
...abilityHintBranchPropertyWorkflowTest.java | 46 +++--
.../multibranch/GitDirectorySCMNavigator.java | 18 +-
.../multibranch/JobPropertyStepTest.java | 181 ++++++++++--------
.../NoTriggerBranchPropertyWorkflowTest.java | 30 ++-
.../multibranch/ReadTrustedStepTest.java | 65 +++++--
.../multibranch/RepairBranchPropertyTest.java | 39 ++--
.../multibranch/ReplayActionTest.java | 58 ++++--
.../multibranch/ResolveScmStepTest.java | 30 +--
.../workflow/multibranch/SCMBinderTest.java | 126 +++++++-----
.../workflow/multibranch/SCMVarTest.java | 111 ++++++-----
.../WorkflowBranchProjectFactoryTest.java | 46 +++--
...WorkflowMultiBranchProjectFactoryTest.java | 98 ++++++++--
.../WorkflowMultiBranchProjectTest.java | 68 ++++---
14 files changed, 587 insertions(+), 331 deletions(-)
diff --git a/pom.xml b/pom.xml
index e1448373..a9dd09ae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@ THE SOFTWARE.
org.jenkins-ci.plugins
plugin
- 5.18
+ 5.19
org.jenkins-ci.plugins.workflow
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/DurabilityHintBranchPropertyWorkflowTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/DurabilityHintBranchPropertyWorkflowTest.java
index cb5b2b4d..709940e6 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/DurabilityHintBranchPropertyWorkflowTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/DurabilityHintBranchPropertyWorkflowTest.java
@@ -32,31 +32,42 @@
import jenkins.branch.NoTriggerOrganizationFolderProperty;
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import org.jenkinsci.plugins.workflow.flow.DurabilityHintProvider;
import org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint;
import org.jenkinsci.plugins.workflow.flow.GlobalDefaultFlowDurabilityLevel;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.job.properties.DurabilityHintJobProperty;
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
import static org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* Integration test for {@link NoTriggerBranchProperty} and {@link NoTriggerOrganizationFolderProperty}.
*/
@Issue("JENKINS-32396")
-public class DurabilityHintBranchPropertyWorkflowTest {
+@WithJenkins
+@WithGitSampleRepo
+class DurabilityHintBranchPropertyWorkflowTest {
- @Rule public JenkinsRule r = new JenkinsRule();
- @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
+ private JenkinsRule r;
+ private GitSampleRepoRule sampleRepo;
+
+ @BeforeEach
+ void setUp(JenkinsRule rule, GitSampleRepoRule repo) {
+ r = rule;
+ sampleRepo = repo;
+ }
@Test
- public void configRoundtrip() throws Exception {
+ void configRoundtrip() throws Exception {
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
BranchSource bs = new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false));
mp.getSourcesList().add(bs);
@@ -70,11 +81,12 @@ public void configRoundtrip() throws Exception {
break;
}
}
- Assert.assertNotNull(prop);
- Assert.assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, prop.getHint());
+ assertNotNull(prop);
+ assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, prop.getHint());
}
- @Test public void durabilityHintByPropertyStep() throws Exception {
+ @Test
+ void durabilityHintByPropertyStep() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile",
"properties([durabilityHint('" + FlowDurabilityHint.SURVIVABLE_NONATOMIC.getName()+"')])\n"+
@@ -82,28 +94,26 @@ public void configRoundtrip() throws Exception {
sampleRepo.git("add", "Jenkinsfile");
sampleRepo.git("commit", "--all", "--message=flow");
-
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false)));
WorkflowJob p = scheduleAndFindBranchProject(mp, "master");
r.waitUntilNoActivity();
WorkflowRun b1 = p.getLastBuild();
- Assert.assertEquals(Result.SUCCESS, b1.getResult());
+ assertEquals(Result.SUCCESS, b1.getResult());
DurabilityHintJobProperty prop = p.getProperty(DurabilityHintJobProperty.class);
- Assert.assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, prop.getHint());
+ assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, prop.getHint());
}
@Test
@Issue("JENKINS-48826")
- public void durabilityHintByBranchProperty() throws Exception {
+ void durabilityHintByBranchProperty() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile",
"echo 'whynot'");
sampleRepo.git("add", "Jenkinsfile");
sampleRepo.git("commit", "--all", "--message=flow");
-
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
BranchSource bs = new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false));
mp.getSourcesList().add(bs);
@@ -111,15 +121,15 @@ public void durabilityHintByBranchProperty() throws Exception {
WorkflowJob p = scheduleAndFindBranchProject(mp, "master");
r.waitUntilNoActivity();
- Assert.assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, DurabilityHintProvider.suggestedFor(p));
+ assertEquals(FlowDurabilityHint.SURVIVABLE_NONATOMIC, DurabilityHintProvider.suggestedFor(p));
WorkflowRun b1 = p.getLastBuild();
- Assert.assertEquals(Result.SUCCESS, b1.getResult());
+ assertEquals(Result.SUCCESS, b1.getResult());
// Ensure when we remove the property, branches see that on the next build
bs.setStrategy(new DefaultBranchPropertyStrategy(new BranchProperty[]{}));
p = scheduleAndFindBranchProject(mp, "master");
r.waitUntilNoActivity();
- Assert.assertEquals(GlobalDefaultFlowDurabilityLevel.getDefaultDurabilityHint(), DurabilityHintProvider.suggestedFor(mp.getItems().iterator().next()));
+ assertEquals(GlobalDefaultFlowDurabilityLevel.getDefaultDurabilityHint(), DurabilityHintProvider.suggestedFor(mp.getItems().iterator().next()));
}
}
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/GitDirectorySCMNavigator.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/GitDirectorySCMNavigator.java
index 85a88328..12c69c24 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/GitDirectorySCMNavigator.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/GitDirectorySCMNavigator.java
@@ -33,6 +33,7 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jenkins.plugins.git.GitSCMSource;
@@ -40,11 +41,12 @@
import jenkins.scm.api.SCMNavigatorDescriptor;
import jenkins.scm.api.SCMSourceObserver;
import org.apache.commons.io.IOUtils;
-import static org.junit.Assert.assertFalse;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
/**
* Sample provider which scans a directory for Git checkouts.
*/
@@ -52,7 +54,8 @@ public class GitDirectorySCMNavigator extends SCMNavigator {
private final String directory;
- @DataBoundConstructor public GitDirectorySCMNavigator(String directory) {
+ @DataBoundConstructor
+ public GitDirectorySCMNavigator(String directory) {
this.directory = directory;
}
@@ -66,7 +69,8 @@ protected String id() {
return directory;
}
- @Override public void visitSources(SCMSourceObserver observer) throws IOException, InterruptedException {
+ @Override
+ public void visitSources(SCMSourceObserver observer) throws IOException, InterruptedException {
TaskListener listener = observer.getListener();
File[] kids = new File(directory).listFiles();
if (kids == null) {
@@ -89,7 +93,7 @@ protected String id() {
continue;
}
String origin = kid.getAbsolutePath(); // fallback
- for (String line : IOUtils.readLines(new ByteArrayInputStream(baos.toByteArray()))) {
+ for (String line : IOUtils.readLines(new ByteArrayInputStream(baos.toByteArray()), StandardCharsets.UTF_8)) {
Matcher m = ORIGIN.matcher(line);
if (m.matches()) {
origin = m.group(1);
@@ -109,11 +113,13 @@ protected String id() {
public static class DescriptorImpl extends SCMNavigatorDescriptor {
@NonNull
- @Override public String getDisplayName() {
+ @Override
+ public String getDisplayName() {
return "Directory of Git checkouts";
}
- @Override public SCMNavigator newInstance(String name) {
+ @Override
+ public SCMNavigator newInstance(String name) {
return null;
}
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/JobPropertyStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/JobPropertyStepTest.java
index e365706b..04c0521b 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/JobPropertyStepTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/JobPropertyStepTest.java
@@ -53,6 +53,7 @@
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitBranchSCMHead;
import jenkins.plugins.git.GitSampleRepoRule;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import jenkins.plugins.git.traits.BranchDiscoveryTrait;
import jenkins.triggers.ReverseBuildTrigger;
import jenkins.scm.api.SCMHead;
@@ -75,40 +76,49 @@
import org.jenkinsci.plugins.workflow.steps.StepConfigTester;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.ClassRule;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-import org.jvnet.hudson.test.BuildWatcher;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
import org.jvnet.hudson.test.recipes.LocalData;
import org.kohsuke.stapler.NoStaplerConstructorException;
import static org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject;
@Issue("JENKINS-30519")
-public class JobPropertyStepTest {
-
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public JenkinsRule r = new JenkinsRule();
- @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
+@WithJenkins
+@WithGitSampleRepo
+class JobPropertyStepTest {
+
+ @SuppressWarnings("unused")
+ private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
+ private JenkinsRule r;
+ private GitSampleRepoRule sampleRepo;
+
+ @BeforeEach
+ void setUp(JenkinsRule rule, GitSampleRepoRule repo) {
+ r = rule;
+ sampleRepo = repo;
+ }
/**
* Needed to ensure that we get a fresh {@code MockTrigger#startsAndStops} with each test run. Has to be *after* rather than
* *before* to avoid weird ordering issues with {@code @LocalData}.
*/
- @After
- public void resetStartsAndStops() {
+ @AfterEach
+ void tearDown() {
MockTrigger.startsAndStops = new ArrayList<>();
}
@SuppressWarnings("rawtypes")
- @Test public void configRoundTripParameters() throws Exception {
+ @Test
+ void configRoundTripParameters() throws Exception {
List properties = Collections.singletonList(new ParametersDefinitionProperty(new BooleanParameterDefinition("flag", true, null)));
// TODO *ParameterDefinition.description ought to be defaulted to null:
new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(properties), "properties([parameters([booleanParam(defaultValue: true, name: 'flag')])])");
@@ -130,7 +140,7 @@ public void resetStartsAndStops() {
@Issue("JENKINS-51290")
@Test
- public void testPreviousBuildFailedHard() throws Exception {
+ void testPreviousBuildFailedHard() throws Exception {
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
// First we simulate a build that has resulted in a null execution
@@ -140,7 +150,7 @@ public void testPreviousBuildFailedHard() throws Exception {
Field f = run.getClass().getDeclaredField("execution");
f.setAccessible(true);
f.set(run, null);
- Assert.assertNull(run.getExecution());
+ assertNull(run.getExecution());
// Verify build runs cleanly
p.setDefinition(new CpsFlowDefinition("properties([buildDiscarder(logRotator(numToKeepStr: '1'))])", true));
@@ -148,7 +158,8 @@ public void testPreviousBuildFailedHard() throws Exception {
}
@SuppressWarnings("rawtypes")
- @Test public void configRoundTripBuildDiscarder() throws Exception {
+ @Test
+ void configRoundTripBuildDiscarder() throws Exception {
List properties = Collections.singletonList(new BuildDiscarderProperty(new LogRotator(1, 2, -1, 3)));
// TODO structural form of LogRotator is awful; confusion between integer and string types, and failure to handle default values:
@@ -169,7 +180,8 @@ public void testPreviousBuildFailedHard() throws Exception {
}
@Issue("JENKINS-35698")
- @Test public void useParameter() throws Exception {
+ @Test
+ void useParameter() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile",
"properties([parameters([string(name: 'myparam', defaultValue: 'default value')])])\n" +
@@ -233,9 +245,10 @@ public void testPreviousBuildFailedHard() throws Exception {
r.assertLogContains("value bar", b9);
}
- @Ignore("TODO does not currently work; b2 says subsequently received #1")
+ @Disabled("TODO does not currently work; b2 says subsequently received #1")
@Issue("JENKINS-70680")
- @Test public void changingParameterDefault() throws Exception {
+ @Test
+ void changingParameterDefault() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "properties([parameters([string(name: 'x', defaultValue: '#1')])]); echo(/initially received $params.x/)");
sampleRepo.git("add", "Jenkinsfile");
@@ -260,7 +273,8 @@ public void testPreviousBuildFailedHard() throws Exception {
}
@Issue({"JENKINS-27295", "https://www.jenkins.io/security/advisory/2016-05-11/#arbitrary-build-parameters-are-passed-to-build-scripts-as-environment-variables"})
- @Test public void triggerWithParameter() throws Exception {
+ @Test
+ void triggerWithParameter() throws Exception {
WorkflowJob p = r.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition("properties([parameters([string(name: 'myparam')])]); echo(/got $params.myparam though the env var is $env.myparam/)", true));
r.assertLogContains("got the value though the env var is null", r.assertBuildStatusSuccess(p.scheduleBuild2(0, new ParametersAction(new StringParameterValue("myparam", "the value")))));
@@ -268,14 +282,15 @@ public void testPreviousBuildFailedHard() throws Exception {
@Issue("JENKINS-26143")
@Test
- public void testChoiceParameterSnippetizer() throws Exception {
+ void testChoiceParameterSnippetizer() throws Exception {
//new SnippetizerTester(r).assertGenerateSnippet();
new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(Collections.singletonList(new ParametersDefinitionProperty(new ChoiceParameterDefinition("paramName", new String[]{"foo", "bar", "baz"}, "test")))),
"properties([parameters([choice(choices: ['foo', 'bar', 'baz'], description: 'test', name: 'paramName')])])");
}
@SuppressWarnings("deprecation") // RunList.size
- @Test public void useBuildDiscarder() throws Exception {
+ @Test
+ void useBuildDiscarder() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "properties([buildDiscarder(logRotator(numToKeepStr: '1'))])");
sampleRepo.git("add", "Jenkinsfile");
@@ -298,7 +313,8 @@ public void testChoiceParameterSnippetizer() throws Exception {
}
@Issue("JENKINS-44848")
- @Test public void onlyRemoveJenkinsfileProperties() throws Exception {
+ @Test
+ void onlyRemoveJenkinsfileProperties() throws Exception {
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
p.addProperty(new DisableConcurrentBuildsJobProperty());
@@ -339,7 +355,7 @@ public void testChoiceParameterSnippetizer() throws Exception {
@Issue("JENKINS-44848")
@LocalData
@Test
- public void trackerPropertyUpgrade() throws Exception {
+ void trackerPropertyUpgrade() throws Exception {
WorkflowJob p = r.jenkins.getItemByFullName("trackerPropertyUpgrade", WorkflowJob.class);
assertNotNull(p);
WorkflowRun b1 = p.getLastBuild();
@@ -359,7 +375,8 @@ public void trackerPropertyUpgrade() throws Exception {
}
@Issue("JENKINS-34547")
- @Test public void concurrentBuildProperty() throws Exception {
+ @Test
+ void concurrentBuildProperty() throws Exception {
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
// Verify the base case behavior.
p.setDefinition(new CpsFlowDefinition("semaphore 'hang'", true));
@@ -404,7 +421,8 @@ public void trackerPropertyUpgrade() throws Exception {
}
@Issue("JENKINS-34005")
- @Test public void triggersProperty() throws Exception {
+ @Test
+ void triggersProperty() throws Exception {
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
// Verify the base case behavior.
p.setDefinition(new CpsFlowDefinition("echo 'foo'", true));
@@ -418,8 +436,10 @@ public void trackerPropertyUpgrade() throws Exception {
// Now add a trigger.
p.setDefinition(new CpsFlowDefinition(
- "properties([pipelineTriggers([\n"
- + " cron('@daily'), [$class: 'MockTrigger']])])\n" + "echo 'foo'",
+ """
+ properties([pipelineTriggers([
+ cron('@daily'), [$class: 'MockTrigger']])])
+ echo 'foo'""",
true));
WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
@@ -457,7 +477,8 @@ public void trackerPropertyUpgrade() throws Exception {
}
@Issue("JENKINS-37731")
- @Test public void scmTriggerProperty() throws Exception {
+ @Test
+ void scmTriggerProperty() throws Exception {
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
// Verify the base case behavior.
p.setDefinition(new CpsFlowDefinition("echo 'foo'", true));
@@ -473,14 +494,16 @@ public void trackerPropertyUpgrade() throws Exception {
// Looking for core versions 2.21 and later for the proper pollScm symbol, rather than the broken scm symbol.
if (SymbolLookup.getSymbolValue(SCMTrigger.class).contains("pollSCM")) {
p.setDefinition(new CpsFlowDefinition(
- "properties([pipelineTriggers([\n"
- + " pollSCM(scmpoll_spec: '@daily', ignorePostCommitHooks: true), [$class: 'MockTrigger']])])\n"
- + "echo 'foo'", true));
+ """
+ properties([pipelineTriggers([
+ pollSCM(scmpoll_spec: '@daily', ignorePostCommitHooks: true), [$class: 'MockTrigger']])])
+ echo 'foo'""", true));
} else {
p.setDefinition(new CpsFlowDefinition(
- "properties([pipelineTriggers([pollSCM(scmpoll_spec: '@daily', ignorePostCommitHooks: true),\n"
- + " [$class: 'MockTrigger']])])\n"
- + "echo 'foo'", true));
+ """
+ properties([pipelineTriggers([pollSCM(scmpoll_spec: '@daily', ignorePostCommitHooks: true),
+ [$class: 'MockTrigger']])])
+ echo 'foo'""", true));
}
WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
@@ -518,7 +541,8 @@ public void trackerPropertyUpgrade() throws Exception {
assertEquals("[null, false, null]", MockTrigger.startsAndStops.toString());
}
- @Test public void scmAndEmptyTriggersProperty() throws Exception {
+ @Test
+ void scmAndEmptyTriggersProperty() throws Exception {
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
// Verify the base case behavior.
p.setDefinition(new CpsFlowDefinition("echo 'foo'", true));
@@ -561,7 +585,7 @@ public void trackerPropertyUpgrade() throws Exception {
@Issue("JENKINS-37477")
@Test
- public void generateHelpTrigger() throws Exception {
+ void generateHelpTrigger() throws Exception {
DescribableModel> model = new DescribableModel<>(PipelineTriggersJobProperty.class);
assertNotNull(model);
@@ -601,16 +625,17 @@ private void recurseOnModel(DescribableModel> model) throws Exception {
@Issue("JENKINS-37477")
@Test
- public void configRoundTripTrigger() throws Exception {
+ void configRoundTripTrigger() throws Exception {
List properties = Collections.singletonList(new PipelineTriggersJobProperty(Collections.singletonList(new TimerTrigger("@daily"))));
- String snippetJson = "{'propertiesMap': {\n" +
- " 'stapler-class-bag': 'true',\n" +
- " 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {\n" +
- " 'stapler-class-bag': 'true',\n" +
- " 'hudson-triggers-TimerTrigger': {'spec': '@daily'}\n" +
- " }}},\n" +
- " 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',\n" +
- " '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}";
+ String snippetJson = """
+ {'propertiesMap': {
+ 'stapler-class-bag': 'true',
+ 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {
+ 'stapler-class-bag': 'true',
+ 'hudson-triggers-TimerTrigger': {'spec': '@daily'}
+ }}},
+ 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',
+ '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}""";
new SnippetizerTester(r).assertGenerateSnippet(snippetJson, "properties([pipelineTriggers([cron('@daily')])])", null);
new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(properties), "properties([pipelineTriggers([cron('@daily')])])");
@@ -618,16 +643,17 @@ public void configRoundTripTrigger() throws Exception {
@Issue("JENKINS-37721")
@Test
- public void configRoundTripSCMTrigger() throws Exception {
+ void configRoundTripSCMTrigger() throws Exception {
List properties = Collections.singletonList(new PipelineTriggersJobProperty(Collections.singletonList(new SCMTrigger("@daily"))));
- String snippetJson = "{'propertiesMap': {\n" +
- " 'stapler-class-bag': 'true',\n" +
- " 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {\n" +
- " 'stapler-class-bag': 'true',\n" +
- " 'hudson-triggers-SCMTrigger': {'scmpoll_spec': '@daily', 'ignorePostCommitHooks': false }\n" +
- " }}},\n" +
- " 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',\n" +
- " '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}";
+ String snippetJson = """
+ {'propertiesMap': {
+ 'stapler-class-bag': 'true',
+ 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {
+ 'stapler-class-bag': 'true',
+ 'hudson-triggers-SCMTrigger': {'scmpoll_spec': '@daily', 'ignorePostCommitHooks': false }
+ }}},
+ 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',
+ '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}""";
new SnippetizerTester(r).assertGenerateSnippet(snippetJson, "properties([pipelineTriggers([pollSCM('@daily')])])", null);
new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(properties), "properties([pipelineTriggers([pollSCM('@daily')])])");
@@ -635,24 +661,25 @@ public void configRoundTripSCMTrigger() throws Exception {
@Issue("JENKINS-34464")
@Test
- public void configRoundTripReverseBuildTrigger() throws Exception {
+ void configRoundTripReverseBuildTrigger() throws Exception {
List properties = Collections.singletonList(new PipelineTriggersJobProperty(Collections.singletonList(new ReverseBuildTrigger("some-job", Result.UNSTABLE))));
- String snippetJson = "{'propertiesMap': {\n" +
- " 'stapler-class-bag': 'true',\n" +
- " 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {\n" +
- " 'stapler-class-bag': 'true',\n" +
- " 'jenkins-triggers-ReverseBuildTrigger': { 'threshold': 'UNSTABLE', 'upstreamProjects': 'some-job'}\n" +
- " }}},\n" +
- " 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',\n" +
- " '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}";
+ String snippetJson = """
+ {'propertiesMap': {
+ 'stapler-class-bag': 'true',
+ 'org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty': {'triggers': {
+ 'stapler-class-bag': 'true',
+ 'jenkins-triggers-ReverseBuildTrigger': { 'threshold': 'UNSTABLE', 'upstreamProjects': 'some-job'}
+ }}},
+ 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',
+ '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}""";
new SnippetizerTester(r).assertGenerateSnippet(snippetJson, "properties([pipelineTriggers([upstream(threshold: 'UNSTABLE', upstreamProjects: 'some-job')])])", null);
new SnippetizerTester(r).assertRoundTrip(new JobPropertyStep(properties), "properties([pipelineTriggers([upstream(threshold: 'UNSTABLE', upstreamProjects: 'some-job')])])");
}
@Issue("JENKINS-37005")
- @Test
- public void noPropertiesWarnings() throws Exception {
+ @Test
+ void noPropertiesWarnings() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "echo \"branch=${env.BRANCH_NAME}\"\n"
+ "properties([disableConcurrentBuilds()])");
@@ -682,7 +709,8 @@ public void noPropertiesWarnings() throws Exception {
}
@Issue("JENKINS-37219")
- @Test public void disableTriggers() throws Exception {
+ @Test
+ void disableTriggers() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "properties([overrideIndexTriggers(false)])");
sampleRepo.git("add", "Jenkinsfile");
@@ -727,12 +755,13 @@ public void noPropertiesWarnings() throws Exception {
@Issue("JENKINS-37219")
@Test
- public void snippetGeneratorOverrideIndexing() throws Exception {
- String snippetJson = "{'propertiesMap':\n" +
- "{'stapler-class-bag': 'true', 'jenkins-branch-OverrideIndexTriggersJobProperty': \n" +
- "{'specified': true, 'enableTriggers': true}},\n" +
- "'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',\n" +
- "'$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}";
+ void snippetGeneratorOverrideIndexing() throws Exception {
+ String snippetJson = """
+ {'propertiesMap':
+ {'stapler-class-bag': 'true', 'jenkins-branch-OverrideIndexTriggersJobProperty':
+ {'specified': true, 'enableTriggers': true}},
+ 'stapler-class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep',
+ '$class': 'org.jenkinsci.plugins.workflow.multibranch.JobPropertyStep'}""";
new SnippetizerTester(r).assertGenerateSnippet(snippetJson, "properties([overrideIndexTriggers(true)])", null);
}
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/NoTriggerBranchPropertyWorkflowTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/NoTriggerBranchPropertyWorkflowTest.java
index 2ef8b1bd..a2ff50d2 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/NoTriggerBranchPropertyWorkflowTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/NoTriggerBranchPropertyWorkflowTest.java
@@ -34,26 +34,39 @@
import jenkins.branch.OrganizationFolder;
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import jenkins.scm.impl.SingleSCMNavigator;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.junit.Rule;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
/**
* Integration test for {@link NoTriggerBranchProperty} and {@link NoTriggerOrganizationFolderProperty}.
*/
@Issue("JENKINS-32396")
-public class NoTriggerBranchPropertyWorkflowTest {
+@WithJenkins
+@WithGitSampleRepo
+class NoTriggerBranchPropertyWorkflowTest {
+
+ private JenkinsRule r;
+ private GitSampleRepoRule sampleRepo;
- @Rule public JenkinsRule r = new JenkinsRule();
- @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
+ @BeforeEach
+ void setUp(JenkinsRule rule, GitSampleRepoRule repo) {
+ r = rule;
+ sampleRepo = repo;
+ }
@Issue("JENKINS-30206")
- @Test public void singleRepo() throws Exception {
+ @Test
+ void singleRepo() throws Exception {
round1();
WorkflowMultiBranchProject p = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
BranchSource branchSource = new BranchSource(new GitSCMSource("source-id", sampleRepo.toString(), "", "*", "", false));
@@ -94,7 +107,8 @@ public class NoTriggerBranchPropertyWorkflowTest {
assertEquals(4, newfeature.getNextBuildNumber());
}
- @Test public void organizationFolder() throws Exception {
+ @Test
+ void organizationFolder() throws Exception {
round1();
OrganizationFolder top = r.jenkins.createProject(OrganizationFolder.class, "top");
top.getProperties().add(new NoTriggerOrganizationFolderProperty("(?!release.*).*"));
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java
index 4a0fdaad..1f822cc5 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReadTrustedStepTest.java
@@ -29,33 +29,52 @@
import jenkins.branch.BranchSource;
import jenkins.plugins.git.GitSampleRepoRule;
import jenkins.plugins.git.GitStep;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.jvnet.hudson.test.BuildWatcher;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import org.jvnet.hudson.test.FlagRule;
-import static org.junit.Assume.assumeFalse;
+import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
-public class ReadTrustedStepTest {
+import static org.junit.jupiter.api.Assumptions.assumeFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public JenkinsRule r = new JenkinsRule();
- @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
- @Rule public FlagRule heavyweightCheckoutFlag = new FlagRule<>(() -> SCMBinder.USE_HEAVYWEIGHT_CHECKOUT, v -> { SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = v; });
+@WithJenkins
+@WithGitSampleRepo
+class ReadTrustedStepTest {
- @Test public void smokes() throws Exception {
+ @SuppressWarnings("unused")
+ private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
+ private boolean heavyweightCheckoutFlag;
+ private JenkinsRule r;
+ private GitSampleRepoRule sampleRepo;
+
+ @BeforeEach
+ void setUp(JenkinsRule rule, GitSampleRepoRule repo) {
+ r = rule;
+ sampleRepo = repo;
+ heavyweightCheckoutFlag = SCMBinder.USE_HEAVYWEIGHT_CHECKOUT;
+ }
+
+ @AfterEach
+ void tearDown() {
+ SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = heavyweightCheckoutFlag;
+ }
+
+ @Test
+ void smokes() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "echo \"said ${readTrusted 'message'}\"");
sampleRepo.write("message", "how do you do");
@@ -98,7 +117,8 @@ public class ReadTrustedStepTest {
r.assertLogContains("Obtained message from ", b);
}
- @Test public void exactRevision() throws Exception {
+ @Test
+ void exactRevision() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "node {checkout scm; semaphore 'wait1'; def alpha = readTrusted 'alpha'; semaphore 'wait2'; echo \"first got ${alpha} then ${readTrusted 'beta'} vs. disk ${readFile 'alpha'} then ${readFile 'beta'}\"}");
sampleRepo.write("alpha", "1");
@@ -135,7 +155,8 @@ public class ReadTrustedStepTest {
r.assertLogContains("now got 2 then 2 vs. disk 2 then 2", r.assertBuildStatusSuccess(r.waitForCompletion(b)));
}
- @Test public void evaluate() throws Exception {
+ @Test
+ void evaluate() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "evaluate readTrusted('lib.groovy')");
sampleRepo.write("lib.groovy", "echo 'trustworthy library'");
@@ -167,7 +188,8 @@ public class ReadTrustedStepTest {
}
@Issue("JENKINS-31386")
- @Test public void nonMultibranch() throws Exception {
+ @Test
+ void nonMultibranch() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "echo \"said ${readTrusted 'message'}\"");
sampleRepo.write("message", "how do you do");
@@ -182,7 +204,8 @@ public class ReadTrustedStepTest {
}
@Issue("JENKINS-42817")
- @Test public void nonMultibranchHeavyweight() throws Exception {
+ @Test
+ void nonMultibranchHeavyweight() throws Exception {
SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true;
try {
sampleRepo.init();
@@ -203,7 +226,7 @@ public class ReadTrustedStepTest {
}
@Test
- public void pathTraversalRejected() throws Exception {
+ void pathTraversalRejected() throws Exception {
SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true;
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "node { checkout scm; echo \"${readTrusted '../../secrets/master.key'}\"}");
@@ -224,7 +247,7 @@ public void pathTraversalRejected() throws Exception {
@Issue("SECURITY-2491")
@Test
- public void symlinksInReadTrustedCannotEscapeWorkspaceContext() throws Exception {
+ void symlinksInReadTrustedCannotEscapeWorkspaceContext() throws Exception {
assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different.
SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true;
sampleRepo.init();
@@ -246,7 +269,7 @@ public void symlinksInReadTrustedCannotEscapeWorkspaceContext() throws Exception
@Issue("SECURITY-2491")
@Test
- public void symlinksInUntrustedRevisionCannotEscapeWorkspace() throws Exception {
+ void symlinksInUntrustedRevisionCannotEscapeWorkspace() throws Exception {
assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different.
SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true;
sampleRepo.init();
@@ -274,7 +297,7 @@ public void symlinksInUntrustedRevisionCannotEscapeWorkspace() throws Exception
@Issue("SECURITY-2491")
@Test
- public void symlinksInNonMultibranchCannotEscapeWorkspaceContextViaReadTrusted() throws Exception {
+ void symlinksInNonMultibranchCannotEscapeWorkspaceContextViaReadTrusted() throws Exception {
assumeFalse(Functions.isWindows()); // On Windows, the symlink is treated as a regular file, so there is no vulnerability, but the behavior is different.
SCMBinder.USE_HEAVYWEIGHT_CHECKOUT = true;
sampleRepo.init();
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/RepairBranchPropertyTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/RepairBranchPropertyTest.java
index 18e7b6d3..724feb41 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/RepairBranchPropertyTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/RepairBranchPropertyTest.java
@@ -37,28 +37,27 @@
import jenkins.scm.impl.mock.MockSCMDiscoverBranches;
import jenkins.scm.impl.mock.MockSCMNavigator;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
import org.jvnet.hudson.test.recipes.LocalData;
import java.io.IOException;
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertNotNull;
-import static junit.framework.TestCase.assertNull;
-import static junit.framework.TestCase.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
-public class RepairBranchPropertyTest {
+@WithJenkins
+class RepairBranchPropertyTest {
- @Rule
- public JenkinsRule j = new JenkinsRule();
+ private JenkinsRule j;
private MockSCMController controller;
- @Before
- public void setUp() throws IOException {
+ @BeforeEach
+ void setUp(JenkinsRule rule) throws IOException {
+ j = rule;
setup(MockSCMController.create());
}
@@ -70,8 +69,9 @@ void setup(MockSCMController co) throws IOException {
"echo 'hello'".getBytes());
}
- @Test @Issue("JENKINS-55116")
- public void removedProperty() throws Exception {
+ @Test
+ @Issue("JENKINS-55116")
+ void removedProperty() throws Exception {
OrganizationFolder org = j.createProject(OrganizationFolder.class, "org");
org.getNavigators().add(new MockSCMNavigator(controller.getId(), new MockSCMDiscoverBranches()));
org.save();
@@ -99,8 +99,9 @@ public void removedProperty() throws Exception {
assertTrue(repo.getPrimaryView().contains((TopLevelItem)master));
}
- @Test @Issue("JENKINS-55116")
- public void removedPropertyLastBuildCorrupt() throws Exception {
+ @Test
+ @Issue("JENKINS-55116")
+ void removedPropertyLastBuildCorrupt() throws Exception {
OrganizationFolder org = j.createProject(OrganizationFolder.class, "org");
org.getNavigators().add(new MockSCMNavigator(controller.getId(), new MockSCMDiscoverBranches()));
org.save();
@@ -136,8 +137,10 @@ public void removedPropertyLastBuildCorrupt() throws Exception {
assertTrue(repo.getPrimaryView().contains((TopLevelItem)master));
}
- @Test @LocalData @Issue("JENKINS-55116")
- public void removedPropertyAtStartup() throws Exception {
+ @Test
+ @LocalData
+ @Issue("JENKINS-55116")
+ void removedPropertyAtStartup() throws Exception {
MockSCMController cont = MockSCMController.recreate("9ea2ef21-aa07-4973-a942-6c4c4c7851d1");
setup(cont);
OrganizationFolder org = j.jenkins.getItem("org", j.jenkins, OrganizationFolder.class);
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReplayActionTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReplayActionTest.java
index 28089529..034d1674 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReplayActionTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ReplayActionTest.java
@@ -29,6 +29,7 @@
import hudson.security.ACL;
import hudson.security.ACLContext;
import java.io.File;
+import java.io.IOException;
import java.util.Collections;
import jenkins.branch.BranchProperty;
import jenkins.branch.BranchSource;
@@ -39,28 +40,41 @@
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
import jenkins.plugins.git.GitStep;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition;
import org.jenkinsci.plugins.workflow.cps.replay.ReplayAction;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.rules.TemporaryFolder;
-import org.jvnet.hudson.test.BuildWatcher;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
+import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
+
+@WithJenkins
+@WithGitSampleRepo
+class ReplayActionTest {
-public class ReplayActionTest {
+ @SuppressWarnings("unused")
+ private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
+ @TempDir
+ private File tmp;
+ private JenkinsRule r;
+ private GitSampleRepoRule sampleRepo;
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public JenkinsRule r = new JenkinsRule();
- @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
- @Rule public TemporaryFolder tmp = new TemporaryFolder();
+ @BeforeEach
+ void setUp(JenkinsRule rule, GitSampleRepoRule repo) {
+ r = rule;
+ sampleRepo = repo;
+ }
- @Test public void scriptFromSCM() throws Exception {
+ @Test
+ void scriptFromSCM() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "node {checkout scm; echo \"loaded ${readFile 'file'}\"}");
sampleRepo.git("add", "Jenkinsfile");
@@ -81,7 +95,8 @@ public class ReplayActionTest {
r.assertLogContains("this time loaded subsequent content", b);
}
- @Test public void multibranch() throws Exception {
+ @Test
+ void multibranch() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}");
sampleRepo.write("file", "initial content");
@@ -105,8 +120,9 @@ public class ReplayActionTest {
r.assertLogContains("INITIAL CONTENT", b2);
}
- @Test public void permissions() throws Exception {
- File clones = tmp.newFolder();
+ @Test
+ void permissions() throws Exception {
+ File clones = newFolder(tmp, "junit");
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "");
sampleRepo.git("add", "Jenkinsfile");
@@ -143,10 +159,11 @@ public class ReplayActionTest {
p.setDefinition(new CpsFlowDefinition("", false));
b1 = p.scheduleBuild2(0).get();
assertTrue(canReplay(b1, "admin"));
- assertFalse("not sandboxed, so only safe for admins", canReplay(b1, "dev1"));
+ assertFalse(canReplay(b1, "dev1"), "not sandboxed, so only safe for admins");
assertFalse(canReplay(b1, "dev2"));
assertFalse(canReplay(b1, "dev3"));
}
+
private static boolean canReplay(WorkflowRun b, String user) {
final ReplayAction a = b.getAction(ReplayAction.class);
try (ACLContext context = ACL.as(User.getById(user, true))) {
@@ -154,4 +171,13 @@ private static boolean canReplay(WorkflowRun b, String user) {
}
}
+ private static File newFolder(File root, String... subDirs) throws IOException {
+ String subFolder = String.join("/", subDirs);
+ File result = new File(root, subFolder);
+ if (!result.mkdirs()) {
+ throw new IOException("Couldn't create folders " + root);
+ }
+ return result;
+ }
+
}
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ResolveScmStepTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ResolveScmStepTest.java
index b339ea9f..6475a69b 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ResolveScmStepTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/ResolveScmStepTest.java
@@ -29,25 +29,31 @@
import jenkins.scm.impl.mock.MockSCMController;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
-public class ResolveScmStepTest {
+@WithJenkins
+class ResolveScmStepTest {
- @ClassRule
- public static JenkinsRule j = new JenkinsRule();
+ private static JenkinsRule j;
- @Before
- public void cleanOutAllItems() throws Exception {
+ @BeforeAll
+ static void setUp(JenkinsRule rule) {
+ j = rule;
+ }
+
+ @BeforeEach
+ void setUp() throws Exception {
for (TopLevelItem i : j.getInstance().getItems()) {
i.delete();
}
}
@Test
- public void given_existingHeadName_when_invoked_then_existingHeadNameReturned() throws Exception {
+ void given_existingHeadName_when_invoked_then_existingHeadNameReturned() throws Exception {
try (MockSCMController c = MockSCMController.create()) {
c.createRepository("repo");
c.createBranch("repo", "foo");
@@ -66,7 +72,7 @@ public void given_existingHeadName_when_invoked_then_existingHeadNameReturned()
}
@Test
- public void given_nonExistingHeadName_when_invokedIgnoringErrors_then_nullReturned() throws Exception {
+ void given_nonExistingHeadName_when_invokedIgnoringErrors_then_nullReturned() throws Exception {
try (MockSCMController c = MockSCMController.create()) {
c.createRepository("repo");
c.createBranch("repo", "foo");
@@ -83,7 +89,7 @@ public void given_nonExistingHeadName_when_invokedIgnoringErrors_then_nullReturn
}
@Test
- public void given_nonExistingHeadName_when_invoked_then_abortThrown() throws Exception {
+ void given_nonExistingHeadName_when_invoked_then_abortThrown() throws Exception {
try (MockSCMController c = MockSCMController.create()) {
c.createRepository("repo");
c.createBranch("repo", "foo");
@@ -104,7 +110,7 @@ public void given_nonExistingHeadName_when_invoked_then_abortThrown() throws Exc
}
@Test
- public void given_nonExistingHeadName_when_invokedWithDefault_then_defaultReturned() throws Exception {
+ void given_nonExistingHeadName_when_invokedWithDefault_then_defaultReturned() throws Exception {
try (MockSCMController c = MockSCMController.create()) {
c.createRepository("repo");
c.createBranch("repo", "manchu");
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMBinderTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMBinderTest.java
index 1699c113..b49cd91c 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMBinderTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMBinderTest.java
@@ -45,42 +45,56 @@
import jenkins.plugins.git.GitBranchSCMRevision;
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMRevision;
import jenkins.scm.api.SCMRevisionAction;
import jenkins.scm.api.SCMSourceDescriptor;
+
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
+import org.junit.jupiter.api.BeforeEach;
+import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
import org.springframework.security.core.Authentication;
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.jvnet.hudson.test.BuildWatcher;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
-public class SCMBinderTest {
+@WithJenkins
+@WithGitSampleRepo
+class SCMBinderTest {
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public JenkinsRule r = new JenkinsRule();
- @Rule public GitSampleRepoRule sampleGitRepo = new GitSampleRepoRule();
+ @SuppressWarnings("unused")
+ private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
+ private JenkinsRule r;
+ private GitSampleRepoRule sampleRepo;
- @Test public void exactRevisionGit() throws Exception {
- sampleGitRepo.init();
+ @BeforeEach
+ void setUp(JenkinsRule rule, GitSampleRepoRule repo) {
+ r = rule;
+ sampleRepo = repo;
+ }
+
+ @Test
+ void exactRevisionGit() throws Exception {
+ sampleRepo.init();
ScriptApproval sa = ScriptApproval.get();
sa.approveSignature("staticField hudson.model.Items XSTREAM2");
sa.approveSignature("method com.thoughtworks.xstream.XStream toXML java.lang.Object");
- sampleGitRepo.write("Jenkinsfile", "echo hudson.model.Items.XSTREAM2.toXML(scm); semaphore 'wait'; node {checkout scm; echo readFile('file')}");
- sampleGitRepo.write("file", "initial content");
- sampleGitRepo.git("add", "Jenkinsfile");
- sampleGitRepo.git("commit", "--all", "--message=flow");
+ sampleRepo.write("Jenkinsfile", "echo hudson.model.Items.XSTREAM2.toXML(scm); semaphore 'wait'; node {checkout scm; echo readFile('file')}");
+ sampleRepo.write("file", "initial content");
+ sampleRepo.git("add", "Jenkinsfile");
+ sampleRepo.git("commit", "--all", "--message=flow");
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
- mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false)));
+ mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false)));
WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master");
SemaphoreStep.waitForStart("wait/1", null);
WorkflowRun b1 = p.getLastBuild();
@@ -88,11 +102,11 @@ public class SCMBinderTest {
assertEquals(1, b1.getNumber());
assertRevisionAction(b1);
r.assertLogContains("Obtained Jenkinsfile from ", b1);
- sampleGitRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file').toUpperCase()}");
- sampleGitRepo.write("file", "subsequent content");
- sampleGitRepo.git("commit", "--all", "--message=tweaked");
+ sampleRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file').toUpperCase()}");
+ sampleRepo.write("file", "subsequent content");
+ sampleRepo.git("commit", "--all", "--message=tweaked");
SemaphoreStep.success("wait/1", null);
- sampleGitRepo.notifyCommit(r);
+ sampleRepo.notifyCommit(r);
WorkflowRun b2 = p.getLastBuild();
assertEquals(2, b2.getNumber());
r.assertLogContains("initial content", r.waitForCompletion(b1));
@@ -127,39 +141,41 @@ public static void assertRevisionAction(WorkflowRun build) {
}
}
- @Test public void deletedJenkinsfile() throws Exception {
- sampleGitRepo.init();
- sampleGitRepo.write("Jenkinsfile", "node { echo 'Hello World' }");
- sampleGitRepo.git("add", "Jenkinsfile");
- sampleGitRepo.git("commit", "--all", "--message=flow");
+ @Test
+ void deletedJenkinsfile() throws Exception {
+ sampleRepo.init();
+ sampleRepo.write("Jenkinsfile", "node { echo 'Hello World' }");
+ sampleRepo.git("add", "Jenkinsfile");
+ sampleRepo.git("commit", "--all", "--message=flow");
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
- mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false)));
+ mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false)));
WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master");
assertEquals(1, mp.getItems().size());
r.waitUntilNoActivity();
WorkflowRun b1 = p.getLastBuild();
assertEquals(1, b1.getNumber());
- sampleGitRepo.git("rm", "Jenkinsfile");
- sampleGitRepo.git("commit", "--all", "--message=remove");
+ sampleRepo.git("rm", "Jenkinsfile");
+ sampleRepo.git("commit", "--all", "--message=remove");
WorkflowRun b2 = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0).get());
r.assertLogContains("Jenkinsfile not found", b2);
}
@Issue("JENKINS-40521")
- @Test public void deletedBranch() throws Exception {
+ @Test
+ void deletedBranch() throws Exception {
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
- sampleGitRepo.init();
+ sampleRepo.init();
// TODO GitSCMSource offers no way to set a GitSCMExtension such as CleanBeforeCheckout; work around with deleteDir
// (without cleaning, b2 will succeed since the workspace will still have a cached origin/feature ref)
- sampleGitRepo.write("Jenkinsfile", "node {deleteDir(); checkout scm; echo 'Hello World'}");
- sampleGitRepo.git("add", "Jenkinsfile");
- sampleGitRepo.git("commit", "--all", "--message=flow");
- sampleGitRepo.git("checkout", "-b", "feature");
- sampleGitRepo.write("somefile", "stuff");
- sampleGitRepo.git("add", "somefile");
- sampleGitRepo.git("commit", "--all", "--message=tweaked");
+ sampleRepo.write("Jenkinsfile", "node {deleteDir(); checkout scm; echo 'Hello World'}");
+ sampleRepo.git("add", "Jenkinsfile");
+ sampleRepo.git("commit", "--all", "--message=flow");
+ sampleRepo.git("checkout", "-b", "feature");
+ sampleRepo.write("somefile", "stuff");
+ sampleRepo.git("add", "somefile");
+ sampleRepo.git("commit", "--all", "--message=tweaked");
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
- mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false)));
+ mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false)));
mp.setOrphanedItemStrategy(new DefaultOrphanedItemStrategy(false, "", ""));
WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "feature");
assertEquals(2, mp.getItems().size());
@@ -169,8 +185,8 @@ public static void assertRevisionAction(WorkflowRun build) {
Authentication auth = User.getById("dev", true).impersonate2();
assertFalse(p.getACL().hasPermission2(auth, Item.DELETE));
assertTrue(p.isBuildable());
- sampleGitRepo.git("checkout", "master");
- sampleGitRepo.git("branch", "-D", "feature");
+ sampleRepo.git("checkout", "master");
+ sampleRepo.git("branch", "-D", "feature");
{ // TODO AbstractGitSCMSource.retrieve(SCMHead, TaskListener) is incorrect: after fetching remote refs into the cache,
// the origin/feature ref remains locally even though it has been deleted upstream, since only the other overload prunes stale remotes:
Util.deleteRecursive(new File(r.jenkins.getRootDir(), "caches"));
@@ -189,14 +205,15 @@ public static void assertRevisionAction(WorkflowRun build) {
assertEquals(1, mp.getItems().size());
}
- @Test public void untrustedRevisions() throws Exception {
- sampleGitRepo.init();
- sampleGitRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}");
- sampleGitRepo.write("file", "initial content");
- sampleGitRepo.git("add", "Jenkinsfile");
- sampleGitRepo.git("commit", "--all", "--message=flow");
+ @Test
+ void untrustedRevisions() throws Exception {
+ sampleRepo.init();
+ sampleRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}");
+ sampleRepo.write("file", "initial content");
+ sampleRepo.git("add", "Jenkinsfile");
+ sampleRepo.git("commit", "--all", "--message=flow");
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
- mp.getSourcesList().add(new BranchSource(new WarySource(null, sampleGitRepo.toString(), "", "*", "", false)));
+ mp.getSourcesList().add(new BranchSource(new WarySource(null, sampleRepo.toString(), "", "*", "", false)));
WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master");
r.waitUntilNoActivity();
WorkflowRun b = p.getLastBuild();
@@ -206,10 +223,10 @@ public static void assertRevisionAction(WorkflowRun build) {
r.assertBuildStatusSuccess(b);
r.assertLogContains("initial content", b);
String branch = "some-other-branch-from-Norway";
- sampleGitRepo.git("checkout", "-b", branch);
- sampleGitRepo.write("Jenkinsfile", "error 'ALL YOUR BUILD STEPS ARE BELONG TO US'");
- sampleGitRepo.write("file", "subsequent content");
- sampleGitRepo.git("commit", "--all", "--message=big evil laugh");
+ sampleRepo.git("checkout", "-b", branch);
+ sampleRepo.write("Jenkinsfile", "error 'ALL YOUR BUILD STEPS ARE BELONG TO US'");
+ sampleRepo.write("file", "subsequent content");
+ sampleRepo.git("commit", "--all", "--message=big evil laugh");
p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, branch);
r.waitUntilNoActivity();
b = p.getLastBuild();
@@ -221,11 +238,13 @@ public static void assertRevisionAction(WorkflowRun build) {
r.assertLogContains("subsequent content", b);
r.assertLogContains("not trusting", b);
}
+
public static class WarySource extends GitSCMSource {
public WarySource(String id, String remote, String credentialsId, String includes, String excludes, boolean ignoreOnPushNotifications) {
super(id, remote, credentialsId, includes, excludes, ignoreOnPushNotifications);
}
- @Override public SCMRevision getTrustedRevision(@NonNull SCMRevision revision, @NonNull TaskListener listener) throws IOException, InterruptedException {
+ @Override
+ public SCMRevision getTrustedRevision(@NonNull SCMRevision revision, @NonNull TaskListener listener) throws IOException, InterruptedException {
String branch = revision.getHead().getName();
if (branch.equals("master")) {
return revision;
@@ -234,7 +253,8 @@ public WarySource(String id, String remote, String credentialsId, String include
return fetch(new SCMHead("master"), listener);
}
}
- @Override public SCMSourceDescriptor getDescriptor() {
+ @Override
+ public SCMSourceDescriptor getDescriptor() {
return Jenkins.get().getDescriptorByType(GitSCMSource.DescriptorImpl.class);
}
}
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMVarTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMVarTest.java
index ee308b1e..d3326679 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMVarTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/SCMVarTest.java
@@ -28,8 +28,11 @@
import hudson.model.Run;
import hudson.model.TaskListener;
import java.io.File;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Arrays;
+import java.util.List;
+
import jenkins.branch.BranchProperty;
import jenkins.branch.BranchSource;
import jenkins.branch.DefaultBranchPropertyStrategy;
@@ -37,6 +40,7 @@
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
import jenkins.plugins.git.GitStep;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import org.apache.commons.io.FileUtils;
import org.jenkinsci.plugins.workflow.cps.CpsScmFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
@@ -45,29 +49,40 @@
import org.jenkinsci.plugins.workflow.libs.LibraryConfiguration;
import org.jenkinsci.plugins.workflow.libs.LibraryRetriever;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.jvnet.hudson.test.BuildWatcher;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
import org.jvnet.hudson.test.Issue;
-import org.jvnet.hudson.test.JenkinsSessionRule;
+import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
+import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension;
-public class SCMVarTest {
+@WithGitSampleRepo
+class SCMVarTest {
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public JenkinsSessionRule story = new JenkinsSessionRule();
- @Rule public GitSampleRepoRule sampleGitRepo = new GitSampleRepoRule();
+ @SuppressWarnings("unused")
+ private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
+ @RegisterExtension
+ private final JenkinsSessionExtension story = new JenkinsSessionExtension();
+ private GitSampleRepoRule sampleRepo;
+
+ @BeforeEach
+ void setUp(GitSampleRepoRule repo) {
+ sampleRepo = repo;
+ }
- @Test public void scmPickle() throws Throwable {
+ @Test
+ void scmPickle() throws Throwable {
story.then(j -> {
- sampleGitRepo.init();
- sampleGitRepo.write("Jenkinsfile", "def _scm = scm; semaphore 'wait'; node {checkout _scm; echo readFile('file')}");
- sampleGitRepo.write("file", "initial content");
- sampleGitRepo.git("add", "Jenkinsfile");
- sampleGitRepo.git("commit", "--all", "--message=flow");
+ sampleRepo.init();
+ sampleRepo.write("Jenkinsfile", "def _scm = scm; semaphore 'wait'; node {checkout _scm; echo readFile('file')}");
+ sampleRepo.write("file", "initial content");
+ sampleRepo.git("add", "Jenkinsfile");
+ sampleRepo.git("commit", "--all", "--message=flow");
WorkflowMultiBranchProject mp = j.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
- mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false), new DefaultBranchPropertyStrategy(new BranchProperty[0])));
+ mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false), new DefaultBranchPropertyStrategy(new BranchProperty[0])));
WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master");
SemaphoreStep.waitForStart("wait/1", null);
WorkflowRun b1 = p.getLastBuild();
@@ -86,37 +101,40 @@ public class SCMVarTest {
}
@Issue("JENKINS-30222")
- @Test public void globalVariable() throws Throwable {
+ @Test
+ void globalVariable() throws Throwable {
story.then(j -> {
// Set up a standardJob definition:
File lib = new File(Jenkins.get().getRootDir(), "somelib");
LibraryConfiguration cfg = new LibraryConfiguration("somelib", new LocalRetriever(lib));
cfg.setImplicit(true);
cfg.setDefaultVersion("fixed");
- GlobalLibraries.get().setLibraries(Arrays.asList(cfg));
+ GlobalLibraries.get().setLibraries(List.of(cfg));
File vars = new File(lib, "vars");
Files.createDirectories(vars.toPath());
FileUtils.writeStringToFile(new File(vars, "standardJob.groovy"),
- "def call(body) {\n" +
- " def config = [:]\n" +
- " body.resolveStrategy = Closure.DELEGATE_FIRST\n" +
- " body.delegate = config\n" +
- " body()\n" +
- " node {\n" +
- " checkout scm\n" +
- " echo \"loaded ${readFile config.file}\"\n" +
- " }\n" +
- "}\n");
+ """
+ def call(body) {
+ def config = [:]
+ body.resolveStrategy = Closure.DELEGATE_FIRST
+ body.delegate = config
+ body()
+ node {
+ checkout scm
+ echo "loaded ${readFile config.file}"
+ }
+ }
+ """, StandardCharsets.UTF_8);
// Then a project using it:
- sampleGitRepo.init();
- sampleGitRepo.write("Jenkinsfile", "standardJob {file = 'resource'}");
- sampleGitRepo.write("resource", "resource content");
- sampleGitRepo.git("add", "Jenkinsfile");
- sampleGitRepo.git("add", "resource");
- sampleGitRepo.git("commit", "--all", "--message=flow");
+ sampleRepo.init();
+ sampleRepo.write("Jenkinsfile", "standardJob {file = 'resource'}");
+ sampleRepo.write("resource", "resource content");
+ sampleRepo.git("add", "Jenkinsfile");
+ sampleRepo.git("add", "resource");
+ sampleRepo.git("commit", "--all", "--message=flow");
// And run:
WorkflowMultiBranchProject mp = j.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
- mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleGitRepo.toString(), "", "*", "", false), new DefaultBranchPropertyStrategy(new BranchProperty[0])));
+ mp.getSourcesList().add(new BranchSource(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", false), new DefaultBranchPropertyStrategy(new BranchProperty[0])));
WorkflowJob p = WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject(mp, "master");
WorkflowRun b = j.assertBuildStatusSuccess(p.scheduleBuild2(0));
j.assertLogContains("loaded resource content", b);
@@ -129,24 +147,27 @@ private static final class LocalRetriever extends LibraryRetriever {
LocalRetriever(File lib) {
this.lib = lib;
}
- @Override public void retrieve(String name, String version, boolean changelog, FilePath target, Run, ?> run, TaskListener listener) throws Exception {
+ @Override
+ public void retrieve(String name, String version, boolean changelog, FilePath target, Run, ?> run, TaskListener listener) throws Exception {
new FilePath(lib).copyRecursiveTo(target);
}
- @Override public void retrieve(String name, String version, FilePath target, Run, ?> run, TaskListener listener) throws Exception {
+ @Override
+ public void retrieve(String name, String version, FilePath target, Run, ?> run, TaskListener listener) throws Exception {
retrieve(name, version, false, target, run, listener);
}
}
@Issue("JENKINS-31386")
- @Test public void standaloneProject() throws Throwable {
+ @Test
+ void standaloneProject() throws Throwable {
story.then(j -> {
- sampleGitRepo.init();
- sampleGitRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}");
- sampleGitRepo.write("file", "some content");
- sampleGitRepo.git("add", "Jenkinsfile");
- sampleGitRepo.git("commit", "--all", "--message=flow");
+ sampleRepo.init();
+ sampleRepo.write("Jenkinsfile", "node {checkout scm; echo readFile('file')}");
+ sampleRepo.write("file", "some content");
+ sampleRepo.git("add", "Jenkinsfile");
+ sampleRepo.git("commit", "--all", "--message=flow");
WorkflowJob p = j.jenkins.createProject(WorkflowJob.class, "p");
- p.setDefinition(new CpsScmFlowDefinition(new GitStep(sampleGitRepo.toString()).createSCM(), "Jenkinsfile"));
+ p.setDefinition(new CpsScmFlowDefinition(new GitStep(sampleRepo.toString()).createSCM(), "Jenkinsfile"));
WorkflowRun b = j.assertBuildStatusSuccess(p.scheduleBuild2(0));
j.assertLogContains("some content", b);
});
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowBranchProjectFactoryTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowBranchProjectFactoryTest.java
index 31732f08..0b116a43 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowBranchProjectFactoryTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowBranchProjectFactoryTest.java
@@ -29,36 +29,49 @@
import jenkins.branch.BranchSource;
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitSampleRepoRule;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import jenkins.plugins.git.traits.BranchDiscoveryTrait;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import static org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProjectTest.scheduleAndFindBranchProject;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.jvnet.hudson.test.BuildWatcher;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
-import org.jvnet.hudson.test.JenkinsSessionRule;
+import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
+import org.jvnet.hudson.test.junit.jupiter.JenkinsSessionExtension;
+
+@WithGitSampleRepo
+class WorkflowBranchProjectFactoryTest {
-public class WorkflowBranchProjectFactoryTest {
+ @SuppressWarnings("unused")
+ private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
+ @RegisterExtension
+ private final JenkinsSessionExtension story = new JenkinsSessionExtension();
+ private GitSampleRepoRule sampleRepo;
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public JenkinsSessionRule story = new JenkinsSessionRule();
- @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
+ @BeforeEach
+ void setUp(GitSampleRepoRule repo) {
+ sampleRepo = repo;
+ }
@Issue("JENKINS-30744")
- @Test public void slashyBranches() throws Throwable {
+ @Test
+ void slashyBranches() throws Throwable {
story.then(j -> {
sampleRepo.init();
sampleRepo.git("checkout", "-b", "dev/main");
String script =
- "echo \"branch=${env.BRANCH_NAME}\"\n" +
- "node {\n" +
- " checkout scm\n" +
- " echo \"workspace=${pwd().replaceFirst('.+dev', 'dev')}\"\n" +
- "}";
+ """
+ echo "branch=${env.BRANCH_NAME}"
+ node {
+ checkout scm
+ echo "workspace=${pwd().replaceFirst('.+dev', 'dev')}"
+ }""";
sampleRepo.write("Jenkinsfile", script);
sampleRepo.git("add", "Jenkinsfile");
sampleRepo.git("commit", "--all", "--message=flow");
@@ -88,6 +101,7 @@ public class WorkflowBranchProjectFactoryTest {
verifyProject(j, p);
});
}
+
private static void verifyProject(JenkinsRule j, WorkflowJob p) throws Exception {
assertEquals("dev%2Fmain", p.getName());
assertEquals("dev/main", p.getDisplayName());
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
index 6563c7c7..f3d5779d 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
@@ -30,35 +30,89 @@
import hudson.security.ACL;
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
import java.io.File;
+import java.io.IOException;
import java.util.List;
import jenkins.branch.MultiBranchProject;
import jenkins.branch.OrganizationFolder;
import jenkins.plugins.git.GitSampleRepoRule;
+import jenkins.plugins.git.junit.jupiter.GitSampleRepoExtension;
import jenkins.scm.api.SCMSource;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.extension.*;
+import org.junit.jupiter.api.io.TempDir;
+import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
import org.springframework.security.core.Authentication;
+
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
-import static org.junit.Assert.*;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.jvnet.hudson.test.BuildWatcher;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
-public class WorkflowMultiBranchProjectFactoryTest {
+@WithJenkins
+@ExtendWith(WorkflowMultiBranchProjectFactoryTest.MultiGitSampleRepoExtension.class)
+class WorkflowMultiBranchProjectFactoryTest {
+
+ @SuppressWarnings("unused")
+ private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
+ @TempDir
+ private File tmp;
+ private JenkinsRule r;
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public JenkinsRule r = new JenkinsRule();
- @Rule public GitSampleRepoRule sampleRepo1 = new GitSampleRepoRule();
- @Rule public GitSampleRepoRule sampleRepo2 = new GitSampleRepoRule();
- @Rule public GitSampleRepoRule sampleRepo3 = new GitSampleRepoRule();
- @Rule public TemporaryFolder tmp = new TemporaryFolder();
+ private GitSampleRepoRule sampleRepo1;
+ private GitSampleRepoRule sampleRepo2;
+ private GitSampleRepoRule sampleRepo3;
- @Test public void smokes() throws Exception {
- File clones = tmp.newFolder();
+ /**
+ * Enables creation of multiple repos per test class.
+ */
+ static class MultiGitSampleRepoExtension extends GitSampleRepoExtension {
+ private static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create(MultiGitSampleRepoExtension.class);
+ private static final String KEY = "git-sample-repo-";
+ private static int counter = 0;
+
+ @Override
+ public void afterEach(ExtensionContext context) {
+ while (counter > 0) {
+ GitSampleRepoRule rule = context.getStore(NAMESPACE).remove(KEY + counter, GitSampleRepoRule.class);
+ if (rule != null) {
+ rule.after();
+ }
+ counter--;
+ }
+ }
+
+ @Override
+ public GitSampleRepoRule resolveParameter(ParameterContext parameterContext, ExtensionContext context) {
+ counter++;
+ GitSampleRepoRule rule = context.getStore(NAMESPACE).getOrComputeIfAbsent(KEY + counter, key -> new GitSampleRepoRule(), GitSampleRepoRule.class);
+ if (rule != null) {
+ try {
+ rule.before();
+ } catch (Throwable t) {
+ throw new ParameterResolutionException(t.getMessage(), t);
+ }
+ }
+ return rule;
+ }
+ }
+
+ @BeforeEach
+ void setUp(JenkinsRule rule, GitSampleRepoRule repo1, GitSampleRepoRule repo2, GitSampleRepoRule repo3) {
+ r = rule;
+ sampleRepo1 = repo1;
+ sampleRepo2 = repo2;
+ sampleRepo3 = repo3;
+ }
+
+ @Test
+ void smokes() throws Exception {
+ File clones = newFolder(tmp, "junit");
sampleRepo1.init();
sampleRepo1.write(WorkflowBranchProjectFactory.SCRIPT, "echo 'ran one'");
sampleRepo1.git("add", WorkflowBranchProjectFactory.SCRIPT);
@@ -125,10 +179,11 @@ public class WorkflowMultiBranchProjectFactoryTest {
}
@Issue("JENKINS-34561")
- @Test public void configuredScriptName() throws Exception {
+ @Test
+ void configuredScriptName() throws Exception {
String alternativeJenkinsFileName = "alternative_Jenkinsfile_name.groovy";
- File clones = tmp.newFolder();
+ File clones = newFolder(tmp, "junit");
sampleRepo1.init();
sampleRepo1.write(WorkflowBranchProjectFactory.SCRIPT,
"echo 'echo from " + WorkflowBranchProjectFactory.SCRIPT + "'");
@@ -187,4 +242,13 @@ public class WorkflowMultiBranchProjectFactoryTest {
assertEquals(1, b1.getNumber());
r.assertLogContains("echo from alternative_Jenkinsfile_name", b1);
}
+
+ private static File newFolder(File root, String... subDirs) throws IOException {
+ String subFolder = String.join("/", subDirs);
+ File result = new File(root, subFolder);
+ if (!result.mkdirs()) {
+ throw new IOException("Couldn't create folders " + root);
+ }
+ return result;
+ }
}
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java
index 86d2af83..164ec6f0 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java
@@ -54,6 +54,7 @@
import jenkins.plugins.git.GitSCMSource;
import jenkins.plugins.git.GitBranchSCMHead;
import jenkins.plugins.git.GitSampleRepoRule;
+import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo;
import jenkins.plugins.git.traits.BranchDiscoveryTrait;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMSource;
@@ -62,26 +63,33 @@
import static org.hamcrest.Matchers.*;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.jvnet.hudson.test.BuildWatcher;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;
+import org.jvnet.hudson.test.junit.jupiter.BuildWatcherExtension;
+import org.jvnet.hudson.test.junit.jupiter.WithJenkins;
+
+@WithJenkins
+@WithGitSampleRepo
+class WorkflowMultiBranchProjectTest {
-public class WorkflowMultiBranchProjectTest {
+ @SuppressWarnings("unused")
+ private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
+ private JenkinsRule r;
+ private GitSampleRepoRule sampleRepo;
- @ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
- @Rule public JenkinsRule r = new JenkinsRule();
- @Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
+ @BeforeEach
+ void setUp(JenkinsRule rule, GitSampleRepoRule repo) {
+ r = rule;
+ sampleRepo = repo;
+ }
- @Test public void basicBranches() throws Exception {
+ @Test
+ void basicBranches() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "echo \"branch=${env.BRANCH_NAME}\"; node {checkout scm; echo readFile('file')}");
sampleRepo.write("file", "initial content");
@@ -140,7 +148,8 @@ static void showIndexing(@NonNull WorkflowMultiBranchProject mp) throws Exceptio
}
@Issue({"JENKINS-32396", "JENKINS-32670"})
- @Test public void visibleBranchProperties() throws Exception {
+ @Test
+ void visibleBranchProperties() throws Exception {
WorkflowMultiBranchProject p = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
Set> propertyTypes = new HashSet<>();
for (BranchPropertyDescriptor d : DescriptorVisibilityFilter.apply(p, BranchPropertyDescriptor.all())) {
@@ -162,7 +171,8 @@ static void showIndexing(@NonNull WorkflowMultiBranchProject mp) throws Exceptio
}
@SuppressWarnings("rawtypes")
- @Test public void applicableSCMs() throws Exception {
+ @Test
+ void applicableSCMs() throws Exception {
final WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
List scmTypes = new ArrayList<>();
List> scmDescriptors = SingleSCMSource.DescriptorImpl.getSCMDescriptors(mp);
@@ -179,21 +189,26 @@ static void showIndexing(@NonNull WorkflowMultiBranchProject mp) throws Exceptio
assertThat(html, not(containsString("OldSCM")));
*/
}
+
public static class OldSCM extends SCM {
- @Override public ChangeLogParser createChangeLogParser() {return null;}
- @TestExtension("applicableSCMs") public static class DescriptorImpl extends SCMDescriptor {
+ @Override
+ public ChangeLogParser createChangeLogParser() {return null;}
+ @TestExtension("applicableSCMs")
+ public static class DescriptorImpl extends SCMDescriptor {
public DescriptorImpl() {
super(null);
}
@NonNull
- @Override public String getDisplayName() {
+ @Override
+ public String getDisplayName() {
return "OldSCM";
}
}
}
@Issue("JENKINS-32179")
- @Test public void conflictingBranches() throws Exception {
+ @Test
+ void conflictingBranches() throws Exception {
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "");
sampleRepo.git("add", "Jenkinsfile");
@@ -221,16 +236,20 @@ public DescriptorImpl() {
// mp.getIndexing().writeWholeLogTo(System.out);
// assertEquals("[p, p/master]", ExtensionList.lookup(Listener.class).get(0).names.toString());
}
- @TestExtension("conflictingBranches") public static class Listener extends ItemListener {
+
+ @TestExtension("conflictingBranches")
+ public static class Listener extends ItemListener {
List names = new ArrayList<>();
- @Override public void onCreated(Item item) {
+ @Override
+ public void onCreated(Item item) {
names.add(item.getFullName());
}
}
@Issue("JENKINS-34561")
- @Test public void configuredScriptNameBranches() throws Exception {
+ @Test
+ void configuredScriptNameBranches() throws Exception {
sampleRepo.init();
WorkflowMultiBranchProject mp = r.jenkins.createProject(WorkflowMultiBranchProject.class, "p");
@@ -275,7 +294,8 @@ public DescriptorImpl() {
}
@Issue("JENKINS-72613")
- @Test public void reloadMangledName() throws Exception {
+ @Test
+ void reloadMangledName() throws Exception {
r.jenkins.setQuietPeriod(0);
sampleRepo.init();
sampleRepo.write("Jenkinsfile", "echo 'on master'");
From 365d87beb37827a19eee251f7a76b292fb019052 Mon Sep 17 00:00:00 2001
From: strangelookingnerd
<49242855+strangelookingnerd@users.noreply.github.com>
Date: Fri, 24 Oct 2025 21:25:39 +0200
Subject: [PATCH 2/4] Change class visibility to public
---
.../multibranch/WorkflowMultiBranchProjectFactoryTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
index f3d5779d..065cc0b6 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
@@ -56,7 +56,7 @@
@WithJenkins
@ExtendWith(WorkflowMultiBranchProjectFactoryTest.MultiGitSampleRepoExtension.class)
-class WorkflowMultiBranchProjectFactoryTest {
+public class WorkflowMultiBranchProjectFactoryTest {
@SuppressWarnings("unused")
private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
From f2fe8295c6899ee1108b9452b0a5d4a71887d63a Mon Sep 17 00:00:00 2001
From: strangelookingnerd
<49242855+strangelookingnerd@users.noreply.github.com>
Date: Fri, 24 Oct 2025 21:26:43 +0200
Subject: [PATCH 3/4] Revert
---
.../multibranch/WorkflowMultiBranchProjectFactoryTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
index 065cc0b6..f3d5779d 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectFactoryTest.java
@@ -56,7 +56,7 @@
@WithJenkins
@ExtendWith(WorkflowMultiBranchProjectFactoryTest.MultiGitSampleRepoExtension.class)
-public class WorkflowMultiBranchProjectFactoryTest {
+class WorkflowMultiBranchProjectFactoryTest {
@SuppressWarnings("unused")
private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();
From 187a21949e89d9b1c3d5cd2099eaa382957a4be7 Mon Sep 17 00:00:00 2001
From: strangelookingnerd
<49242855+strangelookingnerd@users.noreply.github.com>
Date: Fri, 24 Oct 2025 21:27:07 +0200
Subject: [PATCH 4/4] Change WorkflowMultiBranchProjectTest to public
---
.../workflow/multibranch/WorkflowMultiBranchProjectTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java
index 164ec6f0..d27f83eb 100644
--- a/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java
+++ b/src/test/java/org/jenkinsci/plugins/workflow/multibranch/WorkflowMultiBranchProjectTest.java
@@ -75,7 +75,7 @@
@WithJenkins
@WithGitSampleRepo
-class WorkflowMultiBranchProjectTest {
+public class WorkflowMultiBranchProjectTest {
@SuppressWarnings("unused")
private static final BuildWatcherExtension BUILD_WATCHER = new BuildWatcherExtension();