Skip to content

Commit

Permalink
Merge pull request #40 from ikedam/feature/JENKINS-17751-2
Browse files Browse the repository at this point in the history
[JENKINS-17751] set upstream builds to original builds of promotions(improvement of #38)
  • Loading branch information
ikedam committed Aug 8, 2013
2 parents a443010 + 9eecd5b commit ce231ba
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 5 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Expand Up @@ -31,6 +31,12 @@
<version>1.25</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>promoted-builds</artifactId>
<version>2.10</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
Expand Down
Expand Up @@ -69,7 +69,7 @@ protected Future schedule(AbstractBuild<?, ?> build, AbstractProject project, Li

// 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
Future f = project.scheduleBuild2(0, new UpstreamCause((Run) build), list.toArray(new Action[list.size()]));
Future f = schedule(build, project, 0, list);
//when a project is disabled or the configuration is not yet saved f will always be null and we'ure caught in a loop, therefore we need to check for it
if (f!=null || (f==null && !project.isBuildable())){
return f;
Expand Down
Expand Up @@ -13,6 +13,7 @@
import hudson.model.Action;
import hudson.model.AutoCompletionCandidates;
import hudson.model.BuildListener;
import hudson.model.Cause;
import hudson.model.Cause.UpstreamCause;
import hudson.model.Describable;
import hudson.model.Descriptor;
Expand All @@ -28,6 +29,7 @@
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.plugins.parameterizedtrigger.AbstractBuildParameters.DontTriggerException;
import hudson.plugins.promoted_builds.Promotion;
import hudson.tasks.Messages;
import hudson.util.FormValidation;

Expand Down Expand Up @@ -435,12 +437,41 @@ private List<List<AbstractBuildParameters>> getDynamicBuildParameters(AbstractBu
}
}

protected Future schedule(AbstractBuild<?, ?> build, AbstractProject project, List<Action> list) throws InterruptedException, IOException {
return project.scheduleBuild2(project.getQuietPeriod(),
new UpstreamCause((Run) build),
/**
* Create UpstreamCause that triggers a downstream build.
*
* If the upstream build is a promotion, return the UpstreamCause
* as triggered by the target of the promotion.
*
* @param build an upstream build
* @return UpstreamCause
*/
protected Cause createUpstreamCause(AbstractBuild<?, ?> build) {
if(Jenkins.getInstance().getPlugin("promoted-builds") != null) {
// Test only when promoted-builds is installed.
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.getTarget());
}
}
return new UpstreamCause((Run) build);
}

protected Future schedule(AbstractBuild<?, ?> build, AbstractProject project, int quietPeriod, List<Action> list) throws InterruptedException, IOException {
Cause cause = createUpstreamCause(build);
return project.scheduleBuild2(quietPeriod,
cause,
list.toArray(new Action[list.size()]));
}

protected Future schedule(AbstractBuild<?, ?> build, AbstractProject project, List<Action> list) throws InterruptedException, IOException {
return schedule(build, project, project.getQuietPeriod(), list);
}

public boolean onJobRenamed(String oldName, String newName) {
boolean changed = false;
String[] list = projects.split(",");
Expand Down
Expand Up @@ -24,14 +24,18 @@
package hudson.plugins.parameterizedtrigger.test;

import hudson.model.Project;
import hudson.model.FreeStyleBuild;
import hudson.model.Result;
import hudson.model.Cause.UpstreamCause;
import hudson.model.FreeStyleProject;
import hudson.plugins.parameterizedtrigger.AbstractBuildParameterFactory;
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 hudson.plugins.promoted_builds.PromotionProcess;
import hudson.plugins.promoted_builds.conditions.DownstreamPassCondition;
import org.jvnet.hudson.test.Bug;

import hudson.matrix.TextAxis;
Expand All @@ -50,9 +54,10 @@
import org.jvnet.hudson.test.HudsonTestCase;
import com.google.common.collect.ImmutableList;
import hudson.model.Run;
import java.io.IOException;
import java.lang.System;

import jenkins.model.Jenkins;

public class TriggerBuilderTest extends HudsonTestCase {

private BlockableBuildTriggerConfig createTriggerConfig(String projects) {
Expand Down Expand Up @@ -268,6 +273,100 @@ public void testBlockingTriggerWithMatrixProject() throws Exception {
}
}

@Bug(17751)
public void testTriggerFromPromotion() throws Exception {
assertNotNull("promoted-builds must be installed.", Jenkins.getInstance().getPlugin("promoted-builds"));
// Test combination with PromotedBuilds.
// Assert that the original build can be tracked from triggered build.
// The configuration is as following:
// Project1 -> (built-in trigger) -> Project2
// -> (promotion) -> Project1/Promotion/TRIGGER -> (Parameterrized Trigger) -> Project3
FreeStyleProject project1 = createFreeStyleProject();
FreeStyleProject project2 = createFreeStyleProject();
FreeStyleProject project3 = createFreeStyleProject();

// project1 -> project2
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);
project1.addProperty(promote);

// promotion process to trigger project3
PromotionProcess pp = promote.addProcess("TRIGGER");
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"));

// Are there any other ways to enable a new BuildTrigger?
Jenkins.getInstance().rebuildDependencyGraph();

project1.scheduleBuild2(0);

// wait for all builds finish
long timeout = 30000;
long till = System.currentTimeMillis() + timeout;
FreeStyleBuild project1_build = null;
FreeStyleBuild project2_build = null;
FreeStyleBuild project3_build = null;

while(true) {
Thread.sleep(1000);
if(project1_build == null) {
project1_build = project1.getLastBuild();
}
if(project2_build == null) {
project2_build = project2.getLastBuild();
}
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()
) {
break;
}

if(System.currentTimeMillis() > till) {
// something not completed.
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
);
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
);
assertFalse(
String.format("project3(%s) does not finish.", project3.getName()),
project3_build.isBuilding()
);
break;
}
}

assertBuildStatusSuccess(project1_build);
assertBuildStatusSuccess(project2_build);
assertBuildStatusSuccess(project3_build);

UpstreamCause c = project3_build.getCause(UpstreamCause.class);
assertNotNull(String.format("Failed to get UpstreamCause from project3(%s)", project3.getName()), c);
assertEquals("UpstreamCause is not properly set.", project1.getName(), c.getUpstreamProject());
}

@Override
protected MatrixProject createMatrixProject(String name) throws IOException {
Expand Down

0 comments on commit ce231ba

Please sign in to comment.