diff --git a/pom.xml b/pom.xml
index 1462d644..d896cc0b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,6 +105,12 @@
1.10
true
+
+ hudson.plugins
+ project-inheritance
+ 1.5.3
+ true
+
diff --git a/src/main/java/hudson/plugins/promoted_builds/JobPropertyImpl.java b/src/main/java/hudson/plugins/promoted_builds/JobPropertyImpl.java
index c809929d..82d2a76c 100644
--- a/src/main/java/hudson/plugins/promoted_builds/JobPropertyImpl.java
+++ b/src/main/java/hudson/plugins/promoted_builds/JobPropertyImpl.java
@@ -64,13 +64,6 @@ public final class JobPropertyImpl extends JobProperty> imp
* These {@link PromotionProcess}es are active.
*/
private final Set activeProcessNames = new HashSet();
-
-// /**
-// * Names of the processes that are configured.
-// * Used to construct {@link #processes}.
-// */
-// private final List names = new ArrayList();
-
/**
* Programmatic construction.
*/
@@ -78,7 +71,11 @@ public JobPropertyImpl(AbstractProject,?> owner) throws Descriptor.FormExcepti
this.owner = owner;
init();
}
-
+ public JobPropertyImpl(JobPropertyImpl other, AbstractProject,?> owner) throws Descriptor.FormException, IOException {
+ this.owner = owner;
+ this.activeProcessNames.addAll(other.activeProcessNames);
+ loadAllProcesses(other.getRootDir());
+ }
private JobPropertyImpl(StaplerRequest req, JSONObject json) throws Descriptor.FormException, IOException {
// a hack to get the owning AbstractProject.
// this is needed here so that we can load items
@@ -112,7 +109,15 @@ private JobPropertyImpl(StaplerRequest req, JSONObject json) throws Descriptor.F
}
init();
}
+ private void loadAllProcesses(File rootDir) throws IOException {
+ File[] subdirs = rootDir.listFiles(new FileFilter() {
+ public boolean accept(File child) {
+ return child.isDirectory();
+ }
+ });
+ loadProcesses(subdirs);
+ }
private void init() throws IOException {
// load inactive processes
File[] subdirs = getRootDir().listFiles(new FileFilter() {
@@ -120,6 +125,9 @@ public boolean accept(File child) {
return child.isDirectory() && !isActiveProcessNameIgnoreCase(child.getName());
}
});
+ loadProcesses(subdirs);
+ }
+ private void loadProcesses(File[] subdirs) throws IOException {
if(subdirs!=null) {
for (File subdir : subdirs) {
try {
@@ -179,7 +187,7 @@ protected synchronized void setOwner(AbstractProject,?> owner) {
// so use this as the initialization opportunity.
// CopyListener is also using setOwner to re-init after copying config from another job.
processes = new ArrayList(ItemGroupMixIn.loadChildren(
- this,getRootDir(),ItemGroupMixIn.KEYED_BY_NAME).values());
+ this,getRootDir(),ItemGroupMixIn.KEYED_BY_NAME).values());
try {
buildActiveProcess();
} catch (IOException e) {
@@ -201,7 +209,11 @@ private void buildActiveProcess() throws IOException {
// ensure that the name casing matches what's given in the activeProcessName
// this is because in case insensitive file system, we may end up resolving
// to a directory name that differs only in their case.
- p.renameTo(getActiveProcessName(p.getName()));
+ String processName = p.getName();
+ String activeProcessName = getActiveProcessName(processName);
+ if (!activeProcessName.equals(processName)){
+ p.renameTo(activeProcessName);
+ }
}
}
@@ -352,16 +364,16 @@ public Action getJobAction(AbstractProject,?> job) {
@Extension
public static final class DescriptorImpl extends JobPropertyDescriptor {
-
+
public DescriptorImpl() {
- super();
- }
+ super();
+ }
- public DescriptorImpl(Class extends JobProperty>> clazz) {
- super(clazz);
- }
+ public DescriptorImpl(Class extends JobProperty>> clazz) {
+ super(clazz);
+ }
- public String getDisplayName() {
+ public String getDisplayName() {
return "Promote Builds When...";
}
diff --git a/src/main/java/hudson/plugins/promoted_builds/PromotionProcess.java b/src/main/java/hudson/plugins/promoted_builds/PromotionProcess.java
index 7c7f1561..ab331831 100644
--- a/src/main/java/hudson/plugins/promoted_builds/PromotionProcess.java
+++ b/src/main/java/hudson/plugins/promoted_builds/PromotionProcess.java
@@ -415,9 +415,7 @@ public boolean scheduleBuild(AbstractBuild,?> build, Cause cause) {
}
public Future scheduleBuild2(AbstractBuild,?> build, Cause cause, List params) {
- assert build.getProject()==getOwner();
-
List actions = new ArrayList();
Promotion.buildParametersAction(actions, build, params);
actions.add(new PromotionTargetAction(build));
diff --git a/src/main/java/hudson/plugins/promoted_builds/PromotionTargetAction.java b/src/main/java/hudson/plugins/promoted_builds/PromotionTargetAction.java
index 1d5f0061..55f2bfb2 100644
--- a/src/main/java/hudson/plugins/promoted_builds/PromotionTargetAction.java
+++ b/src/main/java/hudson/plugins/promoted_builds/PromotionTargetAction.java
@@ -26,6 +26,11 @@ public AbstractBuild,?> resolve() {
}
public AbstractBuild,?> resolve(PromotionProcess parent) {
+ AbstractBuild,?> build = this.resolve();
+ if (build !=null){
+ return build;
+ }
+ //In case of project renamed.
AbstractProject,?> j = parent.getOwner();
if (j==null) return null;
return j.getBuildByNumber(number);
diff --git a/src/main/java/hudson/plugins/promoted_builds/inheritance/JobPropertyImplSelector.java b/src/main/java/hudson/plugins/promoted_builds/inheritance/JobPropertyImplSelector.java
new file mode 100644
index 00000000..342095f3
--- /dev/null
+++ b/src/main/java/hudson/plugins/promoted_builds/inheritance/JobPropertyImplSelector.java
@@ -0,0 +1,67 @@
+
+package hudson.plugins.promoted_builds.inheritance;
+
+import org.apache.log4j.Logger;
+
+import hudson.Extension;
+import hudson.model.JobProperty;
+
+import hudson.plugins.project_inheritance.projects.InheritanceProject;
+import hudson.plugins.project_inheritance.projects.inheritance.InheritanceSelector;
+
+import hudson.plugins.promoted_builds.JobPropertyImpl;
+
+/**
+ *
+ * @author Jacek Tomaka
+ * @since TODO
+ */
+@Extension(optional=true)
+public class JobPropertyImplSelector extends InheritanceSelector> {
+ private static final long serialVersionUID = 1L;
+ private static final Logger logger = Logger.getLogger(JobPropertyImplSelector.class);
+
+ @Override
+ public boolean isApplicableFor(Class> clazz){
+ return JobProperty.class.isAssignableFrom(clazz);
+ }
+
+ @Override
+ public InheritanceSelector.MODE getModeFor(Class> clazz){
+ if (JobPropertyImpl.class.isAssignableFrom(clazz)) return MODE.USE_LAST;
+ return MODE.NOT_RESPONSIBLE;
+ }
+
+ @Override
+ public String getObjectIdentifier(JobProperty> obj){
+ if ( obj!=null && JobPropertyImpl.class.getName().equals(obj.getClass().getName())){
+ return JobPropertyImplSelector.class.getName();
+ }
+ return null;
+ }
+
+ @Override
+ public JobPropertyImpl merge(JobProperty> prior, JobProperty> latter, InheritanceProject caller){
+ return null;
+ }
+
+ @Override
+ public JobProperty> handleSingleton(JobProperty> jobProperty, InheritanceProject caller){
+ if (jobProperty == null || caller == null) return jobProperty;
+ if (caller.isAbstract) return jobProperty;
+
+ if (!JobPropertyImpl.class.isAssignableFrom(jobProperty.getClass())) return jobProperty;
+
+
+ JobPropertyImpl jobPropertyImpl = (JobPropertyImpl)jobProperty;
+
+ try {
+ JobPropertyImpl newJobProperty = new JobPropertyImpl(jobPropertyImpl, caller);
+ return newJobProperty;
+ } catch (Exception ex){
+ logger.error("Error during hacking up JobPropertyImpl", ex );
+ }
+ return jobProperty;
+ }
+}
+
diff --git a/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/DownstreamPassConditionInheritanceTest.java b/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/DownstreamPassConditionInheritanceTest.java
new file mode 100644
index 00000000..130cf9b5
--- /dev/null
+++ b/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/DownstreamPassConditionInheritanceTest.java
@@ -0,0 +1,99 @@
+/*
+ * The MIT License
+ *
+ * Copyright 2015 Franta Mejta
+ *
+ * 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.promoted_builds.conditions.inheritance;
+
+import static org.junit.Assert.*;
+import org.junit.Rule;
+import org.junit.Test;
+import org.jvnet.hudson.test.Bug;
+
+import hudson.model.Result;
+import hudson.plugins.project_inheritance.projects.InheritanceBuild;
+import hudson.plugins.project_inheritance.projects.InheritanceProject.IMode;
+import hudson.plugins.promoted_builds.JobPropertyImpl;
+import hudson.plugins.promoted_builds.PromotedBuildAction;
+import hudson.plugins.promoted_builds.PromotionProcess;
+import hudson.plugins.promoted_builds.Status;
+import hudson.plugins.promoted_builds.conditions.DownstreamPassCondition;
+import hudson.plugins.promoted_builds.inheritance.helpers.InheritanceProjectRule;
+import hudson.plugins.promoted_builds.inheritance.helpers.InheritanceProjectsPair;
+import hudson.tasks.BuildTrigger;
+import jenkins.model.Jenkins;
+
+public final class DownstreamPassConditionInheritanceTest {
+
+ @Rule
+ public InheritanceProjectRule j = new InheritanceProjectRule();
+
+ @Test
+ @Bug(7739)
+ public void shouldEvaluateUpstreamRecursively() throws Exception {
+ final InheritanceProjectsPair pair1 = j.createInheritanceProjectDerivedWithBase();
+ final InheritanceProjectsPair pair2 = j.createInheritanceProjectDerivedWithBase();
+ final InheritanceProjectsPair pair3 = j.createInheritanceProjectDerivedWithBase();
+
+
+ final JobPropertyImpl property = new JobPropertyImpl(pair1.getBase());
+ pair1.getBase().addProperty(property);
+
+ final PromotionProcess process = property.addProcess("promotion");
+ process.conditions.add(new DownstreamPassCondition(pair3.getDerived().getFullName()));
+
+ pair1.getDerived().getPublishersList().add(new BuildTrigger(pair2.getDerived().getFullName(), Result.SUCCESS));
+ pair2.getDerived().getPublishersList().add(new BuildTrigger(pair3.getDerived().getFullName(), Result.SUCCESS));
+ Jenkins.getInstance().rebuildDependencyGraph();
+
+ final InheritanceBuild run1 = j.buildAndAssertSuccess(pair1.getDerived());
+ j.assertBuildStatusSuccess(run1);
+ j.waitUntilNoActivity();
+ j.assertBuildStatusSuccess(pair2.getDerived().getLastBuild());
+ j.waitUntilNoActivity();
+ final InheritanceBuild run3 = j.assertBuildStatusSuccess(pair3.getDerived().getLastBuild());
+ j.waitUntilNoActivity();
+
+ //We cannot assume that the process will contain builds because the process added to base project is different to the one in derived.
+ JobPropertyImpl jobProperty = pair1.getDerived().getProperty(JobPropertyImpl.class,
+ /*Forcing inheritance as temporary hack for inheritance plugin 1.53
+ because that version of the plugin uses inheritance only for certain predefined cases:
+ -specific methods on the call stack
+ -url paths.
+ This has been changed as pull request https://github.com/i-m-c/jenkins-inheritance-plugin/pull/40
+ */
+ IMode.INHERIT_FORCED);
+
+ assertNotNull("derived jobProperty is null", jobProperty);
+ PromotionProcess processDerived = jobProperty.getItem("promotion");
+
+ assertEquals("fingerprint relation", run3.getUpstreamRelationship(pair1.getDerived()), -1);
+ assertFalse("no promotion process", processDerived.getBuilds().isEmpty());
+
+ final PromotedBuildAction action = run1.getAction(PromotedBuildAction.class);
+ assertNotNull("no promoted action", action);
+
+ final Status promotion = action.getPromotion("promotion");
+ assertNotNull("promotion not found", promotion);
+ assertTrue("promotion not successful", promotion.isPromotionSuccessful());
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/ManualConditionInheritanceTest.java b/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/ManualConditionInheritanceTest.java
new file mode 100644
index 00000000..c6071604
--- /dev/null
+++ b/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/ManualConditionInheritanceTest.java
@@ -0,0 +1,204 @@
+package hudson.plugins.promoted_builds.conditions.inheritance;
+
+import hudson.ExtensionList;
+import hudson.model.FreeStyleBuild;
+import hudson.model.ParameterDefinition;
+import hudson.model.ParameterValue;
+import hudson.model.Descriptor;
+import hudson.model.FreeStyleProject;
+import hudson.model.StringParameterDefinition;
+import hudson.plugins.project_inheritance.projects.InheritanceBuild;
+import hudson.plugins.project_inheritance.projects.InheritanceProject.IMode;
+import hudson.plugins.promoted_builds.JobPropertyImpl;
+import hudson.plugins.promoted_builds.PromotedBuildAction;
+import hudson.plugins.promoted_builds.Promotion;
+import hudson.plugins.promoted_builds.PromotionProcess;
+import hudson.plugins.promoted_builds.Status;
+
+import hudson.plugins.promoted_builds.conditions.ManualCondition;
+import hudson.plugins.promoted_builds.conditions.ManualCondition.ManualApproval;
+import hudson.plugins.promoted_builds.inheritance.helpers.InheritanceProjectRule;
+import hudson.plugins.promoted_builds.inheritance.helpers.InheritanceProjectsPair;
+
+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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.SortedMap;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import jenkins.model.Jenkins;
+
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+
+/**
+ * @author Jacek Tomaka
+ */
+public class ManualConditionInheritanceTest {
+ @Rule
+ public InheritanceProjectRule j = new InheritanceProjectRule();
+ public static List getFormsByName(HtmlPage page, String name){
+ List forms=new ArrayList();
+ for (HtmlForm f:page.getForms()){
+ if (name.equals(f.getNameAttribute())){
+ forms.add(f);
+ }
+ }
+ return forms;
+ }
+ public static List getFormParameters(HtmlForm form){
+ return form.getElementsByAttribute("div", "name", "parameter");
+ }
+ @Test
+ public void testManualPromotionProcess() throws Exception {
+ InheritanceProjectsPair inheritanceProjectsPair = j.createInheritanceProjectDerivedWithBase();
+
+ ExtensionList list=Jenkins.getInstance().getExtensionList(Descriptor.class);
+ list.add(new JobPropertyImpl.DescriptorImpl(JobPropertyImpl.class));
+ JobPropertyImpl base = new JobPropertyImpl(inheritanceProjectsPair.getBase());
+ inheritanceProjectsPair.getBase().addProperty(base);
+ PromotionProcess foo = base.addProcess("foo");
+
+ ManualCondition condition=new ManualCondition();
+ condition.getParameterDefinitions().add(new StringParameterDefinition("bogus_string_param_1", "bogus_value_1", "Bog parameter"));
+ condition.getParameterDefinitions().add(new StringParameterDefinition("bogus_string_param_2", "bogus_value_2", "Bog parameter"));
+ foo.conditions.add(condition);
+
+ InheritanceBuild b1 = j.assertBuildStatusSuccess(inheritanceProjectsPair.getDerived().scheduleBuild2(0));
+
+ // promote a build
+
+ List paramValues = condition.createDefaultValues();
+ //try to add duplicate values
+ paramValues.addAll(condition.createDefaultValues());
+ //We cannot assume that the process will contain builds because the process added to base project is different to the one in derived.
+ JobPropertyImpl jobProperty = inheritanceProjectsPair.getDerived().getProperty(JobPropertyImpl.class,
+ /*Forcing inheritance as temporary hack for inheritance plugin 1.53
+ because that version of the plugin uses inheritance only for certain predefined cases:
+ -specific methods on the call stack
+ -url paths.
+ This has been changed as pull request https://github.com/i-m-c/jenkins-inheritance-plugin/pull/40
+ */
+ IMode.INHERIT_FORCED);
+ assertNotNull("derived jobProperty is null", jobProperty);
+ PromotionProcess fooDerived = jobProperty.getItem("foo");
+
+ j.assertBuildStatusSuccess(condition.approve(b1, fooDerived, paramValues));
+ ManualApproval manualApproval=b1.getAction(ManualApproval.class);
+ assertNotNull(manualApproval);
+
+ PromotedBuildAction statuses=b1.getAction(PromotedBuildAction.class);
+ assertNotNull(statuses);
+ assertNotNull(statuses.getPromotions());
+ assertFalse(statuses.getPromotions().isEmpty());
+ }
+
+
+ @Test
+ public void testManualPromotionProcessViaWebClient() throws Exception {
+ InheritanceProjectsPair inheritanceProjectsPair = j.createInheritanceProjectDerivedWithBase();
+
+ ExtensionList list=Jenkins.getInstance().getExtensionList(Descriptor.class);
+ list.add(new JobPropertyImpl.DescriptorImpl(JobPropertyImpl.class));
+ JobPropertyImpl base = new JobPropertyImpl(inheritanceProjectsPair.getBase());
+ inheritanceProjectsPair.getDerived().addProperty(base);
+ PromotionProcess foo = base.addProcess("foo");
+ ManualCondition condition=new ManualCondition();
+ condition.getParameterDefinitions().add(new StringParameterDefinition("bogus_string_param_1", "bogus_value_1", "Bog parameter"));
+ condition.getParameterDefinitions().add(new StringParameterDefinition("bogus_string_param_2", "bogus_value_2", "Bog parameter"));
+ foo.conditions.add(condition);
+
+ InheritanceBuild b1 = j.assertBuildStatusSuccess(inheritanceProjectsPair.getDerived().scheduleBuild2(0));
+ assertNull(b1.getAction(ManualApproval.class));
+ HtmlPage page=j.createWebClient().getPage(b1, "promotion");
+ //Approve Promotion
+ List forms=getFormsByName(page, "approve");
+ assertFalse(forms.isEmpty());
+ assertTrue(forms.size()==1);
+
+ HtmlForm form=forms.get(0);
+ List parameters=getFormParameters(form);
+ assertTrue(parameters.size()==condition.getParameterDefinitions().size());
+ for(HtmlElement param:parameters){
+ HtmlElement v=param.getElementsByAttribute("input", "name", "value").get(0);
+ v.setAttribute("value", v.getAttribute("value")+"1");
+ }
+ j.submit(forms.get(0));
+ j.waitUntilNoActivity();
+ //We cannot assume that the process will contain builds because the process added to base project is different to the one in derived.
+ final JobPropertyImpl jobProperty = inheritanceProjectsPair.getDerived().getProperty(JobPropertyImpl.class,
+ /*Forcing inheritance as temporary hack for inheritance plugin 1.53
+ because that version of the plugin uses inheritance only for certain predefined cases:
+ -specific methods on the call stack
+ -url paths.
+ This has been changed as pull request https://github.com/i-m-c/jenkins-inheritance-plugin/pull/40
+ */
+ IMode.INHERIT_FORCED);
+ assertNotNull("derived jobProperty is null", jobProperty);
+ final PromotionProcess fooDerived = jobProperty.getItem("foo");
+ ManualApproval approval=b1.getAction(ManualApproval.class);
+ assertNotNull(approval);
+ SortedMap builds=fooDerived.getBuildsAsMap();
+ assertNotNull(builds);
+ assertTrue(builds.size()==1);
+
+ //Re-Execute approved promotion
+ page=j.createWebClient().getPage(b1, "promotion");
+ forms=getFormsByName(page,"build");
+ assertFalse(forms.isEmpty());
+ assertTrue(forms.size()==1);
+ form=forms.get(0);
+ parameters=getFormParameters(form);
+ assertTrue(parameters.size()==condition.getParameterDefinitions().size());
+
+ for(HtmlElement param:parameters){
+ HtmlElement v=param.getElementsByAttribute("input", "name", "value").get(0);
+ v.setAttribute("value", v.getAttribute("value")+"2");
+ }
+ j.submit(form);
+ j.waitUntilNoActivity();
+ final JobPropertyImpl jobProperty2 = inheritanceProjectsPair.getDerived().getProperty(JobPropertyImpl.class,
+ /*Forcing inheritance as temporary hack for inheritance plugin 1.53
+ because that version of the plugin uses inheritance only for certain predefined cases:
+ -specific methods on the call stack
+ -url paths.
+ This has been changed as pull request https://github.com/i-m-c/jenkins-inheritance-plugin/pull/40
+ */
+ IMode.INHERIT_FORCED);
+ assertNotNull("derived jobProperty is null", jobProperty2);
+ final PromotionProcess fooDerived2 = jobProperty2.getItem("foo");
+
+ builds=fooDerived2.getBuildsAsMap();
+ assertTrue(builds.size()==2);
+ List actions=b1.getActions(ManualApproval.class);
+ assertTrue(actions.size()==1);
+
+ PromotedBuildAction buildActions=b1.getAction(PromotedBuildAction.class);
+ int buildIndex=1;
+ String valueSufix="1";
+ List promotions=new ArrayList();
+ promotions.addAll(builds.values());
+
+ Collections.reverse(promotions);
+ for (Promotion build:promotions){
+ List values=build.getParameterDefinitionsWithValue();
+ assertTrue(values.size()==condition.getParameterDefinitions().size());
+ for (ParameterDefinition v:values){
+ assertTrue(v instanceof StringParameterDefinition);
+ String pvalue=((StringParameterDefinition)v).getDefaultValue();
+ assertTrue(pvalue.endsWith(valueSufix));
+ }
+ buildIndex++;
+ valueSufix+=buildIndex;
+ }
+
+ }
+}
diff --git a/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/SelfPromotionInheritanceTest.java b/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/SelfPromotionInheritanceTest.java
new file mode 100644
index 00000000..912ceab1
--- /dev/null
+++ b/src/test/java/hudson/plugins/promoted_builds/conditions/inheritance/SelfPromotionInheritanceTest.java
@@ -0,0 +1,215 @@
+package hudson.plugins.promoted_builds.conditions.inheritance;
+
+import hudson.model.Cause;
+import hudson.model.ParametersAction;
+import hudson.model.ParametersDefinitionProperty;
+import hudson.model.Result;
+import hudson.model.StringParameterDefinition;
+import hudson.model.StringParameterValue;
+import hudson.plugins.project_inheritance.projects.InheritanceBuild;
+import hudson.plugins.project_inheritance.projects.InheritanceProject.IMode;
+import hudson.plugins.promoted_builds.JobPropertyImpl;
+import hudson.plugins.promoted_builds.PromotedBuildAction;
+import hudson.plugins.promoted_builds.Promotion;
+import hudson.plugins.promoted_builds.PromotionProcess;
+import hudson.plugins.promoted_builds.conditions.FixedResultBuilder;
+import hudson.plugins.promoted_builds.conditions.SelfPromotionCondition;
+import hudson.plugins.promoted_builds.inheritance.helpers.InheritanceProjectRule;
+import hudson.plugins.promoted_builds.inheritance.helpers.InheritanceProjectsPair;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.jvnet.hudson.test.Bug;
+
+
+/**
+ * @author Jacek Tomaka
+ */
+public class SelfPromotionInheritanceTest {
+ @Rule
+ public InheritanceProjectRule j = new InheritanceProjectRule();
+ @Test
+ public void testBasic() throws Exception {
+ InheritanceProjectsPair inheritanceProjectPair = j.createInheritanceProjectDerivedWithBase();
+
+ // promote if the downstream passes
+ JobPropertyImpl promotion = new JobPropertyImpl(inheritanceProjectPair.getBase());
+ inheritanceProjectPair.getBase().addProperty(promotion);
+
+ PromotionProcess promo1 = promotion.addProcess("promo1");
+ promo1.conditions.add(new SelfPromotionCondition(false));
+
+ PromotionProcess promo2 = promotion.addProcess("promo2");
+ promo2.conditions.add(new SelfPromotionCondition(false));
+
+
+ InheritanceBuild b = j.assertBuildStatusSuccess(inheritanceProjectPair.getDerived().scheduleBuild2(0));
+
+ // internally, the promotion is still an asynchronous process. It just happens
+ // right away after the build is complete.
+ j.waitUntilNoActivity();
+
+ // rebind
+ promotion = inheritanceProjectPair.getDerived().getProperty(JobPropertyImpl.class,
+ /*Forcing inheritance as temporary hack for inheritance plugin 1.53
+ because that version of the plugin uses inheritance only for certain predefined cases:
+ -specific methods on the call stack
+ -url paths.
+ This has been changed as pull request https://github.com/i-m-c/jenkins-inheritance-plugin/pull/40
+ */
+ IMode.INHERIT_FORCED);
+ promo1 = promotion.getItem("promo1");
+ promo2 = promotion.getItem("promo2");
+
+
+ // verify that both promotions happened
+ Promotion pb = promo1.getBuilds().get(0);
+ assertSame(pb.getTarget(),b);
+
+ pb = promo2.getBuilds().get(0);
+ assertSame(pb.getTarget(),b);
+
+ PromotedBuildAction badge = (PromotedBuildAction) b.getBadgeActions().get(0);
+ assertTrue(badge.contains(promo1));
+ assertTrue(badge.contains(promo2));
+ }
+ @Test
+ public void testUnstable() throws Exception {
+ InheritanceProjectsPair inheritanceProjectPair = j.createInheritanceProjectDerivedWithBase();
+
+ // promote if the downstream passes
+ JobPropertyImpl promotion = new JobPropertyImpl(inheritanceProjectPair.getBase());
+ inheritanceProjectPair.getBase().addProperty(promotion);
+
+ PromotionProcess promo1 = promotion.addProcess("promo1");
+ promo1.conditions.add(new SelfPromotionCondition(false));
+
+ PromotionProcess promo2 = promotion.addProcess("promo2");
+ promo2.conditions.add(new SelfPromotionCondition(true));
+
+
+
+ inheritanceProjectPair.getDerived().getBuildersList().add(unstableBuilder());
+ InheritanceBuild b = j.assertBuildStatus(Result.UNSTABLE, inheritanceProjectPair.getDerived().scheduleBuild2(0).get());
+ j.waitUntilNoActivity();
+ // rebind
+ promotion = inheritanceProjectPair.getDerived().getProperty(JobPropertyImpl.class,
+ /*Forcing inheritance as temporary hack for inheritance plugin 1.53
+ because that version of the plugin uses inheritance only for certain predefined cases:
+ -specific methods on the call stack
+ -url paths.
+ This has been changed as pull request https://github.com/i-m-c/jenkins-inheritance-plugin/pull/40
+ */
+ IMode.INHERIT_FORCED);
+ promo1 = promotion.getItem("promo1");
+ promo2 = promotion.getItem("promo2");
+ // internally, the promotion is still an asynchronous process. It just happens
+ // right away after the build is complete.
+
+
+ // verify that only one promotions happened
+ assertTrue(promo1.getBuilds().isEmpty());
+
+ Promotion pb = promo2.getBuilds().get(0);
+ assertSame(pb.getTarget(),b);
+
+ PromotedBuildAction badge = (PromotedBuildAction) b.getBadgeActions().get(0);
+ assertFalse(badge.contains(promo1));
+ assertTrue(badge.contains(promo2));
+ }
+
+ @Test
+ public void testFailure() throws Exception {
+ InheritanceProjectsPair inheritanceProjectPair = j.createInheritanceProjectDerivedWithBase();
+
+ // promote if the downstream passes
+ JobPropertyImpl promotion = new JobPropertyImpl(inheritanceProjectPair.getBase());
+ inheritanceProjectPair.getBase().addProperty(promotion);
+
+ PromotionProcess promo1 = promotion.addProcess("promo1");
+ promo1.conditions.add(new SelfPromotionCondition(false));
+
+ PromotionProcess promo2 = promotion.addProcess("promo2");
+ promo2.conditions.add(new SelfPromotionCondition(true));
+
+ inheritanceProjectPair.getDerived().getBuildersList().add(failureBuilder());
+ InheritanceBuild b = j.assertBuildStatus(Result.FAILURE, inheritanceProjectPair.getDerived().scheduleBuild2(0).get());
+
+ // internally, the promotion is still an asynchronous process. It just happens
+ // right away after the build is complete.
+ j.waitUntilNoActivity();
+
+ // rebind
+ promotion = inheritanceProjectPair.getDerived().getProperty(JobPropertyImpl.class,
+ /*Forcing inheritance as temporary hack for inheritance plugin 1.53
+ because that version of the plugin uses inheritance only for certain predefined cases:
+ -specific methods on the call stack
+ -url paths.
+ This has been changed as pull request https://github.com/i-m-c/jenkins-inheritance-plugin/pull/40
+ */
+ IMode.INHERIT_FORCED);
+ promo1 = promotion.getItem("promo1");
+ promo2 = promotion.getItem("promo2");
+
+
+ // verify that neither promotions happened
+ assertTrue("promo1 did not occur", promo1.getBuilds().isEmpty());
+ assertTrue("promo2 did not occur", promo2.getBuilds().isEmpty());
+
+ PromotedBuildAction badge = (PromotedBuildAction) b.getBadgeActions().get(0);
+ assertFalse(badge.contains(promo1));
+ assertFalse(badge.contains(promo2));
+ }
+
+ @Test
+ @Bug(22679)
+ public void testPromotionEnvironmentShouldIncludeTargetParameters() throws Exception {
+ String paramName = "param";
+
+ InheritanceProjectsPair inheritanceProjectPair = j.createInheritanceProjectDerivedWithBase();
+
+ // promote if the downstream passes
+ JobPropertyImpl promotion = new JobPropertyImpl(inheritanceProjectPair.getBase());
+ inheritanceProjectPair.getBase().addProperty(promotion);
+
+ inheritanceProjectPair.getBase().addProperty(new ParametersDefinitionProperty(new StringParameterDefinition(paramName, "")));
+ PromotionProcess promo1 = promotion.addProcess("promo1");
+ promo1.conditions.add(new SelfPromotionCondition(false));
+
+ String paramValue = "someString";
+ j.assertBuildStatusSuccess(inheritanceProjectPair.getDerived().scheduleBuild2(0, new Cause.UserCause(),
+ new ParametersAction(new StringParameterValue(paramName, paramValue))));
+ // internally, the promotion is still an asynchronous process. It just happens
+ // right away after the build is complete.
+ j.waitUntilNoActivity();
+
+ // rebind
+ promotion = inheritanceProjectPair.getDerived().getProperty(JobPropertyImpl.class,
+ /*Forcing inheritance as temporary hack for inheritance plugin 1.53
+ because that version of the plugin uses inheritance only for certain predefined cases:
+ -specific methods on the call stack
+ -url paths.
+ This has been changed as pull request https://github.com/i-m-c/jenkins-inheritance-plugin/pull/40
+ */
+ IMode.INHERIT_FORCED);
+ promo1 = promotion.getItem("promo1");
+
+ // verify that the promotion's environment contains the parameter from the target build.
+ Promotion pb = promo1.getBuildByNumber(1);
+ assertEquals(paramValue, pb.getEnvironment(null).get(paramName, null));
+ }
+
+ private FixedResultBuilder failureBuilder() {
+ return new FixedResultBuilder(Result.FAILURE);
+ }
+
+ private FixedResultBuilder unstableBuilder() {
+ return new FixedResultBuilder(Result.UNSTABLE);
+ }
+
+}
diff --git a/src/test/java/hudson/plugins/promoted_builds/inheritance/helpers/InheritanceProjectRule.java b/src/test/java/hudson/plugins/promoted_builds/inheritance/helpers/InheritanceProjectRule.java
new file mode 100644
index 00000000..af3fd938
--- /dev/null
+++ b/src/test/java/hudson/plugins/promoted_builds/inheritance/helpers/InheritanceProjectRule.java
@@ -0,0 +1,28 @@
+package hudson.plugins.promoted_builds.inheritance.helpers;
+
+import java.io.IOException;
+
+import org.jvnet.hudson.test.JenkinsRule;
+
+import hudson.plugins.project_inheritance.projects.InheritanceProject;
+import hudson.plugins.project_inheritance.projects.references.SimpleProjectReference;
+
+public class InheritanceProjectRule extends JenkinsRule {
+ InheritanceProject createInheritanceProject() throws IOException{
+ return createInheritanceProject(createUniqueProjectName());
+ }
+ InheritanceProject createInheritanceProject(String name) throws IOException{
+ return jenkins.createProject(InheritanceProject.class, name);
+ }
+ /**
+ * Returns BASE,DERIVED projects
+ * @throws IOException
+ */
+ public InheritanceProjectsPair createInheritanceProjectDerivedWithBase() throws IOException{
+ String baseProjectName = createUniqueProjectName();
+ InheritanceProject base = createInheritanceProject(baseProjectName);
+ InheritanceProject derived = createInheritanceProject();
+ derived.addParentReference(new SimpleProjectReference(baseProjectName));
+ return new InheritanceProjectsPair(base, derived);
+ }
+}
diff --git a/src/test/java/hudson/plugins/promoted_builds/inheritance/helpers/InheritanceProjectsPair.java b/src/test/java/hudson/plugins/promoted_builds/inheritance/helpers/InheritanceProjectsPair.java
new file mode 100644
index 00000000..3c839064
--- /dev/null
+++ b/src/test/java/hudson/plugins/promoted_builds/inheritance/helpers/InheritanceProjectsPair.java
@@ -0,0 +1,22 @@
+package hudson.plugins.promoted_builds.inheritance.helpers;
+
+import hudson.plugins.project_inheritance.projects.InheritanceProject;
+/**
+ * @author Jacek Tomaka
+ */
+public class InheritanceProjectsPair {
+
+ private InheritanceProject base;
+ private InheritanceProject derived;
+ public InheritanceProject getBase() {
+ return base;
+ }
+ public InheritanceProject getDerived() {
+ return derived;
+ }
+
+ public InheritanceProjectsPair(InheritanceProject base, InheritanceProject derived){
+ this.base = base;
+ this.derived = derived;
+ }
+}