Skip to content

Commit

Permalink
[FIXED JENKINS-38454] Make sure we add the triggers before starting.
Browse files Browse the repository at this point in the history
This was...complex. But it works. We make sure the triggers property
has been added before starting, in case the start method for a trigger
class expects the trigger to already be present on the job. Existing
tests all pass, and the new test failed without the changes to
WorkflowJob and PipelineTriggersJobProperty. Phew.

Note - I'm working on getting rid of the need for posting hardcoded
JSON and just using form manipulation.
  • Loading branch information
abayer committed Sep 23, 2016
1 parent b7b4880 commit d49d3c2
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 9 deletions.
Expand Up @@ -445,6 +445,10 @@ public PipelineTriggersJobProperty getTriggersJobProperty() {
return triggerProp;
}

public void addTriggersJobPropertyWithoutStart(PipelineTriggersJobProperty prop) throws IOException {
super.addProperty(prop);
}

public void setTriggers(List<Trigger<?>> inputTriggers) throws IOException {
triggers = null;
BulkChange bc = new BulkChange(this);
Expand Down
Expand Up @@ -145,14 +145,17 @@ public PipelineTriggersJobProperty reconfigure(@Nonnull StaplerRequest req, @Che
throw new Descriptor.FormException(e, null);
}

this.stopTriggers();

PipelineTriggersJobProperty thisProp = new PipelineTriggersJobProperty(new ArrayList<Trigger>(trigList.toList()));
thisProp.setOwner(owner);
try {
owner.removeProperty(this);
PipelineTriggersJobProperty thisProp = new PipelineTriggersJobProperty(new ArrayList<Trigger>(trigList.toList()));

thisProp.startTriggers(true);
owner.addTriggersJobPropertyWithoutStart(thisProp);

return thisProp;
thisProp.startTriggers(true);
return thisProp;
} catch (IOException e) {
return null;
}
}

@Extension(ordinal = -100)
Expand Down
Expand Up @@ -25,14 +25,14 @@
*/
package org.jenkinsci.plugins.workflow.job.properties;

import hudson.diagnosis.OldDataMonitor;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import hudson.model.Item;
import hudson.model.Items;
import hudson.model.Saveable;
import hudson.triggers.TimerTrigger;
import hudson.triggers.Trigger;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.properties.PipelineTriggersJobProperty;
import org.junit.After;
import org.junit.ClassRule;
import org.junit.Rule;
Expand All @@ -41,12 +41,14 @@
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.recipes.LocalData;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;

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;

public class PipelineTriggersJobPropertyTest {
Expand All @@ -62,6 +64,7 @@ public class PipelineTriggersJobPropertyTest {
@After
public void resetStartsAndStops() {
MockTrigger.startsAndStops = new ArrayList<>();
QueryingMockTrigger.startsAndStops = new ArrayList<>();
}

@Test
Expand Down Expand Up @@ -167,6 +170,30 @@ public void configRoundTrip() throws Exception {
assertEquals("[null, false, null, true]", MockTrigger.startsAndStops.toString());
}

@Test
public void triggerPresentDuringStart() throws Exception {
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "triggerPresent");
r.configRoundtrip(p);
assertNull(getTriggerFromList(QueryingMockTrigger.class,
p.getTriggersJobProperty().getTriggers()));
JenkinsRule.WebClient wc = r.createWebClient();
String newConfig = org.apache.commons.io.IOUtils.toString(
PipelineTriggersJobPropertyTest.class.getResourceAsStream(
"/org/jenkinsci/plugins/workflow/job/properties/PipelineTriggersJobPropertyTest/triggerPresentDuringStart.json"), "UTF-8");
WebRequest request = new WebRequest(new URL(p.getAbsoluteUrl() + "configSubmit"), HttpMethod.POST);
wc.addCrumb(request);
List<NameValuePair> params = new ArrayList<>();
params.addAll(request.getRequestParameters());
params.add(new NameValuePair("json", newConfig));
request.setRequestParameters(params);
wc.getPage(request);
QueryingMockTrigger t = getTriggerFromList(QueryingMockTrigger.class,
p.getTriggersJobProperty().getTriggers());
assertNotNull(t);
assertTrue(t.isStarted);
assertTrue(t.foundSelf);
}

private <T extends Trigger> T getTriggerFromList(Class<T> clazz, List<Trigger<?>> triggers) {
for (Trigger t : triggers) {
if (clazz.isInstance(t)) {
Expand Down
@@ -0,0 +1,86 @@
/*
* The MIT License
*
* Copyright (c) 2016, CloudBees, Inc.
*
* 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 org.jenkinsci.plugins.workflow.job.properties;

import hudson.Extension;
import hudson.model.BuildableItem;
import hudson.model.Item;
import hudson.triggers.Trigger;
import hudson.triggers.TriggerDescriptor;
import jenkins.model.ParameterizedJobMixIn;
import org.kohsuke.stapler.DataBoundConstructor;

import java.util.ArrayList;
import java.util.List;

public class QueryingMockTrigger extends Trigger<BuildableItem> {

/** elements are true or false for {@code start}, null for {@code stop} */
public static List<Boolean> startsAndStops = new ArrayList<>();

public transient boolean isStarted;

public transient boolean foundSelf = false;

@DataBoundConstructor
public QueryingMockTrigger() {}

@Override public void start(BuildableItem project, boolean newInstance) {
super.start(project, newInstance);
for (Trigger t : ((ParameterizedJobMixIn.ParameterizedJob)project).getTriggers().values()) {
if (t instanceof QueryingMockTrigger) {
foundSelf = true;
}
}

startsAndStops.add(newInstance);
isStarted = true;
}

@Override public void stop() {
super.stop();
startsAndStops.add(null);
isStarted = false;
}

public Boolean currentStatus() {
if (!startsAndStops.isEmpty()) {
return startsAndStops.get(startsAndStops.size() - 1);
} else {
return null;
}
}

@Extension
public static class DescriptorImpl extends TriggerDescriptor {

@Override public boolean isApplicable(Item item) {
return true;
}

}
}
@@ -0,0 +1,48 @@
{
"name": "triggerPresent",
"description": "",
"_empty_": [
"",
"0"
],
"properties": {
"stapler-class-bag": "true",
"jenkins-model-BuildDiscarderProperty": {
"specified": false,
"_empty_": "0",
"strategy": {
"daysToKeepStr": "",
"numToKeepStr": "",
"artifactDaysToKeepStr": "",
"artifactNumToKeepStr": "",
"stapler-class": "hudson.tasks.LogRotator",
"$class": "hudson.tasks.LogRotator"
}
},
"hudson-model-ParametersDefinitionProperty": {
"specified": false
},
"org-jenkinsci-plugins-workflow-job-properties-PipelineTriggersJobProperty": {
"triggers": {
"stapler-class-bag": "true",
"org-jenkinsci-plugins-workflow-job-properties-QueryingMockTrigger": {

}
}
}
},
"hasCustomQuietPeriod": false,
"quiet_period": "0",
"displayNameOrNull": "",
"definition": {
"script": "",
"_empty_": [
"try sample Pipeline...",
"\u0001\u0001"
],
"sandbox": true,
"stapler-class": "org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition",
"$class": "org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition"
},
"core:apply": ""
}

0 comments on commit d49d3c2

Please sign in to comment.