diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a280266e..177ba28f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,12 +7,18 @@ Look for contribution areas in the ## Background -Plugin source code is hosted on https://github.com/jenkinsci/parameterized-trigger-plugin[GitHub]. -New feature proposals and bug fix proposals should be submitted as https://help.github.com/articles/creating-a-pull-request[GitHub pull requests]. -Your pull request will be evaluated by the https://ci.jenkins.io/job/Plugins/job/parameterized-trigger-plugin/[Jenkins job]. +Plugin source code is hosted on [GitHub](https://github.com/jenkinsci/parameterized-trigger-plugin). +New feature proposals and bug fix proposals should be submitted as [GitHub pull requests](https://help.github.com/articles/creating-a-pull-request). +Your pull request will be evaluated by the [Jenkins job](https://ci.jenkins.io/job/Plugins/job/parameterized-trigger-plugin/). -Before submitting your change, please assure that you've added tests to verify your change. -Tests help us assure that we're delivering a reliable plugin, and that we've communicated our intent to other developers as executable descriptions of plugin behavior. +Before submitting your change, please assure that you've added tests which verify your change. + +## Code formatting + +Source code and pom file formatting is maintained by the `spotless` maven plugin. +Before submitting a pull request, confirm the formatting is correct with: + +* `mvn spotless:apply` ## Building and Testing @@ -24,11 +30,29 @@ Compile the plugin without running tests using the command: * `mvn clean -DskipTests verify` +### Reviewing code coverage + Code coverage reporting is available as a maven target. Please try to improve code coverage with tests when you submit. * `mvn -P enable-jacoco clean install jacoco:report` to report code coverage +The code coverage report is a set of HTML files that show methods and lines executed. +The following commands will open the `index.html` file in the browser. + +* Windows - `start target\site\jacoco\index.html` +* Linux - `xdg-open target/site/jacoco/index.html` +* Gitpod - `cd target/site/jacoco && python -m http.server 8000` + +The file will have a list of package names. +Click on them to find a list of class names. + +The lines of the code will be covered in three different colors, red, green, and orange. +Red lines are not covered in the tests. +Green lines are covered with tests. + +### Spotbugs static analysis + Please don't introduce new spotbugs output. * `mvn spotbugs:check` to analyze project using https://spotbugs.github.io/[Spotbugs]. diff --git a/pom.xml b/pom.xml index 7c6116b4..a1ab6f61 100644 --- a/pom.xml +++ b/pom.xml @@ -1,3 +1,4 @@ + 4.0.0 @@ -8,6 +9,12 @@ + parameterized-trigger + ${changelist} + hpi + Jenkins Parameterized Trigger plugin + https://github.com/jenkinsci/parameterized-trigger-plugin + The MIT License (MIT) @@ -16,16 +23,38 @@ - parameterized-trigger - hpi - ${changelist} - Jenkins Parameterized Trigger plugin - https://github.com/jenkinsci/parameterized-trigger-plugin + + scm:git:https://github.com/${gitHubRepo}.git + scm:git:git@github.com:${gitHubRepo}.git + ${scmTag} + https://github.com/${gitHubRepo} + + + + 999999-SNAPSHOT + jenkinsci/parameterized-trigger-plugin + 2.387.3 + Max + Low + false + + + + + + io.jenkins.tools.bom + bom-2.387.x + 2543.vfb_1a_5fb_9496d + pom + import + + + org.jenkins-ci.plugins - subversion + conditional-buildstep true @@ -50,24 +79,33 @@ org.jenkins-ci.plugins - conditional-buildstep + script-security + + + org.jenkins-ci.plugins + subversion true + + org.awaitility + awaitility + 4.2.0 + test + org.jenkins-ci.plugins apache-httpcomponents-client-4-api test - - org.jenkins-ci.plugins.workflow - workflow-job + org.jenkins-ci.plugins + matrix-auth test - org.jenkins-ci.plugins.workflow - workflow-cps + org.jenkins-ci.plugins + token-macro test @@ -75,14 +113,20 @@ workflow-basic-steps test + + org.jenkins-ci.plugins.workflow + workflow-cps + test + org.jenkins-ci.plugins.workflow workflow-durable-task-step test + org.jenkins-ci.plugins.workflow - workflow-support + workflow-job test @@ -91,8 +135,8 @@ test - org.jenkins-ci.plugins - matrix-auth + org.jenkins-ci.plugins.workflow + workflow-support test @@ -100,42 +144,8 @@ mockito-core test - - org.jenkins-ci.plugins - script-security - - - org.jenkins-ci.plugins - token-macro - test - - - org.awaitility - awaitility - 4.2.0 - test - - - - - io.jenkins.tools.bom - bom-2.387.x - 2543.vfb_1a_5fb_9496d - import - pom - - - - - - scm:git:https://github.com/${gitHubRepo}.git - scm:git:git@github.com:${gitHubRepo}.git - https://github.com/${gitHubRepo} - ${scmTag} - - repo.jenkins-ci.org @@ -149,12 +159,4 @@ https://repo.jenkins-ci.org/public/ - - - 999999-SNAPSHOT - jenkinsci/parameterized-trigger-plugin - 2.387.3 - Max - Low - diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/AbstractBuildParameterFactory.java b/src/main/java/hudson/plugins/parameterizedtrigger/AbstractBuildParameterFactory.java index 8ddc6b77..e99e2d60 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/AbstractBuildParameterFactory.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/AbstractBuildParameterFactory.java @@ -4,7 +4,6 @@ import hudson.model.AbstractBuild; import hudson.model.AbstractDescribableImpl; import hudson.model.TaskListener; - import java.io.IOException; import java.util.List; @@ -12,7 +11,8 @@ * Generates Build Parameters. These will can be used in the TriggerBuilder to trigger the same projects with many different * parameters. */ -public abstract class AbstractBuildParameterFactory extends AbstractDescribableImpl implements ExtensionPoint { +public abstract class AbstractBuildParameterFactory extends AbstractDescribableImpl + implements ExtensionPoint { /** * Let N be the length of the list returned by this method, and each item in this list X1, X2, X3, ... XN. * @@ -24,14 +24,14 @@ public abstract class AbstractBuildParameterFactory extends AbstractDescribableI * The build which the parameterized trigger is configured and executing. * @param listener * Connected to the build output. - * + * * @return can be empty but never null. */ - public abstract List getParameters(AbstractBuild build, TaskListener listener) + public abstract List getParameters(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException; @Override public AbstractBuildParameterFactoryDescriptor getDescriptor() { - return (AbstractBuildParameterFactoryDescriptor)super.getDescriptor(); + return (AbstractBuildParameterFactoryDescriptor) super.getDescriptor(); } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/AbstractBuildParameterFactoryDescriptor.java b/src/main/java/hudson/plugins/parameterizedtrigger/AbstractBuildParameterFactoryDescriptor.java index a36f8583..1b9ba966 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/AbstractBuildParameterFactoryDescriptor.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/AbstractBuildParameterFactoryDescriptor.java @@ -15,6 +15,5 @@ public AbstractBuildParameterFactoryDescriptor(Class implements ExtensionPoint { +public abstract class AbstractBuildParameters extends AbstractDescribableImpl + implements ExtensionPoint { /** * @@ -29,13 +29,13 @@ public abstract class AbstractBuildParameters extends AbstractDescribableImpl build, TaskListener listener) + public abstract Action getAction(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, DontTriggerException; /** * Retrieve the build environment from the upstream build */ - public EnvVars getEnvironment(AbstractBuild build, TaskListener listener) + public EnvVars getEnvironment(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException { CapturedEnvironmentAction capture = build.getAction(CapturedEnvironmentAction.class); diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BinaryFileParameterFactory.java b/src/main/java/hudson/plugins/parameterizedtrigger/BinaryFileParameterFactory.java index 7a05a480..8d88e3fb 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BinaryFileParameterFactory.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BinaryFileParameterFactory.java @@ -8,8 +8,6 @@ import hudson.model.ParametersAction; import hudson.model.TaskListener; import hudson.plugins.parameterizedtrigger.FileBuildParameterFactory.NoFilesFoundEnum; -import org.kohsuke.stapler.DataBoundConstructor; - import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -17,6 +15,7 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; +import org.kohsuke.stapler.DataBoundConstructor; /** * Creates a {@link FileParameterValue} for each matching file. @@ -36,7 +35,7 @@ public BinaryFileParameterFactory(String parameterName, String filePattern, NoFi } public BinaryFileParameterFactory(String parameterName, String filePattern) { - this(parameterName,filePattern, NoFilesFoundEnum.SKIP); + this(parameterName, filePattern, NoFilesFoundEnum.SKIP); } public String getParameterName() { @@ -52,32 +51,37 @@ public NoFilesFoundEnum getNoFilesFoundAction() { } @Override - public List getParameters(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { + public List getParameters(AbstractBuild build, TaskListener listener) + throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { List result = new ArrayList<>(); FilePath workspace = build.getWorkspace(); if (workspace == null) { throw new IOException("Failed to get workspace"); } try { - // save them into the master because FileParameterValue might need files after the agent workspace have disappeared/reused + // save them into the master because FileParameterValue might need files after the agent workspace have + // disappeared/reused FilePath target = new FilePath(build.getRootDir()).child("parameter-files"); int n = workspace.copyRecursiveTo(getFilePattern(), target); - if (n==0) { + if (n == 0) { noFilesFoundAction.failCheck(listener); } else { - for(final FilePath f: target.list(getFilePattern())) { + for (final FilePath f : target.list(getFilePattern())) { LOGGER.fine("Triggering build with " + f.getName()); result.add(new AbstractBuildParameters() { @Override - public Action getAction(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, DontTriggerException { - assert f.getChannel()==null; // we copied files locally. This file must be local to the master - FileParameterValue fv = new FileParameterValue(parameterName, new File(f.getRemote()), f.getName()); - - if ($setLocation!=null) { + public Action getAction(AbstractBuild build, TaskListener listener) + throws IOException, InterruptedException, DontTriggerException { + assert f.getChannel() + == null; // we copied files locally. This file must be local to the master + FileParameterValue fv = + new FileParameterValue(parameterName, new File(f.getRemote()), f.getName()); + + if ($setLocation != null) { try { - $setLocation.invoke(fv,parameterName); + $setLocation.invoke(fv, parameterName); } catch (IllegalAccessException | InvocationTargetException e) { // be defensive as the core might change } @@ -94,7 +98,6 @@ public Action getAction(AbstractBuild build, TaskListener listener) throws return result; } - @Extension public static class DescriptorImpl extends AbstractBuildParameterFactoryDescriptor { @Override @@ -108,11 +111,12 @@ public String getDisplayName() { static { // work around NPE fixed in the core at 4a95cc6f9269108e607077dc9fd57f06e4c9af26 try { - $setLocation = FileParameterValue.class.getDeclaredMethod("setLocation",String.class); + $setLocation = FileParameterValue.class.getDeclaredMethod("setLocation", String.class); $setLocation.setAccessible(true); } catch (NoSuchMethodException e) { // ignore } } + private static final Logger LOGGER = Logger.getLogger(BinaryFileParameterFactory.class.getName()); } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java index d49d5284..b22f045b 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java @@ -1,7 +1,8 @@ package hudson.plugins.parameterizedtrigger; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - import hudson.Extension; import hudson.Launcher; import hudson.model.AbstractBuild; @@ -9,21 +10,16 @@ import hudson.model.Action; import hudson.model.BuildListener; import hudson.model.Job; -import hudson.model.Node; -import jenkins.model.Jenkins; -import org.kohsuke.stapler.DataBoundConstructor; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ListMultimap; import hudson.model.Label; +import hudson.model.Node; import hudson.model.TaskListener; import hudson.model.queue.QueueTaskFuture; - import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import jenkins.model.Jenkins; +import org.kohsuke.stapler.DataBoundConstructor; /** * {@link BuildTriggerConfig} that supports blocking of the execution. @@ -35,13 +31,18 @@ public class BlockableBuildTriggerConfig extends BuildTriggerConfig { @SuppressFBWarnings(value = "UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD", justification = "Part of the public API") public boolean buildAllNodesWithLabel; - public BlockableBuildTriggerConfig(String projects, BlockingBehaviour block, List configs) { + public BlockableBuildTriggerConfig( + String projects, BlockingBehaviour block, List configs) { super(projects, ResultCondition.ALWAYS, false, configs); this.block = block; } @DataBoundConstructor - public BlockableBuildTriggerConfig(String projects, BlockingBehaviour block, List configFactories,List configs) { + public BlockableBuildTriggerConfig( + String projects, + BlockingBehaviour block, + List configFactories, + List configs) { super(projects, ResultCondition.ALWAYS, false, configFactories, configs, false); this.block = block; } @@ -51,56 +52,63 @@ public BlockingBehaviour getBlock() { } @Override - public List> perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + public List> perform( + AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { List> r = super.perform(build, launcher, listener); - if (block==null) return Collections.emptyList(); + if (block == null) return Collections.emptyList(); return r; } @Override - public ListMultimap> perform2(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { - ListMultimap> futures = super.perform2(build, launcher, listener); - if(block==null) return ArrayListMultimap.create(); + public ListMultimap> perform2( + AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { + ListMultimap> futures = + super.perform2(build, launcher, listener); + if (block == null) return ArrayListMultimap.create(); return futures; } @Override - public ListMultimap> perform3(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + public ListMultimap> perform3( + AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { ListMultimap> futures = super.perform3(build, launcher, listener); - if(block==null) return ArrayListMultimap.create(); + if (block == null) return ArrayListMultimap.create(); return futures; } @Override - protected QueueTaskFuture schedule(AbstractBuild build, Job project, List list, TaskListener listener) throws InterruptedException, IOException { - if (block!=null) { + protected QueueTaskFuture schedule(AbstractBuild build, Job project, List list, TaskListener listener) + throws InterruptedException, IOException { + if (block != null) { while (true) { // add DifferentiatingAction to make sure this doesn't get merged with something else, // which is most likely unintended. Might make sense to do it at BuildTriggerConfig for all. list = CollectionUtils.immutableList(list, new DifferentiatingAction()); - // if we fail to add the item to the queue, wait and retry. // it also means we have to force quiet period = 0, or else it'll never leave the queue QueueTaskFuture f = schedule(build, project, 0, list, listener); - // When a project is disabled or the configuration is not yet saved f will always be null and we're caught in a loop, therefore we need to check for it - if (f != null || !canBeScheduled(project)){ + // When a project is disabled or the configuration is not yet saved f will always be null and we're + // caught in a loop, therefore we need to check for it + if (f != null || !canBeScheduled(project)) { return f; } Thread.sleep(1000); } } else { - return super.schedule(build,project,list,listener); + return super.schedule(build, project, list, listener); } } public Collection getNodes() { Label label = Jenkins.get().getLabel("asrt"); - if (label==null) return Collections.emptyList(); + if (label == null) return Collections.emptyList(); return label.getNodes(); } @Extension - public static class DescriptorImpl extends BuildTriggerConfig.DescriptorImpl { - } + public static class DescriptorImpl extends BuildTriggerConfig.DescriptorImpl {} } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BlockingBehaviour.java b/src/main/java/hudson/plugins/parameterizedtrigger/BlockingBehaviour.java index 90f5974b..65d71f0f 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BlockingBehaviour.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BlockingBehaviour.java @@ -25,18 +25,17 @@ package hudson.plugins.parameterizedtrigger; -import hudson.model.AbstractDescribableImpl; -import org.apache.commons.lang.StringUtils; +import static hudson.model.Result.*; + +import edu.umd.cs.findbugs.annotations.CheckForNull; import hudson.Extension; +import hudson.model.AbstractDescribableImpl; import hudson.model.Descriptor; import hudson.model.Result; -import org.kohsuke.stapler.DataBoundConstructor; - -import edu.umd.cs.findbugs.annotations.CheckForNull; import java.util.Arrays; import java.util.List; - -import static hudson.model.Result.*; +import org.apache.commons.lang.StringUtils; +import org.kohsuke.stapler.DataBoundConstructor; /** * Determines how to handle the status of the triggered builds in {@link TriggerBuilder}. @@ -56,7 +55,7 @@ public BlockingBehaviour(String buildStepFailureThreshold, String unstableThresh } private Result parse(String t) { - if(StringUtils.isBlank(t) || "never".equals(t)) { + if (StringUtils.isBlank(t) || "never".equals(t)) { return null; } return Result.fromString(t); @@ -67,10 +66,10 @@ public BlockingBehaviour(Result buildStepFailureThreshold, Result unstableThresh this.unstableThreshold = unstableThreshold; this.failureThreshold = failureThreshold; } - + /** * Maps the result of a triggered build to the result of the triggering build step. - * + * * @param r the {@link Result} of the triggered build to map * @return {@code false} if the triggering build step has to fail, {@code true} otherwise */ @@ -80,14 +79,14 @@ public boolean mapBuildStepResult(Result r) { /** * Maps the result of a triggered build to the result of the triggering build. - * + * * @param r the {@link Result} of the triggered build to map * @return the result of the triggering build */ @CheckForNull public Result mapBuildResult(Result r) { - if (failureThreshold!=null && r.isWorseOrEqualTo(failureThreshold)) return FAILURE; - if (unstableThreshold!=null && r.isWorseOrEqualTo(unstableThreshold)) return UNSTABLE; + if (failureThreshold != null && r.isWorseOrEqualTo(failureThreshold)) return FAILURE; + if (unstableThreshold != null && r.isWorseOrEqualTo(unstableThreshold)) return UNSTABLE; return null; } @@ -99,7 +98,7 @@ public String getDisplayName() { } public List getAllResults() { - return Arrays.asList(SUCCESS,UNSTABLE,FAILURE); + return Arrays.asList(SUCCESS, UNSTABLE, FAILURE); } } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BooleanParameterConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/BooleanParameterConfig.java index 5486936e..f0a18aed 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BooleanParameterConfig.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BooleanParameterConfig.java @@ -33,34 +33,34 @@ * * @author Chris Johnson */ -public class BooleanParameterConfig implements Describable{ +public class BooleanParameterConfig implements Describable { - private final String name; - private final boolean value; + private final String name; + private final boolean value; - @DataBoundConstructor - public BooleanParameterConfig(String name, boolean value) { - this.name = name; - this.value = value; - } - public boolean getValue() { - return value; - } + @DataBoundConstructor + public BooleanParameterConfig(String name, boolean value) { + this.name = name; + this.value = value; + } - public String getName() { - return name; - } + public boolean getValue() { + return value; + } - public Descriptor getDescriptor() { - return Jenkins.get().getDescriptorOrDie(getClass()); - } - - - @Extension - public static class DescriptorImpl extends Descriptor { - @Override - public String getDisplayName() { - return ""; // unused - } - } + public String getName() { + return name; + } + + public Descriptor getDescriptor() { + return Jenkins.get().getDescriptorOrDie(getClass()); + } + + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return ""; // unused + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BooleanParameters.java b/src/main/java/hudson/plugins/parameterizedtrigger/BooleanParameters.java index 6ef0ee22..5859e2ed 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BooleanParameters.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BooleanParameters.java @@ -32,10 +32,8 @@ import hudson.model.ParametersAction; import hudson.model.TaskListener; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; - import org.kohsuke.stapler.DataBoundConstructor; /** @@ -44,34 +42,33 @@ */ public class BooleanParameters extends AbstractBuildParameters { - private final List configs; + private final List configs; - @DataBoundConstructor - public BooleanParameters(List configs ){ - this.configs = configs; - } + @DataBoundConstructor + public BooleanParameters(List configs) { + this.configs = configs; + } - @Override - public Action getAction(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, DontTriggerException { + @Override + public Action getAction(AbstractBuild build, TaskListener listener) + throws IOException, InterruptedException, DontTriggerException { - List values = configs - .stream() - .map( config -> new BooleanParameterValue(config.getName(), config.getValue()) ) - .collect( Collectors.toList() ); + List values = configs.stream() + .map(config -> new BooleanParameterValue(config.getName(), config.getValue())) + .collect(Collectors.toList()); - return new ParametersAction(values); - } + return new ParametersAction(values); + } - public List getConfigs() { - return configs; - } + public List getConfigs() { + return configs; + } - @Extension - public static class DescriptorImpl extends Descriptor { - @Override - public String getDisplayName() { - return "Boolean parameters"; - } - - } + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "Boolean parameters"; + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BuildInfoExporterAction.java b/src/main/java/hudson/plugins/parameterizedtrigger/BuildInfoExporterAction.java index 1898ec4a..3c1764e3 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BuildInfoExporterAction.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BuildInfoExporterAction.java @@ -30,16 +30,14 @@ import hudson.model.AbstractProject; import hudson.model.EnvironmentContributingAction; import hudson.model.Result; -import jenkins.model.Jenkins; -import org.kohsuke.stapler.export.Exported; -import org.kohsuke.stapler.export.ExportedBean; - import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; +import jenkins.model.Jenkins; +import org.kohsuke.stapler.export.Exported; +import org.kohsuke.stapler.export.ExportedBean; @ExportedBean public class BuildInfoExporterAction implements EnvironmentContributingAction { @@ -51,7 +49,7 @@ public class BuildInfoExporterAction implements EnvironmentContributingAction { public static final String BUILD_RESULT_VARIABLE_PREFIX = "TRIGGERED_BUILD_RESULT_"; public static final String BUILD_RUN_COUNT_PREFIX = "TRIGGERED_BUILD_RUN_COUNT_"; public static final String RUN = "_RUN_"; - //now unused as part of map + // now unused as part of map private transient String buildName; private transient int buildNumber; @@ -70,11 +68,13 @@ public BuildInfoExporterAction(BuildReference buildRef) { lastReference = buildRef; } - public BuildInfoExporterAction(String buildName, int buildNumber, AbstractBuild parentBuild, Result buildResult) { + public BuildInfoExporterAction( + String buildName, int buildNumber, AbstractBuild parentBuild, Result buildResult) { this(new BuildReference(buildName, buildNumber, buildResult)); } - static BuildInfoExporterAction addBuildInfoExporterAction(AbstractBuild parentBuild, String triggeredProject, int buildNumber, Result buildResult) { + static BuildInfoExporterAction addBuildInfoExporterAction( + AbstractBuild parentBuild, String triggeredProject, int buildNumber, Result buildResult) { BuildInfoExporterAction action = parentBuild.getAction(BuildInfoExporterAction.class); if (action == null) { action = new BuildInfoExporterAction(triggeredProject, buildNumber, parentBuild, buildResult); @@ -85,7 +85,8 @@ static BuildInfoExporterAction addBuildInfoExporterAction(AbstractBuild pa return action; } - static BuildInfoExporterAction addBuildInfoExporterAction(AbstractBuild parentBuild, String triggeredProject) { + static BuildInfoExporterAction addBuildInfoExporterAction( + AbstractBuild parentBuild, String triggeredProject) { BuildInfoExporterAction action = parentBuild.getAction(BuildInfoExporterAction.class); if (action == null) { action = new BuildInfoExporterAction(new BuildReference(triggeredProject)); @@ -133,60 +134,58 @@ public BuildReference(final String projectName) { } @Override - public String getIconFileName() - { - return null; + public String getIconFileName() { + return null; } @Override - public String getDisplayName() - { - return null; + public String getDisplayName() { + return null; } @Override - public String getUrlName() - { - return null; + public String getUrlName() { + return null; } @Override public void buildEnvVars(AbstractBuild build, EnvVars env) { - // Note: this will only indicate the last project in the list that is ran - env.put(JOB_NAME_VARIABLE, lastReference.projectName.replaceAll("[^a-zA-Z0-9]+", "_")); - //all projects triggered. - // this should not include projects that don't have a build item. - String sanitizedProjectList = getProjectListString(","); - env.put(ALL_JOBS_NAME_VARIABLE, sanitizedProjectList); - - for (String project : getProjectsWithBuilds()) { - // for each project add the following variables once - // all buildnumbers, lastbuildnumber - // all Run results, last build result - String sanitizedBuildName = project.replaceAll("[^a-zA-Z0-9]+", "_"); - List refs = getBuildRefs(project); - - env.put(ALL_BUILD_NUMBER_VARIABLE_PREFIX + sanitizedBuildName, getBuildNumbersString(refs, ",")); - env.put(BUILD_RUN_COUNT_PREFIX + sanitizedBuildName, Integer.toString(refs.size())); - for (BuildReference br : refs) { - if (br.buildNumber != 0) { - String triggeredBuildRunResultKey = BUILD_RESULT_VARIABLE_PREFIX + sanitizedBuildName + RUN + Integer.toString(br.buildNumber); - env.put(triggeredBuildRunResultKey, br.buildResult.toString()); - } - } - BuildReference lastBuild = null; - for (int i = (refs.size()); i > 0; i--) { - if (refs.get(i - 1).buildNumber != 0) { - lastBuild = refs.get(i - 1); - } - break; + // Note: this will only indicate the last project in the list that is ran + env.put(JOB_NAME_VARIABLE, lastReference.projectName.replaceAll("[^a-zA-Z0-9]+", "_")); + // all projects triggered. + // this should not include projects that don't have a build item. + String sanitizedProjectList = getProjectListString(","); + env.put(ALL_JOBS_NAME_VARIABLE, sanitizedProjectList); + + for (String project : getProjectsWithBuilds()) { + // for each project add the following variables once + // all buildnumbers, lastbuildnumber + // all Run results, last build result + String sanitizedBuildName = project.replaceAll("[^a-zA-Z0-9]+", "_"); + List refs = getBuildRefs(project); + + env.put(ALL_BUILD_NUMBER_VARIABLE_PREFIX + sanitizedBuildName, getBuildNumbersString(refs, ",")); + env.put(BUILD_RUN_COUNT_PREFIX + sanitizedBuildName, Integer.toString(refs.size())); + for (BuildReference br : refs) { + if (br.buildNumber != 0) { + String triggeredBuildRunResultKey = + BUILD_RESULT_VARIABLE_PREFIX + sanitizedBuildName + RUN + Integer.toString(br.buildNumber); + env.put(triggeredBuildRunResultKey, br.buildResult.toString()); + } + } + BuildReference lastBuild = null; + for (int i = (refs.size()); i > 0; i--) { + if (refs.get(i - 1).buildNumber != 0) { + lastBuild = refs.get(i - 1); + } + break; + } + if (lastBuild != null) { + env.put(BUILD_NUMBER_VARIABLE_PREFIX + sanitizedBuildName, Integer.toString(lastBuild.buildNumber)); + env.put(BUILD_RESULT_VARIABLE_PREFIX + sanitizedBuildName, lastBuild.buildResult.toString()); + } } - if (lastBuild != null) { - env.put(BUILD_NUMBER_VARIABLE_PREFIX + sanitizedBuildName, Integer.toString(lastBuild.buildNumber)); - env.put(BUILD_RESULT_VARIABLE_PREFIX + sanitizedBuildName, lastBuild.buildResult.toString()); - } - } } private List getBuildRefs(String project) { @@ -207,120 +206,120 @@ private List getBuildRefs(String project) { @Exported(visibility = 1) public List> getTriggeredBuilds() { - List> builds = new ArrayList<>(); - - for (BuildReference br : this.builds) { - AbstractProject> project = - Jenkins.get().getItemByFullName(br.projectName, AbstractProject.class); - if (br.buildNumber != 0) { - builds.add((project != null)?project.getBuildByNumber(br.buildNumber):null); - } - } - return builds; - } + List> builds = new ArrayList<>(); - /** - * Gets all the projects that triggered from this one which were non blocking, - * which we don't have a builds for. Does not include builds that are returned - * in #link{getTriggeredBuilds} Used in the UI for see Summary.groovy - * - * @return List of Projects that are triggered by this build. May contains null if a project is deleted. - */ - @Exported(visibility = 1) - public List> getTriggeredProjects() { - List> projects = new ArrayList<>(); - - for (BuildReference br : this.builds) { - if (br.buildNumber == 0) { + for (BuildReference br : this.builds) { AbstractProject> project = Jenkins.get().getItemByFullName(br.projectName, AbstractProject.class); - projects.add(project); + if (br.buildNumber != 0) { + builds.add((project != null) ? project.getBuildByNumber(br.buildNumber) : null); + } } + return builds; } - return projects; - } - - /** - * Handle cases from older builds so that they still add old variables if - * needed to. Should not show any UI as there will be no data added. - * - * @return - */ - public Object readResolve() { - if (this.lastReference == null) { - this.lastReference = new BuildReference(this.buildName, this.buildNumber, Result.NOT_BUILT); - } - if (this.builds == null) { - this.builds = new ArrayList<>(); + + /** + * Gets all the projects that triggered from this one which were non blocking, + * which we don't have a builds for. Does not include builds that are returned + * in #link{getTriggeredBuilds} Used in the UI for see Summary.groovy + * + * @return List of Projects that are triggered by this build. May contains null if a project is deleted. + */ + @Exported(visibility = 1) + public List> getTriggeredProjects() { + List> projects = new ArrayList<>(); + + for (BuildReference br : this.builds) { + if (br.buildNumber == 0) { + AbstractProject> project = + Jenkins.get().getItemByFullName(br.projectName, AbstractProject.class); + projects.add(project); + } + } + return projects; } - if (this.buildRefs != null) { - for (List buildReferences : buildRefs.values()) { - this.builds.addAll(buildReferences); + + /** + * Handle cases from older builds so that they still add old variables if + * needed to. Should not show any UI as there will be no data added. + * + * @return + */ + public Object readResolve() { + if (this.lastReference == null) { + this.lastReference = new BuildReference(this.buildName, this.buildNumber, Result.NOT_BUILT); + } + if (this.builds == null) { + this.builds = new ArrayList<>(); } + if (this.buildRefs != null) { + for (List buildReferences : buildRefs.values()) { + this.builds.addAll(buildReferences); + } + } + return this; } - return this; - } - - /** - * Gets a string for all of the build numbers - * - * @param refs List of build references to process. - * @param separator - * @return String containing all the build numbers from refs, never null but - * can be empty - */ - private String getBuildNumbersString(List refs, String separator) { - StringBuilder buf = new StringBuilder(); - boolean first = true; - - for (BuildReference s : refs) { - if (s.buildNumber != 0) { - if (first) { - first = false; - } else { - buf.append(separator); + + /** + * Gets a string for all of the build numbers + * + * @param refs List of build references to process. + * @param separator + * @return String containing all the build numbers from refs, never null but + * can be empty + */ + private String getBuildNumbersString(List refs, String separator) { + StringBuilder buf = new StringBuilder(); + boolean first = true; + + for (BuildReference s : refs) { + if (s.buildNumber != 0) { + if (first) { + first = false; + } else { + buf.append(separator); + } + buf.append(s.buildNumber); + } } - buf.append(s.buildNumber); - } + return buf.toString(); } - return buf.toString(); - } - - /** - * Get a list of projects as a string using the separator - * - * @param separator - * @return list of projects separated by separator - */ - protected String getProjectListString(String separator) { - Set refs = getProjectsWithBuilds(); - StringBuilder buf = new StringBuilder(); - boolean first = true; - - for (String s : refs) { - if (first) { - first = false; - } else { - buf.append(separator); - } - buf.append(s.replaceAll("[^a-zA-Z0-9]+", "_")); + + /** + * Get a list of projects as a string using the separator + * + * @param separator + * @return list of projects separated by separator + */ + protected String getProjectListString(String separator) { + Set refs = getProjectsWithBuilds(); + StringBuilder buf = new StringBuilder(); + boolean first = true; + + for (String s : refs) { + if (first) { + first = false; + } else { + buf.append(separator); + } + buf.append(s.replaceAll("[^a-zA-Z0-9]+", "_")); + } + return buf.toString(); } - return buf.toString(); - } - - /** - * Gets the unique set of project names that have a linked build. - * - * @return Set of project names that have at least one build linked. - */ - private Set getProjectsWithBuilds() { - Set projects = new HashSet(); - - for (BuildReference br : this.builds) { - if (br.buildNumber != 0) { - projects.add(br.projectName); + + /** + * Gets the unique set of project names that have a linked build. + * + * @return Set of project names that have at least one build linked. + */ + private Set getProjectsWithBuilds() { + Set projects = new HashSet(); + + for (BuildReference br : this.builds) { + if (br.buildNumber != 0) { + projects.add(br.projectName); + } } + return projects; } - return projects; - } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BuildTrigger.java b/src/main/java/hudson/plugins/parameterizedtrigger/BuildTrigger.java index 0bf7cc7b..c8b3d4d9 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BuildTrigger.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BuildTrigger.java @@ -18,10 +18,6 @@ import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; import hudson.tasks.Publisher; -import jenkins.model.DependencyDeclarer; -import jenkins.model.Jenkins; -import org.kohsuke.stapler.DataBoundConstructor; - import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -32,167 +28,168 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import jenkins.model.DependencyDeclarer; +import jenkins.model.Jenkins; +import org.kohsuke.stapler.DataBoundConstructor; public class BuildTrigger extends Notifier implements DependencyDeclarer { - private final ArrayList configs; + private final ArrayList configs; @DataBoundConstructor - public BuildTrigger(List configs) { - this.configs = new ArrayList<>(Util.fixNull(configs)); - } - - public BuildTrigger(BuildTriggerConfig... configs) { - this(Arrays.asList(configs)); - } - - public List getConfigs() { - return configs; - } - - @Override - public boolean needsToRunAfterFinalized() { - return true; - } - - @Override - public BuildStepMonitor getRequiredMonitorService() { - return BuildStepMonitor.NONE; - } - - @Override - public Collection getProjectActions(AbstractProject project) { - return Collections.singletonList(new DynamicProjectAction(configs)); - } - - @Override @SuppressWarnings("deprecation") - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { - Map downstreamMap = new HashMap<>(); - Map buildMap = new HashMap<>(); - boolean hasEnvVariables = false; - - HashSet alreadyFired = new HashSet<>(); - - // If this project has non-abstract projects, we need to fire them - for (BuildTriggerConfig config : configs) { - boolean hasNonAbstractProject = false; - hasEnvVariables = hasEnvVariables || hasEnvVariables(config, build.getEnvironment(listener)); - - List jobs = config.getJobs(build.getRootBuild().getProject().getParent(), build.getEnvironment(listener)); - - - for (Job j : jobs) { - if (!(j instanceof AbstractProject)) { - hasNonAbstractProject = true; - break; - } - } - // Fire this config's projects if not already fired - if (hasNonAbstractProject) { - config.perform(build, launcher, listener); - alreadyFired.add(config); - } - } - - if (canDeclare(build.getProject()) && !hasEnvVariables) { - // job will get triggered by dependency graph, so we have to capture buildEnvironment NOW before - // hudson.model.AbstractBuild.AbstractBuildExecution#cleanUp is called and reset - EnvVars env = build.getEnvironment(listener); - build.addAction(new CapturedEnvironmentAction(env)); - } - else { // Not using dependency graph - for (BuildTriggerConfig config : configs) { - if (!alreadyFired.contains(config)) { - //config.perform(build, launcher, listener); - List> futures = config.perform(build, launcher, listener); - for (QueueTaskFuture future : futures) { - AbstractBuild abstractBuild = null; - try { - abstractBuild = (AbstractBuild) future.get(); - if (null != abstractBuild) { - downstreamMap.put(abstractBuild.getProject().getFullName(), abstractBuild); - } - } catch (ExecutionException e) { - listener.getLogger().println("Failed to execute downstream build"); - } - } - - String[] projects = config.getProjects(build.getEnvironment(listener)).split(","); - String[] vars = config.getProjects().split(","); - for (int i = 0; i < projects.length; i++) { - if (vars[i].trim().contains("$")) { - AbstractBuild abstractBuild = downstreamMap.get(projects[i]); - if (null != abstractBuild) { - listener.getLogger().println(makeLogEntry(projects[i].trim())); - buildMap.put(abstractBuild.getProject().getFullName(), abstractBuild.getNumber()); - } - } - } - - } - DynamicBuildAction action = new DynamicBuildAction(buildMap); - build.addAction(action); - } - } - - return true; - } - - private String makeLogEntry(String name) { - String url = name; - url = Jenkins.get().getRootUrl() + "job/" + url.replaceAll("/", "/job/"); - name = name.replaceAll("/", " » "); - String link = ModelHyperlinkNote.encodeTo(url, name); - StringBuilder sb = new StringBuilder(); - sb.append("Triggering a new build of "); - sb.append(link); - return sb.toString(); - } - - private boolean hasEnvVariables(BuildTriggerConfig config, EnvVars env) { - return !config.getProjects().equalsIgnoreCase(config.getProjects(env)); - } - - @Override - public void buildDependencyGraph(AbstractProject owner, DependencyGraph graph) { - if (!canDeclare(owner)) return; - - for (BuildTriggerConfig config : configs) { - List projectList = config.getProjectList(owner.getParent(), null); - for (AbstractProject project : projectList) { - if (config.isTriggerFromChildProjects() && owner instanceof ItemGroup) { - ItemGroup parent = (ItemGroup) owner; - for (Item item : parent.getItems()) { - if(item instanceof AbstractProject){ - AbstractProject child = (AbstractProject) item; - ParameterizedDependency.add(child, project, config, graph); - } - } - } - else{ - ParameterizedDependency.add(owner, project, config, graph); - - } - } - } - } - - private boolean canDeclare(AbstractProject owner) { - // See HUDSON-5679 -- dependency graph is also not used when triggered from a promotion - return !owner.getClass().getName().equals("hudson.plugins.promoted_builds.PromotionProcess"); - } - - @Extension - public static class DescriptorImpl extends BuildStepDescriptor { - @Override - public String getDisplayName() { - return "Trigger parameterized build on other projects"; - } - - @Override - public boolean isApplicable(Class jobType) { - return true; - } - - } + public BuildTrigger(List configs) { + this.configs = new ArrayList<>(Util.fixNull(configs)); + } + + public BuildTrigger(BuildTriggerConfig... configs) { + this(Arrays.asList(configs)); + } + + public List getConfigs() { + return configs; + } + + @Override + public boolean needsToRunAfterFinalized() { + return true; + } + + @Override + public BuildStepMonitor getRequiredMonitorService() { + return BuildStepMonitor.NONE; + } + + @Override + public Collection getProjectActions(AbstractProject project) { + return Collections.singletonList(new DynamicProjectAction(configs)); + } + + @Override + @SuppressWarnings("deprecation") + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { + Map downstreamMap = new HashMap<>(); + Map buildMap = new HashMap<>(); + boolean hasEnvVariables = false; + + HashSet alreadyFired = new HashSet<>(); + + // If this project has non-abstract projects, we need to fire them + for (BuildTriggerConfig config : configs) { + boolean hasNonAbstractProject = false; + hasEnvVariables = hasEnvVariables || hasEnvVariables(config, build.getEnvironment(listener)); + + List jobs = + config.getJobs(build.getRootBuild().getProject().getParent(), build.getEnvironment(listener)); + + for (Job j : jobs) { + if (!(j instanceof AbstractProject)) { + hasNonAbstractProject = true; + break; + } + } + // Fire this config's projects if not already fired + if (hasNonAbstractProject) { + config.perform(build, launcher, listener); + alreadyFired.add(config); + } + } + + if (canDeclare(build.getProject()) && !hasEnvVariables) { + // job will get triggered by dependency graph, so we have to capture buildEnvironment NOW before + // hudson.model.AbstractBuild.AbstractBuildExecution#cleanUp is called and reset + EnvVars env = build.getEnvironment(listener); + build.addAction(new CapturedEnvironmentAction(env)); + } else { // Not using dependency graph + for (BuildTriggerConfig config : configs) { + if (!alreadyFired.contains(config)) { + // config.perform(build, launcher, listener); + List> futures = config.perform(build, launcher, listener); + for (QueueTaskFuture future : futures) { + AbstractBuild abstractBuild = null; + try { + abstractBuild = (AbstractBuild) future.get(); + if (null != abstractBuild) { + downstreamMap.put(abstractBuild.getProject().getFullName(), abstractBuild); + } + } catch (ExecutionException e) { + listener.getLogger().println("Failed to execute downstream build"); + } + } + + String[] projects = + config.getProjects(build.getEnvironment(listener)).split(","); + String[] vars = config.getProjects().split(","); + for (int i = 0; i < projects.length; i++) { + if (vars[i].trim().contains("$")) { + AbstractBuild abstractBuild = downstreamMap.get(projects[i]); + if (null != abstractBuild) { + listener.getLogger().println(makeLogEntry(projects[i].trim())); + buildMap.put(abstractBuild.getProject().getFullName(), abstractBuild.getNumber()); + } + } + } + } + DynamicBuildAction action = new DynamicBuildAction(buildMap); + build.addAction(action); + } + } + + return true; + } + + private String makeLogEntry(String name) { + String url = name; + url = Jenkins.get().getRootUrl() + "job/" + url.replaceAll("/", "/job/"); + name = name.replaceAll("/", " » "); + String link = ModelHyperlinkNote.encodeTo(url, name); + StringBuilder sb = new StringBuilder(); + sb.append("Triggering a new build of "); + sb.append(link); + return sb.toString(); + } + + private boolean hasEnvVariables(BuildTriggerConfig config, EnvVars env) { + return !config.getProjects().equalsIgnoreCase(config.getProjects(env)); + } + + @Override + public void buildDependencyGraph(AbstractProject owner, DependencyGraph graph) { + if (!canDeclare(owner)) return; + + for (BuildTriggerConfig config : configs) { + List projectList = config.getProjectList(owner.getParent(), null); + for (AbstractProject project : projectList) { + if (config.isTriggerFromChildProjects() && owner instanceof ItemGroup) { + ItemGroup parent = (ItemGroup) owner; + for (Item item : parent.getItems()) { + if (item instanceof AbstractProject) { + AbstractProject child = (AbstractProject) item; + ParameterizedDependency.add(child, project, config, graph); + } + } + } else { + ParameterizedDependency.add(owner, project, config, graph); + } + } + } + } + + private boolean canDeclare(AbstractProject owner) { + // See HUDSON-5679 -- dependency graph is also not used when triggered from a promotion + return !owner.getClass().getName().equals("hudson.plugins.promoted_builds.PromotionProcess"); + } + + @Extension + public static class DescriptorImpl extends BuildStepDescriptor { + @Override + public String getDisplayName() { + return "Trigger parameterized build on other projects"; + } + + @Override + public boolean isApplicable(Class jobType) { + return true; + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java index a81a192b..e261c296 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java @@ -2,17 +2,20 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; +import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.EnvVars; import hudson.Extension; import hudson.Launcher; +import hudson.Util; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Action; import hudson.model.AutoCompletionCandidates; import hudson.model.BuildListener; import hudson.model.Cause; -import hudson.model.CauseAction; import hudson.model.Cause.UpstreamCause; +import hudson.model.CauseAction; import hudson.model.Describable; import hudson.model.Descriptor; import hudson.model.Item; @@ -22,27 +25,12 @@ import hudson.model.ParametersAction; import hudson.model.Run; import hudson.model.TaskListener; -import hudson.model.queue.Tasks; import hudson.model.queue.QueueTaskFuture; +import hudson.model.queue.Tasks; import hudson.plugins.parameterizedtrigger.AbstractBuildParameters.DontTriggerException; import hudson.plugins.promoted_builds.Promotion; import hudson.security.ACL; -import hudson.Util; import hudson.util.FormValidation; -import hudson.util.VersionNumber; - -import jenkins.model.Jenkins; -import jenkins.model.ParameterizedJobMixIn; -import jenkins.security.QueueItemAuthenticatorConfiguration; -import org.acegisecurity.Authentication; -import org.apache.commons.lang.StringUtils; -import org.kohsuke.accmod.Restricted; -import org.kohsuke.accmod.restrictions.DoNotUse; -import org.kohsuke.stapler.AncestorInPath; -import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.QueryParameter; - -import edu.umd.cs.findbugs.annotations.CheckForNull; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -55,24 +43,38 @@ import java.util.StringTokenizer; import java.util.logging.Level; import java.util.logging.Logger; -import org.acegisecurity.AccessDeniedException; -import edu.umd.cs.findbugs.annotations.NonNull; +import jenkins.model.Jenkins; +import jenkins.model.ParameterizedJobMixIn; import jenkins.security.QueueItemAuthenticator; +import jenkins.security.QueueItemAuthenticatorConfiguration; +import org.acegisecurity.AccessDeniedException; +import org.acegisecurity.Authentication; +import org.apache.commons.lang.StringUtils; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.DoNotUse; +import org.kohsuke.stapler.AncestorInPath; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.QueryParameter; public class BuildTriggerConfig implements Describable { - + private static final Logger LOGGER = Logger.getLogger(BuildTriggerConfig.class.getName()); - private final List configs; + private final List configs; private final List configFactories; - private String projects; - private final ResultCondition condition; - private final boolean triggerWithNoParameters; - private final boolean triggerFromChildProjects; + private String projects; + private final ResultCondition condition; + private final boolean triggerWithNoParameters; + private final boolean triggerFromChildProjects; - public BuildTriggerConfig(String projects, ResultCondition condition, boolean triggerWithNoParameters, - List configFactories, List configs, boolean triggerFromChildProjects) { + public BuildTriggerConfig( + String projects, + ResultCondition condition, + boolean triggerWithNoParameters, + List configFactories, + List configs, + boolean triggerFromChildProjects) { this.projects = projects; this.condition = condition; this.triggerWithNoParameters = triggerWithNoParameters; @@ -82,58 +84,70 @@ public BuildTriggerConfig(String projects, ResultCondition condition, boolean tr } @Deprecated - public BuildTriggerConfig(String projects, ResultCondition condition, - boolean triggerWithNoParameters, List configFactories, List configs) { + public BuildTriggerConfig( + String projects, + ResultCondition condition, + boolean triggerWithNoParameters, + List configFactories, + List configs) { this(projects, condition, triggerWithNoParameters, configFactories, configs, false); } @DataBoundConstructor - public BuildTriggerConfig(String projects, ResultCondition condition, - boolean triggerWithNoParameters, List configs, boolean triggerFromChildProjects) { + public BuildTriggerConfig( + String projects, + ResultCondition condition, + boolean triggerWithNoParameters, + List configs, + boolean triggerFromChildProjects) { this(projects, condition, triggerWithNoParameters, null, configs, triggerFromChildProjects); } - - public BuildTriggerConfig(String projects, ResultCondition condition, - boolean triggerWithNoParameters, List configs) { + + public BuildTriggerConfig( + String projects, + ResultCondition condition, + boolean triggerWithNoParameters, + List configs) { this(projects, condition, triggerWithNoParameters, null, configs, false); } - public BuildTriggerConfig(String projects, ResultCondition condition, - AbstractBuildParameters... configs) { - this(projects, condition, false, null, Arrays.asList(configs), false); - } + public BuildTriggerConfig(String projects, ResultCondition condition, AbstractBuildParameters... configs) { + this(projects, condition, false, null, Arrays.asList(configs), false); + } - public BuildTriggerConfig(String projects, ResultCondition condition, + public BuildTriggerConfig( + String projects, + ResultCondition condition, List configFactories, - AbstractBuildParameters... configs) { - this(projects, condition, false, configFactories, Arrays.asList(configs), false); - } + AbstractBuildParameters... configs) { + this(projects, condition, false, configFactories, Arrays.asList(configs), false); + } - public List getConfigs() { - return configs; - } + public List getConfigs() { + return configs; + } public List getConfigFactories() { return configFactories; } public String getProjects() { - return projects; - } + return projects; + } public String getProjects(EnvVars env) { return (env != null ? env.expand(projects) : projects); } - public ResultCondition getCondition() { - return condition; - } + public ResultCondition getCondition() { + return condition; + } - public boolean getTriggerWithNoParameters() { + public boolean getTriggerWithNoParameters() { return triggerWithNoParameters; } - - public boolean isTriggerFromChildProjects(){ + + public boolean isTriggerFromChildProjects() { return triggerFromChildProjects; } @@ -155,9 +169,9 @@ public List getProjectList(EnvVars env) { * Use {@link #getJobs(ItemGroup, EnvVars)} */ @Deprecated - public List getProjectList(ItemGroup context, EnvVars env) { + public List getProjectList(ItemGroup context, EnvVars env) { return Util.filter(getJobs(context, env), AbstractProject.class); - } + } /** * Get list of all projects, including workflow job types @@ -232,7 +246,7 @@ private static void iterateBuilds(AbstractProject context, String projects, SubP if (currentBuild == null) { // But we can still get statically defined project subProjectData.getFixed().addAll(readableItemsFromNameList(context.getParent(), projects, Job.class)); - + // Remove them from unsolved for (Job staticProject : subProjectData.getFixed()) { subProjectData.getUnresolved().remove(staticProject.getFullName()); @@ -254,11 +268,11 @@ private static void iterateBuilds(AbstractProject context, String projects, SubP // If oldBuild is null then we have already examined LastSuccessfulBuild as well. if (currentBuild != null && context.getLastSuccessfulBuild() != null) { - resolveProject((AbstractBuild)context.getLastSuccessfulBuild(), subProjectData); + resolveProject((AbstractBuild) context.getLastSuccessfulBuild(), subProjectData); } } } - + /** * Retrieves readable items from the list. * @param Type of the item @@ -272,8 +286,8 @@ private static List readableItemsFromNameList( Jenkins hudson = Jenkins.get(); List r = new ArrayList<>(); - StringTokenizer tokens = new StringTokenizer(list,","); - while(tokens.hasMoreTokens()) { + StringTokenizer tokens = new StringTokenizer(list, ","); + while (tokens.hasMoreTokens()) { String fullName = tokens.nextToken().trim(); T item = null; try { @@ -285,8 +299,7 @@ private static List readableItemsFromNameList( throw x; } } - if(item!=null) - r.add(item); + if (item != null) r.add(item); } return r; } @@ -301,7 +314,8 @@ private static List readableItemsFromNameList( */ private static void resolveProject(AbstractBuild build, SubProjectData subProjectData) { - Iterator unsolvedProjectIterator = subProjectData.getUnresolved().iterator(); + Iterator unsolvedProjectIterator = + subProjectData.getUnresolved().iterator(); while (unsolvedProjectIterator.hasNext()) { @@ -324,7 +338,8 @@ private static void resolveProject(AbstractBuild build, SubProjectData subProjec if (build != null) { Job resolvedProject = null; try { - resolvedProject = Jenkins.get().getItem(unresolvedProjectName, build.getProject().getParent(), Job.class); + resolvedProject = Jenkins.get() + .getItem(unresolvedProjectName, build.getProject().getParent(), Job.class); } catch (RuntimeException x) { if (x.getClass().getSimpleName().startsWith("AccessDeniedException")) { // Permission check failure (DISCOVER w/o READ) => we leave the job unresolved @@ -340,56 +355,60 @@ private static void resolveProject(AbstractBuild build, SubProjectData subProjec } if (build != null && build.getAction(BuildInfoExporterAction.class) != null) { - String triggeredProjects = build.getAction(BuildInfoExporterAction.class).getProjectListString(","); - subProjectData.getTriggered().addAll(readableItemsFromNameList(build.getParent().getParent(), triggeredProjects, AbstractProject.class)); + String triggeredProjects = + build.getAction(BuildInfoExporterAction.class).getProjectListString(","); + subProjectData + .getTriggered() + .addAll(readableItemsFromNameList( + build.getParent().getParent(), triggeredProjects, AbstractProject.class)); } } - - List getBaseActions(AbstractBuild build, TaskListener listener) + List getBaseActions(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, DontTriggerException { return getBaseActions(configs, build, listener); } - List getBaseActions(Collection configs, AbstractBuild build, TaskListener listener) + List getBaseActions( + Collection configs, AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, DontTriggerException { - List actions = new ArrayList<>(); - ParametersAction params = null; - for (AbstractBuildParameters config : configs) { - Action a = config.getAction(build, listener); - if (a instanceof ParametersAction) { - params = params == null ? (ParametersAction)a - : ParameterizedTriggerUtils.mergeParameters(params, (ParametersAction)a); - } else if (a != null) { - actions.add(a); - } - } - if (params != null) actions.add(params); - return actions; - } - - List getBuildActions(List baseActions, Job project) { + List actions = new ArrayList<>(); + ParametersAction params = null; + for (AbstractBuildParameters config : configs) { + Action a = config.getAction(build, listener); + if (a instanceof ParametersAction) { + params = params == null + ? (ParametersAction) a + : ParameterizedTriggerUtils.mergeParameters(params, (ParametersAction) a); + } else if (a != null) { + actions.add(a); + } + } + if (params != null) actions.add(params); + return actions; + } + + List getBuildActions(List baseActions, Job project) { List actions = new ArrayList<>(baseActions); ProjectSpecificParametersActionFactory transformer = new ProjectSpecificParametersActionFactory( - new ProjectSpecificParameterValuesActionTransform(), - new DefaultParameterValuesActionsTransform() - ); + new ProjectSpecificParameterValuesActionTransform(), new DefaultParameterValuesActionsTransform()); return transformer.getProjectSpecificBuildActions(actions, project); } /** * Note that with Hudson 1.341, trigger should be using - * {@link BuildTrigger#buildDependencyGraph(AbstractProject, hudson.model.DependencyGraph)}. - */ - public List> perform(AbstractBuild build, Launcher launcher, - BuildListener listener) throws InterruptedException, IOException { + * {@link BuildTrigger#buildDependencyGraph(AbstractProject, hudson.model.DependencyGraph)}. + */ + public List> perform( + AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { EnvVars env = build.getEnvironment(listener); env.overrideAll(build.getBuildVariables()); try { - if (condition.isMet(build.getResult())) { + if (condition.isMet(build.getResult())) { QueueTaskFuture future = null; List> futures = new ArrayList<>(); @@ -397,11 +416,10 @@ public List> perform(AbstractBuild build, L List buildParams = new ArrayList<>(configs); buildParams.addAll(addConfigs); buildParams = Collections.unmodifiableList(buildParams); - List actions = getBaseActions(buildParams, - build, listener); + List actions = getBaseActions(buildParams, build, listener); for (Job project : getJobs(build.getRootBuild().getProject().getParent(), env)) { List list = getBuildActions(actions, project); - //Future can be null as schedule can return null + // Future can be null as schedule can return null future = schedule(build, project, list, listener); if (future != null) { futures.add(future); @@ -412,47 +430,57 @@ public List> perform(AbstractBuild build, L } return futures; - } - } catch (DontTriggerException e) { - // don't trigger on this configuration - } + } + } catch (DontTriggerException e) { + // don't trigger on this configuration + } return Collections.emptyList(); } - private void reportSchedulingError(@NonNull Run run, @NonNull Job jobToTrigger, @NonNull BuildListener listener) { + private void reportSchedulingError( + @NonNull Run run, @NonNull Job jobToTrigger, @NonNull BuildListener listener) { // Do not print details to Build Listener, they have been reported previously in #canTriggerProject() listener.error("Skipping " + jobToTrigger.getFullName() + "..."); if (LOGGER.isLoggable(Level.CONFIG)) { - String message = String.format("Cannot schedule project %s. Job type is not parameterized, " - + "or there is no Job/Build permission for the current authentication %s. " - + "Skipping...", jobToTrigger, Jenkins.getAuthentication().getName()); - LOGGER.log(Level.CONFIG, String.format("%s: %s", run, message), - new UnsupportedOperationException("Cannot schedule job " + jobToTrigger.getFullName())); + String message = String.format( + "Cannot schedule project %s. Job type is not parameterized, " + + "or there is no Job/Build permission for the current authentication %s. " + + "Skipping...", + jobToTrigger, Jenkins.getAuthentication().getName()); + LOGGER.log( + Level.CONFIG, + String.format("%s: %s", run, message), + new UnsupportedOperationException("Cannot schedule job " + jobToTrigger.getFullName())); } } - + /** - * @deprecated - * Use {@link #perform3(AbstractBuild, Launcher, BuildListener)} - */ + * @deprecated + * Use {@link #perform3(AbstractBuild, Launcher, BuildListener)} + */ @Deprecated - public ListMultimap> perform2(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + public ListMultimap> perform2( + AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { ListMultimap> initialResult = perform3(build, launcher, listener); ListMultimap> output = ArrayListMultimap.create(); for (Map.Entry> entry : initialResult.entries()) { if (entry.getKey() instanceof AbstractProject) { // Due to type erasure we can't check if the Future is a Future - // Plugins extending the method and dependent on the perform2 method will break if we trigger on a WorkflowJob - output.put((AbstractProject)entry.getKey(), (QueueTaskFuture)entry.getValue()); + // Plugins extending the method and dependent on the perform2 method will break if we trigger on a + // WorkflowJob + output.put((AbstractProject) entry.getKey(), (QueueTaskFuture) entry.getValue()); } } return output; } - //Replaces perform2 with more general form - public ListMultimap> perform3(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + // Replaces perform2 with more general form + public ListMultimap> perform3( + AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { EnvVars env = build.getEnvironment(listener); env.overrideAll(build.getBuildVariables()); @@ -461,7 +489,8 @@ public ListMultimap> perform3(AbstractBuild< ListMultimap> futures = ArrayListMultimap.create(); for (List addConfigs : getDynamicBuildParameters(build, listener)) { - List actions = getBaseActions(CollectionUtils.immutableList(configs, addConfigs), build, listener); + List actions = + getBaseActions(CollectionUtils.immutableList(configs, addConfigs), build, listener); for (Job project : getJobs(build.getRootBuild().getProject().getParent(), env)) { List list = getBuildActions(actions, project); @@ -486,7 +515,9 @@ public ListMultimap> perform3(AbstractBuild< * Inner list represents a set of build parameters used together for one invocation of a project, * and outer list represents multiple invocations of the same project. */ - private List> getDynamicBuildParameters(AbstractBuild build, BuildListener listener) throws DontTriggerException, IOException, InterruptedException { + private List> getDynamicBuildParameters( + AbstractBuild build, BuildListener listener) + throws DontTriggerException, IOException, InterruptedException { if (configFactories == null || configFactories.isEmpty()) { return Collections.singletonList(Collections.emptyList()); } else { @@ -496,8 +527,9 @@ private List> getDynamicBuildParameters(AbstractBu for (AbstractBuildParameterFactory configFactory : configFactories) { List> newDynParameters = new ArrayList(); List factoryParameters = configFactory.getParameters(build, listener); - // if factory returns 0 parameters we need to skip assigning newDynParameters to dynamicBuildParameters as we would add invalid list - if(factoryParameters.size() > 0) { + // if factory returns 0 parameters we need to skip assigning newDynParameters to dynamicBuildParameters + // as we would add invalid list + if (factoryParameters.size() > 0) { for (AbstractBuildParameters config : factoryParameters) { for (List dynamicBuildParameter : dynamicBuildParameters) { newDynParameters.add(CollectionUtils.immutableList(dynamicBuildParameter, config)); @@ -520,15 +552,15 @@ private List> getDynamicBuildParameters(AbstractBu * @return UpstreamCause */ protected Cause createUpstreamCause(Run build) { - if(Jenkins.getInstance().getPlugin("promoted-builds") != null) { + if (Jenkins.getInstance().getPlugin("promoted-builds") != null) { // Test only when promoted-builds is installed. - if(build instanceof Promotion) { - Promotion promotion = (Promotion)build; + if (build instanceof Promotion) { + Promotion promotion = (Promotion) build; // This cannot be done for PromotionCause#PromotionCause is in a package scope. // return new PromotionCause(build, promotion.getTarget()); - return new UpstreamCause((Run)promotion.getTargetBuild()); + return new UpstreamCause((Run) promotion.getTargetBuild()); } } return new UpstreamCause(build); @@ -539,14 +571,21 @@ protected Cause createUpstreamCause(Run build) { */ @CheckForNull @Deprecated - protected QueueTaskFuture schedule(AbstractBuild build, final Job project, int quietPeriod, List list) throws InterruptedException, IOException { + protected QueueTaskFuture schedule(AbstractBuild build, final Job project, int quietPeriod, List list) + throws InterruptedException, IOException { return schedule(build, project, quietPeriod, list, TaskListener.NULL); } - + @CheckForNull - protected QueueTaskFuture schedule(@NonNull AbstractBuild build, @NonNull final Job project, int quietPeriod, - @NonNull List list, @NonNull TaskListener listener) throws InterruptedException, IOException { - // TODO Once it's in core (since 1.621) and LTS is out, switch to use new ParameterizedJobMixIn convenience method + protected QueueTaskFuture schedule( + @NonNull AbstractBuild build, + @NonNull final Job project, + int quietPeriod, + @NonNull List list, + @NonNull TaskListener listener) + throws InterruptedException, IOException { + // TODO Once it's in core (since 1.621) and LTS is out, switch to use new ParameterizedJobMixIn convenience + // method // From https://github.com/jenkinsci/jenkins/pull/1771 Cause cause = createUpstreamCause(build); List queueActions = new ArrayList<>(list); @@ -560,21 +599,21 @@ protected QueueTaskFuture schedule(@NonNull AbstractBuild build, @NonNull return project; } }; - + // We check the user permissions. // QueueItemAuthenticator should provide the user if it is configured correctly. - //TODO: It would be also great to print it to the build log, but there is no TaskListener + // TODO: It would be also great to print it to the build log, but there is no TaskListener if (!canTriggerProject(build, project, listener)) { return null; } - + return parameterizedJobMixIn.scheduleBuild2(quietPeriod, queueActions.toArray(new Action[0])); } // Trigger is not compatible with un-parameterized jobs return null; } - + /** * Checks if the build can trigger a project. * @param build Build, which is about to trigger the project @@ -583,30 +622,33 @@ protected QueueTaskFuture schedule(@NonNull AbstractBuild build, @NonNull * @return {@code true} if the project can be scheduled. * {@code false} if there is a lack of permissions, details will be printed to the logs then. */ - /*package*/ static boolean canTriggerProject(@NonNull AbstractBuild build, - @NonNull final Job job, @NonNull TaskListener taskListener) { + /*package*/ static boolean canTriggerProject( + @NonNull AbstractBuild build, @NonNull final Job job, @NonNull TaskListener taskListener) { if (!job.hasPermission(Item.BUILD)) { - String message = String.format("Cannot schedule the build of %s from %s. " - + "The authenticated build user %s has no Job.BUILD permission", - job.getFullDisplayName(), build.getFullDisplayName(), Jenkins.getAuthentication().getName()); + String message = String.format( + "Cannot schedule the build of %s from %s. " + + "The authenticated build user %s has no Job.BUILD permission", + job.getFullDisplayName(), + build.getFullDisplayName(), + Jenkins.getAuthentication().getName()); LOGGER.log(Level.WARNING, message); taskListener.error(message); return false; } return true; } - + /** * Checks if the project is buildable. * The method also takes the security implications from {@link QueueItemAuthenticator} into account. * @param job Job to be checked - * @return true if the job can be scheduled from the + * @return true if the job can be scheduled from the */ protected boolean canBeScheduled(@NonNull Job job) { if (!job.isBuildable()) { return false; } - + return job.hasPermission(Item.BUILD); } @@ -614,14 +656,25 @@ protected boolean canBeScheduled(@NonNull Job job) { * @deprecated Use {@link #schedule(hudson.model.AbstractBuild, hudson.model.Job, int, java.util.List, hudson.model.TaskListener)} */ @Deprecated - protected QueueTaskFuture schedule(AbstractBuild build, Job project, List list) throws InterruptedException, IOException { + protected QueueTaskFuture schedule(AbstractBuild build, Job project, List list) + throws InterruptedException, IOException { return schedule(build, project, list, TaskListener.NULL); } - + @CheckForNull - protected QueueTaskFuture schedule(@NonNull AbstractBuild build, @NonNull Job project, @NonNull List list, @NonNull TaskListener listener) throws InterruptedException, IOException { + protected QueueTaskFuture schedule( + @NonNull AbstractBuild build, + @NonNull Job project, + @NonNull List list, + @NonNull TaskListener listener) + throws InterruptedException, IOException { if (project instanceof ParameterizedJobMixIn.ParameterizedJob) { - return schedule(build, project, ((ParameterizedJobMixIn.ParameterizedJob) project).getQuietPeriod(), list, listener); + return schedule( + build, + project, + ((ParameterizedJobMixIn.ParameterizedJob) project).getQuietPeriod(), + list, + listener); } else { return schedule(build, project, 0, list, listener); } @@ -640,16 +693,17 @@ protected QueueTaskFuture schedule(@NonNull AbstractBuild build, @NonNull * @param context * @return */ - private static String computeRelativeNamesAfterRenaming(String oldFullName, String newFullName, String relativeNames, ItemGroup context) { - StringTokenizer tokens = new StringTokenizer(relativeNames,","); + private static String computeRelativeNamesAfterRenaming( + String oldFullName, String newFullName, String relativeNames, ItemGroup context) { + StringTokenizer tokens = new StringTokenizer(relativeNames, ","); List newValue = new ArrayList<>(); - while(tokens.hasMoreTokens()) { + while (tokens.hasMoreTokens()) { String relativeName = tokens.nextToken().trim(); String canonicalName = Items.getCanonicalName(context, relativeName); if (canonicalName.equals(oldFullName) || canonicalName.startsWith(oldFullName + "/")) { String newCanonicalName = newFullName + canonicalName.substring(oldFullName.length()); // relative name points to the renamed item, let's compute the new relative name - newValue.add( computeRelativeNameAfterRenaming(canonicalName, newCanonicalName, relativeName) ); + newValue.add(computeRelativeNameAfterRenaming(canonicalName, newCanonicalName, relativeName)); } else { newValue.add(relativeName); } @@ -657,17 +711,18 @@ private static String computeRelativeNamesAfterRenaming(String oldFullName, Stri return StringUtils.join(newValue, ","); } - private static String computeRelativeNameAfterRenaming(String oldFullName, String newFullName, String relativeName) { + private static String computeRelativeNameAfterRenaming( + String oldFullName, String newFullName, String relativeName) { String[] a = oldFullName.split("/"); String[] n = newFullName.split("/"); assert a.length == n.length; String[] r = relativeName.split("/"); - int j = a.length-1; - for(int i=r.length-1;i>=0;i--) { + int j = a.length - 1; + for (int i = r.length - 1; i >= 0; i--) { String part = r[i]; - if (part.equals("") && i==0) { + if (part.equals("") && i == 0) { continue; } if (part.equals(".")) { @@ -688,14 +743,14 @@ private static String computeRelativeNameAfterRenaming(String oldFullName, Strin public boolean onJobRenamed(ItemGroup context, String oldName, String newName) { String newProjects = computeRelativeNamesAfterRenaming(oldName, newName, projects, context); - boolean changed = !projects.equals(newProjects); + boolean changed = !projects.equals(newProjects); projects = newProjects; - return changed; + return changed; } public boolean onDeleted(ItemGroup context, String oldName) { List newNames = new ArrayList<>(); - StringTokenizer tokens = new StringTokenizer(projects,","); + StringTokenizer tokens = new StringTokenizer(projects, ","); while (tokens.hasMoreTokens()) { String relativeName = tokens.nextToken().trim(); String fullName = Items.getCanonicalName(context, relativeName); @@ -712,10 +767,10 @@ public Descriptor getDescriptor() { } @Override - public String toString() { - return getClass().getName()+" [projects=" + projects + ", condition=" - + condition + ", configs=" + configs + "]"; - } + public String toString() { + return getClass().getName() + " [projects=" + projects + ", condition=" + condition + ", configs=" + configs + + "]"; + } @Extension public static class DescriptorImpl extends Descriptor { @@ -733,7 +788,7 @@ public List> getBuilderConfigFactoryDe } @Restricted(DoNotUse.class) - public boolean isItemGroup(AbstractProject project){ + public boolean isItemGroup(AbstractProject project) { return project instanceof ItemGroup; } @@ -742,34 +797,37 @@ public boolean isItemGroup(AbstractProject project){ * * Copied from hudson.tasks.BuildTrigger.doCheck(Item project, String value) */ - public FormValidation doCheckProjects(@AncestorInPath Job project, @QueryParameter String value ) { + public FormValidation doCheckProjects(@AncestorInPath Job project, @QueryParameter String value) { // JENKINS-32527: Check that it behaves gracefully for an unknown context if (project == null) return FormValidation.ok("Context Unknown: the value specified cannot be validated"); // Require CONFIGURE permission on this project - if(!project.hasPermission(Item.CONFIGURE)){ - return FormValidation.ok(); + if (!project.hasPermission(Item.CONFIGURE)) { + return FormValidation.ok(); } - StringTokenizer tokens = new StringTokenizer(Util.fixNull(value),","); + StringTokenizer tokens = new StringTokenizer(Util.fixNull(value), ","); boolean hasProjects = false; - while(tokens.hasMoreTokens()) { + while (tokens.hasMoreTokens()) { String projectName = tokens.nextToken().trim(); if (StringUtils.isBlank(projectName)) { return FormValidation.error("Blank project name in the list"); } - Item item = Jenkins.get().getItem(projectName,project,Item.class); // only works after version 1.410 - if(item==null){ + Item item = Jenkins.get().getItem(projectName, project, Item.class); // only works after version 1.410 + if (item == null) { Item nearest = Items.findNearest(Job.class, projectName, Jenkins.get()); String alternative = nearest != null ? nearest.getRelativeNameFrom(project) : "?"; return FormValidation.error(Messages.BuildTrigger_NoSuchProject(projectName, alternative)); } - if(!(item instanceof Job) || !(item instanceof ParameterizedJobMixIn.ParameterizedJob)) { + if (!(item instanceof Job) || !(item instanceof ParameterizedJobMixIn.ParameterizedJob)) { return FormValidation.error(Messages.BuildTrigger_NotBuildable(projectName)); } // check whether the supposed user is expected to be able to build - Authentication auth = Tasks.getAuthenticationOf((ParameterizedJobMixIn.ParameterizedJob)project); - if (auth.equals(ACL.SYSTEM) && !QueueItemAuthenticatorConfiguration.get().getAuthenticators().isEmpty()) { + Authentication auth = Tasks.getAuthenticationOf((ParameterizedJobMixIn.ParameterizedJob) project); + if (auth.equals(ACL.SYSTEM) + && !QueueItemAuthenticatorConfiguration.get() + .getAuthenticators() + .isEmpty()) { auth = Jenkins.ANONYMOUS; } if (!item.getACL().hasPermission(auth, Item.BUILD)) { @@ -779,7 +837,7 @@ public FormValidation doCheckProjects(@AncestorInPath Job project, @QueryPa hasProjects = true; } if (!hasProjects) { - return FormValidation.error(Messages.BuildTrigger_NoProjectSpecified()); + return FormValidation.error(Messages.BuildTrigger_NoProjectSpecified()); } return FormValidation.ok(); @@ -793,10 +851,11 @@ public FormValidation doCheckProjects(@AncestorInPath Job project, @QueryPa * @param value * @return */ - public AutoCompletionCandidates doAutoCompleteProjects(@QueryParameter String value, @AncestorInPath ItemGroup context) { + public AutoCompletionCandidates doAutoCompleteProjects( + @QueryParameter String value, @AncestorInPath ItemGroup context) { AutoCompletionCandidates candidates = new AutoCompletionCandidates(); List jobs = Jenkins.get().getAllItems(Job.class); - for (Job job: jobs) { + for (Job job : jobs) { String relativeName = job.getRelativeNameFrom(context); if (relativeName.startsWith(value)) { if (job.hasPermission(Item.READ)) { @@ -806,6 +865,5 @@ public AutoCompletionCandidates doAutoCompleteProjects(@QueryParameter String va } return candidates; } - } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/CapturedEnvironmentAction.java b/src/main/java/hudson/plugins/parameterizedtrigger/CapturedEnvironmentAction.java index 26589090..cf0a694c 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/CapturedEnvironmentAction.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/CapturedEnvironmentAction.java @@ -4,16 +4,16 @@ import hudson.diagnosis.OldDataMonitor; import hudson.model.InvisibleAction; import hudson.model.Run; -import jenkins.model.RunAction2; - import java.util.Collections; +import jenkins.model.RunAction2; /** * @author Nicolas De Loof */ public class CapturedEnvironmentAction extends InvisibleAction implements RunAction2 { - static final String OLD_DATA_MESSAGE = "The build.xml contains captured environment variables at the time of building which could contain sensitive data."; + static final String OLD_DATA_MESSAGE = + "The build.xml contains captured environment variables at the time of building which could contain sensitive data."; private transient volatile EnvVars env; public CapturedEnvironmentAction(EnvVars env) { @@ -26,7 +26,7 @@ public EnvVars getCapturedEnvironment() { @Override public void onAttached(final Run r) { - //noop + // noop } @Override @@ -34,7 +34,8 @@ public void onLoad(final Run r) { if (env != null) { OldDataMonitor.report(r, Collections.singletonList(new AssertionError(OLD_DATA_MESSAGE))); } - //If it is not null then we loaded old data that needs to be cleaned, if it is null then it needs to be something. + // If it is not null then we loaded old data that needs to be cleaned, if it is null then it needs to be + // something. env = new EnvVars(); } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/CounterBuildParameterFactory.java b/src/main/java/hudson/plugins/parameterizedtrigger/CounterBuildParameterFactory.java index b7f18125..a3acdc73 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/CounterBuildParameterFactory.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/CounterBuildParameterFactory.java @@ -7,14 +7,13 @@ import hudson.model.TaskListener; import hudson.util.FormValidation; import hudson.util.VariableResolver; -import org.apache.commons.lang.StringUtils; -import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.QueryParameter; - import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.apache.commons.lang.StringUtils; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.QueryParameter; /** * A BuildParameterFactory generating Predefined Parameters for a counter @@ -30,24 +29,27 @@ public class CounterBuildParameterFactory extends AbstractBuildParameterFactory private final SteppingValidationEnum validationFail; public enum SteppingValidationEnum { - FAIL("Fail the build step"), // previous behaviour (default) - SKIP("Don't trigger these projects"){ + FAIL("Fail the build step"), // previous behaviour (default) + SKIP("Don't trigger these projects") { @Override public void failCheck(TaskListener listener) throws AbstractBuildParameters.DontTriggerException { listener.getLogger().println(Messages.CounterBuildParameterFactory_CountingWillNotTerminateSkipping()); throw new AbstractBuildParameters.DontTriggerException(); - }}, - NOPARMS("Skip these parameters"){ + } + }, + NOPARMS("Skip these parameters") { @Override public void failCheck(TaskListener listener) throws AbstractBuildParameters.DontTriggerException { listener.getLogger().println(Messages.CounterBuildParameterFactory_CountingWillNotTerminateIgnore()); - }}; + } + }; private final String description; public String getDescription() { return description; } + SteppingValidationEnum(String description) { this.description = description; } @@ -60,7 +62,9 @@ public void failCheck(TaskListener listener) throws AbstractBuildParameters.Dont public CounterBuildParameterFactory(long from, long to, long step, String paramExpr) { this(Long.toString(from), Long.toString(to), Long.toString(step), paramExpr); } - public CounterBuildParameterFactory(long from, long to, long step, String paramExpr, SteppingValidationEnum validationFail) { + + public CounterBuildParameterFactory( + long from, long to, long step, String paramExpr, SteppingValidationEnum validationFail) { this(Long.toString(from), Long.toString(to), Long.toString(step), paramExpr, validationFail); } @@ -70,7 +74,8 @@ public CounterBuildParameterFactory(String from, String to, String step, String } @DataBoundConstructor - public CounterBuildParameterFactory(String from, String to, String step, String paramExpr, SteppingValidationEnum validationFail) { + public CounterBuildParameterFactory( + String from, String to, String step, String paramExpr, SteppingValidationEnum validationFail) { this.from = from; this.to = to; this.step = step; @@ -78,9 +83,9 @@ public CounterBuildParameterFactory(String from, String to, String step, String this.validationFail = validationFail; } - @Override - public List getParameters(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { + public List getParameters(AbstractBuild build, TaskListener listener) + throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { EnvVars envVars = build.getEnvironment(listener); long fromNum = Long.parseLong(envVars.expand(from)); @@ -118,11 +123,14 @@ public String getDisplayName() { return Messages.CounterBuildParameterFactory_CounterBuildParameterFactory(); } - public FormValidation doCheckFrom(@QueryParameter String value) { return validateNumberField(value); + public FormValidation doCheckFrom(@QueryParameter String value) { + return validateNumberField(value); } + public FormValidation doCheckTo(@QueryParameter String value) { return validateNumberField(value); } + public FormValidation doCheckStep(@QueryParameter String value) { return validateNumberField(value); } @@ -175,5 +183,4 @@ public String resolve(String name) { return ""; } }; - } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/CurrentBuildParameters.java b/src/main/java/hudson/plugins/parameterizedtrigger/CurrentBuildParameters.java index a8d61f9e..80852ea3 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/CurrentBuildParameters.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/CurrentBuildParameters.java @@ -8,45 +8,38 @@ import hudson.model.ParameterValue; import hudson.model.ParametersAction; import hudson.model.TaskListener; - import java.io.IOException; import java.util.ArrayList; import java.util.List; - import org.kohsuke.stapler.DataBoundConstructor; public class CurrentBuildParameters extends AbstractBuildParameters { - @DataBoundConstructor - public CurrentBuildParameters() { - } - - @Override - public Action getAction(AbstractBuild build, TaskListener listener) - throws IOException { - - ParametersAction action = build.getAction(ParametersAction.class); - if (action == null) { - listener.getLogger().println(Plugin.LOG_TAG + " Current build has no parameters."); - return null; - } else { - List values = new ArrayList<>(action.getParameters().size()); - for (ParameterValue value : action.getParameters()) - // FileParameterValue is currently not reusable, so omit these: - if (!(value instanceof FileParameterValue)) - values.add(value); - return new ParametersAction(values); - } - } - - @Extension - public static class DescriptorImpl extends Descriptor { - - @Override - public String getDisplayName() { - return "Current build parameters"; - } - - } - + @DataBoundConstructor + public CurrentBuildParameters() {} + + @Override + public Action getAction(AbstractBuild build, TaskListener listener) throws IOException { + + ParametersAction action = build.getAction(ParametersAction.class); + if (action == null) { + listener.getLogger().println(Plugin.LOG_TAG + " Current build has no parameters."); + return null; + } else { + List values = new ArrayList<>(action.getParameters().size()); + for (ParameterValue value : action.getParameters()) + // FileParameterValue is currently not reusable, so omit these: + if (!(value instanceof FileParameterValue)) values.add(value); + return new ParametersAction(values); + } + } + + @Extension + public static class DescriptorImpl extends Descriptor { + + @Override + public String getDisplayName() { + return "Current build parameters"; + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/DefaultParameterValuesActionsTransform.java b/src/main/java/hudson/plugins/parameterizedtrigger/DefaultParameterValuesActionsTransform.java index a1e29075..764a9083 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/DefaultParameterValuesActionsTransform.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/DefaultParameterValuesActionsTransform.java @@ -1,9 +1,8 @@ package hudson.plugins.parameterizedtrigger; import hudson.model.*; - -import java.util.List; import java.util.ArrayList; +import java.util.List; /** * Ensure the given project's parameters with default values exist in the parameter list. @@ -11,11 +10,11 @@ * If they do not, append them with the specified default value. */ public class DefaultParameterValuesActionsTransform implements ITransformProjectParametersAction { - public ParametersAction transformParametersAction(ParametersAction a, Job project) { + public ParametersAction transformParametersAction(ParametersAction a, Job project) { return ParameterizedTriggerUtils.mergeParameters(getDefaultParameters(project), a); } - private static ParametersAction getDefaultParameters(Job project) { + private static ParametersAction getDefaultParameters(Job project) { ParametersDefinitionProperty property = project.getProperty(ParametersDefinitionProperty.class); diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/DifferentiatingAction.java b/src/main/java/hudson/plugins/parameterizedtrigger/DifferentiatingAction.java index c53bdf08..7dbcdb74 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/DifferentiatingAction.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/DifferentiatingAction.java @@ -3,7 +3,6 @@ import hudson.model.Action; import hudson.model.InvisibleAction; import hudson.model.Queue; - import java.util.List; /** diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/DynamicBuildAction.java b/src/main/java/hudson/plugins/parameterizedtrigger/DynamicBuildAction.java index b9c3992c..30909a19 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/DynamicBuildAction.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/DynamicBuildAction.java @@ -4,12 +4,11 @@ import hudson.model.AbstractProject; import hudson.model.Job; import hudson.model.Run; -import jenkins.model.Jenkins; -import jenkins.model.RunAction2; - import java.util.ArrayList; import java.util.List; import java.util.Map; +import jenkins.model.Jenkins; +import jenkins.model.RunAction2; /** * Shows a list of a dynamic downstream builds @@ -23,14 +22,10 @@ public DynamicBuildAction(Map buildsMap) { } @Override - public void onAttached(Run run) { - - } + public void onAttached(Run run) {} @Override - public void onLoad(Run run) { - - } + public void onLoad(Run run) {} public List> getBuilds() { List> builds = new ArrayList<>(); @@ -49,7 +44,6 @@ public void onLoad(Run run) { return builds; } - @Override public String getIconFileName() { return null; diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/DynamicProjectAction.java b/src/main/java/hudson/plugins/parameterizedtrigger/DynamicProjectAction.java index e3696498..077fe87a 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/DynamicProjectAction.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/DynamicProjectAction.java @@ -1,7 +1,6 @@ package hudson.plugins.parameterizedtrigger; import hudson.model.Action; - import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildParameterFactory.java b/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildParameterFactory.java index 69f43679..1212ff0b 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildParameterFactory.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildParameterFactory.java @@ -11,10 +11,6 @@ import hudson.model.AbstractBuild; import hudson.model.TaskListener; import hudson.util.FormValidation; -import org.apache.commons.lang.StringUtils; -import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.QueryParameter; - import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; @@ -23,7 +19,9 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; - +import org.apache.commons.lang.StringUtils; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.QueryParameter; /** * For each matching property file, invoke a build. @@ -38,23 +36,26 @@ public class FileBuildParameterFactory extends AbstractBuildParameterFactory { * */ public enum NoFilesFoundEnum { - SKIP("Don't trigger these projects"){ // previous behaviour (default) + SKIP("Don't trigger these projects") { // previous behaviour (default) @Override public void failCheck(TaskListener listener) throws AbstractBuildParameters.DontTriggerException { listener.getLogger().println(Messages.FileBuildParameterFactory_NoFilesFoundSkipping()); throw new AbstractBuildParameters.DontTriggerException(); - }}, - NOPARMS("Skip these parameters"){ + } + }, + NOPARMS("Skip these parameters") { @Override public void failCheck(TaskListener listener) throws AbstractBuildParameters.DontTriggerException { listener.getLogger().println(Messages.FileBuildParameterFactory_NoFilesFoundIgnore()); - }}, - FAIL("Fail the build step"){ + } + }, + FAIL("Fail the build step") { @Override public void failCheck(TaskListener listener) throws AbstractBuildParameters.DontTriggerException { listener.getLogger().println(Messages.FileBuildParameterFactory_NoFilesFoundTerminate()); throw new RuntimeException(); - }}; + } + }; private final String description; @@ -101,7 +102,8 @@ public NoFilesFoundEnum getNoFilesFoundAction() { } @Override - public List getParameters(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { + public List getParameters(AbstractBuild build, TaskListener listener) + throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { EnvVars env = build.getEnvironment(listener); @@ -110,12 +112,13 @@ public List getParameters(AbstractBuild build, Ta try { FilePath workspace = getWorkspace(build); FilePath[] files = workspace.list(env.expand(getFilePattern())); - if(files.length == 0) { + if (files.length == 0) { noFilesFoundAction.failCheck(listener); } else { - for(FilePath f: files) { + for (FilePath f : files) { String parametersStr = ParameterizedTriggerUtils.readFileToString(f, getEncoding()); - Logger.getLogger(FileBuildParameterFactory.class.getName()).log(Level.INFO, null, "Triggering build with " + f.getName()); + Logger.getLogger(FileBuildParameterFactory.class.getName()) + .log(Level.INFO, null, "Triggering build with " + f.getName()); result.add(new PredefinedBuildParameters(parametersStr)); } } @@ -140,14 +143,14 @@ public static class DescriptorImpl extends AbstractBuildParameterFactoryDescript public String getDisplayName() { return Messages.FileBuildParameterFactory_FileBuildParameterFactory(); } - + public FormValidation doCheckEncoding(@QueryParameter String encoding) { if (!StringUtils.isBlank(encoding)) { try { Charset.forName(encoding.trim()); - } catch(UnsupportedCharsetException e) { + } catch (UnsupportedCharsetException e) { return FormValidation.error("Unsupported Encoding"); - } catch(IllegalCharsetNameException e) { + } catch (IllegalCharsetNameException e) { return FormValidation.error("Bad Encoding Name"); } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildParameters.java b/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildParameters.java index 13fb9e38..9a796548 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildParameters.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildParameters.java @@ -18,11 +18,6 @@ import hudson.model.TaskListener; import hudson.model.TextParameterValue; import hudson.util.FormValidation; - -import org.apache.commons.lang.StringUtils; -import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.QueryParameter; - import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; @@ -36,212 +31,234 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jenkins.util.VirtualFile; +import org.apache.commons.lang.StringUtils; +import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.QueryParameter; public class FileBuildParameters extends AbstractBuildParameters { - private final String propertiesFile; - private final String encoding; - private final boolean failTriggerOnMissing; - private final boolean textParamValueOnNewLine; - - /*properties used for a matrix project*/ - private final boolean useMatrixChild; - private final String combinationFilter; - private final boolean onlyExactRuns; - - @DataBoundConstructor - public FileBuildParameters(String propertiesFile, String encoding, boolean failTriggerOnMissing, boolean useMatrixChild, String combinationFilter, boolean onlyExactRuns, boolean textParamValueOnNewLine) { - this.propertiesFile = propertiesFile; - this.encoding = Util.fixEmptyAndTrim(encoding); - this.failTriggerOnMissing = failTriggerOnMissing; - this.useMatrixChild = useMatrixChild; - if (this.useMatrixChild) { - this.combinationFilter = combinationFilter; - this.onlyExactRuns = onlyExactRuns; - } else { - this.combinationFilter = null; - this.onlyExactRuns = false; - } - this.textParamValueOnNewLine = textParamValueOnNewLine; - } - - public FileBuildParameters(String propertiesFile, String encoding, boolean failTriggerOnMissing, boolean useMatrixChild, String combinationFilter, boolean onlyExactRuns) { - this(propertiesFile, encoding, failTriggerOnMissing, useMatrixChild, combinationFilter, onlyExactRuns, false); - } - - public FileBuildParameters(String propertiesFile, String encoding, boolean failTriggerOnMissing) { - this(propertiesFile, encoding, failTriggerOnMissing, false, null, false); - } - - public FileBuildParameters(String propertiesFile, boolean failTriggerOnMissing) { - this(propertiesFile, null, failTriggerOnMissing); - } - - public FileBuildParameters(String propertiesFile) { - this(propertiesFile, false); - } - - /** - * This function returns the Action that should be passed to the triggered build - * to not trigger the build it can throw the {@link DontTriggerException} - * - * @return Action to be passed to the triggered build, can be Null if no parameters. - */ - public Action getAction(AbstractBuild build, TaskListener listener) - throws IOException, InterruptedException, DontTriggerException{ - - EnvVars env = getEnvironment(build, listener); - - String resolvedPropertiesFile = env.expand(propertiesFile); - - String[] allFiles = Util.tokenize(resolvedPropertiesFile, ","); - String[] trimmedFiles = new String[allFiles.length]; - for (int i = 0; i < allFiles.length; i++) - trimmedFiles[i] = allFiles[i].trim(); - - List values = new ArrayList<>(); - - // builds to scan. - Collection> targetBuilds = getTargetBuilds(build); - - for (AbstractBuild targetBuild: targetBuilds) { - values.addAll(extractAllValues(targetBuild, listener, trimmedFiles)); - } - //Values might be empty, in that case don't return anything. - return values.size() == 0 ? null :new ParametersAction(values); - } - - private List extractAllValues(AbstractBuild build, TaskListener listener, String[] allFiles) throws IOException, InterruptedException, DontTriggerException { - List values = new ArrayList<>(); - EnvVars env = getEnvironment(build, listener); - for(String file:allFiles) { - String s = null; - VirtualFile artifact = build.getArtifactManager().root().child(file); - if (artifact.isFile()) { - s = ParameterizedTriggerUtils.readFileToString(artifact); - } - - if (s == null) { - FilePath workspace = build.getWorkspace(); - if (workspace == null) { - listener.getLogger().printf(Plugin.LOG_TAG + " Could not load workspace of build %s%n", build.getFullDisplayName()); - } else { - FilePath f = workspace.child(file); - if (f.exists()) { - s = ParameterizedTriggerUtils.readFileToString(f, getEncoding()); - } - } - } - - if (s == null) { - listener.getLogger().println(Plugin.LOG_TAG + " Properties file " - + file + " did not exist."); - if (getFailTriggerOnMissing()) { - listener.getLogger().println("Not triggering due to missing file - did you archive it as a build artifact ?"); - throw new DontTriggerException(); - } - // goto next file. - continue; - } - - s = env.expand(s); - Properties p = ParameterizedTriggerUtils.loadProperties(s); - - for (Map.Entry entry : p.entrySet()) { - // support multi-line parameters correctly - s = entry.getValue().toString(); - if(textParamValueOnNewLine && s.contains("\n")) { - values.add(new TextParameterValue(entry.getKey().toString(), s)); - } else { - values.add(new StringParameterValue(entry.getKey().toString(), s)); - } - } - } - return values; - } - - private Collection> getTargetBuilds(AbstractBuild build) { - if ((build instanceof MatrixBuild) && isUseMatrixChild()) { - Stream buildsStream = isOnlyExactRuns() ? ((MatrixBuild) build).getExactRuns().stream() : ((MatrixBuild) build).getRuns().stream(); - return buildsStream.filter(run -> { - if (run == null) { - return false; - } - if (StringUtils.isBlank(getCombinationFilter())) { - // no combination filter stands for all children. - return true; - } - Combination c = run.getParent().getCombination(); - AxisList axes = run.getParent().getParent().getAxes(); - - return c.evalGroovyExpression(axes, getCombinationFilter()); - }).collect(Collectors.toList()); - - } else { - return Arrays.>asList(build); - } - } - - public String getPropertiesFile() { - return propertiesFile; - } - - public String getEncoding() { - return encoding; - } - - public boolean getFailTriggerOnMissing() { - return failTriggerOnMissing; - } - - public boolean getTextParamValueOnNewLine() { - return textParamValueOnNewLine; - } - - public boolean isUseMatrixChild() { - return useMatrixChild; - } - - public String getCombinationFilter() { - return combinationFilter; - } - - public boolean isOnlyExactRuns() { - return onlyExactRuns; - } - - @Extension - public static class DescriptorImpl extends Descriptor { - @Override - public String getDisplayName() { - return "Parameters from properties file"; - } - - public FormValidation doCheckEncoding(@QueryParameter String encoding) { - if (!StringUtils.isBlank(encoding)) { - try { - Charset.forName(encoding.trim()); - } catch(UnsupportedCharsetException e) { - return FormValidation.error("Unsupported Encoding"); - } catch(IllegalCharsetNameException e) { - return FormValidation.error("Bad Encoding Name"); - } - } - return FormValidation.ok(); - } - - /** - * Check whether the configuring model is {@link MatrixProject}. Called from jelly. - * - * Note: Caller should pass it for the model is not bound to - * {@link org.kohsuke.stapler.StaplerRequest#findAncestorObject(Class)} - * when called via hetero-list. - * - * @param it Object to check - * @return true if the target model is {@link MatrixProject} - */ - public boolean isMatrixProject(Object it) { - return (it != null) && (it instanceof MatrixProject); - } - } + private final String propertiesFile; + private final String encoding; + private final boolean failTriggerOnMissing; + private final boolean textParamValueOnNewLine; + + /*properties used for a matrix project*/ + private final boolean useMatrixChild; + private final String combinationFilter; + private final boolean onlyExactRuns; + + @DataBoundConstructor + public FileBuildParameters( + String propertiesFile, + String encoding, + boolean failTriggerOnMissing, + boolean useMatrixChild, + String combinationFilter, + boolean onlyExactRuns, + boolean textParamValueOnNewLine) { + this.propertiesFile = propertiesFile; + this.encoding = Util.fixEmptyAndTrim(encoding); + this.failTriggerOnMissing = failTriggerOnMissing; + this.useMatrixChild = useMatrixChild; + if (this.useMatrixChild) { + this.combinationFilter = combinationFilter; + this.onlyExactRuns = onlyExactRuns; + } else { + this.combinationFilter = null; + this.onlyExactRuns = false; + } + this.textParamValueOnNewLine = textParamValueOnNewLine; + } + + public FileBuildParameters( + String propertiesFile, + String encoding, + boolean failTriggerOnMissing, + boolean useMatrixChild, + String combinationFilter, + boolean onlyExactRuns) { + this(propertiesFile, encoding, failTriggerOnMissing, useMatrixChild, combinationFilter, onlyExactRuns, false); + } + + public FileBuildParameters(String propertiesFile, String encoding, boolean failTriggerOnMissing) { + this(propertiesFile, encoding, failTriggerOnMissing, false, null, false); + } + + public FileBuildParameters(String propertiesFile, boolean failTriggerOnMissing) { + this(propertiesFile, null, failTriggerOnMissing); + } + + public FileBuildParameters(String propertiesFile) { + this(propertiesFile, false); + } + + /** + * This function returns the Action that should be passed to the triggered build + * to not trigger the build it can throw the {@link DontTriggerException} + * + * @return Action to be passed to the triggered build, can be Null if no parameters. + */ + public Action getAction(AbstractBuild build, TaskListener listener) + throws IOException, InterruptedException, DontTriggerException { + + EnvVars env = getEnvironment(build, listener); + + String resolvedPropertiesFile = env.expand(propertiesFile); + + String[] allFiles = Util.tokenize(resolvedPropertiesFile, ","); + String[] trimmedFiles = new String[allFiles.length]; + for (int i = 0; i < allFiles.length; i++) trimmedFiles[i] = allFiles[i].trim(); + + List values = new ArrayList<>(); + + // builds to scan. + Collection> targetBuilds = getTargetBuilds(build); + + for (AbstractBuild targetBuild : targetBuilds) { + values.addAll(extractAllValues(targetBuild, listener, trimmedFiles)); + } + // Values might be empty, in that case don't return anything. + return values.size() == 0 ? null : new ParametersAction(values); + } + + private List extractAllValues(AbstractBuild build, TaskListener listener, String[] allFiles) + throws IOException, InterruptedException, DontTriggerException { + List values = new ArrayList<>(); + EnvVars env = getEnvironment(build, listener); + for (String file : allFiles) { + String s = null; + VirtualFile artifact = build.getArtifactManager().root().child(file); + if (artifact.isFile()) { + s = ParameterizedTriggerUtils.readFileToString(artifact); + } + + if (s == null) { + FilePath workspace = build.getWorkspace(); + if (workspace == null) { + listener.getLogger() + .printf( + Plugin.LOG_TAG + " Could not load workspace of build %s%n", + build.getFullDisplayName()); + } else { + FilePath f = workspace.child(file); + if (f.exists()) { + s = ParameterizedTriggerUtils.readFileToString(f, getEncoding()); + } + } + } + + if (s == null) { + listener.getLogger().println(Plugin.LOG_TAG + " Properties file " + file + " did not exist."); + if (getFailTriggerOnMissing()) { + listener.getLogger() + .println("Not triggering due to missing file - did you archive it as a build artifact ?"); + throw new DontTriggerException(); + } + // goto next file. + continue; + } + + s = env.expand(s); + Properties p = ParameterizedTriggerUtils.loadProperties(s); + + for (Map.Entry entry : p.entrySet()) { + // support multi-line parameters correctly + s = entry.getValue().toString(); + if (textParamValueOnNewLine && s.contains("\n")) { + values.add(new TextParameterValue(entry.getKey().toString(), s)); + } else { + values.add(new StringParameterValue(entry.getKey().toString(), s)); + } + } + } + return values; + } + + private Collection> getTargetBuilds(AbstractBuild build) { + if ((build instanceof MatrixBuild) && isUseMatrixChild()) { + Stream buildsStream = isOnlyExactRuns() + ? ((MatrixBuild) build).getExactRuns().stream() + : ((MatrixBuild) build).getRuns().stream(); + return buildsStream + .filter(run -> { + if (run == null) { + return false; + } + if (StringUtils.isBlank(getCombinationFilter())) { + // no combination filter stands for all children. + return true; + } + Combination c = run.getParent().getCombination(); + AxisList axes = run.getParent().getParent().getAxes(); + + return c.evalGroovyExpression(axes, getCombinationFilter()); + }) + .collect(Collectors.toList()); + + } else { + return Arrays.>asList(build); + } + } + + public String getPropertiesFile() { + return propertiesFile; + } + + public String getEncoding() { + return encoding; + } + + public boolean getFailTriggerOnMissing() { + return failTriggerOnMissing; + } + + public boolean getTextParamValueOnNewLine() { + return textParamValueOnNewLine; + } + + public boolean isUseMatrixChild() { + return useMatrixChild; + } + + public String getCombinationFilter() { + return combinationFilter; + } + + public boolean isOnlyExactRuns() { + return onlyExactRuns; + } + + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "Parameters from properties file"; + } + + public FormValidation doCheckEncoding(@QueryParameter String encoding) { + if (!StringUtils.isBlank(encoding)) { + try { + Charset.forName(encoding.trim()); + } catch (UnsupportedCharsetException e) { + return FormValidation.error("Unsupported Encoding"); + } catch (IllegalCharsetNameException e) { + return FormValidation.error("Bad Encoding Name"); + } + } + return FormValidation.ok(); + } + /** + * Check whether the configuring model is {@link MatrixProject}. Called from jelly. + * + * Note: Caller should pass it for the model is not bound to + * {@link org.kohsuke.stapler.StaplerRequest#findAncestorObject(Class)} + * when called via hetero-list. + * + * @param it Object to check + * @return true if the target model is {@link MatrixProject} + */ + public boolean isMatrixProject(Object it) { + return (it != null) && (it instanceof MatrixProject); + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildTriggerConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildTriggerConfig.java index aca8eb29..89a86c54 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildTriggerConfig.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/FileBuildTriggerConfig.java @@ -9,25 +9,24 @@ @Deprecated public class FileBuildTriggerConfig extends BuildTriggerConfig { - public FileBuildTriggerConfig(String projects, - ResultCondition condition, AbstractBuildParameters[] configs) { - super(projects, condition, configs); - } - - private String projectsValue; + public FileBuildTriggerConfig(String projects, ResultCondition condition, AbstractBuildParameters[] configs) { + super(projects, condition, configs); + } + + private String projectsValue; private String propertiesFile; private ResultCondition condition; private boolean triggerWithNoParameters; private boolean includeCurrentParameters; - + public Object readResolve() { - List configs = new ArrayList<>(); - if (includeCurrentParameters) { - configs.add(new CurrentBuildParameters()); - } - if (propertiesFile != null) { - configs.add(new FileBuildParameters(propertiesFile)); - } - return new BuildTriggerConfig(projectsValue, condition, triggerWithNoParameters, configs); + List configs = new ArrayList<>(); + if (includeCurrentParameters) { + configs.add(new CurrentBuildParameters()); + } + if (propertiesFile != null) { + configs.add(new FileBuildParameters(propertiesFile)); + } + return new BuildTriggerConfig(projectsValue, condition, triggerWithNoParameters, configs); } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/ITransformProjectParametersAction.java b/src/main/java/hudson/plugins/parameterizedtrigger/ITransformProjectParametersAction.java index 423935e5..42a31662 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/ITransformProjectParametersAction.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/ITransformProjectParametersAction.java @@ -6,6 +6,6 @@ public interface ITransformProjectParametersAction { /** * Called if there's an existing ParametersAction to transform. - */ - ParametersAction transformParametersAction(ParametersAction a, Job project); + */ + ParametersAction transformParametersAction(ParametersAction a, Job project); } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/NodeAction.java b/src/main/java/hudson/plugins/parameterizedtrigger/NodeAction.java index 233ba099..90e2af27 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/NodeAction.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/NodeAction.java @@ -34,37 +34,37 @@ import java.util.List; /** - * {@link Action} that restricts the job to a particular node + * {@link Action} that restricts the job to a particular node * when a project is scheduled * Will cause a unique build for each different node if a job is already queued. - * + * * @author Chris Johnson */ public class NodeAction extends InvisibleAction implements LabelAssignmentAction, Queue.QueueAction, BuildBadgeAction { - private final Label nodeLabel; - - public NodeAction(Label nodeLabel) { - this.nodeLabel = nodeLabel; - } + private final Label nodeLabel; + + public NodeAction(Label nodeLabel) { + this.nodeLabel = nodeLabel; + } + + public Label getAssignedLabel(SubTask task) { + return nodeLabel; + } - public Label getAssignedLabel(SubTask task) { - return nodeLabel; - } - - public boolean shouldSchedule(List actions) { - // see if there is already a matching action with same node - for (NodeAction other:Util.filter(actions, NodeAction.class)) { - if(this.nodeLabel.equals(other.nodeLabel)){ - // there is already a task for this node. - return false; - } - } - return true; - } - /** - * @return the tooltip - */ - public String getTooltip() { - return nodeLabel.getDisplayName(); - } + public boolean shouldSchedule(List actions) { + // see if there is already a matching action with same node + for (NodeAction other : Util.filter(actions, NodeAction.class)) { + if (this.nodeLabel.equals(other.nodeLabel)) { + // there is already a task for this node. + return false; + } + } + return true; + } + /** + * @return the tooltip + */ + public String getTooltip() { + return nodeLabel.getDisplayName(); + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/NodeParameters.java b/src/main/java/hudson/plugins/parameterizedtrigger/NodeParameters.java index 5bbaa98c..ec76c6a3 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/NodeParameters.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/NodeParameters.java @@ -19,34 +19,34 @@ * * @author Chris johnson */ -public class NodeParameters extends AbstractBuildParameters{ +public class NodeParameters extends AbstractBuildParameters { - @DataBoundConstructor - public NodeParameters() { - } + @DataBoundConstructor + public NodeParameters() {} - @Override - public Action getAction(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException, DontTriggerException { - String nodeName = build.getBuiltOnStr(); - Label nodeLabel; - String nodeDisplayName; - // Controller does not return a node name so add it explicitly. - if( StringUtils.isEmpty( nodeName ) ) { - nodeLabel = Jenkins.get().getSelfLabel(); - nodeDisplayName = nodeLabel.getDisplayName(); - } else { - nodeLabel = Label.get(nodeName); - nodeDisplayName = nodeLabel != null ? nodeLabel.getDisplayName() : "null label of " + nodeName; - } - listener.getLogger().println("Returning node parameter for " + nodeDisplayName); - return new NodeAction(nodeLabel); - } + @Override + public Action getAction(AbstractBuild build, TaskListener listener) + throws IOException, InterruptedException, DontTriggerException { + String nodeName = build.getBuiltOnStr(); + Label nodeLabel; + String nodeDisplayName; + // Controller does not return a node name so add it explicitly. + if (StringUtils.isEmpty(nodeName)) { + nodeLabel = Jenkins.get().getSelfLabel(); + nodeDisplayName = nodeLabel.getDisplayName(); + } else { + nodeLabel = Label.get(nodeName); + nodeDisplayName = nodeLabel != null ? nodeLabel.getDisplayName() : "null label of " + nodeName; + } + listener.getLogger().println("Returning node parameter for " + nodeDisplayName); + return new NodeAction(nodeLabel); + } - @Extension - public static class DescriptorImpl extends Descriptor { - @Override - public String getDisplayName() { - return "Build on the same node"; - } - } + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "Build on the same node"; + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/ParameterizedDependency.java b/src/main/java/hudson/plugins/parameterizedtrigger/ParameterizedDependency.java index 1676d07c..fac4ffee 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/ParameterizedDependency.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/ParameterizedDependency.java @@ -6,7 +6,6 @@ import hudson.model.DependencyGraph; import hudson.model.DependencyGraph.Dependency; import hudson.model.TaskListener; - import java.util.List; /** @@ -15,69 +14,70 @@ * @author Alan Harder */ public class ParameterizedDependency extends Dependency { - private final BuildTriggerConfig config; + private final BuildTriggerConfig config; + + public ParameterizedDependency(AbstractProject upstream, AbstractProject downstream, BuildTriggerConfig config) { + super(upstream, downstream); + this.config = config; + } - public ParameterizedDependency(AbstractProject upstream, AbstractProject downstream, - BuildTriggerConfig config) { - super(upstream, downstream); - this.config = config; - } + public static void add( + AbstractProject upstream, AbstractProject downstream, BuildTriggerConfig config, DependencyGraph graph) { + // Keeping graph.addDependency() call in this class so classloader + // won't look for DependencyGraph.Dependency when running on older Hudson + graph.addDependency(new ParameterizedDependency(upstream, downstream, config)); + } - public static void add(AbstractProject upstream, AbstractProject downstream, - BuildTriggerConfig config, DependencyGraph graph) { - // Keeping graph.addDependency() call in this class so classloader - // won't look for DependencyGraph.Dependency when running on older Hudson - graph.addDependency(new ParameterizedDependency(upstream, downstream, config)); - } + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; - @Override - public boolean equals(Object obj) { - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - final ParameterizedDependency that = (ParameterizedDependency) obj; - return this.getUpstreamProject() == that.getUpstreamProject() || this.getDownstreamProject() == that.getDownstreamProject() + final ParameterizedDependency that = (ParameterizedDependency) obj; + return this.getUpstreamProject() == that.getUpstreamProject() + || this.getDownstreamProject() == that.getDownstreamProject() || this.config == that.config; - } + } - @Override - public int hashCode() { - int hash = 7; - hash = 23 * hash + this.getUpstreamProject().hashCode(); - hash = 23 * hash + this.getDownstreamProject().hashCode(); - hash = 23 * hash + this.config.hashCode(); - return hash; + @Override + public int hashCode() { + int hash = 7; + hash = 23 * hash + this.getUpstreamProject().hashCode(); + hash = 23 * hash + this.getDownstreamProject().hashCode(); + hash = 23 * hash + this.config.hashCode(); + return hash; + } + + @Override + public boolean shouldTriggerBuild(AbstractBuild build, TaskListener listener, List actions) { + if (!config.getCondition().isMet(build.getResult())) { + return false; } - @Override - public boolean shouldTriggerBuild(AbstractBuild build, TaskListener listener, List actions) { - if (!config.getCondition().isMet(build.getResult())){ - return false; - } - - if (!BuildTriggerConfig.canTriggerProject(build, getDownstreamProject(), listener)) { - return false; - } - try { - List actionList = config.getBaseActions(build, listener); - if (!actionList.isEmpty()) { - actions.addAll(config.getBuildActions(actionList, getDownstreamProject())); - return true; - } + if (!BuildTriggerConfig.canTriggerProject(build, getDownstreamProject(), listener)) { + return false; + } + try { + List actionList = config.getBaseActions(build, listener); + if (!actionList.isEmpty()) { + actions.addAll(config.getBuildActions(actionList, getDownstreamProject())); + return true; + } if (config.getTriggerWithNoParameters()) { return true; } - listener.getLogger().println(Plugin.LOG_TAG + " Downstream builds will not be triggered as no parameter is set."); + listener.getLogger() + .println(Plugin.LOG_TAG + " Downstream builds will not be triggered as no parameter is set."); return false; - } catch (AbstractBuildParameters.DontTriggerException ex) { - // don't trigger on this configuration - return false; - } catch (Exception ex) { - listener.error("Failed to build parameters to trigger project: " - + getDownstreamProject().getName()); - ex.printStackTrace(listener.getLogger()); - return false; - } - } + } catch (AbstractBuildParameters.DontTriggerException ex) { + // don't trigger on this configuration + return false; + } catch (Exception ex) { + listener.error("Failed to build parameters to trigger project: " + + getDownstreamProject().getName()); + ex.printStackTrace(listener.getLogger()); + return false; + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/ParameterizedTriggerUtils.java b/src/main/java/hudson/plugins/parameterizedtrigger/ParameterizedTriggerUtils.java index 9913a604..d19075b2 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/ParameterizedTriggerUtils.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/ParameterizedTriggerUtils.java @@ -1,92 +1,88 @@ -/* - * The MIT License - * - * Copyright (c) 2013 IKEDA Yasuyuki - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package hudson.plugins.parameterizedtrigger; - -import hudson.FilePath; -import hudson.model.ParameterValue; -import hudson.model.ParametersAction; -import org.apache.commons.io.IOUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.StringReader; -import java.util.LinkedHashMap; -import java.util.Properties; -import jenkins.util.VirtualFile; - -/** - * Common utility methods. - */ -public class ParameterizedTriggerUtils { - public static final String DISABLE_ACTION_VIEWS_KEY = "ptp.disableActionViews"; - - /** - * Load properties from string. - * - * @throws IOException - */ - public static Properties loadProperties(String properties) throws IOException { - Properties p = new Properties(); - p.load(new StringReader(properties)); - return p; - } - - /** - * {@link FilePath#readToString()} with encoding. - * - * @param f file to read - * @param encoding null for platform default encoding. - * @return read string - * @throws IOException - */ - public static String readFileToString(FilePath f, String encoding) throws IOException, InterruptedException { - try (InputStream in = f.read()) { - return IOUtils.toString(in, encoding); - } - } - - /** - * Read VirtualFile. - * - * @param f file to read - * @return read string - * @throws IOException - */ - public static String readFileToString(VirtualFile f) throws IOException, InterruptedException { - try (InputStream in = f.open()) { - return IOUtils.toString(in); - } - } - - public static ParametersAction mergeParameters(ParametersAction base, ParametersAction overlay) { - LinkedHashMap params = new LinkedHashMap<>(); - for (ParameterValue param : base.getParameters()) - params.put(param.getName(), param); - for (ParameterValue param : overlay.getParameters()) - params.put(param.getName(), param); - return new ParametersAction(params.values().toArray(new ParameterValue[0])); - } - -} +/* + * The MIT License + * + * Copyright (c) 2013 IKEDA Yasuyuki + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package hudson.plugins.parameterizedtrigger; + +import hudson.FilePath; +import hudson.model.ParameterValue; +import hudson.model.ParametersAction; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.util.LinkedHashMap; +import java.util.Properties; +import jenkins.util.VirtualFile; +import org.apache.commons.io.IOUtils; + +/** + * Common utility methods. + */ +public class ParameterizedTriggerUtils { + public static final String DISABLE_ACTION_VIEWS_KEY = "ptp.disableActionViews"; + + /** + * Load properties from string. + * + * @throws IOException + */ + public static Properties loadProperties(String properties) throws IOException { + Properties p = new Properties(); + p.load(new StringReader(properties)); + return p; + } + + /** + * {@link FilePath#readToString()} with encoding. + * + * @param f file to read + * @param encoding null for platform default encoding. + * @return read string + * @throws IOException + */ + public static String readFileToString(FilePath f, String encoding) throws IOException, InterruptedException { + try (InputStream in = f.read()) { + return IOUtils.toString(in, encoding); + } + } + + /** + * Read VirtualFile. + * + * @param f file to read + * @return read string + * @throws IOException + */ + public static String readFileToString(VirtualFile f) throws IOException, InterruptedException { + try (InputStream in = f.open()) { + return IOUtils.toString(in); + } + } + + public static ParametersAction mergeParameters(ParametersAction base, ParametersAction overlay) { + LinkedHashMap params = new LinkedHashMap<>(); + for (ParameterValue param : base.getParameters()) params.put(param.getName(), param); + for (ParameterValue param : overlay.getParameters()) params.put(param.getName(), param); + return new ParametersAction(params.values().toArray(new ParameterValue[0])); + } +} diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/Plugin.java b/src/main/java/hudson/plugins/parameterizedtrigger/Plugin.java index 587f170f..a4d23c69 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/Plugin.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/Plugin.java @@ -1,36 +1,33 @@ package hudson.plugins.parameterizedtrigger; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import static org.apache.commons.lang.StringUtils.isEmpty; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.model.Item; import hudson.model.ItemGroup; import hudson.model.Project; import hudson.model.listeners.ItemListener; import hudson.util.EnumConverter; - import java.io.IOException; import java.util.List; import java.util.ListIterator; import java.util.logging.Level; import java.util.logging.Logger; - import jenkins.model.Jenkins; - import org.jenkinsci.plugins.conditionalbuildstep.ConditionalBuildStepHelper; import org.kohsuke.stapler.Stapler; -import static org.apache.commons.lang.StringUtils.isEmpty; - -@SuppressFBWarnings(value="NM_SAME_SIMPLE_NAME_AS_SUPERCLASS", justification="Part of public API, reviewed all uses of Plugin are fully quantified in this class") +@SuppressFBWarnings( + value = "NM_SAME_SIMPLE_NAME_AS_SUPERCLASS", + justification = "Part of public API, reviewed all uses of Plugin are fully quantified in this class") public class Plugin extends hudson.Plugin { public static final String LOG_TAG = "[parameterized-trigger]"; - @Override - public void start() throws Exception { - Stapler.CONVERT_UTILS.register(new EnumConverter(), - ResultCondition.class); - } + @Override + public void start() throws Exception { + Stapler.CONVERT_UTILS.register(new EnumConverter(), ResultCondition.class); + } /** * If a job is renamed, update all parameterized-triggers with the new name. @@ -43,108 +40,114 @@ public void onRenamed(Item item, String oldName, String newName) { String full = isEmpty(context.getFullName()) ? "" : context.getFullName() + '/'; String fullOldName = full + oldName; String fullNewName = full + newName; - for (Project p : Jenkins.get().getAllItems(Project.class)) { + for (Project p : Jenkins.get().getAllItems(Project.class)) { boolean changed = false; - //iterate over post build triggers + // iterate over post build triggers BuildTrigger bt = p.getPublishersList().get(BuildTrigger.class); if (bt != null) { - for (BuildTriggerConfig c : bt.getConfigs()){ + for (BuildTriggerConfig c : bt.getConfigs()) { changed |= c.onJobRenamed(p.getParent(), fullOldName, fullNewName); } } - //iterate over build step triggers + // iterate over build step triggers TriggerBuilder tb = p.getBuildersList().get(TriggerBuilder.class); if (tb != null) { - for (BuildTriggerConfig co : tb.getConfigs()){ + for (BuildTriggerConfig co : tb.getConfigs()) { changed |= co.onJobRenamed(p.getParent(), fullOldName, fullNewName); } } - //iterate the BuildTriggers within conditional buildsteps - if(isConditionalBuildStepInstalled()) { + // iterate the BuildTriggers within conditional buildsteps + if (isConditionalBuildStepInstalled()) { changed |= renameInConditionalBuildStep(p, oldName, newName); } - //if something changed, save the project - if (changed){ + // if something changed, save the project + if (changed) { try { p.save(); } catch (IOException e) { - Logger.getLogger(RenameListener.class.getName()).log(Level.WARNING, - "Failed to persist project setting during rename from "+fullOldName+" to "+fullNewName, e); + Logger.getLogger(RenameListener.class.getName()) + .log( + Level.WARNING, + "Failed to persist project setting during rename from " + fullOldName + " to " + + fullNewName, + e); } } - } } @Override public void onDeleted(Item item) { - for (Project p : Jenkins.get().getAllItems(Project.class)) { + for (Project p : Jenkins.get().getAllItems(Project.class)) { String oldName = item.getFullName(); boolean changed = false; - //iterate over post build triggers + // iterate over post build triggers BuildTrigger bt = p.getPublishersList().get(BuildTrigger.class); if (bt != null) { - for (ListIterator btc = bt.getConfigs().listIterator(); btc.hasNext();) { + for (ListIterator btc = bt.getConfigs().listIterator(); btc.hasNext(); ) { BuildTriggerConfig c = btc.next(); if (c.onDeleted(p.getParent(), oldName)) { changed = true; - if (c.getProjects().length() == 0){ + if (c.getProjects().length() == 0) { btc.remove(); } } } } - //iterate over build step triggers + // iterate over build step triggers TriggerBuilder tb = p.getBuildersList().get(TriggerBuilder.class); if (tb != null) { - for (ListIterator bbtc = tb.getConfigs().listIterator(); bbtc.hasNext();) { + for (ListIterator bbtc = + tb.getConfigs().listIterator(); + bbtc.hasNext(); ) { BuildTriggerConfig c = bbtc.next(); if (c.onDeleted(p.getParent(), oldName)) { changed = true; - if (c.getProjects().length() == 0){ + if (c.getProjects().length() == 0) { bbtc.remove(); } } } } - //iterate the BuildTriggers within conditional buildsteps - if(isConditionalBuildStepInstalled()) { + // iterate the BuildTriggers within conditional buildsteps + if (isConditionalBuildStepInstalled()) { changed |= deleteInConditionalBuildStep(p, oldName); } - //if something changed, save the project - if (changed){ + // if something changed, save the project + if (changed) { try { - if (bt!=null && bt.getConfigs().isEmpty()){ + if (bt != null && bt.getConfigs().isEmpty()) { p.getPublishersList().remove(bt); } - if (tb!=null && tb.getConfigs().isEmpty()){ + if (tb != null && tb.getConfigs().isEmpty()) { p.getBuildersList().remove(tb); } p.save(); } catch (IOException e) { - Logger.getLogger(RenameListener.class.getName()).log(Level.WARNING, - "Failed to persist project setting during remove of "+oldName, e); + Logger.getLogger(RenameListener.class.getName()) + .log(Level.WARNING, "Failed to persist project setting during remove of " + oldName, e); } } } } /** - * renames the project references within all {@link TriggerBuilder}s which are wrapped by a conditional buildsteps - * @param p the project the check - * @param oldName the old project name - * @param newName the new project name - * @return whether a change has been made - */ - private boolean renameInConditionalBuildStep(Project p, String oldName, String newName) { + * renames the project references within all {@link TriggerBuilder}s which are wrapped by a conditional buildsteps + * @param p the project the check + * @param oldName the old project name + * @param newName the new project name + * @return whether a change has been made + */ + private boolean renameInConditionalBuildStep(Project p, String oldName, String newName) { boolean changed = false; - final List containedBuilders = ConditionalBuildStepHelper.getContainedBuilders(p, TriggerBuilder.class); + final List containedBuilders = + ConditionalBuildStepHelper.getContainedBuilders(p, TriggerBuilder.class); for (TriggerBuilder triggerBuilder : containedBuilders) { - for (BuildTriggerConfig co : triggerBuilder.getConfigs()){ + for (BuildTriggerConfig co : triggerBuilder.getConfigs()) { changed |= co.onJobRenamed(p.getParent(), oldName, newName); } } @@ -152,20 +155,23 @@ private boolean renameInConditionalBuildStep(Project p, String oldName, Str } /** - * removes the project references within all {@link TriggerBuilder}s which are wrapped by a conditional buildsteps - * @param p the project the check - * @param oldName the old project name - * @return whether a change has been made - */ - private boolean deleteInConditionalBuildStep(Project p, String oldName) { + * removes the project references within all {@link TriggerBuilder}s which are wrapped by a conditional buildsteps + * @param p the project the check + * @param oldName the old project name + * @return whether a change has been made + */ + private boolean deleteInConditionalBuildStep(Project p, String oldName) { boolean changed = false; - final List containedBuilders = ConditionalBuildStepHelper.getContainedBuilders(p, TriggerBuilder.class); + final List containedBuilders = + ConditionalBuildStepHelper.getContainedBuilders(p, TriggerBuilder.class); for (TriggerBuilder triggerBuilder : containedBuilders) { - for (ListIterator bbtc = triggerBuilder.getConfigs().listIterator(); bbtc.hasNext();) { + for (ListIterator bbtc = + triggerBuilder.getConfigs().listIterator(); + bbtc.hasNext(); ) { BuildTriggerConfig c = bbtc.next(); if (c.onDeleted(p.getParent(), oldName)) { changed = true; - if (c.getProjects().length() == 0){ + if (c.getProjects().length() == 0) { bbtc.remove(); } } @@ -173,10 +179,9 @@ private boolean deleteInConditionalBuildStep(Project p, String oldName) { } return changed; } - } - public static boolean isConditionalBuildStepInstalled(){ + public static boolean isConditionalBuildStepInstalled() { final hudson.Plugin plugin = Jenkins.get().getPlugin("conditional-buildstep"); return plugin != null && plugin.getWrapper().isActive(); } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/PredefinedBuildParameters.java b/src/main/java/hudson/plugins/parameterizedtrigger/PredefinedBuildParameters.java index 1b7d6aa6..854ac10b 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/PredefinedBuildParameters.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/PredefinedBuildParameters.java @@ -10,66 +10,61 @@ import hudson.model.StringParameterValue; import hudson.model.TaskListener; import hudson.model.TextParameterValue; - import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Properties; - import org.kohsuke.stapler.DataBoundConstructor; public class PredefinedBuildParameters extends AbstractBuildParameters { - private final String properties; - private final boolean textParamValueOnNewLine; - - - @DataBoundConstructor - public PredefinedBuildParameters(String properties, boolean textParamValueOnNewLine) { - this.properties = properties; - this.textParamValueOnNewLine = textParamValueOnNewLine; - } - - public PredefinedBuildParameters(String properties) { - this(properties, false); - } - - public Action getAction(AbstractBuild build, TaskListener listener) - throws IOException, InterruptedException { - - EnvVars env = getEnvironment(build, listener); - - Properties p = ParameterizedTriggerUtils.loadProperties(getProperties()); - - List values = new ArrayList<>(); - for (Map.Entry entry : p.entrySet()) { - // support multi-line parameters correctly - String s = entry.getValue().toString(); - if(textParamValueOnNewLine && s.contains("\n")) { - values.add(new TextParameterValue(entry.getKey().toString(), env.expand(s))); - } else { - values.add(new StringParameterValue(entry.getKey().toString(), env.expand(s))); - } - } - - return new ParametersAction(values); - } - - public String getProperties() { - return properties; - } - - public boolean getTextParamValueOnNewLine() { - return textParamValueOnNewLine; - } - - @Extension - public static class DescriptorImpl extends Descriptor { - @Override - public String getDisplayName() { - return "Predefined parameters"; - } - } - + private final String properties; + private final boolean textParamValueOnNewLine; + + @DataBoundConstructor + public PredefinedBuildParameters(String properties, boolean textParamValueOnNewLine) { + this.properties = properties; + this.textParamValueOnNewLine = textParamValueOnNewLine; + } + + public PredefinedBuildParameters(String properties) { + this(properties, false); + } + + public Action getAction(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException { + + EnvVars env = getEnvironment(build, listener); + + Properties p = ParameterizedTriggerUtils.loadProperties(getProperties()); + + List values = new ArrayList<>(); + for (Map.Entry entry : p.entrySet()) { + // support multi-line parameters correctly + String s = entry.getValue().toString(); + if (textParamValueOnNewLine && s.contains("\n")) { + values.add(new TextParameterValue(entry.getKey().toString(), env.expand(s))); + } else { + values.add(new StringParameterValue(entry.getKey().toString(), env.expand(s))); + } + } + + return new ParametersAction(values); + } + + public String getProperties() { + return properties; + } + + public boolean getTextParamValueOnNewLine() { + return textParamValueOnNewLine; + } + + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "Predefined parameters"; + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/PredefinedPropertiesBuildTriggerConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/PredefinedPropertiesBuildTriggerConfig.java index d35f11fb..ad39f528 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/PredefinedPropertiesBuildTriggerConfig.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/PredefinedPropertiesBuildTriggerConfig.java @@ -1,7 +1,6 @@ package hudson.plugins.parameterizedtrigger; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - import java.util.ArrayList; import java.util.List; @@ -11,27 +10,28 @@ @Deprecated public class PredefinedPropertiesBuildTriggerConfig extends BuildTriggerConfig { - public PredefinedPropertiesBuildTriggerConfig(String projects, - ResultCondition condition, AbstractBuildParameters[] configs) { - super(projects, condition, configs); - } - - private String projectsValue; + public PredefinedPropertiesBuildTriggerConfig( + String projects, ResultCondition condition, AbstractBuildParameters[] configs) { + super(projects, condition, configs); + } + + private String projectsValue; private String properties; private ResultCondition condition; private boolean triggerWithNoParameters; private boolean includeCurrentParameters; + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "Do not risk compatibility") private String batchCondition; - + public Object readResolve() { - List configs = new ArrayList<>(); - if (includeCurrentParameters) { - configs.add(new CurrentBuildParameters()); - } - if (properties != null) { - configs.add(new PredefinedBuildParameters(properties)); - } - return new BuildTriggerConfig(projectsValue, condition, triggerWithNoParameters, configs); + List configs = new ArrayList<>(); + if (includeCurrentParameters) { + configs.add(new CurrentBuildParameters()); + } + if (properties != null) { + configs.add(new PredefinedBuildParameters(properties)); + } + return new BuildTriggerConfig(projectsValue, condition, triggerWithNoParameters, configs); } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/ProjectSpecificParameterValuesActionTransform.java b/src/main/java/hudson/plugins/parameterizedtrigger/ProjectSpecificParameterValuesActionTransform.java index d7fb916e..ffda2933 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/ProjectSpecificParameterValuesActionTransform.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/ProjectSpecificParameterValuesActionTransform.java @@ -3,30 +3,27 @@ import hudson.model.AbstractBuild; import hudson.model.Executor; import hudson.model.Job; -import hudson.model.ParametersAction; import hudson.model.ParameterDefinition; +import hudson.model.ParameterValue; +import hudson.model.ParametersAction; import hudson.model.ParametersDefinitionProperty; import hudson.model.Queue; -import hudson.model.ParameterValue; import hudson.model.SimpleParameterDefinition; import hudson.model.StringParameterDefinition; import hudson.model.StringParameterValue; - -import java.util.List; import java.util.ArrayList; -import java.util.Map; import java.util.HashMap; -import java.util.logging.Logger; +import java.util.List; +import java.util.Map; import java.util.logging.Level; -import java.lang.RuntimeException; +import java.util.logging.Logger; /** * Convert Generic ParameterValues to the type indicated by the Project's ParameterDefinitions */ public class ProjectSpecificParameterValuesActionTransform implements ITransformProjectParametersAction { - public ParametersAction transformParametersAction(ParametersAction a, Job project) { - Map parameterDefinitions = - getParameterDefinitionsMap(project); + public ParametersAction transformParametersAction(ParametersAction a, Job project) { + Map parameterDefinitions = getParameterDefinitionsMap(project); List params = new ArrayList<>(); for (ParameterValue param : a.getParameters()) { @@ -37,7 +34,7 @@ public ParametersAction transformParametersAction(ParametersAction a, Job p return new ParametersAction(params); } - private static Map getParameterDefinitionsMap(Job project) { + private static Map getParameterDefinitionsMap(Job project) { HashMap m = new HashMap<>(); ParametersDefinitionProperty property = project.getProperty(ParametersDefinitionProperty.class); @@ -52,23 +49,23 @@ private static Map getParameterDefinitionsMap(Job)task).getFullDisplayName(); + + return ((AbstractBuild) task).getFullDisplayName(); } private static ParameterValue convertToDefinedType(Map defs, ParameterValue pv) { @@ -77,22 +74,25 @@ private static ParameterValue convertToDefinedType(Map(Arrays.asList(transforms)); } - public final List getProjectSpecificBuildActions(List baseActions, Job project) { + public final List getProjectSpecificBuildActions(List baseActions, Job project) { List actions = new ArrayList<>(); ParametersAction pa = getParametersAction(baseActions); // Copy everything except the ParametersAction for (Action a : baseActions) { - if (! (a instanceof ParametersAction)) { + if (!(a instanceof ParametersAction)) { actions.add(a); } } @@ -40,7 +39,7 @@ public final List getProjectSpecificBuildActions(List baseAction private static ParametersAction getParametersAction(List actions) { for (Action a : actions) { if (a instanceof ParametersAction) { - return (ParametersAction)a; + return (ParametersAction) a; } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/ResultCondition.java b/src/main/java/hudson/plugins/parameterizedtrigger/ResultCondition.java index eb5c29f8..b4d30bcf 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/ResultCondition.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/ResultCondition.java @@ -1,55 +1,53 @@ -package hudson.plugins.parameterizedtrigger; - -import hudson.model.Result; - -public enum ResultCondition { - - SUCCESS("Stable") { - boolean isMet(Result result) { - return result == Result.SUCCESS; - } - }, - UNSTABLE("Unstable") { - boolean isMet(Result result) { - return result == Result.UNSTABLE; - } - }, - FAILED_OR_BETTER("Stable, unstable or failed, but not aborted") { - boolean isMet(Result result) { - return result.isBetterOrEqualTo(Result.FAILURE); - } - }, - UNSTABLE_OR_BETTER("Stable or unstable but not failed") { - boolean isMet(Result result) { - return result.isBetterOrEqualTo(Result.UNSTABLE); - } - }, - UNSTABLE_OR_WORSE("Unstable or Failed but not stable") { - boolean isMet(Result result) { - return result.isWorseOrEqualTo(Result.UNSTABLE); - } - }, - FAILED("Failed") { - boolean isMet(Result result) { - return result == Result.FAILURE; - } - }, - ALWAYS("Complete (always trigger)") { - boolean isMet(Result result) { - return true; - } - }; - - ResultCondition(String displayName) { - this.displayName = displayName; - } - - private final String displayName; - - public String getDisplayName() { - return displayName; - } - - abstract boolean isMet(Result result); - -} +package hudson.plugins.parameterizedtrigger; + +import hudson.model.Result; + +public enum ResultCondition { + SUCCESS("Stable") { + boolean isMet(Result result) { + return result == Result.SUCCESS; + } + }, + UNSTABLE("Unstable") { + boolean isMet(Result result) { + return result == Result.UNSTABLE; + } + }, + FAILED_OR_BETTER("Stable, unstable or failed, but not aborted") { + boolean isMet(Result result) { + return result.isBetterOrEqualTo(Result.FAILURE); + } + }, + UNSTABLE_OR_BETTER("Stable or unstable but not failed") { + boolean isMet(Result result) { + return result.isBetterOrEqualTo(Result.UNSTABLE); + } + }, + UNSTABLE_OR_WORSE("Unstable or Failed but not stable") { + boolean isMet(Result result) { + return result.isWorseOrEqualTo(Result.UNSTABLE); + } + }, + FAILED("Failed") { + boolean isMet(Result result) { + return result == Result.FAILURE; + } + }, + ALWAYS("Complete (always trigger)") { + boolean isMet(Result result) { + return true; + } + }; + + ResultCondition(String displayName) { + this.displayName = displayName; + } + + private final String displayName; + + public String getDisplayName() { + return displayName; + } + + abstract boolean isMet(Result result); +} diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/SubProjectData.java b/src/main/java/hudson/plugins/parameterizedtrigger/SubProjectData.java index 1ca148df..8793ec4b 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/SubProjectData.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/SubProjectData.java @@ -25,9 +25,7 @@ package hudson.plugins.parameterizedtrigger; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - import hudson.model.Job; - import java.util.Comparator; import java.util.Set; import java.util.TreeSet; @@ -44,7 +42,7 @@ * * @author JO Sivtoft */ -@SuppressFBWarnings(value="SIC_INNER_SHOULD_BE_STATIC_ANON") +@SuppressFBWarnings(value = "SIC_INNER_SHOULD_BE_STATIC_ANON") public class SubProjectData { private final Comparator customComparator = new Comparator() { diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/SubProjectsAction.java b/src/main/java/hudson/plugins/parameterizedtrigger/SubProjectsAction.java index 31c6bfed..0934144e 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/SubProjectsAction.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/SubProjectsAction.java @@ -4,6 +4,7 @@ import hudson.model.Action; import java.util.Collections; import java.util.List; + /** * Action added Projects to track what projects are * were triggered from the trigger builds on other projects buildstep. @@ -15,10 +16,10 @@ */ public class SubProjectsAction implements Action { - private final AbstractProject project; + private final AbstractProject project; private final List configs; - public SubProjectsAction(AbstractProject project, List configs) { + public SubProjectsAction(AbstractProject project, List configs) { this.project = project; this.configs = configs; } @@ -49,7 +50,7 @@ public List getSubProjectActions() { return Collections.emptyList(); } - public AbstractProject getProject() { + public AbstractProject getProject() { return project; } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/SubversionRevisionBuildParameters.java b/src/main/java/hudson/plugins/parameterizedtrigger/SubversionRevisionBuildParameters.java index 49873007..ee24cd9a 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/SubversionRevisionBuildParameters.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/SubversionRevisionBuildParameters.java @@ -6,65 +6,64 @@ import hudson.model.Descriptor; import hudson.model.TaskListener; import hudson.scm.RevisionParameterAction; -import hudson.scm.SubversionTagAction; import hudson.scm.SubversionSCM.SvnInfo; - +import hudson.scm.SubversionTagAction; import java.util.ArrayList; import java.util.List; - import org.kohsuke.stapler.DataBoundConstructor; public class SubversionRevisionBuildParameters extends AbstractBuildParameters { - private boolean includeUpstreamParameters = false; - - public SubversionRevisionBuildParameters() { - this(false); - } - - @DataBoundConstructor - public SubversionRevisionBuildParameters(boolean includeUpstreamParameters ) { - this.includeUpstreamParameters = includeUpstreamParameters; - } + private boolean includeUpstreamParameters = false; - public boolean getIncludeUpstreamParameters() { - return includeUpstreamParameters; - } - @Override - public Action getAction(AbstractBuild build, TaskListener listener) { + public SubversionRevisionBuildParameters() { + this(false); + } - SubversionTagAction tagAction = build.getAction(SubversionTagAction.class); - RevisionParameterAction revisionAction = build.getAction(RevisionParameterAction.class); + @DataBoundConstructor + public SubversionRevisionBuildParameters(boolean includeUpstreamParameters) { + this.includeUpstreamParameters = includeUpstreamParameters; + } - List infos = new ArrayList<>(); + public boolean getIncludeUpstreamParameters() { + return includeUpstreamParameters; + } - if (tagAction == null ) { - listener.getLogger().println( - Plugin.LOG_TAG + " no SubversionTagAction found -- is this project an SVN project ?"); - } else { - infos.addAll(tagAction.getTags().keySet()); - } + @Override + public Action getAction(AbstractBuild build, TaskListener listener) { - if (includeUpstreamParameters) { - if (revisionAction == null ) { - listener.getLogger().println( - Plugin.LOG_TAG + " no RevisionParameterAction found -- project did not have SVN parameters passed to it?"); - } else { - infos.addAll(revisionAction.getRevisions()); - } - } - //if infos is empty don't return an action. - return (infos.size() == 0 ) ? null : new RevisionParameterAction(infos); - } + SubversionTagAction tagAction = build.getAction(SubversionTagAction.class); + RevisionParameterAction revisionAction = build.getAction(RevisionParameterAction.class); - @Extension - public static class DescriptorImpl extends Descriptor { + List infos = new ArrayList<>(); - @Override - public String getDisplayName() { - return "Subversion revision"; - } + if (tagAction == null) { + listener.getLogger() + .println(Plugin.LOG_TAG + " no SubversionTagAction found -- is this project an SVN project ?"); + } else { + infos.addAll(tagAction.getTags().keySet()); + } + + if (includeUpstreamParameters) { + if (revisionAction == null) { + listener.getLogger() + .println( + Plugin.LOG_TAG + + " no RevisionParameterAction found -- project did not have SVN parameters passed to it?"); + } else { + infos.addAll(revisionAction.getRevisions()); + } + } + // if infos is empty don't return an action. + return (infos.size() == 0) ? null : new RevisionParameterAction(infos); + } - } + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return "Subversion revision"; + } + } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java b/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java index 52d898e1..528ccce9 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java @@ -34,24 +34,23 @@ import hudson.model.Action; import hudson.model.BuildListener; import hudson.model.DependencyGraph; +import hudson.model.Job; import hudson.model.Result; +import hudson.model.Run; import hudson.model.TaskListener; +import hudson.model.User; +import hudson.model.queue.QueueTaskFuture; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Builder; -import hudson.model.Job; -import hudson.model.Run; -import hudson.model.User; -import hudson.model.queue.QueueTaskFuture; -import jenkins.model.DependencyDeclarer; -import org.kohsuke.accmod.Restricted; -import org.kohsuke.stapler.DataBoundConstructor; - import java.io.IOException; import java.util.*; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.logging.Logger; +import jenkins.model.DependencyDeclarer; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.stapler.DataBoundConstructor; /** * {@link Builder} that triggers other projects and optionally waits for their completion. @@ -83,8 +82,8 @@ public BuildStepMonitor getRequiredMonitorService() { } @Override - public boolean perform(AbstractBuild build, Launcher launcher, - BuildListener listener) throws InterruptedException, IOException { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { EnvVars env = build.getEnvironment(listener); env.overrideAll(build.getBuildVariables()); @@ -94,7 +93,8 @@ public boolean perform(AbstractBuild build, Launcher launcher, for (BlockableBuildTriggerConfig config : configs) { ListMultimap> futures = config.perform3(build, launcher, listener); // Only contains resolved projects - List projectList = config.getJobs(build.getRootBuild().getProject().getParent(), env); + List projectList = + config.getJobs(build.getRootBuild().getProject().getParent(), env); // Get the actual defined projects StringTokenizer tokenizer = new StringTokenizer(config.getProjects(env), ","); @@ -103,7 +103,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, throw new AbortException("Build aborted. No projects to trigger. Check your configuration!"); } else if (tokenizer.countTokens() != projectList.size()) { - int nbrOfResolved = tokenizer.countTokens()-projectList.size(); + int nbrOfResolved = tokenizer.countTokens() - projectList.size(); // Identify the unresolved project(s) Set unsolvedProjectNames = new TreeSet<>(); @@ -122,62 +122,87 @@ public boolean perform(AbstractBuild build, Launcher launcher, missingProject.append("\n"); } - throw new AbortException("Build aborted. Can't trigger undefined projects. "+nbrOfResolved+" of the below project(s) can't be resolved:\n" + missingProject.toString() + "Check your configuration!"); + throw new AbortException("Build aborted. Can't trigger undefined projects. " + nbrOfResolved + + " of the below project(s) can't be resolved:\n" + missingProject.toString() + + "Check your configuration!"); } else { - //handle non-blocking configs - if(futures.isEmpty()){ + // handle non-blocking configs + if (futures.isEmpty()) { listener.getLogger().println("Triggering projects: " + getProjectListAsString(projectList)); - for(Job p : projectList) { + for (Job p : projectList) { BuildInfoExporterAction.addBuildInfoExporterAction(build, p.getFullName()); } continue; } - //handle blocking configs + // handle blocking configs for (Job p : projectList) { - //handle non-buildable projects - if(!config.canBeScheduled(p)){ + // handle non-buildable projects + if (!config.canBeScheduled(p)) { User user = User.current(); String userName = user != null ? ModelHyperlinkNote.encodeTo(user) : "unknown"; - listener.getLogger().println("Skipping " + HyperlinkNote.encodeTo('/'+ p.getUrl(), p.getFullDisplayName()) + - ". The project is either disabled," - + " or the authenticated user " + userName + " has no Item.BUILD permissions," - + " or the configuration has not been saved yet."); + listener.getLogger() + .println("Skipping " + + HyperlinkNote.encodeTo('/' + p.getUrl(), p.getFullDisplayName()) + + ". The project is either disabled," + + " or the authenticated user " + userName + + " has no Item.BUILD permissions," + + " or the configuration has not been saved yet."); continue; } for (QueueTaskFuture future : futures.get(p)) { try { - if (future != null ) { - listener.getLogger().println("Waiting for the completion of " + HyperlinkNote.encodeTo('/'+ p.getUrl(), p.getFullDisplayName())); + if (future != null) { + listener.getLogger() + .println("Waiting for the completion of " + + HyperlinkNote.encodeTo('/' + p.getUrl(), p.getFullDisplayName())); Run startedRun; try { startedRun = future.waitForStart(); } catch (InterruptedException x) { - listener.getLogger().println( "Build aborting: cancelling queued project " + HyperlinkNote.encodeTo('/'+ p.getUrl(), p.getFullDisplayName()) ); + listener.getLogger() + .println("Build aborting: cancelling queued project " + + HyperlinkNote.encodeTo( + '/' + p.getUrl(), p.getFullDisplayName())); future.cancel(true); throw x; // rethrow so that the triggering project get flagged as cancelled } - listener.getLogger().println(HyperlinkNote.encodeTo('/' + startedRun.getUrl(), startedRun.getFullDisplayName()) + " started."); + listener.getLogger() + .println(HyperlinkNote.encodeTo( + '/' + startedRun.getUrl(), startedRun.getFullDisplayName()) + + " started."); Run completedRun = future.get(); - listener.getLogger().println(HyperlinkNote.encodeTo('/' + completedRun.getUrl(), completedRun.getFullDisplayName()) + " completed. Result was " + completedRun.getResult()); - BuildInfoExporterAction.addBuildInfoExporterAction(build, completedRun.getParent().getFullName(), completedRun.getNumber(), completedRun.getResult()); - - if (buildStepResult && config.getBlock().mapBuildStepResult(completedRun.getResult())) { + listener.getLogger() + .println(HyperlinkNote.encodeTo( + '/' + completedRun.getUrl(), + completedRun.getFullDisplayName()) + + " completed. Result was " + completedRun.getResult()); + BuildInfoExporterAction.addBuildInfoExporterAction( + build, + completedRun.getParent().getFullName(), + completedRun.getNumber(), + completedRun.getResult()); + + if (buildStepResult + && config.getBlock().mapBuildStepResult(completedRun.getResult())) { Result r = config.getBlock().mapBuildResult(completedRun.getResult()); if (r != null) { build.setResult(r); } else { - LOGGER.warning("Attempting to use the result of unfinished build " + completedRun.toString()); + LOGGER.warning("Attempting to use the result of unfinished build " + + completedRun.toString()); } } else { buildStepResult = false; } } else { - listener.getLogger().println("Skipping " + ModelHyperlinkNote.encodeTo(p) + ". The project was not triggered by some reason."); + listener.getLogger() + .println("Skipping " + ModelHyperlinkNote.encodeTo(p) + + ". The project was not triggered by some reason."); } } catch (CancellationException x) { - throw new AbortException(p.getFullDisplayName() +" aborted."); + throw new AbortException(p.getFullDisplayName() + " aborted."); } } } @@ -191,13 +216,13 @@ public boolean perform(AbstractBuild build, Launcher launcher, } // Public but restricted so we can add tests without completely changing the tests package - @Restricted(value=org.kohsuke.accmod.restrictions.NoExternalUse.class) - public String getProjectListAsString(List projectList){ + @Restricted(value = org.kohsuke.accmod.restrictions.NoExternalUse.class) + public String getProjectListAsString(List projectList) { StringBuilder projectListString = new StringBuilder(); - for (Iterator iterator = projectList.iterator(); iterator.hasNext();) { + for (Iterator iterator = projectList.iterator(); iterator.hasNext(); ) { Job project = iterator.next(); - projectListString.append(HyperlinkNote.encodeTo('/'+ project.getUrl(), project.getFullDisplayName())); - if(iterator.hasNext()){ + projectListString.append(HyperlinkNote.encodeTo('/' + project.getUrl(), project.getFullDisplayName())); + if (iterator.hasNext()) { projectListString.append(", "); } } @@ -227,7 +252,8 @@ public void buildDependencyGraph(AbstractProject owner, DependencyGraph graph) { } public static class TriggerBuilderDependency extends ParameterizedDependency { - public TriggerBuilderDependency(AbstractProject upstream, AbstractProject downstream, BuildTriggerConfig config) { + public TriggerBuilderDependency( + AbstractProject upstream, AbstractProject downstream, BuildTriggerConfig config) { super(upstream, downstream, config); } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/matrix/MatrixBuildListenerImpl.java b/src/main/java/hudson/plugins/parameterizedtrigger/matrix/MatrixBuildListenerImpl.java index 005e6358..ed2ff17a 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/matrix/MatrixBuildListenerImpl.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/matrix/MatrixBuildListenerImpl.java @@ -14,9 +14,9 @@ public class MatrixBuildListenerImpl extends MatrixBuildListener { @Override public boolean doBuildConfiguration(MatrixBuild b, MatrixConfiguration c) { MatrixSubsetAction a = b.getAction(MatrixSubsetAction.class); - if (a==null) return true; + if (a == null) return true; // run the filter and restrict the subset to run - return c.getCombination().evalGroovyExpression(b.getParent().getAxes(),a.getFilter()); + return c.getCombination().evalGroovyExpression(b.getParent().getAxes(), a.getFilter()); } } diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/matrix/MatrixSubsetBuildParameters.java b/src/main/java/hudson/plugins/parameterizedtrigger/matrix/MatrixSubsetBuildParameters.java index 90f54390..59711332 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/matrix/MatrixSubsetBuildParameters.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/matrix/MatrixSubsetBuildParameters.java @@ -7,9 +7,8 @@ import hudson.model.Descriptor; import hudson.model.TaskListener; import hudson.plugins.parameterizedtrigger.AbstractBuildParameters; -import org.kohsuke.stapler.DataBoundConstructor; - import java.io.IOException; +import org.kohsuke.stapler.DataBoundConstructor; /** * Build parameter that controls which subset of {@link MatrixConfiguration} a downstream build will run. @@ -19,27 +18,25 @@ public class MatrixSubsetBuildParameters extends AbstractBuildParameters { private final String filter; - @DataBoundConstructor - public MatrixSubsetBuildParameters(String filter) { + @DataBoundConstructor + public MatrixSubsetBuildParameters(String filter) { this.filter = filter; - } + } public String getFilter() { return filter; } @Override - public Action getAction(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException { + public Action getAction(AbstractBuild build, TaskListener listener) throws IOException, InterruptedException { return new MatrixSubsetAction(getEnvironment(build, listener).expand(filter)); - } - - @Extension - public static class DescriptorImpl extends Descriptor { - @Override - public String getDisplayName() { - return Messages.MatrixSubsetBuildParameters_DisplayName(); - } - } + } + @Extension + public static class DescriptorImpl extends Descriptor { + @Override + public String getDisplayName() { + return Messages.MatrixSubsetBuildParameters_DisplayName(); + } + } } - diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/CapturedEnvironmentActionTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/CapturedEnvironmentActionTest.java index 121f9354..82feb648 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/CapturedEnvironmentActionTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/CapturedEnvironmentActionTest.java @@ -1,5 +1,17 @@ package hudson.plugins.parameterizedtrigger; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.anEmptyMap; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.sameInstance; +import static org.hamcrest.collection.IsMapContaining.hasEntry; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import hudson.ExtensionList; import hudson.FilePath; import hudson.Functions; @@ -7,6 +19,9 @@ import hudson.model.FreeStyleBuild; import hudson.model.FreeStyleProject; import hudson.model.Saveable; +import java.io.File; +import java.net.URL; +import java.util.Map; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; @@ -16,33 +31,18 @@ import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsSessionRule; -import java.io.File; -import java.net.URL; -import java.util.Map; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.anEmptyMap; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.sameInstance; -import static org.hamcrest.collection.IsMapContaining.hasEntry; -import static org.hamcrest.core.IsNot.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - public class CapturedEnvironmentActionTest { @Rule public JenkinsSessionRule j = new JenkinsSessionRule(); @Test - @Issue("SECURITY-2185") //@LocalData + @Issue("SECURITY-2185") // @LocalData public void onLoad() throws Throwable { Assume.assumeFalse("test can not run on windows", Functions.isWindows()); j.then(r -> { - final URL url = CapturedEnvironmentActionTest.class.getResource("/hudson/plugins/parameterizedtrigger/CapturedEnvironmentActionTest/onLoad"); + final URL url = CapturedEnvironmentActionTest.class.getResource( + "/hudson/plugins/parameterizedtrigger/CapturedEnvironmentActionTest/onLoad"); if (url == null) { fail("No test resources found!"); } @@ -59,9 +59,12 @@ public void onLoad() throws Throwable { assertTrue("OldDataMonitor should be active.", monitor.isActivated()); Map data = monitor.getData(); - assertThat(data, - hasEntry(sameInstance(build), - new HasExtra(containsString("AssertionError: " + CapturedEnvironmentAction.OLD_DATA_MESSAGE)))); + assertThat( + data, + hasEntry( + sameInstance(build), + new HasExtra( + containsString("AssertionError: " + CapturedEnvironmentAction.OLD_DATA_MESSAGE)))); build.save(); data = monitor.getData(); @@ -123,9 +126,10 @@ public void describeTo(final Description description) { } @Override - protected void describeMismatchSafely(final OldDataMonitor.VersionRange item, final Description mismatchDescription) { + protected void describeMismatchSafely( + final OldDataMonitor.VersionRange item, final Description mismatchDescription) { mismatchDescription.appendText(" extra was "); valueMatcher.describeMismatch(item, mismatchDescription); } } -} \ No newline at end of file +} diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/AbortedBuilder.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/AbortedBuilder.java index 8cd77158..9d9f281f 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/AbortedBuilder.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/AbortedBuilder.java @@ -7,33 +7,32 @@ import hudson.model.Descriptor; import hudson.model.Result; import hudson.tasks.Builder; +import java.io.IOException; import net.sf.json.JSONObject; import org.kohsuke.stapler.StaplerRequest; -import java.io.IOException; - /** * A Builder which simulates an aborted build. * To use for testing behaviour of Build Results. */ public class AbortedBuilder extends Builder { - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { - listener.getLogger().println("Simulating an aborted build"); - build.setResult(Result.ABORTED); - return true; - } - - @Extension - public static final class DescriptorImpl extends Descriptor { - public DescriptorImpl() { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { + listener.getLogger().println("Simulating an aborted build"); + build.setResult(Result.ABORTED); + return true; } - public String getDisplayName() { - return "Make build aborted"; - } + @Extension + public static final class DescriptorImpl extends Descriptor { + public DescriptorImpl() {} + + public String getDisplayName() { + return "Make build aborted"; + } - public AbortedBuilder newInstance(StaplerRequest req, JSONObject data) { - return new AbortedBuilder(); + public AbortedBuilder newInstance(StaplerRequest req, JSONObject data) { + return new AbortedBuilder(); + } } - } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildInfoExporterTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildInfoExporterTest.java index 1c5bdaa1..87b9df2a 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildInfoExporterTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildInfoExporterTest.java @@ -23,6 +23,13 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; +import static org.hamcrest.collection.IsMapContaining.hasEntry; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + import hudson.EnvVars; import hudson.model.AbstractBuild; import hudson.model.Cause.UserIdCause; @@ -39,34 +46,26 @@ import hudson.plugins.parameterizedtrigger.CurrentBuildParameters; import hudson.plugins.parameterizedtrigger.PredefinedBuildParameters; import hudson.plugins.parameterizedtrigger.TriggerBuilder; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.hamcrest.collection.IsMapContaining.hasEntry; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertNotNull; - import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.BuildWatcher; import org.jvnet.hudson.test.CaptureEnvironmentBuilder; -import org.jvnet.hudson.test.recipes.LocalData; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.recipes.LocalData; public class BuildInfoExporterTest { @Rule public JenkinsRule r = new JenkinsRule(); - - @Rule public BuildWatcher buildWatcher = new BuildWatcher(); + + @Rule + public BuildWatcher buildWatcher = new BuildWatcher(); @Test public void test() throws Exception { @@ -92,13 +91,19 @@ public void test() throws Exception { Run buildB1 = projectB.getBuildByNumber(expectedBuildNumber); EnvVars envVars = builder.getEnvVars(); - //System.out.println("envVars: " + envVars); + // System.out.println("envVars: " + envVars); assertThat(envVars, notNullValue()); assertThat(envVars, hasEntry("LAST_TRIGGERED_JOB_NAME", "projectB")); assertThat(envVars, hasEntry("TRIGGERED_BUILD_NUMBER_projectB", Integer.toString(expectedBuildNumber))); - assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectB", buildB1.getResult().toString())); - assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectB_RUN_" + Integer.toString(expectedBuildNumber), buildB1.getResult().toString())); + assertThat( + envVars, + hasEntry("TRIGGERED_BUILD_RESULT_projectB", buildB1.getResult().toString())); + assertThat( + envVars, + hasEntry( + "TRIGGERED_BUILD_RESULT_projectB_RUN_" + Integer.toString(expectedBuildNumber), + buildB1.getResult().toString())); assertThat(envVars, hasEntry("TRIGGERED_BUILD_RUN_COUNT_projectB", "1")); assertThat(envVars, hasEntry("TRIGGERED_JOB_NAMES", "projectB")); @@ -107,17 +112,23 @@ public void test() throws Exception { assertThat(projectB.getNextBuildNumber(), is(not(expectedBuildNumber))); expectedBuildNumber = projectB.getNextBuildNumber(); - AbstractBuild buildA2 = projectA.scheduleBuild2(0, new UserIdCause()).get(); + AbstractBuild buildA2 = + projectA.scheduleBuild2(0, new UserIdCause()).get(); envVars = builder.getEnvVars(); assertThat(envVars, notNullValue()); assertThat(envVars, hasEntry("LAST_TRIGGERED_JOB_NAME", "projectB")); assertThat(envVars, hasEntry("TRIGGERED_BUILD_NUMBER_projectB", Integer.toString(expectedBuildNumber))); - assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectB", buildA2.getResult().toString())); - assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectB_RUN_" + Integer.toString(expectedBuildNumber), buildA2.getResult().toString())); + assertThat( + envVars, + hasEntry("TRIGGERED_BUILD_RESULT_projectB", buildA2.getResult().toString())); + assertThat( + envVars, + hasEntry( + "TRIGGERED_BUILD_RESULT_projectB_RUN_" + Integer.toString(expectedBuildNumber), + buildA2.getResult().toString())); assertThat(envVars, hasEntry("TRIGGERED_BUILD_RUN_COUNT_projectB", "1")); assertThat(envVars, hasEntry("TRIGGERED_JOB_NAMES", "projectB")); - } @Test @@ -145,11 +156,12 @@ public void test_oddchars() throws Exception { projectA.scheduleBuild2(0, new UserIdCause()).get(); EnvVars envVars = builder.getEnvVars(); - //System.out.println("envVars: " + envVars); + // System.out.println("envVars: " + envVars); assertThat(envVars, notNullValue()); assertThat(envVars, hasEntry("LAST_TRIGGERED_JOB_NAME", testNameResult)); - assertThat(envVars, hasEntry("TRIGGERED_BUILD_NUMBER_" + testNameResult, Integer.toString(expectedBuildNumber))); + assertThat( + envVars, hasEntry("TRIGGERED_BUILD_NUMBER_" + testNameResult, Integer.toString(expectedBuildNumber))); // The below test for expectedBuildNumber is meaningless if the // value doesn't update, though it should always update. @@ -161,7 +173,8 @@ public void test_oddchars() throws Exception { assertThat(envVars, notNullValue()); assertThat(envVars, hasEntry("LAST_TRIGGERED_JOB_NAME", testNameResult)); - assertThat(envVars, hasEntry("TRIGGERED_BUILD_NUMBER_" + testNameResult, Integer.toString(expectedBuildNumber))); + assertThat( + envVars, hasEntry("TRIGGERED_BUILD_NUMBER_" + testNameResult, Integer.toString(expectedBuildNumber))); } @Test @@ -173,12 +186,13 @@ public void test_multipletriggers() throws Exception { Project projectA = r.createFreeStyleProject(); Project projectB = r.createFreeStyleProject(testNameResult); Project projectC = r.createFreeStyleProject(testNameResult2); - projectA.getBuildersList().add( - new TriggerBuilder( - new BlockableBuildTriggerConfig(testNameResult + "," + testNameResult2, - new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), - Collections.singletonList(new CounterBuildParameterFactory("0", Integer.toString(buildsToTest - 1), "1", "TEST=COUNT$COUNT")), - Collections.emptyList()))); + projectA.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + testNameResult + "," + testNameResult2, + new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), + Collections.singletonList(new CounterBuildParameterFactory( + "0", Integer.toString(buildsToTest - 1), "1", "TEST=COUNT$COUNT")), + Collections.emptyList()))); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); projectA.getBuildersList().add(builder); @@ -197,27 +211,27 @@ public void test_multipletriggers() throws Exception { r.waitUntilNoActivity(); EnvVars envVars = builder.getEnvVars(); - //System.out.println("envVars: " + envVars); + // System.out.println("envVars: " + envVars); assertEquals(buildsToTest, projectB.getBuilds().size()); assertEquals(buildsToTest, projectC.getBuilds().size()); String allBuildNumbersB = ""; for (int run = 1, buildNumber = firstExpectedBuildNumberB; run <= buildsToTest; run++, buildNumber++) { - if (allBuildNumbersB.length() > 0) { - allBuildNumbersB += ","; - } - allBuildNumbersB += buildNumber; - assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectB_RUN_" + buildNumber, "SUCCESS")); + if (allBuildNumbersB.length() > 0) { + allBuildNumbersB += ","; + } + allBuildNumbersB += buildNumber; + assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectB_RUN_" + buildNumber, "SUCCESS")); } String allBuildNumbersC = ""; for (int run = 1, buildNumber = firstExpectedBuildNumberC; run <= buildsToTest; run++, buildNumber++) { - if (allBuildNumbersC.length() > 0) { - allBuildNumbersC += ","; - } - allBuildNumbersC += buildNumber; - assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectC_RUN_" + buildNumber, "SUCCESS")); + if (allBuildNumbersC.length() > 0) { + allBuildNumbersC += ","; + } + allBuildNumbersC += buildNumber; + assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectC_RUN_" + buildNumber, "SUCCESS")); } int lastBuildNumberB = firstExpectedBuildNumberB + (buildsToTest - 1); @@ -230,7 +244,6 @@ public void test_multipletriggers() throws Exception { assertThat(envVars, hasEntry("TRIGGERED_JOB_NAMES", testNameResult + "," + testNameResult2)); assertThat(envVars, hasEntry("TRIGGERED_BUILD_NUMBERS_" + testNameResult, allBuildNumbersB)); assertThat(envVars, hasEntry("TRIGGERED_BUILD_NUMBERS_" + testNameResult2, allBuildNumbersC)); - } @Test @@ -241,7 +254,8 @@ public void testNonBlocking() throws Exception { BlockingBehaviour neverFail = new BlockingBehaviour("never", "never", "never"); BlockableBuildTriggerConfig config = new BlockableBuildTriggerConfig("projectB", neverFail, buildParameters); - BlockableBuildTriggerConfig nonBlockingConfig = new BlockableBuildTriggerConfig("projectC", null, buildParameters); + BlockableBuildTriggerConfig nonBlockingConfig = + new BlockableBuildTriggerConfig("projectC", null, buildParameters); projectA.getBuildersList().add(new TriggerBuilder(config, nonBlockingConfig)); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); @@ -265,135 +279,204 @@ public void testNonBlocking() throws Exception { Run buildB1 = projectB.getBuildByNumber(expectedBuildNumber); Run buildC1 = projectC.getBuildByNumber(expectedBuildNumberC); EnvVars envVars = builder.getEnvVars(); - //System.out.println("envVars: " + envVars); + // System.out.println("envVars: " + envVars); assertThat(envVars, notNullValue()); assertThat(envVars, hasEntry("LAST_TRIGGERED_JOB_NAME", "projectB")); assertThat(envVars, hasEntry("TRIGGERED_BUILD_NUMBER_projectB", Integer.toString(expectedBuildNumber))); - assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectB", buildB1.getResult().toString())); - assertThat(envVars, hasEntry("TRIGGERED_BUILD_RESULT_projectB_RUN_" + expectedBuildNumber, buildB1.getResult().toString())); + assertThat( + envVars, + hasEntry("TRIGGERED_BUILD_RESULT_projectB", buildB1.getResult().toString())); + assertThat( + envVars, + hasEntry( + "TRIGGERED_BUILD_RESULT_projectB_RUN_" + expectedBuildNumber, + buildB1.getResult().toString())); assertThat(envVars, hasEntry("TRIGGERED_BUILD_RUN_COUNT_projectB", "1")); assertThat(envVars, hasEntry("TRIGGERED_JOB_NAMES", "projectB")); // check that we don't see entries for projectC assertThat(envVars, not(hasEntry("TRIGGERED_BUILD_NUMBER_projectC", Integer.toString(expectedBuildNumberC)))); - assertThat(envVars, not(hasEntry("TRIGGERED_BUILD_RESULT_projectC_RUN_" + expectedBuildNumberC, buildC1.getResult().toString()))); - + assertThat( + envVars, + not(hasEntry( + "TRIGGERED_BUILD_RESULT_projectC_RUN_" + expectedBuildNumberC, + buildC1.getResult().toString()))); } - + @Test public void testProjectDeleted() throws Exception { FreeStyleProject p1 = r.createFreeStyleProject(); FreeStyleProject p2 = r.createFreeStyleProject(); // Blocked build - p1.getBuildersList().add(new TriggerBuilder(new BlockableBuildTriggerConfig( - p2.getName(), - new BlockingBehaviour( - Result.FAILURE, - Result.UNSTABLE, - Result.FAILURE - ), - Arrays.asList( - new PredefinedBuildParameters("test=test") - ) - ))); + p1.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + p2.getName(), + new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), + Arrays.asList(new PredefinedBuildParameters("test=test"))))); FreeStyleBuild blockedBuild = p1.scheduleBuild2(0).get(); r.assertBuildStatusSuccess(blockedBuild); // Unblocked build p1.getBuildersList().clear(); - p1.getBuildersList().add(new TriggerBuilder(new BlockableBuildTriggerConfig( - p2.getName(), - null, - Arrays.asList( - new PredefinedBuildParameters("test=test") - ) - ))); + p1.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + p2.getName(), + null, + Arrays.asList(new PredefinedBuildParameters("test=test"))))); FreeStyleBuild unblockedBuild = p1.scheduleBuild2(0).get(); r.assertBuildStatusSuccess(unblockedBuild); r.waitUntilNoActivity(); - assertEquals(1, blockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredBuilds().size()); - assertEquals(p2.getBuildByNumber(1), blockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredBuilds().get(0)); - assertEquals(0, blockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredProjects().size()); - - assertEquals(0, unblockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredBuilds().size()); - assertEquals(1, unblockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredProjects().size()); - assertEquals(p2, unblockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredProjects().get(0)); + assertEquals( + 1, + blockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredBuilds() + .size()); + assertEquals( + p2.getBuildByNumber(1), + blockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredBuilds() + .get(0)); + assertEquals( + 0, + blockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredProjects() + .size()); + + assertEquals( + 0, + unblockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredBuilds() + .size()); + assertEquals( + 1, + unblockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredProjects() + .size()); + assertEquals( + p2, + unblockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredProjects() + .get(0)); p2.delete(); - assertEquals(1, blockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredBuilds().size()); - assertNull(blockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredBuilds().get(0)); - assertEquals(0, blockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredProjects().size()); - - assertEquals(0, unblockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredBuilds().size()); - assertEquals(1, unblockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredProjects().size()); - assertNull(unblockedBuild.getAction(BuildInfoExporterAction.class).getTriggeredProjects().get(0)); + assertEquals( + 1, + blockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredBuilds() + .size()); + assertNull(blockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredBuilds() + .get(0)); + assertEquals( + 0, + blockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredProjects() + .size()); + + assertEquals( + 0, + unblockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredBuilds() + .size()); + assertEquals( + 1, + unblockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredProjects() + .size()); + assertNull(unblockedBuild + .getAction(BuildInfoExporterAction.class) + .getTriggeredProjects() + .get(0)); } @LocalData @Test - public void testMigrateFrom221() throws Exception - { + public void testMigrateFrom221() throws Exception { // lastReference should be preserved after migration. String lastReferenceValue = null; { - FreeStyleProject p = r.jenkins.getItemByFullName("upstream", FreeStyleProject.class); - assertNotNull(p); - FreeStyleBuild b = p.getLastBuild(); - assertNotNull(b); - BuildInfoExporterAction action = b.getAction(BuildInfoExporterAction.class); - assertNotNull(action); - - // action should contain following builds: - // downstream1#1 - // downstream1#2 - // downstream2#1 - - Set> expected = new HashSet<>(); - expected.addAll(Arrays.asList(r.jenkins.getItemByFullName("downstream1", FreeStyleProject.class).getBuildByNumber(1), - r.jenkins.getItemByFullName("downstream1", FreeStyleProject.class).getBuildByNumber(2), - r.jenkins.getItemByFullName("downstream2", FreeStyleProject.class).getBuildByNumber(1))); - - assertEquals(expected, new HashSet<>(action.getTriggeredBuilds())); - - EnvVars env = new EnvVars(); - action.buildEnvVars(b, env); - lastReferenceValue = env.get(BuildInfoExporterAction.JOB_NAME_VARIABLE); - assertEquals("downstream1", lastReferenceValue); - - b.save(); + FreeStyleProject p = r.jenkins.getItemByFullName("upstream", FreeStyleProject.class); + assertNotNull(p); + FreeStyleBuild b = p.getLastBuild(); + assertNotNull(b); + BuildInfoExporterAction action = b.getAction(BuildInfoExporterAction.class); + assertNotNull(action); + + // action should contain following builds: + // downstream1#1 + // downstream1#2 + // downstream2#1 + + Set> expected = new HashSet<>(); + expected.addAll(Arrays.asList( + r.jenkins + .getItemByFullName("downstream1", FreeStyleProject.class) + .getBuildByNumber(1), + r.jenkins + .getItemByFullName("downstream1", FreeStyleProject.class) + .getBuildByNumber(2), + r.jenkins + .getItemByFullName("downstream2", FreeStyleProject.class) + .getBuildByNumber(1))); + + assertEquals(expected, new HashSet<>(action.getTriggeredBuilds())); + + EnvVars env = new EnvVars(); + action.buildEnvVars(b, env); + lastReferenceValue = env.get(BuildInfoExporterAction.JOB_NAME_VARIABLE); + assertEquals("downstream1", lastReferenceValue); + + b.save(); } { - FreeStyleProject p = r.jenkins.getItemByFullName("upstream", FreeStyleProject.class); - assertNotNull(p); - FreeStyleBuild b = p.getLastBuild(); - assertNotNull(b); - BuildInfoExporterAction action = b.getAction(BuildInfoExporterAction.class); - assertNotNull(action); - - // action should contain following builds: - // downstream1#1 - // downstream1#2 - // downstream2#1 - - Set> expected = new HashSet<>(); - expected.addAll(Arrays.asList(r.jenkins.getItemByFullName("downstream1", FreeStyleProject.class).getBuildByNumber(1), - r.jenkins.getItemByFullName("downstream1", FreeStyleProject.class).getBuildByNumber(2), - r.jenkins.getItemByFullName("downstream2", FreeStyleProject.class).getBuildByNumber(1))); - - assertEquals(expected, new HashSet<>(action.getTriggeredBuilds()) - ); - - EnvVars env = new EnvVars(); - action.buildEnvVars(b, env); - assertEquals(lastReferenceValue, env.get(BuildInfoExporterAction.JOB_NAME_VARIABLE)); + FreeStyleProject p = r.jenkins.getItemByFullName("upstream", FreeStyleProject.class); + assertNotNull(p); + FreeStyleBuild b = p.getLastBuild(); + assertNotNull(b); + BuildInfoExporterAction action = b.getAction(BuildInfoExporterAction.class); + assertNotNull(action); + + // action should contain following builds: + // downstream1#1 + // downstream1#2 + // downstream2#1 + + Set> expected = new HashSet<>(); + expected.addAll(Arrays.asList( + r.jenkins + .getItemByFullName("downstream1", FreeStyleProject.class) + .getBuildByNumber(1), + r.jenkins + .getItemByFullName("downstream1", FreeStyleProject.class) + .getBuildByNumber(2), + r.jenkins + .getItemByFullName("downstream2", FreeStyleProject.class) + .getBuildByNumber(1))); + + assertEquals(expected, new HashSet<>(action.getTriggeredBuilds())); + + EnvVars env = new EnvVars(); + action.buildEnvVars(b, env); + assertEquals(lastReferenceValue, env.get(BuildInfoExporterAction.JOB_NAME_VARIABLE)); } } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildTriggerConfigTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildTriggerConfigTest.java index 8d320fe8..1664aa3d 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildTriggerConfigTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildTriggerConfigTest.java @@ -24,6 +24,12 @@ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + import hudson.model.AbstractProject; import hudson.model.Cause.UserIdCause; import hudson.model.FreeStyleProject; @@ -48,7 +54,16 @@ import hudson.security.Permission; import hudson.security.ProjectMatrixAuthorizationStrategy; import hudson.util.FormValidation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import jenkins.model.Jenkins; +import jenkins.security.QueueItemAuthenticatorConfiguration; import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; import org.jenkinsci.plugins.workflow.job.WorkflowJob; import org.jenkinsci.plugins.workflow.job.WorkflowRun; @@ -58,22 +73,6 @@ import org.jvnet.hudson.test.CaptureEnvironmentBuilder; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import jenkins.security.QueueItemAuthenticatorConfiguration; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; import org.jvnet.hudson.test.MockAuthorizationStrategy; import org.jvnet.hudson.test.MockQueueItemAuthenticator; @@ -81,11 +80,11 @@ public class BuildTriggerConfigTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Rule public BuildWatcher buildWatcher = new BuildWatcher(); - private BlockableBuildTriggerConfig createConfig(String projectToTrigger){ + private BlockableBuildTriggerConfig createConfig(String projectToTrigger) { List buildParameters = new ArrayList(); buildParameters.add(new CurrentBuildParameters()); BlockingBehaviour neverFail = new BlockingBehaviour("never", "never", "never"); @@ -98,15 +97,32 @@ private void addParameterizedTrigger(Project projectA, BlockableBuildTrigg projectA.getBuildersList().add(builder); } - private void validateOutcome(Project project, BuildTriggerConfig config, - int fixedExpected, int dynamicExpected, int triggeredExpected, int unresolvedExpected) { + private void validateOutcome( + Project project, + BuildTriggerConfig config, + int fixedExpected, + int dynamicExpected, + int triggeredExpected, + int unresolvedExpected) { SubProjectData subProjectData = config.getProjectInfo(project); - assertEquals("Not the expected number of fixed project(s)", fixedExpected, subProjectData.getFixed().size()); - assertEquals("Not the expected number of dynamic project(s)", dynamicExpected, subProjectData.getDynamic().size()); - assertEquals("Not the expected number of triggered project(s)", triggeredExpected, subProjectData.getTriggered().size()); - assertEquals("Not the expected number of unresolved project(s)", unresolvedExpected, subProjectData.getUnresolved().size()); + assertEquals( + "Not the expected number of fixed project(s)", + fixedExpected, + subProjectData.getFixed().size()); + assertEquals( + "Not the expected number of dynamic project(s)", + dynamicExpected, + subProjectData.getDynamic().size()); + assertEquals( + "Not the expected number of triggered project(s)", + triggeredExpected, + subProjectData.getTriggered().size()); + assertEquals( + "Not the expected number of unresolved project(s)", + unresolvedExpected, + subProjectData.getUnresolved().size()); } /** @@ -131,7 +147,6 @@ public void testGetProjectListDynamic() throws Exception { // Expects 1 dynamic and 1 unresolved project validateOutcome(masterProject, masterConfig, 0, 1, 0, 1); - } /** @@ -156,7 +171,6 @@ public void testGetProjectListStatic() throws Exception { // Expects 1 fixed and 1 unresolved project validateOutcome(masterProject, masterConfig, 1, 0, 0, 1); - } @Test @@ -192,7 +206,7 @@ public void testBuildWithWorkflowProjects() throws Exception { workflowProject.setDefinition(new CpsFlowDefinition("node { echo myParam; }", false)); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("myParam","myParam")); + definition.add(new StringParameterDefinition("myParam", "myParam")); workflowProject.addProperty(new ParametersDefinitionProperty(definition)); // Trigger a normal and workflow project @@ -204,7 +218,8 @@ public void testBuildWithWorkflowProjects() throws Exception { buildParameters.add(customParams); BlockingBehaviour neverFail = new BlockingBehaviour("never", "never", "never"); - BlockableBuildTriggerConfig masterConfig = new BlockableBuildTriggerConfig(projectToTrigger, neverFail, buildParameters); + BlockableBuildTriggerConfig masterConfig = + new BlockableBuildTriggerConfig(projectToTrigger, neverFail, buildParameters); addParameterizedTrigger(masterProject, masterConfig); @@ -242,7 +257,7 @@ public void testShouldNotFailOnDiscoverWithoutReadPermission() throws Exception addParameterizedTrigger(upstreamProject, triggerConfig); // Setup upstream project security - Map> permissions = new HashMap>(); + Map> permissions = new HashMap>(); Set userIds = new HashSet(Arrays.asList("testUser")); permissions.put(Item.READ, userIds); AuthorizationMatrixProperty projectPermissions = new AuthorizationMatrixProperty(permissions); @@ -253,7 +268,8 @@ public void testShouldNotFailOnDiscoverWithoutReadPermission() throws Exception @Override public void run() { SubProjectData projectInfo = triggerConfig.getProjectInfo(upstreamProject); - assertTrue("Downstream project should be unresolved, because testUser has no READ permission", + assertTrue( + "Downstream project should be unresolved, because testUser has no READ permission", projectInfo.getUnresolved().contains(downstreamProject.getName())); } }); @@ -264,7 +280,8 @@ public void run() { @Override public void run() { SubProjectData projectInfo = triggerConfig.getProjectInfo(upstreamProject); - assertTrue("Downstream project should be unresolved, because testUser has no READ permission", + assertTrue( + "Downstream project should be unresolved, because testUser has no READ permission", projectInfo.getUnresolved().contains(downstreamProject.getName())); } }); @@ -292,7 +309,6 @@ public void testGetProjectListMix() throws Exception { // Expects 1 fixed and 1 unresolved project validateOutcome(masterProject, masterConfig, 1, 1, 0, 0); - } /** @@ -324,14 +340,15 @@ public void testGetProjectListTriggered() throws Exception { // Expects 1 fixed and 1 triggered project validateOutcome(masterProject, masterConfig, 1, 0, 1, 0); - } @Test public void testBlankConfig() throws Exception { Project masterProject = r.createFreeStyleProject("project"); - FormValidation form = r.jenkins.getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class).doCheckProjects(masterProject, ""); + FormValidation form = r.jenkins + .getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class) + .doCheckProjects(masterProject, ""); assertEquals(FormValidation.Kind.ERROR, form.kind); } @@ -340,7 +357,9 @@ public void testBlankConfig() throws Exception { public void testNonExistedProject() throws Exception { Project masterProject = r.createFreeStyleProject("project"); - FormValidation form = r.jenkins.getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class).doCheckProjects(masterProject, "nonExistedProject"); + FormValidation form = r.jenkins + .getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class) + .doCheckProjects(masterProject, "nonExistedProject"); assertEquals(FormValidation.Kind.ERROR, form.kind); } @@ -349,7 +368,9 @@ public void testNonExistedProject() throws Exception { public void testValidConfig() throws Exception { Project masterProject = r.createFreeStyleProject("project"); - FormValidation form = r.jenkins.getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class).doCheckProjects(masterProject, "project"); + FormValidation form = r.jenkins + .getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class) + .doCheckProjects(masterProject, "project"); assertEquals(FormValidation.Kind.OK, form.kind); } @@ -358,7 +379,9 @@ public void testValidConfig() throws Exception { public void testBlankProjectNameInConfig() throws Exception { Project masterProject = r.createFreeStyleProject("project"); - FormValidation form = r.jenkins.getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class).doCheckProjects(masterProject, "project, "); + FormValidation form = r.jenkins + .getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class) + .doCheckProjects(masterProject, "project, "); assertEquals(FormValidation.Kind.ERROR, form.kind); } @@ -367,13 +390,14 @@ public void testBlankProjectNameInConfig() throws Exception { @Test public void testFieldValidation() throws Exception { FreeStyleProject p = r.createFreeStyleProject("project"); - BuildTriggerConfig.DescriptorImpl descriptor = r.jenkins.getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class); + BuildTriggerConfig.DescriptorImpl descriptor = + r.jenkins.getDescriptorByType(BuildTriggerConfig.DescriptorImpl.class); assertNotNull(descriptor); // Valid value, Empty Value assertSame(FormValidation.Kind.OK, descriptor.doCheckProjects(p, p.getFullName()).kind); assertSame(FormValidation.Kind.ERROR, descriptor.doCheckProjects(p, "FOO").kind); assertSame(FormValidation.Kind.ERROR, descriptor.doCheckProjects(p, "").kind); - //JENKINS-32526: Check that it behaves gracefully for an unknown context. + // JENKINS-32526: Check that it behaves gracefully for an unknown context. assertSame(FormValidation.Kind.OK, descriptor.doCheckProjects(null, p.getFullName()).kind); assertSame(FormValidation.Kind.OK, descriptor.doCheckProjects(null, "FOO").kind); assertSame(FormValidation.Kind.OK, descriptor.doCheckProjects(null, "").kind); @@ -386,9 +410,15 @@ public void testFieldValidation() throws Exception { } r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); - QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(new MockQueueItemAuthenticator(Collections.singletonMap("project", User.get("alice").impersonate()))); + QueueItemAuthenticatorConfiguration.get() + .getAuthenticators() + .add(new MockQueueItemAuthenticator( + Collections.singletonMap("project", User.get("alice").impersonate()))); FreeStyleProject other = r.createFreeStyleProject("other"); - MockAuthorizationStrategy auth = new MockAuthorizationStrategy().grant(Jenkins.READ, Item.READ).onItems(other).to("alice"); + MockAuthorizationStrategy auth = new MockAuthorizationStrategy() + .grant(Jenkins.READ, Item.READ) + .onItems(other) + .to("alice"); r.jenkins.setAuthorizationStrategy(auth); assertSame(FormValidation.Kind.ERROR, descriptor.doCheckProjects(p, "other").kind); auth.grant(Item.BUILD).onItems(other).to("alice"); diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildTriggerTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildTriggerTest.java index 8aa49ae0..050eb2e4 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildTriggerTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/BuildTriggerTest.java @@ -1,5 +1,7 @@ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.*; + import hudson.AbortException; import hudson.FilePath; import hudson.Launcher; @@ -24,19 +26,16 @@ import hudson.plugins.parameterizedtrigger.CurrentBuildParameters; import hudson.plugins.parameterizedtrigger.FileBuildParameters; import hudson.plugins.parameterizedtrigger.ResultCondition; +import hudson.tasks.Builder; import hudson.util.FormValidation; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; - -import static org.junit.Assert.*; - +import java.util.logging.Level; import org.junit.Rule; import org.junit.Test; -import hudson.tasks.Builder; -import java.util.logging.Level; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.LoggerRule; @@ -45,26 +44,27 @@ * @author Lucie Votypkova */ public class BuildTriggerTest { - + @Rule public JenkinsRule r = new JenkinsRule(); @Rule public LoggerRule logging = new LoggerRule().record(Run.class, Level.FINE); - + @Test public void testParentProjectTrigger() throws Exception { FreeStyleProject downstream = r.createFreeStyleProject("downstream"); MatrixProject upstream = r.createProject(MatrixProject.class, "upstream"); List definition = new ArrayList(); - definition.add(new StringParameterDefinition("parameter","parameter-value")); + definition.add(new StringParameterDefinition("parameter", "parameter-value")); upstream.addProperty(new ParametersDefinitionProperty(definition)); AxisList axes = new AxisList(); - axes.add(new TextAxis("textAxis","one","two")); + axes.add(new TextAxis("textAxis", "one", "two")); upstream.setAxes(axes); List params = new ArrayList(); params.add(new CurrentBuildParameters()); - BuildTrigger triggerBuilder = new BuildTrigger(new BuildTriggerConfig("downstream", ResultCondition.SUCCESS, false, null, params, false)); + BuildTrigger triggerBuilder = new BuildTrigger( + new BuildTriggerConfig("downstream", ResultCondition.SUCCESS, false, null, params, false)); upstream.getPublishersList().add(triggerBuilder); /* @@ -77,40 +77,42 @@ public void testParentProjectTrigger() throws Exception { r.buildAndAssertSuccess(upstream); r.waitUntilNoActivity(); - String project = downstream.getLastBuild().getCause(Cause.UpstreamCause.class).getUpstreamProject(); + String project = + downstream.getLastBuild().getCause(Cause.UpstreamCause.class).getUpstreamProject(); assertEquals("Build should be triggered by matrix project.", "upstream", project); } - + @Test public void testChildProjectsTrigger() throws Exception { MatrixProject upstream = r.createProject(MatrixProject.class, "upstream"); FreeStyleProject downstream = r.createFreeStyleProject("downstream"); List definition = new ArrayList(); - definition.add(new StringParameterDefinition("parameter","parameter-value")); + definition.add(new StringParameterDefinition("parameter", "parameter-value")); ParametersDefinitionProperty property = new ParametersDefinitionProperty(definition); upstream.addProperty(property); - + AxisList axes = new AxisList(); - axes.add(new TextAxis("textAxis","a","b")); + axes.add(new TextAxis("textAxis", "a", "b")); upstream.setAxes(axes); upstream.getBuildersList().add(new CreatePropertyFileBuilder()); DefaultMatrixExecutionStrategyImpl strategy = new DefaultMatrixExecutionStrategyImpl(true, null, null, null); upstream.setExecutionStrategy(strategy); - + List params = new ArrayList(); params.add(new CurrentBuildParameters()); List parameters = new ArrayList(); parameters.add(new FileBuildParameters("property.prop", null, false, true, null, false)); - BuildTriggerConfig config = new BuildTriggerConfig("downstream", ResultCondition.SUCCESS, false, parameters, true); + BuildTriggerConfig config = + new BuildTriggerConfig("downstream", ResultCondition.SUCCESS, false, parameters, true); BuildTrigger triggerBuilder = new BuildTrigger(config); upstream.getPublishersList().add(triggerBuilder); r.jenkins.rebuildDependencyGraph(); strategy.setSorter(new MatrixConfigurationSorterTestImpl()); - + r.buildAndAssertSuccess(upstream); r.waitUntilNoActivity(); - + FreeStyleBuild downstreamBuild2 = downstream.getLastBuild(); FreeStyleBuild downstreamBuild1 = downstreamBuild2.getPreviousBuild(); assertNotNull("Downstream job should be triggered by matrix configuration", downstreamBuild1); @@ -120,28 +122,34 @@ public void testChildProjectsTrigger() throws Exception { String project2 = downstreamBuild2.getCause(Cause.UpstreamCause.class).getUpstreamProject(); ArrayList configurations = new ArrayList<>(upstream.getItems()); Collections.sort(configurations, new MatrixConfigurationSorterTestImpl()); - assertEquals("Build should be triggered by matrix project.", configurations.get(0).getFullName(), project1); - assertEquals("Build should be triggered by matrix project.", configurations.get(1).getFullName(), project2); + assertEquals( + "Build should be triggered by matrix project.", + configurations.get(0).getFullName(), + project1); + assertEquals( + "Build should be triggered by matrix project.", + configurations.get(1).getFullName(), + project2); } - + public static class MatrixConfigurationSorterTestImpl extends MatrixConfigurationSorter implements Serializable { @Override public void validate(MatrixProject mp) throws FormValidation { - //do nothing + // do nothing } @Override public int compare(MatrixConfiguration o1, MatrixConfiguration o2) { return o1.getName().compareTo(o2.getName()); } - } - + public static class CreatePropertyFileBuilder extends Builder { - + @Override - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { listener.getLogger().println("Creating a file property.prop"); FilePath workspace = build.getWorkspace(); @@ -153,5 +161,4 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen return true; } } - } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/CaptureAllEnvironmentBuilder.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/CaptureAllEnvironmentBuilder.java index 81f48452..0000c2d6 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/CaptureAllEnvironmentBuilder.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/CaptureAllEnvironmentBuilder.java @@ -7,24 +7,24 @@ import hudson.model.BuildListener; import hudson.model.Descriptor; import hudson.tasks.Builder; -import net.sf.json.JSONObject; -import org.kohsuke.stapler.StaplerRequest; - import java.io.IOException; import java.util.HashMap; import java.util.Map; +import net.sf.json.JSONObject; +import org.kohsuke.stapler.StaplerRequest; /** * @author wolfs */ public class CaptureAllEnvironmentBuilder extends Builder { - private final Map envVars = new HashMap<>(); + private final Map envVars = new HashMap<>(); - public Map getEnvVars() { - return envVars; - } + public Map getEnvVars() { + return envVars; + } - public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { envVars.put(build.getId(), build.getEnvironment(listener)); return true; } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/CompatibilityTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/CompatibilityTest.java index 61276025..0a6c6d08 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/CompatibilityTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/CompatibilityTest.java @@ -1,49 +1,47 @@ -/* - * The MIT License - * - * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package hudson.plugins.parameterizedtrigger.test; - -import hudson.model.AbstractProject; -import hudson.plugins.parameterizedtrigger.BuildTrigger; - -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.recipes.LocalData; - -import static org.junit.Assert.assertEquals; - -public class CompatibilityTest { - - @Rule - public JenkinsRule r = new JenkinsRule(); - - @LocalData - @Test - public void test() throws Exception { - AbstractProject p = (AbstractProject) r.jenkins.getItem("old"); - BuildTrigger trigger = (BuildTrigger) p.getPublishersList().get(BuildTrigger.class); - assertEquals(2, trigger.getConfigs().size()); - } - -} +/* + * The MIT License + * + * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.plugins.parameterizedtrigger.test; + +import static org.junit.Assert.assertEquals; + +import hudson.model.AbstractProject; +import hudson.plugins.parameterizedtrigger.BuildTrigger; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.recipes.LocalData; + +public class CompatibilityTest { + + @Rule + public JenkinsRule r = new JenkinsRule(); + + @LocalData + @Test + public void test() throws Exception { + AbstractProject p = (AbstractProject) r.jenkins.getItem("old"); + BuildTrigger trigger = (BuildTrigger) p.getPublishersList().get(BuildTrigger.class); + assertEquals(2, trigger.getConfigs().size()); + } +} diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/ConfigurationRoundtripTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/ConfigurationRoundtripTest.java index e5274ef1..7e47e53d 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/ConfigurationRoundtripTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/ConfigurationRoundtripTest.java @@ -31,27 +31,27 @@ * @author Kohsuke Kawaguchi */ public class ConfigurationRoundtripTest { - + @Rule public JenkinsRule r = new JenkinsRule(); - + @Test public void testConfigRoundtrip() throws Exception { -/* poorly written core breaks this test, so this is not yet testable. - FreeStyleProject p = createFreeStyleProject(); - BuildTrigger orig = new BuildTrigger( - // try 0, 1, and 2 build parameters - new BuildTriggerConfig("x", ResultCondition.ALWAYS), - new BuildTriggerConfig("y", ResultCondition.FAILED, - new FileBuildParameters("foo")), - new BuildTriggerConfig("z", ResultCondition.UNSTABLE_OR_BETTER, - new CurrentBuildParameters(), - new SubversionRevisionBuildParameters())); - p.getPublishersList().add(orig); - submit(createWebClient().getPage(p,"configure").getFormByName("config")); + /* poorly written core breaks this test, so this is not yet testable. + FreeStyleProject p = createFreeStyleProject(); + BuildTrigger orig = new BuildTrigger( + // try 0, 1, and 2 build parameters + new BuildTriggerConfig("x", ResultCondition.ALWAYS), + new BuildTriggerConfig("y", ResultCondition.FAILED, + new FileBuildParameters("foo")), + new BuildTriggerConfig("z", ResultCondition.UNSTABLE_OR_BETTER, + new CurrentBuildParameters(), + new SubversionRevisionBuildParameters())); + p.getPublishersList().add(orig); + submit(createWebClient().getPage(p,"configure").getFormByName("config")); - // TODO: switch to assertEqualDataBoundBeans in newer Hudson test harness. - assertEqualBeans(orig, p.getPublishersList().get(BuildTrigger.class), "configs"); -*/ + // TODO: switch to assertEqualDataBoundBeans in newer Hudson test harness. + assertEqualBeans(orig, p.getPublishersList().get(BuildTrigger.class), "configs"); + */ } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/CounterBuildParameterFactoryTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/CounterBuildParameterFactoryTest.java index 62462a44..ffc74295 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/CounterBuildParameterFactoryTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/CounterBuildParameterFactoryTest.java @@ -1,55 +1,53 @@ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import hudson.EnvVars; import hudson.model.Cause.UserIdCause; import hudson.model.FreeStyleBuild; import hudson.model.ParameterDefinition; import hudson.model.ParametersDefinitionProperty; import hudson.model.Project; -import hudson.model.StringParameterDefinition; import hudson.model.Result; +import hudson.model.StringParameterDefinition; import hudson.plugins.parameterizedtrigger.AbstractBuildParameters; import hudson.plugins.parameterizedtrigger.BlockableBuildTriggerConfig; import hudson.plugins.parameterizedtrigger.BlockingBehaviour; import hudson.plugins.parameterizedtrigger.CounterBuildParameterFactory; import hudson.plugins.parameterizedtrigger.TriggerBuilder; - -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.JenkinsRule; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; public class CounterBuildParameterFactoryTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test public void testWithOneParameter() throws Exception { - Project projectA = r.createFreeStyleProject(); + Project projectA = r.createFreeStyleProject(); Project projectB = r.createFreeStyleProject(); - projectA.getBuildersList().add( - new TriggerBuilder( - new BlockableBuildTriggerConfig(projectB.getName(), - new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), - Collections.singletonList(new CounterBuildParameterFactory("0","1","1", "TEST=COUNT$COUNT")), - Collections.emptyList()))); + projectA.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + projectB.getName(), + new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), + Collections.singletonList(new CounterBuildParameterFactory("0", "1", "1", "TEST=COUNT$COUNT")), + Collections.emptyList()))); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); projectB.setQuietPeriod(0); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("TEST","test")); + definition.add(new StringParameterDefinition("TEST", "test")); projectB.addProperty(new ParametersDefinitionProperty(definition)); r.jenkins.rebuildDependencyGraph(); @@ -63,22 +61,21 @@ public void testWithOneParameter() throws Exception { assertTrue(buildEnvVar.containsKey("TEST")); values.add(buildEnvVar.get("TEST")); } - assertEquals(new HashSet<>(Arrays.asList("COUNT0","COUNT1")), values); + assertEquals(new HashSet<>(Arrays.asList("COUNT0", "COUNT1")), values); } @Test public void testWithTwoParameters() throws Exception { - Project projectA = r.createFreeStyleProject(); + Project projectA = r.createFreeStyleProject(); Project projectB = r.createFreeStyleProject(); - projectA.getBuildersList().add( - new TriggerBuilder( - new BlockableBuildTriggerConfig(projectB.getName(), - new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), - Arrays.asList( - new CounterBuildParameterFactory("0","1","1", "TEST=COUNT$COUNT"), - new CounterBuildParameterFactory("0","2","1", "NEWTEST=COUNT$COUNT") - ), - Collections.emptyList()))); + projectA.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + projectB.getName(), + new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), + Arrays.asList( + new CounterBuildParameterFactory("0", "1", "1", "TEST=COUNT$COUNT"), + new CounterBuildParameterFactory("0", "2", "1", "NEWTEST=COUNT$COUNT")), + Collections.emptyList()))); projectB.setConcurrentBuild(true); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); @@ -86,8 +83,8 @@ public void testWithTwoParameters() throws Exception { projectB.setQuietPeriod(0); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("TEST","test")); - definition.add(new StringParameterDefinition("NEWTEST","newtest")); + definition.add(new StringParameterDefinition("TEST", "test")); + definition.add(new StringParameterDefinition("NEWTEST", "newtest")); projectB.addProperty(new ParametersDefinitionProperty(definition)); r.jenkins.rebuildDependencyGraph(); @@ -104,8 +101,7 @@ public void testWithTwoParameters() throws Exception { values.add(buildEnvVar.get("TEST")); newValues.add(buildEnvVar.get("NEWTEST")); } - assertEquals(new HashSet<>(Arrays.asList("COUNT0","COUNT1")), values); + assertEquals(new HashSet<>(Arrays.asList("COUNT0", "COUNT1")), values); assertEquals(new HashSet<>(Arrays.asList("COUNT0", "COUNT1", "COUNT2")), newValues); } - } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/CounterBuildParameterFactoryUnitTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/CounterBuildParameterFactoryUnitTest.java index 81e27f70..04a8d824 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/CounterBuildParameterFactoryUnitTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/CounterBuildParameterFactoryUnitTest.java @@ -1,18 +1,17 @@ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + import hudson.EnvVars; import hudson.model.AbstractBuild; import hudson.model.TaskListener; import hudson.plugins.parameterizedtrigger.AbstractBuildParameters; import hudson.plugins.parameterizedtrigger.CounterBuildParameterFactory; import hudson.plugins.parameterizedtrigger.CounterBuildParameterFactory.SteppingValidationEnum; -import org.junit.Test; - import java.io.IOException; import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; +import org.junit.Test; /** * @@ -22,71 +21,72 @@ public class CounterBuildParameterFactoryUnitTest { @Test public void countingShouldWork() throws Exception { - List parameters = getParameters(1,2,1); + List parameters = getParameters(1, 2, 1); assertEquals(2, parameters.size()); } @Test public void countingWithNegativeIncrementShouldWork() throws Exception { - List parameters = getParameters(2,1,-1); + List parameters = getParameters(2, 1, -1); assertEquals(2, parameters.size()); } @Test public void countingWithBigNegativeIncrementShouldWork() throws Exception { - List parameters = getParameters(2,1,-3); + List parameters = getParameters(2, 1, -3); assertEquals(1, parameters.size()); } @Test(expected = RuntimeException.class) public void countingWithNoIncrementShouldNotWork() throws Exception { - getParameters(1,2,0); + getParameters(1, 2, 0); } @Test public void countingWithNoIncrementOnlyOneElement() throws Exception { // step is ignored if from and to are equal - List parameters = getParameters(1,1,0); + List parameters = getParameters(1, 1, 0); assertEquals(1, parameters.size()); } @Test public void countingWhenFromToIsSameShouldWork() throws Exception { - List parameters = getParameters(1,1,1); + List parameters = getParameters(1, 1, 1); assertEquals(1, parameters.size()); } @Test(expected = RuntimeException.class) public void countingWithNoIncrementShouldNotWork1() throws Exception { - getParameters(1,2,0,SteppingValidationEnum.FAIL); + getParameters(1, 2, 0, SteppingValidationEnum.FAIL); } @Test(expected = AbstractBuildParameters.DontTriggerException.class) public void countingWithNoIncrementShouldNotWork2() throws Exception { - getParameters(1,2,0,SteppingValidationEnum.SKIP); - + getParameters(1, 2, 0, SteppingValidationEnum.SKIP); } @Test public void countingWithNoIncrementShouldNotWork3() throws Exception { - List parameters = getParameters(1,2,0,SteppingValidationEnum.NOPARMS); + List parameters = getParameters(1, 2, 0, SteppingValidationEnum.NOPARMS); assertEquals(0, parameters.size()); } - private List getParameters(long from, long to, long step) throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { + private List getParameters(long from, long to, long step) + throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { return getParameters(from, to, step, SteppingValidationEnum.FAIL); } - private List getParameters(long from, long to, long step, SteppingValidationEnum validationFailure) throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { - AbstractBuild build = mock(AbstractBuild.class); + private List getParameters( + long from, long to, long step, SteppingValidationEnum validationFailure) + throws IOException, InterruptedException, AbstractBuildParameters.DontTriggerException { + AbstractBuild build = mock(AbstractBuild.class); EnvVars vars = new EnvVars(); TaskListener listener = mock(TaskListener.class); when(build.getEnvironment(listener)).thenReturn(vars); when(listener.getLogger()).thenReturn(System.out); - CounterBuildParameterFactory counterFactory = new CounterBuildParameterFactory(from,to,step,"",validationFailure); + CounterBuildParameterFactory counterFactory = + new CounterBuildParameterFactory(from, to, step, "", validationFailure); return counterFactory.getParameters(build, listener); } - - } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/CurrentBuildParametersTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/CurrentBuildParametersTest.java index acfe5c16..b6dada56 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/CurrentBuildParametersTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/CurrentBuildParametersTest.java @@ -23,9 +23,14 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import hudson.model.Cause.UserIdCause; -import hudson.model.ParametersAction; import hudson.model.ParameterDefinition; +import hudson.model.ParametersAction; import hudson.model.ParametersDefinitionProperty; import hudson.model.Project; import hudson.model.StringParameterDefinition; @@ -37,135 +42,138 @@ import hudson.plugins.parameterizedtrigger.CurrentBuildParameters; import hudson.plugins.parameterizedtrigger.ResultCondition; import hudson.plugins.parameterizedtrigger.TriggerBuilder; - import java.util.ArrayList; import java.util.List; - -import org.jvnet.hudson.test.JenkinsRule; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.CaptureEnvironmentBuilder; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import org.jvnet.hudson.test.JenkinsRule; public class CurrentBuildParametersTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test - public void test() throws Exception { - Project projectA = r.createFreeStyleProject("projectA"); - // SECURITY-170: must define parameters in subjobs + public void test() throws Exception { + Project projectA = r.createFreeStyleProject("projectA"); + // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("KEY","key")); - projectA.addProperty(new ParametersDefinitionProperty(definition)); - projectA.getPublishersList().add( - new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new CurrentBuildParameters()))); - - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); + definition.add(new StringParameterDefinition("KEY", "key")); + projectA.addProperty(new ParametersDefinitionProperty(definition)); + projectA.getPublishersList() + .add(new BuildTrigger( + new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new CurrentBuildParameters()))); + + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); projectB.addProperty(new ParametersDefinitionProperty(definition)); - r.jenkins.rebuildDependencyGraph(); - - projectA.scheduleBuild2(0, new UserIdCause(), new ParametersAction( - new StringParameterValue("KEY", "value"))).get(); - r.jenkins.getQueue().getItem(projectB).getFuture().get(); - - assertNotNull("builder should record environment", builder.getEnvVars()); - assertEquals("value", builder.getEnvVars().get("KEY")); - - // Now rename projectB and confirm projectA's build trigger is updated automatically: - projectB.renameTo("new-projectB"); - assertEquals("rename in trigger", "new-projectB", projectA.getPublishersList() - .get(BuildTrigger.class).getConfigs().get(0).getProjects()); - - // Now delete projectB and confirm projectA's build trigger is updated automatically: - projectB.delete(); - assertNull("now-empty trigger should be removed", - projectA.getPublishersList().get(BuildTrigger.class)); - } - - /** - * Project A: Post-build build-trigger - * + currentBuildParameters - * + no parameters defined - * + Trigger Build without parameters = false - * => Project B should NOT be triggered - * - * @throws Exception - */ + r.jenkins.rebuildDependencyGraph(); + + projectA.scheduleBuild2(0, new UserIdCause(), new ParametersAction(new StringParameterValue("KEY", "value"))) + .get(); + r.jenkins.getQueue().getItem(projectB).getFuture().get(); + + assertNotNull("builder should record environment", builder.getEnvVars()); + assertEquals("value", builder.getEnvVars().get("KEY")); + + // Now rename projectB and confirm projectA's build trigger is updated automatically: + projectB.renameTo("new-projectB"); + assertEquals( + "rename in trigger", + "new-projectB", + projectA.getPublishersList() + .get(BuildTrigger.class) + .getConfigs() + .get(0) + .getProjects()); + + // Now delete projectB and confirm projectA's build trigger is updated automatically: + projectB.delete(); + assertNull( + "now-empty trigger should be removed", + projectA.getPublishersList().get(BuildTrigger.class)); + } + + /** + * Project A: Post-build build-trigger + * + currentBuildParameters + * + no parameters defined + * + Trigger Build without parameters = false + * => Project B should NOT be triggered + * + * @throws Exception + */ @Test - public void testPostBuildTriggerNoParametersWithoutParametersFalse() throws Exception { - testPostBuildTriggerNoParameters(false); - } - - /** - * Project A: Post-build build-trigger - * + currentBuildParameters - * + no parameters defined - * + Trigger Build without parameters = true - * => Project B should be triggered - * - * @throws Exception - */ + public void testPostBuildTriggerNoParametersWithoutParametersFalse() throws Exception { + testPostBuildTriggerNoParameters(false); + } + + /** + * Project A: Post-build build-trigger + * + currentBuildParameters + * + no parameters defined + * + Trigger Build without parameters = true + * => Project B should be triggered + * + * @throws Exception + */ @Test - public void testPostBuildTriggerNoParametersWithoutParametersTrue() throws Exception { - testPostBuildTriggerNoParameters(true); - } - - public void testPostBuildTriggerNoParameters(boolean pWithoutParameters) throws Exception { - Project projectA = r.createFreeStyleProject("projectA"); - List buildParameters = new ArrayList(); - buildParameters.add(new CurrentBuildParameters()); - projectA.getPublishersList().add(new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, pWithoutParameters, buildParameters))); - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); - r.jenkins.rebuildDependencyGraph(); - - projectA.scheduleBuild2(0, new UserIdCause()).get(); - assertEquals(pWithoutParameters, r.jenkins.getQueue().contains(projectB)); - List log = projectA.getLastBuild().getLog(20); - for (String string : log) { - System.out.println(string); - } - } - - /** - * Project A: Build step trigger build - * + currentBuildParameters - * + no parameters defined - * => Project B should be triggered - * - * @throws Exception - */ + public void testPostBuildTriggerNoParametersWithoutParametersTrue() throws Exception { + testPostBuildTriggerNoParameters(true); + } + + public void testPostBuildTriggerNoParameters(boolean pWithoutParameters) throws Exception { + Project projectA = r.createFreeStyleProject("projectA"); + List buildParameters = new ArrayList(); + buildParameters.add(new CurrentBuildParameters()); + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", ResultCondition.SUCCESS, pWithoutParameters, buildParameters))); + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); + r.jenkins.rebuildDependencyGraph(); + + projectA.scheduleBuild2(0, new UserIdCause()).get(); + assertEquals(pWithoutParameters, r.jenkins.getQueue().contains(projectB)); + List log = projectA.getLastBuild().getLog(20); + for (String string : log) { + System.out.println(string); + } + } + + /** + * Project A: Build step trigger build + * + currentBuildParameters + * + no parameters defined + * => Project B should be triggered + * + * @throws Exception + */ @Test - public void testBuildStepTriggerBuildNoParameters() throws Exception { - Project projectA = r.createFreeStyleProject("projectA"); - List buildParameters = new ArrayList(); - buildParameters.add(new CurrentBuildParameters()); - projectA.getBuildersList().add(new TriggerBuilder(new BlockableBuildTriggerConfig("projectB", null, buildParameters))); - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); - r.jenkins.rebuildDependencyGraph(); - - projectA.scheduleBuild2(0, new UserIdCause()).get(); - assertTrue(r.jenkins.getQueue().contains(projectB)); - List log = projectA.getLastBuild().getLog(20); - for (String string : log) { - System.out.println(string); - } - } - + public void testBuildStepTriggerBuildNoParameters() throws Exception { + Project projectA = r.createFreeStyleProject("projectA"); + List buildParameters = new ArrayList(); + buildParameters.add(new CurrentBuildParameters()); + projectA.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig("projectB", null, buildParameters))); + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); + r.jenkins.rebuildDependencyGraph(); + + projectA.scheduleBuild2(0, new UserIdCause()).get(); + assertTrue(r.jenkins.getQueue().contains(projectB)); + List log = projectA.getLastBuild().getLog(20); + for (String string : log) { + System.out.println(string); + } + } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/DefaultParameterValuesActionsTransformTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/DefaultParameterValuesActionsTransformTest.java index ff4165a0..718fe9da 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/DefaultParameterValuesActionsTransformTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/DefaultParameterValuesActionsTransformTest.java @@ -1,40 +1,34 @@ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import hudson.model.ParameterValue; import hudson.model.ParametersAction; import hudson.model.ParametersDefinitionProperty; -import hudson.model.ParameterValue; +import hudson.model.Project; import hudson.model.StringParameterDefinition; import hudson.model.StringParameterValue; -import hudson.model.Project; import hudson.plugins.parameterizedtrigger.DefaultParameterValuesActionsTransform; - import java.io.IOException; - import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - public class DefaultParameterValuesActionsTransformTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test public void test() throws IOException { Project project = r.createFreeStyleProject("project"); project.addProperty(new ParametersDefinitionProperty( - new StringParameterDefinition("key1", "value1"), - new StringParameterDefinition("key2", "value2") - )); + new StringParameterDefinition("key1", "value1"), new StringParameterDefinition("key2", "value2"))); ParametersAction action = new ParametersAction( - new StringParameterValue("key2", "not-value2"), - new StringParameterValue("key3", "value3") - ); + new StringParameterValue("key2", "not-value2"), new StringParameterValue("key3", "value3")); DefaultParameterValuesActionsTransform transform = new DefaultParameterValuesActionsTransform(); @@ -51,10 +45,7 @@ private static void assertStringParameterValueEquals(String expected, ParameterV if (actual == null) { fail("ParameterValue is Null"); } else { - assertEquals( - expected, - ((StringParameterValue)actual).value - ); + assertEquals(expected, ((StringParameterValue) actual).value); } } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/DefaultParametersTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/DefaultParametersTest.java index 2c59630d..f46fcb2f 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/DefaultParametersTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/DefaultParametersTest.java @@ -23,6 +23,9 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + import hudson.EnvVars; import hudson.model.Cause.UserIdCause; import hudson.model.ParametersAction; @@ -37,46 +40,40 @@ import hudson.plugins.parameterizedtrigger.CurrentBuildParameters; import hudson.plugins.parameterizedtrigger.PredefinedBuildParameters; import hudson.plugins.parameterizedtrigger.ResultCondition; - import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.CaptureEnvironmentBuilder; import org.jvnet.hudson.test.JenkinsRule; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertEquals; - public class DefaultParametersTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test - public void test() throws Exception { + public void test() throws Exception { - Project projectA = r.createFreeStyleProject("projectA"); - projectA.getPublishersList().add( - new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, - new CurrentBuildParameters()))); + Project projectA = r.createFreeStyleProject("projectA"); + projectA.getPublishersList() + .add(new BuildTrigger( + new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new CurrentBuildParameters()))); - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); projectB.addProperty(new ParametersDefinitionProperty( - new StringParameterDefinition("key1", "value1"), - new StringParameterDefinition("key2", "value2") - )); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); - r.jenkins.rebuildDependencyGraph(); + new StringParameterDefinition("key1", "value1"), new StringParameterDefinition("key2", "value2"))); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); + r.jenkins.rebuildDependencyGraph(); try { // SECURITY-170: this is needed for tests down the line. - //System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); + // System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); System.setProperty("hudson.model.ParametersAction.keepUndefinedParameters", "true"); - - String log = JenkinsRule.getLog((Run)projectA.scheduleBuild2(0, new UserIdCause(), - new ParametersAction(new StringParameterValue("KEY3", "value3"))).get()); + String log = JenkinsRule.getLog((Run) projectA.scheduleBuild2( + 0, new UserIdCause(), new ParametersAction(new StringParameterValue("KEY3", "value3"))) + .get()); Queue.Item q = r.jenkins.getQueue().getItem(projectB); assertNotNull("projectB should be triggered: " + log, q); q.getFuture().get(); @@ -85,15 +82,17 @@ public void test() throws Exception { assertEquals("value2", builder.getEnvVars().get("KEY2")); assertEquals("value3", builder.getEnvVars().get("KEY3")); - projectA.scheduleBuild2(0, new UserIdCause(), new ParametersAction(new StringParameterValue("key1", "value3"))).get(); + projectA.scheduleBuild2( + 0, new UserIdCause(), new ParametersAction(new StringParameterValue("key1", "value3"))) + .get(); r.jenkins.getQueue().getItem(projectB).getFuture().get(); assertEquals("value3", builder.getEnvVars().get("KEY1")); assertEquals("value2", builder.getEnvVars().get("KEY2")); } finally { - //System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); + // System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); System.clearProperty("hudson.model.ParametersAction.keepUndefinedParameters"); } - } + } @Test public void testMergeParameters() throws Exception { @@ -104,29 +103,36 @@ public void testMergeParameters() throws Exception { // Merge in predefined: BAZ=moo HOHO=blah // Expected result: FOO=bar BAR=foo BAZ=moo HOHO=blah projectB.addProperty(new ParametersDefinitionProperty( - new StringParameterDefinition("FOO", "bar"), - new StringParameterDefinition("BAR", "override-me"))); + new StringParameterDefinition("FOO", "bar"), new StringParameterDefinition("BAR", "override-me"))); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); projectB.getBuildersList().add(builder); projectB.setQuietPeriod(1); - projectA.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, - new CurrentBuildParameters(), - new PredefinedBuildParameters("BAZ=moo\nHOHO=blah")))); + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", + ResultCondition.SUCCESS, + new CurrentBuildParameters(), + new PredefinedBuildParameters("BAZ=moo\nHOHO=blah")))); r.jenkins.rebuildDependencyGraph(); try { - //System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); + // System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); System.setProperty("hudson.model.ParametersAction.keepUndefinedParameters", "true"); - Run run = (Run)projectA.scheduleBuild2(0, new UserIdCause(), new ParametersAction( - new StringParameterValue("BAR", "foo"), - new StringParameterValue("BAZ", "override-me"))).get(); + Run run = (Run) projectA.scheduleBuild2( + 0, + new UserIdCause(), + new ParametersAction( + new StringParameterValue("BAR", "foo"), + new StringParameterValue("BAZ", "override-me"))) + .get(); Queue.Item q = r.jenkins.getQueue().getItem(projectB); assertNotNull("projectB should be triggered: " + JenkinsRule.getLog(run), q); - run = (Run)q.getFuture().get(); - assertEquals("should be exactly one ParametersAction", 1, - run.getActions(ParametersAction.class).size()); + run = (Run) q.getFuture().get(); + assertEquals( + "should be exactly one ParametersAction", + 1, + run.getActions(ParametersAction.class).size()); EnvVars envVars = builder.getEnvVars(); assertNotNull("builder should record environment", envVars); assertEquals("FOO", "bar", envVars.get("FOO")); @@ -134,7 +140,7 @@ public void testMergeParameters() throws Exception { assertEquals("BAZ", "moo", envVars.get("BAZ")); assertEquals("HOHO", "blah", envVars.get("HOHO")); } finally { - //System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); + // System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); System.clearProperty("hudson.model.ParametersAction.keepUndefinedParameters"); } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/DontBuildTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/DontBuildTest.java index d4ea70ae..d51f1fc2 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/DontBuildTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/DontBuildTest.java @@ -23,6 +23,9 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import hudson.model.AbstractBuild; import hudson.model.Action; import hudson.model.Project; @@ -31,48 +34,43 @@ import hudson.plugins.parameterizedtrigger.BuildTrigger; import hudson.plugins.parameterizedtrigger.BuildTriggerConfig; import hudson.plugins.parameterizedtrigger.ResultCondition; - import java.io.IOException; - import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.JenkinsRule; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - public class DontBuildTest { @Rule public JenkinsRule r = new JenkinsRule(); - - public static final class DontBuildTrigger extends AbstractBuildParameters { - boolean called = false; - @Override - public Action getAction(AbstractBuild build, TaskListener listener) - throws IOException, InterruptedException, DontTriggerException { - called = true; - throw new DontTriggerException(); - } - } - @Test - public void test() throws Exception { + public static final class DontBuildTrigger extends AbstractBuildParameters { + boolean called = false; + + @Override + public Action getAction(AbstractBuild build, TaskListener listener) + throws IOException, InterruptedException, DontTriggerException { + called = true; + throw new DontTriggerException(); + } + } - Project projectA = r.createFreeStyleProject("projectA"); - DontBuildTrigger dbt = new DontBuildTrigger(); - projectA.getPublishersList().add( - new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, dbt))); + @Test + public void test() throws Exception { - Project projectB = r.createFreeStyleProject("projectB"); - projectB.setQuietPeriod(0); - r.jenkins.rebuildDependencyGraph(); + Project projectA = r.createFreeStyleProject("projectA"); + DontBuildTrigger dbt = new DontBuildTrigger(); + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, dbt))); - projectA.scheduleBuild2(0).get(); - Thread.sleep(1000); + Project projectB = r.createFreeStyleProject("projectB"); + projectB.setQuietPeriod(0); + r.jenkins.rebuildDependencyGraph(); - assertEquals(0, projectB.getBuilds().size()); - assertTrue("trigger was not called", dbt.called); - } + projectA.scheduleBuild2(0).get(); + Thread.sleep(1000); + assertEquals(0, projectB.getBuilds().size()); + assertTrue("trigger was not called", dbt.called); + } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/FileBuildParameterFactoryTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/FileBuildParameterFactoryTest.java index 637f433d..61957e6a 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/FileBuildParameterFactoryTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/FileBuildParameterFactoryTest.java @@ -23,6 +23,10 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import hudson.EnvVars; import hudson.Launcher; import hudson.model.AbstractBuild; @@ -33,8 +37,8 @@ import hudson.model.ParameterDefinition; import hudson.model.ParametersDefinitionProperty; import hudson.model.Project; -import hudson.model.StringParameterDefinition; import hudson.model.Result; +import hudson.model.StringParameterDefinition; import hudson.plugins.parameterizedtrigger.AbstractBuildParameters; import hudson.plugins.parameterizedtrigger.BlockableBuildTriggerConfig; import hudson.plugins.parameterizedtrigger.BlockingBehaviour; @@ -42,12 +46,7 @@ import hudson.plugins.parameterizedtrigger.FileBuildParameterFactory.NoFilesFoundEnum; import hudson.plugins.parameterizedtrigger.TriggerBuilder; import hudson.util.FormValidation; - -import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.TestBuilder; -import org.junit.Rule; -import org.junit.Test; - +import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; @@ -55,50 +54,49 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.io.IOException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertNull; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.TestBuilder; public class FileBuildParameterFactoryTest { @Rule public JenkinsRule r = new JenkinsRule(); - - private TriggerBuilder createTriggerBuilder(AbstractProject project, NoFilesFoundEnum action){ + + private TriggerBuilder createTriggerBuilder(AbstractProject project, NoFilesFoundEnum action) { return createTriggerBuilder(project, action, null); } - - private TriggerBuilder createTriggerBuilder(AbstractProject project, NoFilesFoundEnum action, String encoding){ - - TriggerBuilder tBuilder = new TriggerBuilder( - new BlockableBuildTriggerConfig(project.getName(), - new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), - Collections.singletonList(new FileBuildParameterFactory("*.txt", encoding, action)), - Collections.emptyList())); + + private TriggerBuilder createTriggerBuilder(AbstractProject project, NoFilesFoundEnum action, String encoding) { + + TriggerBuilder tBuilder = new TriggerBuilder(new BlockableBuildTriggerConfig( + project.getName(), + new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE), + Collections.singletonList(new FileBuildParameterFactory("*.txt", encoding, action)), + Collections.emptyList())); return tBuilder; } @Test - public void testSingleFile() throws Exception { + public void testSingleFile() throws Exception { - //create triggered build, with capture env builder + // create triggered build, with capture env builder Project projectB = r.createFreeStyleProject(); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("TEST","test")); + definition.add(new StringParameterDefinition("TEST", "test")); projectB.addProperty(new ParametersDefinitionProperty(definition)); - //create triggering build + // create triggering build FreeStyleProject projectA = r.createFreeStyleProject(); projectA.getBuildersList().add(new TestBuilder() { - public boolean perform(AbstractBuild build, Launcher launcher, - BuildListener listener) throws InterruptedException, IOException { - build.getWorkspace().child("abc.txt").write("TEST=hello_abc","UTF-8"); - return true; + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { + build.getWorkspace().child("abc.txt").write("TEST=hello_abc", "UTF-8"); + return true; } }); @@ -119,30 +117,29 @@ public boolean perform(AbstractBuild build, Launcher launcher, values.add(buildEnvVar.get("TEST")); } assertEquals(Collections.singleton("hello_abc"), values); - } @Test public void testMultipleFiles() throws Exception { - //create triggered build, with capture env builder + // create triggered build, with capture env builder Project projectB = r.createFreeStyleProject(); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("TEST","test")); + definition.add(new StringParameterDefinition("TEST", "test")); projectB.addProperty(new ParametersDefinitionProperty(definition)); - //create triggering build + // create triggering build FreeStyleProject projectA = r.createFreeStyleProject(); projectA.getBuildersList().add(new TestBuilder() { - public boolean perform(AbstractBuild build, Launcher launcher, - BuildListener listener) throws InterruptedException, IOException { - build.getWorkspace().child("abc.txt").write("TEST=hello_abc","UTF-8"); - build.getWorkspace().child("xyz.txt").write("TEST=hello_xyz","UTF-8"); - build.getWorkspace().child("xyz.properties").write("TEST=hello_xyz","UTF-8"); - return true; + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { + build.getWorkspace().child("abc.txt").write("TEST=hello_abc", "UTF-8"); + build.getWorkspace().child("xyz.txt").write("TEST=hello_xyz", "UTF-8"); + build.getWorkspace().child("xyz.properties").write("TEST=hello_xyz", "UTF-8"); + return true; } }); // add Trigger builder, with file parameter factory @@ -161,19 +158,18 @@ public boolean perform(AbstractBuild build, Launcher launcher, assertTrue(buildEnvVar.containsKey("TEST")); values.add(buildEnvVar.get("TEST")); } - assertEquals(new HashSet<>(Arrays.asList("hello_abc","hello_xyz")), values); - + assertEquals(new HashSet<>(Arrays.asList("hello_abc", "hello_xyz")), values); } @Test public void testNoFilesSkip() throws Exception { - //create triggered build, with capture env builder + // create triggered build, with capture env builder Project projectB = r.createFreeStyleProject(); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); - //create triggering build + // create triggering build FreeStyleProject projectA = r.createFreeStyleProject(); // add Trigger builder, with file parameter factory @@ -190,12 +186,12 @@ public void testNoFilesSkip() throws Exception { @Test public void testNoFilesNoParams() throws Exception { - //create triggered build, with capture env builder + // create triggered build, with capture env builder Project projectB = r.createFreeStyleProject(); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); - //create triggering build + // create triggering build FreeStyleProject projectA = r.createFreeStyleProject(); // add Trigger builder, with file parameter factory @@ -212,12 +208,12 @@ public void testNoFilesNoParams() throws Exception { @Test public void testNoFilesFail() throws Exception { - //create triggered build, with capture env builder + // create triggered build, with capture env builder Project projectB = r.createFreeStyleProject(); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); - //create triggering build + // create triggering build FreeStyleProject projectA = r.createFreeStyleProject(); // add Trigger builder, with file parameter factory @@ -234,28 +230,29 @@ public void testNoFilesFail() throws Exception { @Test public void testUtf8File() throws Exception { - //create triggered build, with capture env builder + // create triggered build, with capture env builder Project projectB = r.createFreeStyleProject(); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); - //create triggering build + // create triggering build FreeStyleProject projectA = r.createFreeStyleProject(); projectA.getBuildersList().add(new TestBuilder() { - public boolean perform(AbstractBuild build, Launcher launcher, - BuildListener listener) throws InterruptedException, IOException { - build.getWorkspace().child("abc.txt").write( - "TEST=こんにちは\n" // "hello" in Japanese. - + "TEST=hello_abc", // TEST in multibytes. - "UTF-8" - ); - return true; + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { + build.getWorkspace() + .child("abc.txt") + .write( + "TEST=こんにちは\n" // "hello" in Japanese. + + "TEST=hello_abc", // TEST in multibytes. + "UTF-8"); + return true; } }); // SECURITY-170: need to allow multibyte params that can't be traditionally declared. try { - //System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); + // System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); System.setProperty("hudson.model.ParametersAction.keepUndefinedParameters", "true"); // add Trigger builder, with file parameter factory @@ -276,10 +273,9 @@ public boolean perform(AbstractBuild build, Launcher launcher, assertEquals("hello_abc", buildEnvVar.get("TEST")); } } finally { - //System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); + // System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); System.clearProperty("hudson.model.ParametersAction.keepUndefinedParameters"); } - } @Test @@ -287,28 +283,29 @@ public void testShiftJISFile() throws Exception { // ShiftJIS is an encoding of Japanese texts. // I test here that a non-UTF-8 encoding also works. - //create triggered build, with capture env builder + // create triggered build, with capture env builder Project projectB = r.createFreeStyleProject(); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); - //create triggering build + // create triggering build FreeStyleProject projectA = r.createFreeStyleProject(); projectA.getBuildersList().add(new TestBuilder() { - public boolean perform(AbstractBuild build, Launcher launcher, - BuildListener listener) throws InterruptedException, IOException { - build.getWorkspace().child("abc.txt").write( - "TEST=こんにちは\n" // "hello" in Japanese. - + "TEST=hello_abc", // TEST in multibytes. - "Shift_JIS" - ); - return true; + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { + build.getWorkspace() + .child("abc.txt") + .write( + "TEST=こんにちは\n" // "hello" in Japanese. + + "TEST=hello_abc", // TEST in multibytes. + "Shift_JIS"); + return true; } }); // SECURITY-170: need to allow multibyte params that can't be traditionally declared. try { - //System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); + // System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); System.setProperty("hudson.model.ParametersAction.keepUndefinedParameters", "true"); // add Trigger builder, with file parameter factory @@ -327,36 +324,36 @@ public boolean perform(AbstractBuild build, Launcher launcher, assertEquals("hello_abc", buildEnvVar.get("TEST")); } } finally { - //System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); + // System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); System.clearProperty("hudson.model.ParametersAction.keepUndefinedParameters"); } - } @Test public void testPlatformDefaultEncodedFile() throws Exception { - //create triggered build, with capture env builder + // create triggered build, with capture env builder Project projectB = r.createFreeStyleProject(); CaptureAllEnvironmentBuilder builder = new CaptureAllEnvironmentBuilder(); projectB.getBuildersList().add(builder); - //create triggering build + // create triggering build FreeStyleProject projectA = r.createFreeStyleProject(); projectA.getBuildersList().add(new TestBuilder() { - public boolean perform(AbstractBuild build, Launcher launcher, - BuildListener listener) throws InterruptedException, IOException { - build.getWorkspace().child("abc.txt").write( - "TEST=hello_abc", // TEST=hello_abc in multibytes. - null - ); - return true; + public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) + throws InterruptedException, IOException { + build.getWorkspace() + .child("abc.txt") + .write( + "TEST=hello_abc", // TEST=hello_abc in multibytes. + null); + return true; } }); // SECURITY-170: need to allow multibyte params that can't be traditionally declared. try { - //System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); + // System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); System.setProperty("hudson.model.ParametersAction.keepUndefinedParameters", "true"); // add Trigger builder, with file parameter factory @@ -369,9 +366,12 @@ public boolean perform(AbstractBuild build, Launcher launcher, List builds = projectB.getBuilds(); assertEquals(1, builds.size()); - // This test explicitly uses the platform's default encoding, which e.g. on Windows is likely to be windows-1250 - // or windows-1252. With these single-byte encodings we cannot expect multi-byte strings to be encoded correctly. - final boolean isMultiByteDefaultCharset = Charset.defaultCharset().newEncoder().maxBytesPerChar() > 1.0f; + // This test explicitly uses the platform's default encoding, which e.g. on Windows is likely to be + // windows-1250 + // or windows-1252. With these single-byte encodings we cannot expect multi-byte strings to be encoded + // correctly. + final boolean isMultiByteDefaultCharset = + Charset.defaultCharset().newEncoder().maxBytesPerChar() > 1.0f; if (isMultiByteDefaultCharset) { for (FreeStyleBuild build : builds) { EnvVars buildEnvVar = builder.getEnvVars().get(build.getId()); @@ -379,16 +379,16 @@ public boolean perform(AbstractBuild build, Launcher launcher, } } } finally { - //System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); + // System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); System.clearProperty("hudson.model.ParametersAction.keepUndefinedParameters"); } } - + @Test public void testDoCheckEncoding() throws Exception { - FileBuildParameterFactory.DescriptorImpl d - = (FileBuildParameterFactory.DescriptorImpl)r.jenkins.getDescriptorOrDie(FileBuildParameterFactory.class); - + FileBuildParameterFactory.DescriptorImpl d = (FileBuildParameterFactory.DescriptorImpl) + r.jenkins.getDescriptorOrDie(FileBuildParameterFactory.class); + assertEquals(FormValidation.Kind.OK, d.doCheckEncoding(null).kind); assertEquals(FormValidation.Kind.OK, d.doCheckEncoding("").kind); assertEquals(FormValidation.Kind.OK, d.doCheckEncoding(" ").kind); @@ -397,25 +397,23 @@ public void testDoCheckEncoding() throws Exception { assertEquals(FormValidation.Kind.OK, d.doCheckEncoding(" UTF-8 ").kind); assertEquals(FormValidation.Kind.ERROR, d.doCheckEncoding("NoSuchEncoding").kind); } - + @Test public void testNullifyEncoding() throws Exception { // to use default encoding, encoding must be null. { - FileBuildParameterFactory target - = new FileBuildParameterFactory("*.properties", null, NoFilesFoundEnum.SKIP); + FileBuildParameterFactory target = + new FileBuildParameterFactory("*.properties", null, NoFilesFoundEnum.SKIP); assertNull(target.getEncoding()); } { - FileBuildParameterFactory target - = new FileBuildParameterFactory("*.properties", "", NoFilesFoundEnum.SKIP); + FileBuildParameterFactory target = new FileBuildParameterFactory("*.properties", "", NoFilesFoundEnum.SKIP); assertNull(target.getEncoding()); } { - FileBuildParameterFactory target - = new FileBuildParameterFactory("*.properties", " ", NoFilesFoundEnum.SKIP); + FileBuildParameterFactory target = + new FileBuildParameterFactory("*.properties", " ", NoFilesFoundEnum.SKIP); assertNull(target.getEncoding()); } } - } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/FileBuildTriggerConfigTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/FileBuildTriggerConfigTest.java index f1b2133e..24252f45 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/FileBuildTriggerConfigTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/FileBuildTriggerConfigTest.java @@ -23,10 +23,10 @@ */ package hudson.plugins.parameterizedtrigger.test; -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.Arrays; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import hudson.EnvVars; import hudson.Launcher; @@ -39,10 +39,10 @@ import hudson.model.BuildListener; import hudson.model.Cause; import hudson.model.FreeStyleBuild; -import hudson.model.ParameterValue; import hudson.model.FreeStyleProject; -import hudson.model.ParametersAction; import hudson.model.ParameterDefinition; +import hudson.model.ParameterValue; +import hudson.model.ParametersAction; import hudson.model.ParametersDefinitionProperty; import hudson.model.Project; import hudson.model.StringParameterDefinition; @@ -55,132 +55,130 @@ import hudson.plugins.parameterizedtrigger.FileBuildParameters; import hudson.plugins.parameterizedtrigger.ResultCondition; import hudson.plugins.parameterizedtrigger.TriggerBuilder; -import hudson.tasks.Builder; import hudson.tasks.ArtifactArchiver; +import hudson.tasks.Builder; import hudson.util.FormValidation; - +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.apache.commons.io.FileUtils; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.CaptureEnvironmentBuilder; +import org.jvnet.hudson.test.ExtractResourceSCM; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.SingleFileSCM; -import org.jvnet.hudson.test.ExtractResourceSCM; - -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; public class FileBuildTriggerConfigTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test - public void test() throws Exception { - - Project projectA = r.createFreeStyleProject("projectA"); - String properties = "KEY=value"; - projectA.setScm(new SingleFileSCM("properties.txt", properties)); - projectA.getPublishersList().add( - new BuildTrigger( - new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, - new FileBuildParameters("properties.txt")))); - - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); + public void test() throws Exception { + + Project projectA = r.createFreeStyleProject("projectA"); + String properties = "KEY=value"; + projectA.setScm(new SingleFileSCM("properties.txt", properties)); + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", ResultCondition.SUCCESS, new FileBuildParameters("properties.txt")))); + + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("KEY","key")); + definition.add(new StringParameterDefinition("KEY", "key")); projectB.addProperty(new ParametersDefinitionProperty(definition)); - r.jenkins.rebuildDependencyGraph(); + r.jenkins.rebuildDependencyGraph(); - projectA.scheduleBuild2(0).get(); - r.jenkins.getQueue().getItem(projectB).getFuture().get(); + projectA.scheduleBuild2(0).get(); + r.jenkins.getQueue().getItem(projectB).getFuture().get(); - assertNotNull("builder should record environment", builder.getEnvVars()); - assertEquals("value", builder.getEnvVars().get("KEY")); - } + assertNotNull("builder should record environment", builder.getEnvVars()); + assertEquals("value", builder.getEnvVars().get("KEY")); + } @Test - public void test_multiplefiles() throws Exception { - - Project projectA = r.createFreeStyleProject("projectA"); - projectA.setScm(new ExtractResourceSCM(getClass().getResource("multiple_property_files.zip"))); - projectA.getPublishersList().add( - new BuildTrigger( - new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, - new FileBuildParameters("a_properties.txt,z_properties.txt")))); - projectA.getPublishersList().add(new ArtifactArchiver("a_properties.txt")); - - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); + public void test_multiplefiles() throws Exception { + + Project projectA = r.createFreeStyleProject("projectA"); + projectA.setScm(new ExtractResourceSCM(getClass().getResource("multiple_property_files.zip"))); + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", + ResultCondition.SUCCESS, + new FileBuildParameters("a_properties.txt,z_properties.txt")))); + projectA.getPublishersList().add(new ArtifactArchiver("a_properties.txt")); + + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("A_TEST_01","test1")); - definition.add(new StringParameterDefinition("A_TEST_02","test2")); - definition.add(new StringParameterDefinition("A_TEST_03","test3")); - definition.add(new StringParameterDefinition("Z_TEST_100","test1")); - definition.add(new StringParameterDefinition("Z_TEST_101","test2")); + definition.add(new StringParameterDefinition("A_TEST_01", "test1")); + definition.add(new StringParameterDefinition("A_TEST_02", "test2")); + definition.add(new StringParameterDefinition("A_TEST_03", "test3")); + definition.add(new StringParameterDefinition("Z_TEST_100", "test1")); + definition.add(new StringParameterDefinition("Z_TEST_101", "test2")); projectB.addProperty(new ParametersDefinitionProperty(definition)); - r.jenkins.rebuildDependencyGraph(); + r.jenkins.rebuildDependencyGraph(); - projectA.scheduleBuild2(0).get(); - r.jenkins.getQueue().getItem(projectB).getFuture().get(); + projectA.scheduleBuild2(0).get(); + r.jenkins.getQueue().getItem(projectB).getFuture().get(); + + assertNotNull("builder should record environment", builder.getEnvVars()); + // test from first file + assertEquals("These_three_values_should", builder.getEnvVars().get("A_TEST_01")); + assertEquals("be_from_file_a_properties_txt", builder.getEnvVars().get("A_TEST_02")); + assertEquals("which_has_three_definitions", builder.getEnvVars().get("A_TEST_03")); + // test from second file + assertEquals("These_two_values_should", builder.getEnvVars().get("Z_TEST_100")); + assertEquals("be_from_file_z_properties_txt", builder.getEnvVars().get("Z_TEST_101")); + } - assertNotNull("builder should record environment", builder.getEnvVars()); - // test from first file - assertEquals("These_three_values_should", builder.getEnvVars().get("A_TEST_01")); - assertEquals("be_from_file_a_properties_txt", builder.getEnvVars().get("A_TEST_02")); - assertEquals("which_has_three_definitions", builder.getEnvVars().get("A_TEST_03")); - // test from second file - assertEquals("These_two_values_should", builder.getEnvVars().get("Z_TEST_100")); - assertEquals("be_from_file_z_properties_txt", builder.getEnvVars().get("Z_TEST_101")); + @Test + public void test_failOnMissingFile() throws Exception { - } + Project projectA = r.createFreeStyleProject("projectA"); + projectA.setScm(new ExtractResourceSCM(getClass().getResource("multiple_property_files.zip"))); + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", + ResultCondition.SUCCESS, + new FileBuildParameters("a_properties.txt,missing_file.txt,z_properties.txt", true)))); + + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); + r.jenkins.rebuildDependencyGraph(); + + projectA.scheduleBuild2(0).get(); + r.waitUntilNoActivity(); + + // There should be no builds of projectB as not triggered. + assertEquals(0, projectB.getBuilds().size()); + } - @Test - public void test_failOnMissingFile() throws Exception { - - Project projectA = r.createFreeStyleProject("projectA"); - projectA.setScm(new ExtractResourceSCM(getClass().getResource("multiple_property_files.zip"))); - projectA.getPublishersList().add( - new BuildTrigger( - new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, - new FileBuildParameters("a_properties.txt,missing_file.txt,z_properties.txt",true)))); - - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); - r.jenkins.rebuildDependencyGraph(); - - projectA.scheduleBuild2(0).get(); - r.waitUntilNoActivity(); - - // There should be no builds of projectB as not triggered. - assertEquals(0, projectB.getBuilds().size()); - } - @Test public void testUtf8File() throws Exception { FreeStyleProject projectA = r.createFreeStyleProject("projectA"); - String properties = "KEY=こんにちは\n" // "hello" in Japanese. + String properties = "KEY=こんにちは\n" // "hello" in Japanese. + "KEY=value"; // "KEY" in multibytes. projectA.setScm(new SingleFileSCM("properties.txt", properties.getBytes("UTF-8"))); - projectA.getPublishersList().add( - new BuildTrigger( - new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", + ResultCondition.SUCCESS, new FileBuildParameters("properties.txt", "UTF-8", true)))); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); @@ -191,7 +189,7 @@ public void testUtf8File() throws Exception { // SECURITY-170: need to allow multibyte params that can't be traditionally declared. try { - //System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); + // System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); System.setProperty("hudson.model.ParametersAction.keepUndefinedParameters", "true"); projectA.scheduleBuild2(0).get(); @@ -201,7 +199,7 @@ public void testUtf8File() throws Exception { assertEquals("こんにちは", builder.getEnvVars().get("KEY")); assertEquals("value", builder.getEnvVars().get("KEY")); } finally { - //System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); + // System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); System.clearProperty("hudson.model.ParametersAction.keepUndefinedParameters"); } } @@ -212,12 +210,13 @@ public void testShiftJISFile() throws Exception { // I test here that a non-UTF-8 encoding also works. FreeStyleProject projectA = r.createFreeStyleProject("projectA"); - String properties = "KEY=こんにちは\n" // "hello" in Japanese. + String properties = "KEY=こんにちは\n" // "hello" in Japanese. + "KEY=value"; // "KEY" in multibytes. projectA.setScm(new SingleFileSCM("properties.txt", properties.getBytes("Shift_JIS"))); - projectA.getPublishersList().add( - new BuildTrigger( - new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", + ResultCondition.SUCCESS, new FileBuildParameters("properties.txt", "Shift_JIS", true)))); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); @@ -228,7 +227,7 @@ public void testShiftJISFile() throws Exception { // SECURITY-170: need to allow multibyte params that can't be traditionally declared. try { - //System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); + // System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); System.setProperty("hudson.model.ParametersAction.keepUndefinedParameters", "true"); projectA.scheduleBuild2(0).get(); @@ -238,24 +237,23 @@ public void testShiftJISFile() throws Exception { assertEquals("こんにちは", builder.getEnvVars().get("KEY")); assertEquals("value", builder.getEnvVars().get("KEY")); } finally { - //System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); + // System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); System.clearProperty("hudson.model.ParametersAction.keepUndefinedParameters"); } } - + @Test public void testPlatformDefaultEncodedFile() throws Exception { // ShiftJIS is an encoding of Japanese texts. // I test here that a non-UTF-8 encoding also works. FreeStyleProject projectA = r.createFreeStyleProject("projectA"); - String properties = "KEY=こんにちは\n" // "hello" in Japanese. + String properties = "KEY=こんにちは\n" // "hello" in Japanese. + "KEY=value"; // "KEY" in multibytes. projectA.setScm(new SingleFileSCM("properties.txt", properties.getBytes())); - projectA.getPublishersList().add( - new BuildTrigger( - new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, - new FileBuildParameters("properties.txt")))); + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", ResultCondition.SUCCESS, new FileBuildParameters("properties.txt")))); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); FreeStyleProject projectB = r.createFreeStyleProject("projectB"); @@ -265,7 +263,7 @@ public void testPlatformDefaultEncodedFile() throws Exception { // SECURITY-170: need to allow multibyte params that can't be traditionally declared. try { - //System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); + // System.setProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME, "true"); System.setProperty("hudson.model.ParametersAction.keepUndefinedParameters", "true"); projectA.scheduleBuild2(0).get(); @@ -273,24 +271,27 @@ public void testPlatformDefaultEncodedFile() throws Exception { assertNotNull("builder should record environment", builder.getEnvVars()); - // This test explicitly uses the platform's default encoding, which e.g. on Windows is likely to be windows-1250 - // or windows-1252. With these single-byte encodings we cannot expect multi-byte strings to be encoded correctly. - final boolean isMultiByteDefaultCharset = Charset.defaultCharset().newEncoder().maxBytesPerChar() > 1.0f; + // This test explicitly uses the platform's default encoding, which e.g. on Windows is likely to be + // windows-1250 + // or windows-1252. With these single-byte encodings we cannot expect multi-byte strings to be encoded + // correctly. + final boolean isMultiByteDefaultCharset = + Charset.defaultCharset().newEncoder().maxBytesPerChar() > 1.0f; if (isMultiByteDefaultCharset) { assertEquals("こんにちは", builder.getEnvVars().get("KEY")); assertEquals("value", builder.getEnvVars().get("KEY")); } } finally { - //System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); + // System.clearProperty(ParametersAction.KEEP_UNDEFINED_PARAMETERS_SYSTEM_PROPERTY_NAME); System.clearProperty("hudson.model.ParametersAction.keepUndefinedParameters"); } } @Test public void testDoCheckEncoding() throws Exception { - FileBuildParameters.DescriptorImpl d - = (FileBuildParameters.DescriptorImpl)r.jenkins.getDescriptorOrDie(FileBuildParameters.class); - + FileBuildParameters.DescriptorImpl d = + (FileBuildParameters.DescriptorImpl) r.jenkins.getDescriptorOrDie(FileBuildParameters.class); + assertEquals(FormValidation.Kind.OK, d.doCheckEncoding(null).kind); assertEquals(FormValidation.Kind.OK, d.doCheckEncoding("").kind); assertEquals(FormValidation.Kind.OK, d.doCheckEncoding(" ").kind); @@ -299,27 +300,24 @@ public void testDoCheckEncoding() throws Exception { assertEquals(FormValidation.Kind.OK, d.doCheckEncoding(" UTF-8 ").kind); assertEquals(FormValidation.Kind.ERROR, d.doCheckEncoding("NoSuchEncoding").kind); } - + @Test public void testNullifyEncoding() throws Exception { // to use default encoding, encoding must be null. { - FileBuildParameters target - = new FileBuildParameters("*.properties", null, false); + FileBuildParameters target = new FileBuildParameters("*.properties", null, false); assertNull(target.getEncoding()); } { - FileBuildParameters target - = new FileBuildParameters("*.properties", "", false); + FileBuildParameters target = new FileBuildParameters("*.properties", "", false); assertNull(target.getEncoding()); } { - FileBuildParameters target - = new FileBuildParameters("*.properties", " ", false); + FileBuildParameters target = new FileBuildParameters("*.properties", " ", false); assertNull(target.getEncoding()); } } - + /** * Builder that writes a file. */ @@ -327,29 +325,28 @@ private static class WriteFileBuilder extends Builder { private final String filename; private final String content; private final String encoding; - + public WriteFileBuilder(String filename, String content, String encoding) { this.filename = filename; this.content = content; this.encoding = encoding; } - + public WriteFileBuilder(String filename, String content) { this(filename, content, Charset.defaultCharset().name()); } - + @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) - throws InterruptedException, IOException - { + throws InterruptedException, IOException { EnvVars env = build.getEnvironment(listener); env.putAll(build.getBuildVariables()); build.getWorkspace().child(filename).write(env.expand(content), encoding); return true; } } - - private static String getStringParameterValue(AbstractBuild build, String name) { + + private static String getStringParameterValue(AbstractBuild build, String name) { ParametersAction action = build.getAction(ParametersAction.class); if (action == null) { return null; @@ -358,9 +355,9 @@ private static String getStringParameterValue(AbstractBuild build, String n if (v == null || !(v instanceof StringParameterValue)) { return null; } - return ((StringParameterValue)v).value; + return ((StringParameterValue) v).value; } - + @Test public void testMatrixBuildsOnSameNodes() throws Exception { // all builds runs on controller. @@ -368,56 +365,60 @@ public void testMatrixBuildsOnSameNodes() throws Exception { MatrixProject upstream = r.createProject(MatrixProject.class); upstream.setAxes(new AxisList(new TextAxis("childname", "child1", "child2"))); WriteFileBuilder wfb = new WriteFileBuilder("properties.txt", "triggered_${childname}=true"); - + FreeStyleProject downstream = r.createFreeStyleProject(); - + // Without useMatrixBuild, publisher // Downstream project is triggered without parameters. { upstream.getBuildersList().clear(); upstream.getBuildersList().add(wfb); - + upstream.getPublishersList().clear(); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, false, null, false) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, false, null, false))))); + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + assertEquals(1, downstream.getBuilds().size()); FreeStyleBuild build = downstream.getLastBuild(); assertNull(getStringParameterValue(build, "triggered_child1")); assertNull(getStringParameterValue(build, "triggered_child2")); build.delete(); } - + // With useMatrixBuild, publisher // Downstream project is triggered with parameters, merging properties files in all children. { upstream.getBuildersList().clear(); upstream.getBuildersList().add(wfb); - + upstream.getPublishersList().clear(); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, true, null, false) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, true, null, false))))); + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + // Build is triggered without parameters. assertEquals(1, downstream.getBuilds().size()); FreeStyleBuild build = downstream.getLastBuild(); @@ -425,272 +426,282 @@ public void testMatrixBuildsOnSameNodes() throws Exception { assertEquals("true", getStringParameterValue(build, "triggered_child2")); build.delete(); } - + // Without useMatrixBuild, builder // Downstream project is triggered with parameters of each child. { upstream.getBuildersList().clear(); upstream.getBuildersList().add(wfb); - upstream.getBuildersList().add(new TriggerBuilder( - new BlockableBuildTriggerConfig(downstream.getFullName(), null, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, false, null, false) - )) - )); - + upstream.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + downstream.getFullName(), + null, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, false, null, false))))); + upstream.getPublishersList().clear(); - + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + // Build is triggered in each builds with parameters. assertEquals(2, downstream.getBuilds().size()); FreeStyleBuild build1 = downstream.getLastBuild(); FreeStyleBuild build2 = build1.getPreviousBuild(); - + if (build1.getCause(Cause.UpstreamCause.class).getUpstreamProject().contains("child1")) { assertEquals("true", getStringParameterValue(build1, "triggered_child1")); assertNull(getStringParameterValue(build1, "triggered_child2")); - + assertNull(getStringParameterValue(build2, "triggered_child1")); assertEquals("true", getStringParameterValue(build2, "triggered_child2")); } else { assertEquals("true", getStringParameterValue(build2, "triggered_child1")); assertNull(getStringParameterValue(build2, "triggered_child2")); - + assertNull(getStringParameterValue(build1, "triggered_child1")); assertEquals("true", getStringParameterValue(build1, "triggered_child2")); } - + build2.delete(); build1.delete(); } - + // With useMatrixBuild, publisher // Downstream project is triggered with parameters of each child. // (useMatrixBuild is ignored) { upstream.getBuildersList().clear(); upstream.getBuildersList().add(wfb); - upstream.getBuildersList().add(new TriggerBuilder( - new BlockableBuildTriggerConfig(downstream.getFullName(), null, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, true, null, false) - )) - )); - + upstream.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + downstream.getFullName(), + null, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, true, null, false))))); + upstream.getPublishersList().clear(); - + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + // Build is triggered in each builds with parameters. assertEquals(2, downstream.getBuilds().size()); FreeStyleBuild build1 = downstream.getLastBuild(); FreeStyleBuild build2 = build1.getPreviousBuild(); - + if (build1.getCause(Cause.UpstreamCause.class).getUpstreamProject().contains("child1")) { assertEquals("true", getStringParameterValue(build1, "triggered_child1")); assertNull(getStringParameterValue(build1, "triggered_child2")); - + assertNull(getStringParameterValue(build2, "triggered_child1")); assertEquals("true", getStringParameterValue(build2, "triggered_child2")); } else { assertEquals("true", getStringParameterValue(build2, "triggered_child1")); assertNull(getStringParameterValue(build2, "triggered_child2")); - + assertNull(getStringParameterValue(build1, "triggered_child1")); assertEquals("true", getStringParameterValue(build1, "triggered_child2")); } - + build2.delete(); build1.delete(); } } - + @Test public void testMatrixBuildsOnOtherNodes() throws Exception { // each builds run on other nodes. // upstream matrix projects creates properties files in each builds. r.createOnlineSlave(LabelExpression.parseExpression("child1")); r.createOnlineSlave(LabelExpression.parseExpression("child2")); - + MatrixProject upstream = r.createProject(MatrixProject.class); upstream.setAxes(new AxisList(new LabelAxis("childname", Arrays.asList("child1", "child2")))); WriteFileBuilder wfb = new WriteFileBuilder("properties.txt", "triggered_${childname}=true"); - + FreeStyleProject downstream = r.createFreeStyleProject(); - + // Without useMatrixBuild, publisher // Downstream project is triggered without parameters. { upstream.getBuildersList().clear(); upstream.getBuildersList().add(wfb); - + upstream.getPublishersList().clear(); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, false, null, false) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, false, null, false))))); + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + assertEquals(1, downstream.getBuilds().size()); FreeStyleBuild build = downstream.getLastBuild(); assertNull(getStringParameterValue(build, "triggered_child1")); assertNull(getStringParameterValue(build, "triggered_child2")); build.delete(); } - + // With useMatrixBuild, publisher // Downstream project is triggered with parameters, merging properties files in all children. { upstream.getBuildersList().clear(); upstream.getBuildersList().add(wfb); - + upstream.getPublishersList().clear(); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, true, null, false) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, true, null, false))))); + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + assertEquals(1, downstream.getBuilds().size()); FreeStyleBuild build = downstream.getLastBuild(); assertEquals("true", getStringParameterValue(build, "triggered_child1")); assertEquals("true", getStringParameterValue(build, "triggered_child2")); build.delete(); } - + // Without useMatrixBuild, builder // Downstream project is triggered with parameters of each child. { upstream.getBuildersList().clear(); upstream.getBuildersList().add(wfb); - upstream.getBuildersList().add(new TriggerBuilder( - new BlockableBuildTriggerConfig(downstream.getFullName(), null, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, false, null, false) - )) - )); - + upstream.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + downstream.getFullName(), + null, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, false, null, false))))); + upstream.getPublishersList().clear(); - + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + assertEquals(2, downstream.getBuilds().size()); FreeStyleBuild build1 = downstream.getLastBuild(); FreeStyleBuild build2 = build1.getPreviousBuild(); - + if (build1.getCause(Cause.UpstreamCause.class).getUpstreamProject().contains("child1")) { assertEquals("true", getStringParameterValue(build1, "triggered_child1")); assertNull(getStringParameterValue(build1, "triggered_child2")); - + assertNull(getStringParameterValue(build2, "triggered_child1")); assertEquals("true", getStringParameterValue(build2, "triggered_child2")); } else { assertEquals("true", getStringParameterValue(build2, "triggered_child1")); assertNull(getStringParameterValue(build2, "triggered_child2")); - + assertNull(getStringParameterValue(build1, "triggered_child1")); assertEquals("true", getStringParameterValue(build1, "triggered_child2")); } - + build2.delete(); build1.delete(); } - + // With useMatrixBuild, publisher // Downstream project is triggered with parameters of each child. // (useMatrixBuild is ignored) { upstream.getBuildersList().clear(); upstream.getBuildersList().add(wfb); - upstream.getBuildersList().add(new TriggerBuilder( - new BlockableBuildTriggerConfig(downstream.getFullName(), null, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, true, null, false) - )) - )); - + upstream.getBuildersList() + .add(new TriggerBuilder(new BlockableBuildTriggerConfig( + downstream.getFullName(), + null, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, true, null, false))))); + upstream.getPublishersList().clear(); - + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + assertEquals(2, downstream.getBuilds().size()); FreeStyleBuild build1 = downstream.getLastBuild(); FreeStyleBuild build2 = build1.getPreviousBuild(); - + if (build1.getCause(Cause.UpstreamCause.class).getUpstreamProject().contains("child1")) { assertEquals("true", getStringParameterValue(build1, "triggered_child1")); assertNull(getStringParameterValue(build1, "triggered_child2")); - + assertNull(getStringParameterValue(build2, "triggered_child1")); assertEquals("true", getStringParameterValue(build2, "triggered_child2")); } else { assertEquals("true", getStringParameterValue(build2, "triggered_child1")); assertNull(getStringParameterValue(build2, "triggered_child2")); - + assertNull(getStringParameterValue(build1, "triggered_child1")); assertEquals("true", getStringParameterValue(build1, "triggered_child2")); } - + build2.delete(); build1.delete(); } } - + @Test public void testMatrixBuildsCombinationFilter() throws Exception { MatrixProject upstream = r.createProject(MatrixProject.class); upstream.setAxes(new AxisList(new TextAxis("childname", "child1", "child2", "child3"))); upstream.getBuildersList().add(new WriteFileBuilder("properties.txt", "triggered_${childname}=true")); - + FreeStyleProject downstream = r.createFreeStyleProject(); - + // without combinationFilter { upstream.getPublishersList().clear(); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, true, null, false) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, true, null, false))))); + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + assertEquals(1, downstream.getBuilds().size()); FreeStyleBuild build = downstream.getLastBuild(); assertEquals("true", getStringParameterValue(build, "triggered_child1")); @@ -698,23 +709,25 @@ public void testMatrixBuildsCombinationFilter() throws Exception { assertEquals("true", getStringParameterValue(build, "triggered_child3")); build.delete(); } - + // with combinationFilter { upstream.getPublishersList().clear(); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, true, "childname!='child2'", false) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList(new FileBuildParameters( + "properties.txt", null, false, true, "childname!='child2'", false))))); + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + assertEquals(1, downstream.getBuilds().size()); FreeStyleBuild build = downstream.getLastBuild(); assertEquals("true", getStringParameterValue(build, "triggered_child1")); @@ -723,38 +736,40 @@ public void testMatrixBuildsCombinationFilter() throws Exception { build.delete(); } } - + @Test public void testMatrixBuildsOnlyExactRuns() throws Exception { MatrixProject upstream = r.createProject(MatrixProject.class); upstream.setAxes(new AxisList(new TextAxis("childname", "child1", "child2", "child3"))); upstream.getBuildersList().add(new WriteFileBuilder("properties.txt", "triggered_${childname}=true")); - + FreeStyleProject downstream = r.createFreeStyleProject(); - + // Run build. // builds of child1, child2, child3 is created. upstream.scheduleBuild2(0).get(); - + // child2 is dropped upstream.setAxes(new AxisList(new TextAxis("childname", "child1", "child3"))); - + // without onlyExactRuns { upstream.getPublishersList().clear(); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, true, null, false) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, true, null, false))))); + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + MatrixBuild b = upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - System.out.println(">>>>>>>>"+b.getLog()); + System.out.println(">>>>>>>>" + b.getLog()); assertEquals(1, downstream.getBuilds().size()); FreeStyleBuild build = downstream.getLastBuild(); @@ -763,23 +778,25 @@ public void testMatrixBuildsOnlyExactRuns() throws Exception { assertEquals("true", getStringParameterValue(build, "triggered_child3")); build.delete(); } - + // with onlyExactRuns { upstream.getPublishersList().clear(); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", null, false, true, null, true) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList( + new FileBuildParameters("properties.txt", null, false, true, null, true))))); + r.jenkins.rebuildDependencyGraph(); - + assertEquals(0, downstream.getBuilds().size()); - + upstream.scheduleBuild2(0).get(); r.waitUntilNoActivity(); - + assertEquals(1, downstream.getBuilds().size()); FreeStyleBuild build = downstream.getLastBuild(); assertEquals("true", getStringParameterValue(build, "triggered_child1")); @@ -788,35 +805,37 @@ public void testMatrixBuildsOnlyExactRuns() throws Exception { build.delete(); } } - + @Issue("JENKINS-22705") @Test public void testMatrixBuildsConfiguration() throws Exception { FreeStyleProject downstream = r.createFreeStyleProject(); - + MatrixProject upstream = r.createProject(MatrixProject.class); upstream.setAxes(new AxisList(new TextAxis("axis1", "value1", "value2"))); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters("properties.txt", "UTF-8", true, true, "axis1=value1", true) - )) - )); + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList(new FileBuildParameters( + "properties.txt", "UTF-8", true, true, "axis1=value1", true))))); upstream.save(); - + String upstreamName = upstream.getFullName(); - + upstream = r.jenkins.getItemByFullName(upstreamName, MatrixProject.class); assertNotNull(upstream); - + BuildTrigger trigger = upstream.getPublishersList().get(BuildTrigger.class); assertNotNull(trigger); - + assertEquals(1, trigger.getConfigs().size()); - + BuildTriggerConfig config = trigger.getConfigs().get(0); - + assertEquals(1, config.getConfigs().size()); - FileBuildParameters p = (FileBuildParameters)config.getConfigs().get(0); + FileBuildParameters p = (FileBuildParameters) config.getConfigs().get(0); assertEquals("properties.txt", p.getPropertiesFile()); assertEquals("UTF-8", p.getEncoding()); assertTrue(p.getFailTriggerOnMissing()); @@ -824,87 +843,90 @@ public void testMatrixBuildsConfiguration() throws Exception { assertEquals("axis1=value1", p.getCombinationFilter()); assertTrue(p.isOnlyExactRuns()); } - + @Test public void testAbsolutePath() throws Exception { FreeStyleProject downstream = r.createFreeStyleProject(); - + FreeStyleProject upstream = r.createFreeStyleProject(); - + File absoluteFile = new File(r.jenkins.getRootDir(), "properties.txt"); - if(!absoluteFile.getParentFile().exists()) { + if (!absoluteFile.getParentFile().exists()) { FileUtils.forceMkdir(absoluteFile.getParentFile()); } FileUtils.writeStringToFile(absoluteFile, "absolute_param=value1"); - + File workspace = new File(r.jenkins.getWorkspaceFor(upstream).getRemote()); File relativeDir = workspace.getParentFile(); - - if(!relativeDir.exists()) { + + if (!relativeDir.exists()) { FileUtils.forceMkdir(relativeDir); } File relativeFile = new File(relativeDir, "properties.txt"); FileUtils.writeStringToFile(relativeFile, "relative_param1=value2"); - + upstream.getBuildersList().add(new WriteFileBuilder("properties.txt", "relative_param2=value3")); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters(String.format("%s,../properties.txt,properties.txt", absoluteFile.getAbsolutePath())) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList(new FileBuildParameters(String.format( + "%s,../properties.txt,properties.txt", absoluteFile.getAbsolutePath())))))); + r.jenkins.rebuildDependencyGraph(); - + r.assertBuildStatusSuccess(upstream.scheduleBuild2(0)); r.waitUntilNoActivity(); - + FreeStyleBuild build = downstream.getLastBuild(); assertNotNull(build); assertEquals("value1", getStringParameterValue(build, "absolute_param")); assertEquals("value2", getStringParameterValue(build, "relative_param1")); assertEquals("value3", getStringParameterValue(build, "relative_param2")); } - + /** * Builder that removes a workspace. */ private static class WorkspaceRemoveBuilder extends Builder { @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) - throws InterruptedException, IOException - { + throws InterruptedException, IOException { build.getWorkspace().deleteRecursive(); return true; } } - + @Issue("JENKINS-22229") @Test public void testAbsolutePathWithoutWorkspace() throws Exception { - // Though it is rather a problem with ws-cleanup-plugin, + // Though it is rather a problem with ws-cleanup-plugin, // there's a case a workspace is removed. FreeStyleProject downstream = r.createFreeStyleProject(); - + FreeStyleProject upstream = r.createFreeStyleProject(); - + File absoluteFile = new File(r.jenkins.getRootDir(), "properties.txt"); - if(!absoluteFile.getParentFile().exists()) { + if (!absoluteFile.getParentFile().exists()) { FileUtils.forceMkdir(absoluteFile.getParentFile()); } FileUtils.writeStringToFile(absoluteFile, "absolute_param=value1"); - + upstream.getBuildersList().add(new WorkspaceRemoveBuilder()); - upstream.getPublishersList().add(new BuildTrigger( - new BuildTriggerConfig(downstream.getFullName(), ResultCondition.SUCCESS, true, Arrays.asList( - new FileBuildParameters(absoluteFile.getAbsolutePath()) - )) - )); - + upstream.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + downstream.getFullName(), + ResultCondition.SUCCESS, + true, + Arrays.asList( + new FileBuildParameters(absoluteFile.getAbsolutePath()))))); + r.jenkins.rebuildDependencyGraph(); - + r.assertBuildStatusSuccess(upstream.scheduleBuild2(0)); r.waitUntilNoActivity(); - + FreeStyleBuild build = downstream.getLastBuild(); assertNotNull(build); assertEquals("value1", getStringParameterValue(build, "absolute_param")); diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/NodeParametersTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/NodeParametersTest.java index f16836eb..8332e435 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/NodeParametersTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/NodeParametersTest.java @@ -4,6 +4,9 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + import hudson.model.AbstractBuild; import hudson.model.Project; import hudson.plugins.parameterizedtrigger.BuildTrigger; @@ -11,15 +14,11 @@ import hudson.plugins.parameterizedtrigger.NodeParameters; import hudson.plugins.parameterizedtrigger.ResultCondition; import hudson.slaves.DumbSlave; - import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.CaptureEnvironmentBuilder; import org.jvnet.hudson.test.JenkinsRule; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - /** * * @author cjohnson @@ -28,116 +27,117 @@ public class NodeParametersTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test - public void test() throws Exception { - - DumbSlave slave0 = r.createOnlineSlave(); - DumbSlave slave1 = r.createOnlineSlave(); - - Project projectA = r.createFreeStyleProject("projectA"); - projectA.getPublishersList().add( - new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new NodeParameters()))); - - projectA.setAssignedNode(slave0); - - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); - // set to build on slave1 - projectB.setAssignedNode(slave1); - r.jenkins.rebuildDependencyGraph(); - - AbstractBuild buildA = projectA.scheduleBuild2(0).get(); - r.waitUntilNoActivity(); -// hudson.getQueue().getItem(projectB).getFuture().get(); - - assertEquals(slave0, buildA.getBuiltOn()); - assertNotNull("builder should record environment", builder.getEnvVars()); - // ProjectB will be built on slave 0 regardless of assigned node. - assertEquals("slave0", builder.getEnvVars().get("NODE_NAME")); - - } + public void test() throws Exception { + + DumbSlave slave0 = r.createOnlineSlave(); + DumbSlave slave1 = r.createOnlineSlave(); + + Project projectA = r.createFreeStyleProject("projectA"); + projectA.getPublishersList() + .add(new BuildTrigger( + new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new NodeParameters()))); + + projectA.setAssignedNode(slave0); + + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); + // set to build on slave1 + projectB.setAssignedNode(slave1); + r.jenkins.rebuildDependencyGraph(); + + AbstractBuild buildA = projectA.scheduleBuild2(0).get(); + r.waitUntilNoActivity(); + // hudson.getQueue().getItem(projectB).getFuture().get(); + + assertEquals(slave0, buildA.getBuiltOn()); + assertNotNull("builder should record environment", builder.getEnvVars()); + // ProjectB will be built on slave 0 regardless of assigned node. + assertEquals("slave0", builder.getEnvVars().get("NODE_NAME")); + } @Test - public void testQueuedJobsCombined() throws Exception { - - DumbSlave slave0 = r.createOnlineSlave(); - DumbSlave slave1 = r.createOnlineSlave(); - - Project projectA = r.createFreeStyleProject("projectA"); - projectA.getPublishersList().add( - new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new NodeParameters()))); - - projectA.setAssignedNode(slave0); - - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(10); - // set to build on slave1 - projectB.setAssignedNode(slave1); - r.jenkins.rebuildDependencyGraph(); - - AbstractBuild buildA = projectA.scheduleBuild2(0).get(); - AbstractBuild buildA2 = projectA.scheduleBuild2(0).get(); - r.waitUntilNoActivity(); -// hudson.getQueue().getItem(projectB).getFuture().get(); - assertEquals(2, projectA.getBuilds().size()); - - assertEquals(slave0, buildA.getBuiltOn()); - assertEquals(slave0, buildA2.getBuiltOn()); - assertNotNull("builder should record environment", builder.getEnvVars()); - // ProjectB will be built on slave 0 regardless of assigned node. - assertEquals("slave0", builder.getEnvVars().get("NODE_NAME")); - // should only be a single build of projectB - assertEquals(1, projectB.getBuilds().size()); - } - + public void testQueuedJobsCombined() throws Exception { + + DumbSlave slave0 = r.createOnlineSlave(); + DumbSlave slave1 = r.createOnlineSlave(); + + Project projectA = r.createFreeStyleProject("projectA"); + projectA.getPublishersList() + .add(new BuildTrigger( + new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new NodeParameters()))); + + projectA.setAssignedNode(slave0); + + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(10); + // set to build on slave1 + projectB.setAssignedNode(slave1); + r.jenkins.rebuildDependencyGraph(); + + AbstractBuild buildA = projectA.scheduleBuild2(0).get(); + AbstractBuild buildA2 = projectA.scheduleBuild2(0).get(); + r.waitUntilNoActivity(); + // hudson.getQueue().getItem(projectB).getFuture().get(); + assertEquals(2, projectA.getBuilds().size()); + + assertEquals(slave0, buildA.getBuiltOn()); + assertEquals(slave0, buildA2.getBuiltOn()); + assertNotNull("builder should record environment", builder.getEnvVars()); + // ProjectB will be built on slave 0 regardless of assigned node. + assertEquals("slave0", builder.getEnvVars().get("NODE_NAME")); + // should only be a single build of projectB + assertEquals(1, projectB.getBuilds().size()); + } + @Test - public void testQueuedJobsNotCombined() throws Exception { - - DumbSlave slave0 = r.createOnlineSlave(); - DumbSlave slave1 = r.createOnlineSlave(); - DumbSlave slave2 = r.createOnlineSlave(); - - Project projectA = r.createFreeStyleProject("projectA"); - projectA.getPublishersList().add( - new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new NodeParameters()))); - - projectA.setAssignedNode(slave0); - - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); - - int firstBuildNumber = projectB.getNextBuildNumber(); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(5); - // set to build on slave1 - projectB.setAssignedNode(slave1); - r.jenkins.rebuildDependencyGraph(); - - AbstractBuild buildA = projectA.scheduleBuild2(0).get(); - // Now trigger on another slave - projectA.setAssignedNode(slave2); - AbstractBuild buildA2 = projectA.scheduleBuild2(0).get(); - r.waitUntilNoActivity(); - - assertEquals(slave0, buildA.getBuiltOn()); - assertEquals(slave2, buildA2.getBuiltOn()); - - // should have two builds of projectB - assertEquals(2, projectB.getBuilds().size()); - - AbstractBuild buildB = projectB.getBuildByNumber(firstBuildNumber); - assertNotNull("ProjectB failed to build", buildB); - assertEquals(slave0, buildB.getBuiltOn()); - - // get the second build of projectB - AbstractBuild buildB2 = buildB.getNextBuild(); - assertNotNull("ProjectB failed to build second time", buildB2); - assertEquals(slave2, buildB2.getBuiltOn()); - - } + public void testQueuedJobsNotCombined() throws Exception { + + DumbSlave slave0 = r.createOnlineSlave(); + DumbSlave slave1 = r.createOnlineSlave(); + DumbSlave slave2 = r.createOnlineSlave(); + + Project projectA = r.createFreeStyleProject("projectA"); + projectA.getPublishersList() + .add(new BuildTrigger( + new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, new NodeParameters()))); + + projectA.setAssignedNode(slave0); + + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); + + int firstBuildNumber = projectB.getNextBuildNumber(); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(5); + // set to build on slave1 + projectB.setAssignedNode(slave1); + r.jenkins.rebuildDependencyGraph(); + + AbstractBuild buildA = projectA.scheduleBuild2(0).get(); + // Now trigger on another slave + projectA.setAssignedNode(slave2); + AbstractBuild buildA2 = projectA.scheduleBuild2(0).get(); + r.waitUntilNoActivity(); + + assertEquals(slave0, buildA.getBuiltOn()); + assertEquals(slave2, buildA2.getBuiltOn()); + + // should have two builds of projectB + assertEquals(2, projectB.getBuilds().size()); + + AbstractBuild buildB = projectB.getBuildByNumber(firstBuildNumber); + assertNotNull("ProjectB failed to build", buildB); + assertEquals(slave0, buildB.getBuiltOn()); + + // get the second build of projectB + AbstractBuild buildB2 = buildB.getNextBuild(); + assertNotNull("ProjectB failed to build second time", buildB2); + assertEquals(slave2, buildB2.getBuiltOn()); + } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/ParameterizedTriggerPermissionTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/ParameterizedTriggerPermissionTest.java index 694e7f4e..4d348965 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/ParameterizedTriggerPermissionTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/ParameterizedTriggerPermissionTest.java @@ -23,6 +23,10 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.*; + +import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.model.Cause; import hudson.model.Computer; import hudson.model.FreeStyleBuild; @@ -50,37 +54,33 @@ import java.util.List; import java.util.Set; import java.util.TreeSet; -import edu.umd.cs.findbugs.annotations.CheckForNull; -import edu.umd.cs.findbugs.annotations.NonNull; import jenkins.model.Jenkins; import jenkins.security.QueueItemAuthenticator; import jenkins.security.QueueItemAuthenticatorConfiguration; import jenkins.security.QueueItemAuthenticatorDescriptor; import org.acegisecurity.Authentication; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.CaptureEnvironmentBuilder; -import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.TestExtension; - -import static org.junit.Assert.*; -import org.junit.Before; import org.jvnet.hudson.test.Issue; +import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockQueueItemAuthenticator; +import org.jvnet.hudson.test.TestExtension; /** * Provides some permission checks for {@link TriggerBuilder}. * @author Oleg Nenashev */ public class ParameterizedTriggerPermissionTest { - + @Rule public JenkinsRule r = new JenkinsRule(); - + @Before public void setUpUserAndPermissions() { r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); - + User.get("foo"); ProjectMatrixAuthorizationStrategy str = new ProjectMatrixAuthorizationStrategy(); str.add(Jenkins.READ, "foo"); @@ -88,52 +88,55 @@ public void setUpUserAndPermissions() { str.add(Item.DISCOVER, "foo"); str.add(Computer.BUILD, "foo"); r.jenkins.setAuthorizationStrategy(str); - + QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(new FooUserAuthenticator("foo")); } - + @Test @Issue("SECURITY-201") public void shouldBeUnableToTriggerWithoutPermissions_BuildStep() throws Exception { shouldBeUnableToTriggerWithoutPermissions(true); } - + @Test @Issue("SECURITY-201") public void shouldBeUnableToTriggerWithoutPermissions_Recorder() throws Exception { shouldBeUnableToTriggerWithoutPermissions(false); } - - public void shouldBeUnableToTriggerWithoutPermissions(boolean useBuildStep) throws Exception { + + public void shouldBeUnableToTriggerWithoutPermissions(boolean useBuildStep) throws Exception { // Create controller project FreeStyleProject masterProject = createProjectWithPermissions("project", "foo", Arrays.asList(Item.BUILD)); - + if (useBuildStep) { - addParameterizedTrigger_BuildStep(masterProject, createBlockableConfig( "subproject1,subproject2")); + addParameterizedTrigger_BuildStep(masterProject, createBlockableConfig("subproject1,subproject2")); } else { addParameterizedTrigger_Recorder(masterProject, createNonBlockableConfig("subproject1,subproject2")); } - + // Create subprojects FreeStyleProject subproject1 = createProjectWithPermissions("subproject1", "foo", null); FreeStyleProject subproject2 = createProjectWithPermissions("subproject2", "foo", Arrays.asList(Item.BUILD)); r.jenkins.rebuildDependencyGraph(); FreeStyleBuild build = r.buildAndAssertSuccess(masterProject); - + // Assert the subproject1 has not been built - assertTrue("The subproject1 has been triggered, but it should not happen due to the build permissions", + assertTrue( + "The subproject1 has been triggered, but it should not happen due to the build permissions", subproject1.getBuilds().isEmpty()); r.assertLogContains("has no Job.BUILD permission", build); - + if (!useBuildStep) { // Non-blocking, we have to check the status r.jenkins.getQueue().maintain(); r.waitUntilNoActivity(); } - + // Assert the subproject2 has been built properly - assertEquals("The subproject2 should have been triggered once during the build", - 1, subproject2.getBuilds().size()); + assertEquals( + "The subproject2 should have been triggered once during the build", + 1, + subproject2.getBuilds().size()); FreeStyleBuild lastBuild = subproject2.getLastBuild(); assertNotNull("Cannot retrieve the last build of subproject2", lastBuild); Cause.UpstreamCause cause = lastBuild.getCause(Cause.UpstreamCause.class); @@ -141,10 +144,11 @@ public void shouldBeUnableToTriggerWithoutPermissions(boolean useBuildStep) thro } @NonNull - private FreeStyleProject createProjectWithPermissions(@NonNull String projectName, @NonNull String userName, - @CheckForNull List permissions) throws Exception { + private FreeStyleProject createProjectWithPermissions( + @NonNull String projectName, @NonNull String userName, @CheckForNull List permissions) + throws Exception { final TreeSet userSet = new TreeSet<>(Arrays.asList(userName)); - + FreeStyleProject project = r.createFreeStyleProject(projectName); HashMap> masterPermissions = new HashMap<>(); if (permissions != null) { @@ -153,36 +157,40 @@ private FreeStyleProject createProjectWithPermissions(@NonNull String projectNam } } AuthorizationMatrixProperty masterProp = new AuthorizationMatrixProperty(masterPermissions); - + project.addProperty(masterProp); project.setQuietPeriod(0); - + return project; } - - private BlockableBuildTriggerConfig createBlockableConfig(String projectToTrigger){ + + private BlockableBuildTriggerConfig createBlockableConfig(String projectToTrigger) { List buildParameters = new ArrayList<>(); buildParameters.add(new CurrentBuildParameters()); BlockingBehaviour neverFail = new BlockingBehaviour("never", "never", "never"); return new BlockableBuildTriggerConfig(projectToTrigger, neverFail, buildParameters); } - - private BuildTriggerConfig createNonBlockableConfig(String projectToTrigger){ + + private BuildTriggerConfig createNonBlockableConfig(String projectToTrigger) { List buildParameters = new ArrayList<>(); buildParameters.add(new CurrentBuildParameters()); - return new BuildTriggerConfig(projectToTrigger, ResultCondition.SUCCESS, true, - Collections.emptyList(), Collections.emptyList(), false); + return new BuildTriggerConfig( + projectToTrigger, + ResultCondition.SUCCESS, + true, + Collections.emptyList(), + Collections.emptyList(), + false); } - - private void addParameterizedTrigger_BuildStep(Project projectA, BlockableBuildTriggerConfig config) + + private void addParameterizedTrigger_BuildStep(Project projectA, BlockableBuildTriggerConfig config) throws Exception { projectA.getBuildersList().add(new TriggerBuilder(config)); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); projectA.getBuildersList().add(builder); } - - private void addParameterizedTrigger_Recorder(Project projectA, BuildTriggerConfig config) - throws Exception { + + private void addParameterizedTrigger_Recorder(Project projectA, BuildTriggerConfig config) throws Exception { projectA.getPublishersList().add(new BuildTrigger(config)); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); projectA.getBuildersList().add(builder); @@ -199,27 +207,27 @@ public static class FooUserAuthenticator extends QueueItemAuthenticator { public FooUserAuthenticator(String username) { this.username = username; } - + public String getUsername() { return username; } - + @Override public Authentication authenticate(Queue.Task task) { return User.get(username).impersonate(); } - + @Override public Authentication authenticate(Queue.Item item) { return User.get(username).impersonate(); } - + @TestExtension("shouldBeUnableToTriggerWithoutPermissions") public static class DescriptorImpl extends QueueItemAuthenticatorDescriptor { @Override public String getDisplayName() { return "Authenticate as a specified user"; } - } + } } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/ParameterizedTriggerUtilsTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/ParameterizedTriggerUtilsTest.java index 4d0e18df..298c81cb 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/ParameterizedTriggerUtilsTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/ParameterizedTriggerUtilsTest.java @@ -1,24 +1,19 @@ package hudson.plugins.parameterizedtrigger.test; -import hudson.plugins.parameterizedtrigger.ParameterizedTriggerUtils; -import hudson.model.ParametersAction; import hudson.model.ParameterValue; +import hudson.model.ParametersAction; import hudson.model.StringParameterValue; - +import hudson.plugins.parameterizedtrigger.ParameterizedTriggerUtils; import junit.framework.TestCase; public class ParameterizedTriggerUtilsTest extends TestCase { public void testMergeParameters() { ParametersAction base = new ParametersAction( - new StringParameterValue("key1", "value1"), - new StringParameterValue("key2", "value2") - ); + new StringParameterValue("key1", "value1"), new StringParameterValue("key2", "value2")); ParametersAction overlay = new ParametersAction( - new StringParameterValue("key2", "not-value2"), - new StringParameterValue("key3", "value3") - ); + new StringParameterValue("key2", "not-value2"), new StringParameterValue("key3", "value3")); ParametersAction result = ParameterizedTriggerUtils.mergeParameters(base, overlay); @@ -31,10 +26,7 @@ private static void assertStringParameterValueEquals(String expected, ParameterV if (actual == null) { fail("ParameterValue is Null"); } else { - assertEquals( - expected, - ((StringParameterValue)actual).value - ); + assertEquals(expected, ((StringParameterValue) actual).value); } } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/PredefinedPropertiesBuildTriggerConfigTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/PredefinedPropertiesBuildTriggerConfigTest.java index 4b353418..4e939d7b 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/PredefinedPropertiesBuildTriggerConfigTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/PredefinedPropertiesBuildTriggerConfigTest.java @@ -23,6 +23,10 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + import hudson.model.FreeStyleBuild; import hudson.model.ParameterDefinition; import hudson.model.ParametersAction; @@ -36,60 +40,54 @@ import hudson.plugins.parameterizedtrigger.BuildTriggerConfig; import hudson.plugins.parameterizedtrigger.PredefinedBuildParameters; import hudson.plugins.parameterizedtrigger.ResultCondition; - +import java.util.ArrayList; +import java.util.List; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.CaptureEnvironmentBuilder; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.List; - public class PredefinedPropertiesBuildTriggerConfigTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test - public void test() throws Exception { - - Project projectA = r.createFreeStyleProject("projectA"); - String properties = "KEY=value"; - projectA.getPublishersList().add( - new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, - new PredefinedBuildParameters(properties)))); - - CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); - Project projectB = r.createFreeStyleProject("projectB"); - projectB.getBuildersList().add(builder); - projectB.setQuietPeriod(1); + public void test() throws Exception { + + Project projectA = r.createFreeStyleProject("projectA"); + String properties = "KEY=value"; + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", ResultCondition.SUCCESS, new PredefinedBuildParameters(properties)))); + + CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); + Project projectB = r.createFreeStyleProject("projectB"); + projectB.getBuildersList().add(builder); + projectB.setQuietPeriod(1); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("KEY","key")); + definition.add(new StringParameterDefinition("KEY", "key")); projectB.addProperty(new ParametersDefinitionProperty(definition)); - r.jenkins.rebuildDependencyGraph(); + r.jenkins.rebuildDependencyGraph(); - projectA.scheduleBuild2(0).get(); - r.jenkins.getQueue().getItem(projectB).getFuture().get(); + projectA.scheduleBuild2(0).get(); + r.jenkins.getQueue().getItem(projectB).getFuture().get(); + + assertNotNull("builder should record environment", builder.getEnvVars()); + assertEquals("value", builder.getEnvVars().get("KEY")); + } - assertNotNull("builder should record environment", builder.getEnvVars()); - assertEquals("value", builder.getEnvVars().get("KEY")); - } - @Test public void testNonAscii() throws Exception { Project projectA = r.createFreeStyleProject("projectA"); String properties = "KEY=123\n" // 123 in multibytes - + "KEY=value\n"; // "KEY" in multibytes - projectA.getPublishersList().add( - new BuildTrigger(new BuildTriggerConfig("projectB", ResultCondition.SUCCESS, - new PredefinedBuildParameters(properties)))); + + "KEY=value\n"; // "KEY" in multibytes + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + "projectB", ResultCondition.SUCCESS, new PredefinedBuildParameters(properties)))); CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder(); Project projectB = r.createFreeStyleProject("projectB"); @@ -97,8 +95,8 @@ public void testNonAscii() throws Exception { projectB.setQuietPeriod(1); // SECURITY-170: must define parameters in subjobs List definition = new ArrayList(); - definition.add(new StringParameterDefinition("KEY","key")); - definition.add(new StringParameterDefinition("KEY","otherkey")); + definition.add(new StringParameterDefinition("KEY", "key")); + definition.add(new StringParameterDefinition("KEY", "otherkey")); projectB.addProperty(new ParametersDefinitionProperty(definition)); r.jenkins.rebuildDependencyGraph(); @@ -109,43 +107,37 @@ public void testNonAscii() throws Exception { assertEquals("123", builder.getEnvVars().get("KEY")); assertEquals("value", builder.getEnvVars().get("KEY")); } - + @Test @Issue("SECURITY-101") public void ensureTextBasedParameterAreCorrectlyConvertedToPassword() throws Exception { // creation Project parent = r.createFreeStyleProject("parent"); Project child = r.createFreeStyleProject("child"); - - {// configuration on parent - String properties = "login=derp\n" + - "pwd=d3rp\n"; - - parent.getPublishersList().add( - new BuildTrigger( - new BuildTriggerConfig( - child.getName(), ResultCondition.SUCCESS, - new PredefinedBuildParameters(properties) - ) - ) - ); + + { // configuration on parent + String properties = "login=derp\n" + "pwd=d3rp\n"; + + parent.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + child.getName(), ResultCondition.SUCCESS, new PredefinedBuildParameters(properties)))); } - - {// configuration of child + + { // configuration of child child.setQuietPeriod(1); - + child.addProperty(new ParametersDefinitionProperty( new StringParameterDefinition("login", "default-login", null), - new PasswordParameterDefinition("pwd", "default-pwd", null) - )); + new PasswordParameterDefinition("pwd", "default-pwd", null))); } - + r.jenkins.rebuildDependencyGraph(); - + // run of parent parent.scheduleBuild2(0).get(); - FreeStyleBuild childLastBuild = (FreeStyleBuild) r.jenkins.getQueue().getItem(child).getFuture().get(); - + FreeStyleBuild childLastBuild = + (FreeStyleBuild) r.jenkins.getQueue().getItem(child).getFuture().get(); + List actions = childLastBuild.getActions(ParametersAction.class); assertFalse(actions.isEmpty()); ParametersAction pa = actions.get(0); diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/ProjectSpecificParameterValuesActionTransformTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/ProjectSpecificParameterValuesActionTransformTest.java index 357d4a19..6ae0f0c5 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/ProjectSpecificParameterValuesActionTransformTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/ProjectSpecificParameterValuesActionTransformTest.java @@ -1,5 +1,8 @@ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import hudson.model.BooleanParameterDefinition; import hudson.model.BooleanParameterValue; import hudson.model.FreeStyleProject; @@ -7,37 +10,28 @@ import hudson.model.ParametersDefinitionProperty; import hudson.model.PasswordParameterDefinition; import hudson.model.PasswordParameterValue; +import hudson.model.Project; import hudson.model.StringParameterDefinition; import hudson.model.StringParameterValue; -import hudson.model.Project; import hudson.plugins.parameterizedtrigger.ProjectSpecificParameterValuesActionTransform; - import java.io.IOException; - import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - public class ProjectSpecificParameterValuesActionTransformTest { - + @Rule public JenkinsRule r = new JenkinsRule(); - + @Test public void test() throws IOException { Project project = r.createFreeStyleProject("project"); - project.addProperty(new ParametersDefinitionProperty( - new BooleanParameterDefinition("key1", false, "derp") - )); + project.addProperty(new ParametersDefinitionProperty(new BooleanParameterDefinition("key1", false, "derp"))); - ParametersAction action = new ParametersAction( - new StringParameterValue("key1", "true") - ); + ParametersAction action = new ParametersAction(new StringParameterValue("key1", "true")); ProjectSpecificParameterValuesActionTransform transform = new ProjectSpecificParameterValuesActionTransform(); @@ -45,32 +39,31 @@ public void test() throws IOException { assertEquals(1, result.getParameters().size()); assertTrue(result.getParameter("key1") instanceof BooleanParameterValue); - assertTrue(((BooleanParameterValue)result.getParameter("key1")).value); + assertTrue(((BooleanParameterValue) result.getParameter("key1")).value); } @Test @Issue("SECURITY-101") public void passwordParameterAreCorrectlyConvertedFromUpstreamProject() throws IOException { FreeStyleProject project = r.createFreeStyleProject("child"); - + project.addProperty(new ParametersDefinitionProperty( new StringParameterDefinition("login", "default-login", null), - new PasswordParameterDefinition("pwd", "default-password", null) - )); - + new PasswordParameterDefinition("pwd", "default-password", null))); + ParametersAction action = new ParametersAction( - new StringParameterValue("login", "derpLogin"), - new StringParameterValue("pwd", "pa33") - ); - + new StringParameterValue("login", "derpLogin"), new StringParameterValue("pwd", "pa33")); + ProjectSpecificParameterValuesActionTransform transform = new ProjectSpecificParameterValuesActionTransform(); - + ParametersAction result = transform.transformParametersAction(action, project); - + assertEquals(2, result.getParameters().size()); assertTrue(result.getParameter("login") instanceof StringParameterValue); assertTrue(result.getParameter("pwd") instanceof PasswordParameterValue); - assertEquals("derpLogin", ((StringParameterValue)result.getParameter("login")).value); - assertEquals("pa33", ((PasswordParameterValue)result.getParameter("pwd")).getValue().getPlainText()); + assertEquals("derpLogin", ((StringParameterValue) result.getParameter("login")).value); + assertEquals( + "pa33", + ((PasswordParameterValue) result.getParameter("pwd")).getValue().getPlainText()); } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/RenameJobTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/RenameJobTest.java index ff4fd387..3ed9d74d 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/RenameJobTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/RenameJobTest.java @@ -23,11 +23,15 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + import hudson.model.FreeStyleBuild; -import hudson.model.TopLevelItem; -import hudson.model.TopLevelItemDescriptor; import hudson.model.FreeStyleProject; import hudson.model.Project; +import hudson.model.TopLevelItem; +import hudson.model.TopLevelItemDescriptor; import hudson.plugins.parameterizedtrigger.AbstractBuildParameters; import hudson.plugins.parameterizedtrigger.BlockableBuildTriggerConfig; import hudson.plugins.parameterizedtrigger.BuildTrigger; @@ -36,15 +40,12 @@ import hudson.plugins.parameterizedtrigger.ResultCondition; import hudson.plugins.parameterizedtrigger.TriggerBuilder; import hudson.tasks.BuildStep; - import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; - import jenkins.model.ModifiableTopLevelItemGroup; - import org.jenkins_ci.plugins.run_condition.BuildStepRunner; import org.jenkins_ci.plugins.run_condition.core.AlwaysRun; import org.jenkinsci.plugins.conditionalbuildstep.ConditionalBuilder; @@ -54,108 +55,130 @@ import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockFolder; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertEquals; - public class RenameJobTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test - public void testRenameAndDeleteJobSingleProject() throws Exception { - FreeStyleProject projectA = r.createFreeStyleProject("projectA"); - configureTriggeringOf(projectA, "projectB"); - Project projectB = r.createFreeStyleProject("projectB"); - r.jenkins.rebuildDependencyGraph(); + public void testRenameAndDeleteJobSingleProject() throws Exception { + FreeStyleProject projectA = r.createFreeStyleProject("projectA"); + configureTriggeringOf(projectA, "projectB"); + Project projectB = r.createFreeStyleProject("projectB"); + r.jenkins.rebuildDependencyGraph(); - projectB.renameTo("projectB-renamed"); + projectB.renameTo("projectB-renamed"); - assertTriggering(projectA, "projectB-renamed"); - - projectB.delete(); + assertTriggering(projectA, "projectB-renamed"); - //confirm projectA's build step trigger is updated automatically: - assertNull("now-empty build step trigger should be removed", projectA.getBuildersList().get(TriggerBuilder.class)); + projectB.delete(); - //confirm projectA's post build trigger is updated automatically: - assertNull("now-empty post build trigger should be removed", projectA.getPublishersList().get(BuildTrigger.class)); - } + // confirm projectA's build step trigger is updated automatically: + assertNull( + "now-empty build step trigger should be removed", + projectA.getBuildersList().get(TriggerBuilder.class)); + + // confirm projectA's post build trigger is updated automatically: + assertNull( + "now-empty post build trigger should be removed", + projectA.getPublishersList().get(BuildTrigger.class)); + } @Test - public void testRenameAndDeleteJobMultipleProjects() throws Exception { - Project projectA = r.createFreeStyleProject("projectA"); - configureTriggeringOf(projectA, "projectB", "projectC"); - Project projectB = r.createFreeStyleProject("projectB"); - r.createFreeStyleProject("projectC"); - r.jenkins.rebuildDependencyGraph(); - - projectB.renameTo("projectB-renamed"); - - assertTriggering(projectA, "projectB-renamed,projectC"); - - projectB.delete(); - - assertTriggering(projectA, "projectC"); - } - - /** - * Configure all the triggers to point to a set of child jobs. - * - * @see {@link #assertTriggering(Project, String)} - */ - private Project configureTriggeringOf(Project project, String... childJobNames) throws IOException { - List buildParameters = new ArrayList(); - buildParameters.add(new CurrentBuildParameters()); - - StringBuilder childJobNamesString = new StringBuilder(); - for(String childJobName : childJobNames){ - childJobNamesString.append(childJobName); - childJobNamesString.append(","); - } - - //setup build step trigger - project.getBuildersList().add(new TriggerBuilder(new BlockableBuildTriggerConfig(childJobNamesString.toString(), null, buildParameters))); - - // setup triggers for conditional buildsteps - // test conditional builder (multi) - List blist = new ArrayList(); - TriggerBuilder tb = new TriggerBuilder(new BlockableBuildTriggerConfig(childJobNamesString.toString(), null, buildParameters)); - blist.add(tb); - project.getBuildersList().add(new ConditionalBuilder(new AlwaysRun(), new BuildStepRunner.Run(), blist)); - - // test conditional builder (single) - TriggerBuilder tb2 = new TriggerBuilder(new BlockableBuildTriggerConfig(childJobNamesString.toString(), null, buildParameters)); - project.getBuildersList().add(new SingleConditionalBuilder(tb2, new AlwaysRun(), new BuildStepRunner.Run())); - - //setup post build trigger - project.getPublishersList().add(new BuildTrigger(new BuildTriggerConfig(childJobNamesString.toString(), ResultCondition.SUCCESS, new CurrentBuildParameters()))); - return project; - } - - /** + public void testRenameAndDeleteJobMultipleProjects() throws Exception { + Project projectA = r.createFreeStyleProject("projectA"); + configureTriggeringOf(projectA, "projectB", "projectC"); + Project projectB = r.createFreeStyleProject("projectB"); + r.createFreeStyleProject("projectC"); + r.jenkins.rebuildDependencyGraph(); + + projectB.renameTo("projectB-renamed"); + + assertTriggering(projectA, "projectB-renamed,projectC"); + + projectB.delete(); + + assertTriggering(projectA, "projectC"); + } + + /** + * Configure all the triggers to point to a set of child jobs. + * + * @see {@link #assertTriggering(Project, String)} + */ + private Project configureTriggeringOf(Project project, String... childJobNames) throws IOException { + List buildParameters = new ArrayList(); + buildParameters.add(new CurrentBuildParameters()); + + StringBuilder childJobNamesString = new StringBuilder(); + for (String childJobName : childJobNames) { + childJobNamesString.append(childJobName); + childJobNamesString.append(","); + } + + // setup build step trigger + project.getBuildersList() + .add(new TriggerBuilder( + new BlockableBuildTriggerConfig(childJobNamesString.toString(), null, buildParameters))); + + // setup triggers for conditional buildsteps + // test conditional builder (multi) + List blist = new ArrayList(); + TriggerBuilder tb = new TriggerBuilder( + new BlockableBuildTriggerConfig(childJobNamesString.toString(), null, buildParameters)); + blist.add(tb); + project.getBuildersList().add(new ConditionalBuilder(new AlwaysRun(), new BuildStepRunner.Run(), blist)); + + // test conditional builder (single) + TriggerBuilder tb2 = new TriggerBuilder( + new BlockableBuildTriggerConfig(childJobNamesString.toString(), null, buildParameters)); + project.getBuildersList().add(new SingleConditionalBuilder(tb2, new AlwaysRun(), new BuildStepRunner.Run())); + + // setup post build trigger + project.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + childJobNamesString.toString(), ResultCondition.SUCCESS, new CurrentBuildParameters()))); + return project; + } + + /** * Assert that all the triggers refers to expected jobs. */ private void assertTriggering(Project p, String expected) { - String actual = p.getBuildersList().get(TriggerBuilder.class).getConfigs().get(0).getProjects(); + String actual = p.getBuildersList() + .get(TriggerBuilder.class) + .getConfigs() + .get(0) + .getProjects(); assertEquals("build step trigger", expected, actual); - final TriggerBuilder triggerBuilder = (TriggerBuilder) p.getBuildersList().getAll(ConditionalBuilder.class).get(0).getConditionalbuilders().get(0); + final TriggerBuilder triggerBuilder = (TriggerBuilder) p.getBuildersList() + .getAll(ConditionalBuilder.class) + .get(0) + .getConditionalbuilders() + .get(0); actual = triggerBuilder.getConfigs().get(0).getProjects(); assertEquals("build step trigger project within first conditionalbuildstep", expected, actual); - final TriggerBuilder singleCondTrigger0 = (TriggerBuilder)p.getBuildersList().getAll(SingleConditionalBuilder.class).get(0).getBuildStep(); + final TriggerBuilder singleCondTrigger0 = (TriggerBuilder) p.getBuildersList() + .getAll(SingleConditionalBuilder.class) + .get(0) + .getBuildStep(); actual = singleCondTrigger0.getConfigs().get(0).getProjects(); assertEquals("build step trigger project within first singleconditionalbuildstep", expected, actual); - actual = p.getPublishersList().get(BuildTrigger.class).getConfigs().get(0).getProjects(); + actual = p.getPublishersList() + .get(BuildTrigger.class) + .getConfigs() + .get(0) + .getProjects(); assertEquals("post build step trigger", expected, actual); } - private T createProject(Class type, ModifiableTopLevelItemGroup owner, String name) throws IOException { - return (T) owner.createProject((TopLevelItemDescriptor) r.jenkins.getDescriptorOrDie(type), name, true); - } + private T createProject(Class type, ModifiableTopLevelItemGroup owner, String name) + throws IOException { + return (T) owner.createProject((TopLevelItemDescriptor) r.jenkins.getDescriptorOrDie(type), name, true); + } @Test public void testRenameAndDeleteJobInSameFolder() throws Exception { @@ -163,51 +186,54 @@ public void testRenameAndDeleteJobInSameFolder() throws Exception { FreeStyleProject p1 = createProject(FreeStyleProject.class, folder1, "ProjectA"); FreeStyleProject p2 = createProject(FreeStyleProject.class, folder1, "ProjectB"); - p1.getPublishersList().add(new BuildTrigger(new BuildTriggerConfig( - p2.getName(), // This should not be getFullName(). - ResultCondition.ALWAYS, - true, - Arrays.asList((AbstractBuildParameters)new CurrentBuildParameters()) - ))); - + p1.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + p2.getName(), // This should not be getFullName(). + ResultCondition.ALWAYS, + true, + Arrays.asList((AbstractBuildParameters) new CurrentBuildParameters())))); + r.jenkins.rebuildDependencyGraph(); - + // Test this works { assertNull(p2.getLastBuild()); - + r.buildAndAssertSuccess(p1); - + r.jenkins.getQueue().getItem(p2).getFuture().get(60, TimeUnit.SECONDS); FreeStyleBuild b = p2.getLastBuild(); assertNotNull(b); r.assertBuildStatusSuccess(b); b.delete(); } - + // Rename p2.renameTo("ProjectB-renamed"); assertEquals("ProjectB-renamed", p2.getName()); - + // assertRenamed assertEquals( p2.getName(), - p1.getPublishersList().get(BuildTrigger.class).getConfigs().get(0).getProjects() - ); - + p1.getPublishersList() + .get(BuildTrigger.class) + .getConfigs() + .get(0) + .getProjects()); + // Test this works { assertNull(p2.getLastBuild()); - + r.buildAndAssertSuccess(p1); - + r.jenkins.getQueue().getItem(p2).getFuture().get(60, TimeUnit.SECONDS); FreeStyleBuild b = p2.getLastBuild(); assertNotNull(b); r.assertBuildStatusSuccess(b); b.delete(); } - + p2.delete(); assertNull(p1.getPublishersList().get(BuildTrigger.class)); } @@ -218,55 +244,58 @@ public void testRenameAndDeleteJobInSubFolder() throws Exception { MockFolder folder2 = createProject(MockFolder.class, folder1, "Folder2"); FreeStyleProject p1 = createProject(FreeStyleProject.class, folder1, "ProjectA"); FreeStyleProject p2 = createProject(FreeStyleProject.class, folder2, "ProjectB"); - - p1.getPublishersList().add(new BuildTrigger(new BuildTriggerConfig( - String.format("%s/%s", folder2.getName(), p2.getName()), - // This should not be getFullName(). - ResultCondition.ALWAYS, - true, - null, - Arrays.asList((AbstractBuildParameters)new CurrentBuildParameters()), - false - ))); - + + p1.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + String.format("%s/%s", folder2.getName(), p2.getName()), + // This should not be getFullName(). + ResultCondition.ALWAYS, + true, + null, + Arrays.asList((AbstractBuildParameters) new CurrentBuildParameters()), + false))); + r.jenkins.rebuildDependencyGraph(); - + // Test this works { assertNull(p2.getLastBuild()); - + r.buildAndAssertSuccess(p1); - + r.jenkins.getQueue().getItem(p2).getFuture().get(60, TimeUnit.SECONDS); FreeStyleBuild b = p2.getLastBuild(); assertNotNull(b); r.assertBuildStatusSuccess(b); b.delete(); } - + // Rename p2.renameTo("ProjectB-renamed"); assertEquals("ProjectB-renamed", p2.getName()); - + // assertRenamed assertEquals( String.format("%s/%s", folder2.getName(), p2.getName()), - p1.getPublishersList().get(BuildTrigger.class).getConfigs().get(0).getProjects() - ); - + p1.getPublishersList() + .get(BuildTrigger.class) + .getConfigs() + .get(0) + .getProjects()); + // Test this works { assertNull(p2.getLastBuild()); - + r.buildAndAssertSuccess(p1); - + r.jenkins.getQueue().getItem(p2).getFuture().get(60, TimeUnit.SECONDS); FreeStyleBuild b = p2.getLastBuild(); assertNotNull(b); r.assertBuildStatusSuccess(b); b.delete(); } - + p2.delete(); assertNull(p1.getPublishersList().get(BuildTrigger.class)); } @@ -278,89 +307,95 @@ public void testRenameAndDeleteJobInParentFolder() throws Exception { FreeStyleProject p1 = createProject(FreeStyleProject.class, folder2, "ProjectA"); FreeStyleProject p2 = createProject(FreeStyleProject.class, folder1, "ProjectB"); - p1.getPublishersList().add(new BuildTrigger(new BuildTriggerConfig( - String.format("../%s", p2.getName()), - // This should not be getFullName(). - ResultCondition.ALWAYS, - true, - null, - Arrays.asList((AbstractBuildParameters)new CurrentBuildParameters()), - false - ))); - + p1.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + String.format("../%s", p2.getName()), + // This should not be getFullName(). + ResultCondition.ALWAYS, + true, + null, + Arrays.asList((AbstractBuildParameters) new CurrentBuildParameters()), + false))); + r.jenkins.rebuildDependencyGraph(); - + // Test this works { assertNull(p2.getLastBuild()); - + r.buildAndAssertSuccess(p1); - + r.jenkins.getQueue().getItem(p2).getFuture().get(60, TimeUnit.SECONDS); FreeStyleBuild b = p2.getLastBuild(); assertNotNull(b); r.assertBuildStatusSuccess(b); b.delete(); } - + // Rename p2.renameTo("ProjectB-renamed"); assertEquals("ProjectB-renamed", p2.getName()); - + // assertRenamed assertEquals( String.format("../%s", p2.getName()), - p1.getPublishersList().get(BuildTrigger.class).getConfigs().get(0).getProjects() - ); - + p1.getPublishersList() + .get(BuildTrigger.class) + .getConfigs() + .get(0) + .getProjects()); + // Test this works { assertNull(p2.getLastBuild()); - + r.buildAndAssertSuccess(p1); - + r.jenkins.getQueue().getItem(p2).getFuture().get(60, TimeUnit.SECONDS); FreeStyleBuild b = p2.getLastBuild(); assertNotNull(b); r.assertBuildStatusSuccess(b); b.delete(); } - + p2.delete(); assertNull(p1.getPublishersList().get(BuildTrigger.class)); } - + /** * {@link hudson.model.Items#computeRelativeNamesAfterRenaming(String, String, String, hudson.model.ItemGroup)} has a bug * that renaming names that contains the target name as prefix. * E.g. renaming ProjectB to ProjectB-renamed results in renaming ProjectB2 to ProjectB-renamed2. * This is fixed in Jenkins 1.530. - * + * * This test verifies this plugin is not affected by that problem. - */ + */ @Test public void testComputeRelativeNamesAfterRenaming() throws Exception { FreeStyleProject projectA = r.createFreeStyleProject("ProjectA"); FreeStyleProject projectB = r.createFreeStyleProject("ProjectB"); FreeStyleProject projectB2 = r.createFreeStyleProject("ProjectB2"); - - projectA.getPublishersList().add(new BuildTrigger(new BuildTriggerConfig( - String.format("%s,%s", projectB.getName(), projectB2.getName()), - ResultCondition.ALWAYS, - true, - null, - Arrays.asList((AbstractBuildParameters)new CurrentBuildParameters()), - false - ))); - + + projectA.getPublishersList() + .add(new BuildTrigger(new BuildTriggerConfig( + String.format("%s,%s", projectB.getName(), projectB2.getName()), + ResultCondition.ALWAYS, + true, + null, + Arrays.asList((AbstractBuildParameters) new CurrentBuildParameters()), + false))); + r.jenkins.rebuildDependencyGraph(); - + projectB.renameTo("ProjectB-renamed"); - + // assertRenamed assertEquals( String.format("%s,%s", projectB.getName(), projectB2.getName()), - projectA.getPublishersList().get(BuildTrigger.class).getConfigs().get(0).getProjects() - ); + projectA.getPublishersList() + .get(BuildTrigger.class) + .getConfigs() + .get(0) + .getProjects()); } } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/ResultConditionTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/ResultConditionTest.java index c04892f1..3789ee52 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/ResultConditionTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/ResultConditionTest.java @@ -1,18 +1,18 @@ /* * The MIT License - * + * * Copyright (c) 2004-2010, Sun Microsystems, Inc., Tom Huybrechts - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,19 +23,22 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + import hudson.model.Build; -import hudson.model.Result; import hudson.model.FreeStyleProject; import hudson.model.Project; import hudson.model.Queue; +import hudson.model.Result; import hudson.plugins.parameterizedtrigger.BuildTrigger; import hudson.plugins.parameterizedtrigger.BuildTriggerConfig; import hudson.plugins.parameterizedtrigger.PredefinedBuildParameters; import hudson.plugins.parameterizedtrigger.ResultCondition; - import java.io.IOException; import java.util.concurrent.ExecutionException; - import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.FailureBuilder; @@ -43,16 +46,11 @@ import org.jvnet.hudson.test.SleepBuilder; import org.jvnet.hudson.test.UnstableBuilder; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; - public class ResultConditionTest { @Rule public JenkinsRule r = new JenkinsRule(); - + @Test public void testTriggerByStableBuild() throws Exception { Project projectA = r.createFreeStyleProject("projectA"); @@ -67,10 +65,10 @@ public void testTriggerByStableBuild() throws Exception { schedule(projectA, projectB, ResultCondition.UNSTABLE_OR_BETTER); assertEquals(2, projectB.getLastBuild().getNumber()); - + schedule(projectA, projectB, ResultCondition.UNSTABLE); assertEquals(2, projectB.getLastBuild().getNumber()); - + schedule(projectA, projectB, ResultCondition.UNSTABLE_OR_WORSE); assertEquals(2, projectB.getLastBuild().getNumber()); @@ -96,7 +94,7 @@ public void testTriggerByUnstableBuild() throws Exception { schedule(projectA, projectB, ResultCondition.UNSTABLE); assertEquals(2, projectB.getLastBuild().getNumber()); - + schedule(projectA, projectB, ResultCondition.UNSTABLE_OR_WORSE); assertEquals(3, projectB.getLastBuild().getNumber()); @@ -106,32 +104,36 @@ public void testTriggerByUnstableBuild() throws Exception { private void schedule(Project projectA, Project projectB, ResultCondition condition) throws IOException, InterruptedException, ExecutionException { - projectA.getPublishersList().replace(new BuildTrigger(new BuildTriggerConfig("projectB", condition, new PredefinedBuildParameters("")))); + projectA.getPublishersList() + .replace(new BuildTrigger( + new BuildTriggerConfig("projectB", condition, new PredefinedBuildParameters("")))); r.jenkins.rebuildDependencyGraph(); projectA.scheduleBuild2(0).get(); Queue.Item q = r.jenkins.getQueue().getItem(projectB); if (q != null) q.getFuture().get(); } - private Build waitForBuildStarts(Project project, long timeoutMillis) throws Exception { + private Build waitForBuildStarts(Project project, long timeoutMillis) throws Exception { long current = System.currentTimeMillis(); - while(project.getLastBuild() == null || !project.getLastBuild().isBuilding()) { + while (project.getLastBuild() == null || !project.getLastBuild().isBuilding()) { assertTrue(System.currentTimeMillis() - current < timeoutMillis); Thread.sleep(100); } - Build build = project.getLastBuild(); + Build build = project.getLastBuild(); assertTrue(build.isBuilding()); assertNotNull(build.getExecutor()); - + return build; } - - private void scheduleAndAbort(Project projectA, Project projectB, ResultCondition condition) + + private void scheduleAndAbort(Project projectA, Project projectB, ResultCondition condition) throws Exception { - projectA.getPublishersList().replace(new BuildTrigger(new BuildTriggerConfig(projectB.getFullName(), condition, new PredefinedBuildParameters("")))); + projectA.getPublishersList() + .replace(new BuildTrigger( + new BuildTriggerConfig(projectB.getFullName(), condition, new PredefinedBuildParameters("")))); r.jenkins.rebuildDependencyGraph(); projectA.scheduleBuild2(0); - Build build = waitForBuildStarts(projectA, 5000); + Build build = waitForBuildStarts(projectA, 5000); build.getExecutor().interrupt(); r.waitUntilNoActivity(); r.assertBuildStatus(Result.ABORTED, build); @@ -155,7 +157,7 @@ public void testTriggerByFailedBuild() throws Exception { schedule(projectA, projectB, ResultCondition.UNSTABLE); assertEquals(1, projectB.getLastBuild().getNumber()); - + schedule(projectA, projectB, ResultCondition.UNSTABLE_OR_WORSE); assertEquals(2, projectB.getLastBuild().getNumber()); @@ -198,27 +200,26 @@ public void testTriggerByAbortedByInterrupted() throws Exception { projectA.getBuildersList().add(new SleepBuilder(10000)); FreeStyleProject projectB = r.createFreeStyleProject("projectB"); projectB.setQuietPeriod(1); - + scheduleAndAbort(projectA, projectB, ResultCondition.SUCCESS); assertNull(projectB.getLastBuild()); - + scheduleAndAbort(projectA, projectB, ResultCondition.FAILED); assertNull(projectB.getLastBuild()); - + scheduleAndAbort(projectA, projectB, ResultCondition.UNSTABLE_OR_BETTER); assertNull(projectB.getLastBuild()); - + scheduleAndAbort(projectA, projectB, ResultCondition.UNSTABLE); assertNull(projectB.getLastBuild()); - + scheduleAndAbort(projectA, projectB, ResultCondition.UNSTABLE_OR_WORSE); assertEquals(1, projectB.getLastBuild().getNumber()); - + scheduleAndAbort(projectA, projectB, ResultCondition.FAILED_OR_BETTER); assertEquals(1, projectB.getLastBuild().getNumber()); - + scheduleAndAbort(projectA, projectB, ResultCondition.ALWAYS); assertEquals(2, projectB.getLastBuild().getNumber()); } - } diff --git a/src/test/java/hudson/plugins/parameterizedtrigger/test/TriggerBuilderTest.java b/src/test/java/hudson/plugins/parameterizedtrigger/test/TriggerBuilderTest.java index a91779ca..733349eb 100644 --- a/src/test/java/hudson/plugins/parameterizedtrigger/test/TriggerBuilderTest.java +++ b/src/test/java/hudson/plugins/parameterizedtrigger/test/TriggerBuilderTest.java @@ -23,13 +23,26 @@ */ package hudson.plugins.parameterizedtrigger.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + import com.google.common.collect.ArrayListMultimap; import hudson.EnvVars; import hudson.Launcher; import hudson.Plugin; +import hudson.matrix.AxisList; +import hudson.matrix.MatrixProject; +import hudson.matrix.MatrixRun; +import hudson.matrix.TextAxis; import hudson.model.*; -import hudson.model.Cause.UserIdCause; import hudson.model.Cause.UpstreamCause; +import hudson.model.Cause.UserIdCause; +import hudson.model.queue.QueueTaskFuture; import hudson.plugins.parameterizedtrigger.AbstractBuildParameterFactory; import hudson.plugins.parameterizedtrigger.AbstractBuildParameters; import hudson.plugins.parameterizedtrigger.BlockableBuildTriggerConfig; @@ -38,46 +51,24 @@ import hudson.plugins.parameterizedtrigger.TriggerBuilder; import hudson.plugins.promoted_builds.PromotionProcess; import hudson.plugins.promoted_builds.conditions.DownstreamPassCondition; -import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; -import org.jenkinsci.plugins.workflow.job.WorkflowJob; -import org.junit.Assume; -import org.junit.Rule; -import org.junit.Test; - -import hudson.matrix.TextAxis; -import hudson.matrix.MatrixProject; -import hudson.matrix.MatrixRun; -import hudson.matrix.AxisList; -import hudson.model.queue.QueueTaskFuture; - - +import java.io.IOException; import java.util.ArrayList; -import java.util.concurrent.Future; import java.util.Collections; import java.util.List; import java.util.ListIterator; -import java.util.regex.Pattern; import java.util.regex.Matcher; -import java.io.IOException; - -import java.lang.System; - +import java.util.regex.Pattern; import jenkins.model.Jenkins; +import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; +import org.jenkinsci.plugins.workflow.job.WorkflowJob; +import org.junit.Assume; +import org.junit.Rule; +import org.junit.Test; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.SleepBuilder; import org.mockito.Mockito; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - - public class TriggerBuilderTest { @Rule @@ -96,9 +87,8 @@ public void testProjectWasEnabledDuringTheBuild() throws Exception { when(config.getBlock()).thenReturn(new BlockingBehaviour(Result.FAILURE, Result.FAILURE, Result.FAILURE)); final ArrayListMultimap> futures = ArrayListMultimap.create(); - when(config.perform3(any(AbstractBuild.class), - Mockito.any(Launcher.class), - Mockito.any(BuildListener.class))).thenReturn(futures); + when(config.perform3(any(AbstractBuild.class), Mockito.any(Launcher.class), Mockito.any(BuildListener.class))) + .thenReturn(futures); // Then project is disabled scheduler returns null instead of QueueTaskFuture object futures.put(disabledJob, null); @@ -137,7 +127,8 @@ public void testOrderOfLogEntries() throws Exception { triggerProject.scheduleBuild2(0).get(); - assertLines(triggerProject.getLastBuild(), + assertLines( + triggerProject.getLastBuild(), "project1 #1 started.", "project1 #1 completed. Result was SUCCESS", "project2 #1 started.", @@ -155,13 +146,17 @@ public void testOrderOfLogEntries() throws Exception { @Test public void testSubParameterBuilds() throws Exception { r.jenkins.setNumExecutors(10); // makes sure there are enough executors so that there are no deadlocks - r.jenkins.setNodes(r.jenkins.getNodes()); // update nodes configuration (TODO https://github.com/jenkinsci/jenkins/pull/1596 renders this workaround unnecessary) + r.jenkins.setNodes( + r.jenkins + .getNodes()); // update nodes configuration (TODO https://github.com/jenkinsci/jenkins/pull/1596 + // renders + // this workaround unnecessary) FreeStyleProject p1 = r.createFreeStyleProject("project1"); r.createFreeStyleProject("project2"); r.createFreeStyleProject("project3"); - ///triggered from project 1 + /// triggered from project 1 r.createFreeStyleProject("projectZ4"); r.createFreeStyleProject("projectZ5"); r.createFreeStyleProject("projectZ6"); @@ -180,13 +175,14 @@ public void testSubParameterBuilds() throws Exception { triggerProject.getBuildersList().add(triggerBuilder); triggerProject.scheduleBuild2(0).get(); - assertLines(triggerProject.getLastBuild(), - "project1 #1 started.", - "project1 #1 completed. Result was SUCCESS", - "project2 #1 started.", - "project2 #1 completed. Result was SUCCESS", - "project3 #1 started.", - "project3 #1 completed. Result was SUCCESS"); + assertLines( + triggerProject.getLastBuild(), + "project1 #1 started.", + "project1 #1 completed. Result was SUCCESS", + "project2 #1 started.", + "project2 #1 completed. Result was SUCCESS", + "project3 #1 started.", + "project3 #1 completed. Result was SUCCESS"); } @Test @@ -203,7 +199,8 @@ public void testWaitingForCompletion() throws Exception { triggerProject.scheduleBuild2(0).get(); - assertLines(triggerProject.getLastBuild(), + assertLines( + triggerProject.getLastBuild(), "Waiting for the completion of project1", "Waiting for the completion of project2", "Waiting for the completion of project3"); @@ -217,19 +214,19 @@ public void testNonBlockingTrigger() throws Exception { Project triggerProject = r.createFreeStyleProject("projectA"); - BlockableBuildTriggerConfig config = new BlockableBuildTriggerConfig("project1, project2, project3", null, null); + BlockableBuildTriggerConfig config = + new BlockableBuildTriggerConfig("project1, project2, project3", null, null); TriggerBuilder triggerBuilder = new TriggerBuilder(config); triggerProject.getBuildersList().add(triggerBuilder); triggerProject.scheduleBuild2(0).get(); - assertLines(triggerProject.getLastBuild(), - "Triggering projects: project1, project2, project3"); + assertLines(triggerProject.getLastBuild(), "Triggering projects: project1, project2, project3"); } @Test - public void testCancelsDownstreamBuildWhenInterrupted() throws Exception{ + public void testCancelsDownstreamBuildWhenInterrupted() throws Exception { r.jenkins.setNumExecutors(1); // the downstream-project would be in the build queue FreeStyleProject triggerProject = r.createFreeStyleProject("upstream-project"); @@ -246,35 +243,38 @@ public void testCancelsDownstreamBuildWhenInterrupted() throws Exception{ triggerProject.getLastBuild().getExecutor().interrupt(); parentBuild.get(); - assertLines(triggerProject.getLastBuild(), - "Waiting for the completion of downstream-project", - "Build aborting: cancelling queued project downstream-project", - "Build was aborted", - "Finished: ABORTED" - ); + assertLines( + triggerProject.getLastBuild(), + "Waiting for the completion of downstream-project", + "Build aborting: cancelling queued project downstream-project", + "Build was aborted", + "Finished: ABORTED"); assertNull("No downstream build has been run", downstreamProject.getLastBuild()); assertEquals("No build left in queue", 0, r.jenkins.getQueue().countBuildableItems()); } @Test - public void testConsoleOutputWithCounterParameters() throws Exception{ + public void testConsoleOutputWithCounterParameters() throws Exception { r.createFreeStyleProject("project1"); r.createFreeStyleProject("project2"); r.createFreeStyleProject("project3"); - Project triggerProject = r.createFreeStyleProject(); + Project triggerProject = r.createFreeStyleProject(); BlockingBehaviour blockingBehaviour = new BlockingBehaviour(Result.FAILURE, Result.UNSTABLE, Result.FAILURE); - List buildParameter = Collections.singletonList(new CounterBuildParameterFactory("0", "2", "1", "TEST=COUNT$COUNT")); + List buildParameter = + Collections.singletonList(new CounterBuildParameterFactory("0", "2", "1", "TEST=COUNT$COUNT")); List emptyList = Collections.emptyList(); - BlockableBuildTriggerConfig bBTConfig = new BlockableBuildTriggerConfig("project1, project2, project3", blockingBehaviour, buildParameter, emptyList); + BlockableBuildTriggerConfig bBTConfig = new BlockableBuildTriggerConfig( + "project1, project2, project3", blockingBehaviour, buildParameter, emptyList); triggerProject.getBuildersList().add(new TriggerBuilder(bBTConfig)); triggerProject.scheduleBuild2(0).get(); - assertLines(triggerProject.getLastBuild(), + assertLines( + triggerProject.getLastBuild(), "project1 #1 started.", "project1 #1 completed. Result was SUCCESS", "project1 #2 started.", @@ -310,10 +310,11 @@ public void testBlockingTriggerWithDisabledProjects() throws Exception { triggerProject.scheduleBuild2(0).get(); - assertLines(triggerProject.getLastBuild(), + assertLines( + triggerProject.getLastBuild(), "Waiting for the completion of project1", - "Skipping project2. The project is either disabled, or the authenticated user " + User.current() + - " has no Item.BUILD permissions, or the configuration has not been saved yet.", + "Skipping project2. The project is either disabled, or the authenticated user " + User.current() + + " has no Item.BUILD permissions, or the configuration has not been saved yet.", "Waiting for the completion of project3"); } @@ -416,24 +417,25 @@ public void testBlockingTriggerWithMatrixProject() throws Exception { List runs = matrixProject.getLastBuild().getRuns(); - assertEquals(4,runs.size()); + assertEquals(4, runs.size()); for (MatrixRun run : runs) { - assertLinesRegex(run, - "project1 #[0-9] completed. Result was SUCCESS", - "project2 #[0-9] completed. Result was SUCCESS", - "project3 #[0-9] completed. Result was SUCCESS", - "project4 #[0-9] completed. Result was SUCCESS", - "project5 #[0-9] completed. Result was SUCCESS", - "project6 #[0-9] completed. Result was SUCCESS"); + assertLinesRegex( + run, + "project1 #[0-9] completed. Result was SUCCESS", + "project2 #[0-9] completed. Result was SUCCESS", + "project3 #[0-9] completed. Result was SUCCESS", + "project4 #[0-9] completed. Result was SUCCESS", + "project5 #[0-9] completed. Result was SUCCESS", + "project6 #[0-9] completed. Result was SUCCESS"); } } @Issue("JENKINS-17751") @Test public void testTriggerFromPromotion() throws Exception { - Plugin plugin = Jenkins.get().getPlugin( "promoted-builds"); - Assume.assumeTrue(plugin!=null); + Plugin plugin = Jenkins.get().getPlugin("promoted-builds"); + Assume.assumeTrue(plugin != null); // Test combination with PromotedBuilds. // Assert that the original build can be tracked from triggered build. // The configuration is as following: @@ -447,7 +449,8 @@ public void testTriggerFromPromotion() throws Exception { project1.getPublishersList().add(new hudson.tasks.BuildTrigger(project2.getName(), "SUCCESS")); // promotion for project1. - hudson.plugins.promoted_builds.JobPropertyImpl promote = new hudson.plugins.promoted_builds.JobPropertyImpl(project1); + hudson.plugins.promoted_builds.JobPropertyImpl promote = + new hudson.plugins.promoted_builds.JobPropertyImpl(project1); project1.addProperty(promote); // promotion process to trigger project3 @@ -455,7 +458,7 @@ public void testTriggerFromPromotion() throws Exception { pp.conditions.add(new DownstreamPassCondition(project2.getName())); pp.getBuildSteps().add(new TriggerBuilder(createTriggerConfig(project3.getName()))); // When using built-in BuildTrigger, set up as following: - //pp.getBuildSteps().add(new hudson.tasks.BuildTrigger(project3.getName(), "SUCCESS")); + // pp.getBuildSteps().add(new hudson.tasks.BuildTrigger(project3.getName(), "SUCCESS")); // Are there any other ways to enable a new BuildTrigger? Jenkins.getInstance().rebuildDependencyGraph(); @@ -469,50 +472,40 @@ public void testTriggerFromPromotion() throws Exception { FreeStyleBuild project2_build = null; FreeStyleBuild project3_build = null; - while(true) { + while (true) { Thread.sleep(1000); - if(project1_build == null) { + if (project1_build == null) { project1_build = project1.getLastBuild(); } - if(project2_build == null) { + if (project2_build == null) { project2_build = project2.getLastBuild(); } - if(project3_build == null) { + if (project3_build == null) { project3_build = project3.getLastBuild(); } - if(project1_build != null && !project1_build.isBuilding() - && project2_build != null && !project2_build.isBuilding() - && project3_build != null && !project3_build.isBuilding() - ) { + if (project1_build != null + && !project1_build.isBuilding() + && project2_build != null + && !project2_build.isBuilding() + && project3_build != null + && !project3_build.isBuilding()) { break; } - if(System.currentTimeMillis() > till) { + if (System.currentTimeMillis() > till) { // something not completed. - assertNotNull( - String.format("Failed to trigger project1(%s)", project1.getName()), - project1_build - ); + assertNotNull(String.format("Failed to trigger project1(%s)", project1.getName()), project1_build); assertFalse( String.format("project1(%s) does not finish.", project1.getName()), - project1_build.isBuilding() - ); - assertNotNull( - String.format("Failed to trigger project2(%s)", project2.getName()), - project2_build - ); + project1_build.isBuilding()); + assertNotNull(String.format("Failed to trigger project2(%s)", project2.getName()), project2_build); assertFalse( String.format("project2(%s) does not finish.", project2.getName()), - project2_build.isBuilding() - ); - assertNotNull( - String.format("Failed to trigger project3(%s)", project3.getName()), - project3_build - ); + project2_build.isBuilding()); + assertNotNull(String.format("Failed to trigger project3(%s)", project3.getName()), project3_build); assertFalse( String.format("project3(%s) does not finish.", project3.getName()), - project3_build.isBuilding() - ); + project3_build.isBuilding()); break; } } @@ -530,8 +523,8 @@ protected MatrixProject createMatrixProject(String name) throws IOException { MatrixProject p = r.createProject(MatrixProject.class, name); // set up 2x2 matrix AxisList axes = new AxisList(); - axes.add(new TextAxis("db","mysql","oracle")); - axes.add(new TextAxis("direction","north","south")); + axes.add(new TextAxis("db", "mysql", "oracle")); + axes.add(new TextAxis("direction", "north", "south")); p.setAxes(axes); return p; @@ -540,9 +533,8 @@ protected MatrixProject createMatrixProject(String name) throws IOException { @Test public void testExpansionOfMultipleProjectsInEnvVariable() throws Exception { FreeStyleProject upstream = r.createFreeStyleProject(); - upstream.addProperty(new ParametersDefinitionProperty( - new StringParameterDefinition("PARAM", "downstream1,downstream2") - )); + upstream.addProperty( + new ParametersDefinitionProperty(new StringParameterDefinition("PARAM", "downstream1,downstream2"))); FreeStyleProject downstream1 = r.createFreeStyleProject("downstream1"); FreeStyleProject downstream2 = r.createFreeStyleProject("downstream2"); @@ -551,7 +543,11 @@ public void testExpansionOfMultipleProjectsInEnvVariable() throws Exception { upstream.getBuildersList().add(triggerBuilder); - FreeStyleBuild upstreamBuild = upstream.scheduleBuild2(0, new UserIdCause(), new ParametersAction(new StringParameterValue("PARAM", "downstream1,downstream2"))).get(); + FreeStyleBuild upstreamBuild = upstream.scheduleBuild2( + 0, + new UserIdCause(), + new ParametersAction(new StringParameterValue("PARAM", "downstream1,downstream2"))) + .get(); r.assertBuildStatusSuccess(upstreamBuild); r.waitUntilNoActivity(); FreeStyleBuild downstream1Build = downstream1.getLastBuild(); @@ -572,13 +568,12 @@ public void testProjectTriggeredOnce() throws Exception { triggerProject.getBuildersList().add(triggerBuilder); triggerProject.getBuildersList().add(new SleepBuilder(500)); - triggerProject.scheduleBuild2(0).get(); Thread.sleep(500); assertEquals(triggeredProject.getBuilds().toArray().length, 1); } - private void assertLines(Run build, String... lines) throws IOException { + private void assertLines(Run build, String... lines) throws IOException { List log = build.getLog(Integer.MAX_VALUE); List rest = log; for (String line : lines) { @@ -588,19 +583,19 @@ private void assertLines(Run build, String... lines) throws IOException { } } - private void assertLinesRegex (Run build, String... regexs) throws IOException { + private void assertLinesRegex(Run build, String... regexs) throws IOException { // Same function as above but allows regex instead of just strings List log = build.getLog(Integer.MAX_VALUE); List rest = log; ListIterator li = log.listIterator(); Pattern p = Pattern.compile(""); // initial pattern will be replaced in loop - Matcher m = p.matcher((String)li.next()); + Matcher m = p.matcher((String) li.next()); for (String regex : regexs) { int lastmatched = 0; m.usePattern(Pattern.compile(regex)); while (li.hasNext()) { - m.reset((String)li.next()); + m.reset((String) li.next()); if (m.matches()) { lastmatched = li.nextIndex(); li = log.listIterator(li.nextIndex()); @@ -609,7 +604,7 @@ private void assertLinesRegex (Run build, String... regexs) throws IOExcept } // set up rest to contain the part of the log that has not been successfully checked rest = log.subList(lastmatched + 1, log.size()); - assertTrue("Could not find regex '" + regex + "' among remaining log lines " + rest, li.hasNext() ); + assertTrue("Could not find regex '" + regex + "' among remaining log lines " + rest, li.hasNext()); } } }