Skip to content

Commit 446925c

Browse files
committed
[JENKINS-27136] Add more tests for wf-stuff
1 parent 27f9802 commit 446925c

File tree

11 files changed

+207
-252
lines changed

11 files changed

+207
-252
lines changed

src/main/java/com/cloudbees/jenkins/GitHubPushTrigger.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.slf4j.Logger;
2828
import org.slf4j.LoggerFactory;
2929

30-
3130
import java.io.File;
3231
import java.io.IOException;
3332
import java.io.PrintStream;
@@ -41,6 +40,7 @@
4140
import java.util.Set;
4241

4342
import static org.apache.commons.lang3.StringUtils.isEmpty;
43+
import static org.jenkinsci.plugins.github.util.JobInfoHelpers.asParameterizedJobMixIn;
4444

4545
/**
4646
* Triggers a build when we receive a GitHub post-commit webhook.
@@ -110,14 +110,7 @@ public void run() {
110110
LOGGER.warn("Failed to parse the polling log", e);
111111
cause = new GitHubPushCause(pushBy);
112112
}
113-
// TODO use standard method in 1.621+
114-
ParameterizedJobMixIn scheduledJob = new ParameterizedJobMixIn() {
115-
@Override
116-
protected Job asJob() {
117-
return job;
118-
}
119-
};
120-
if (scheduledJob.scheduleBuild(cause)) {
113+
if (asParameterizedJobMixIn(job).scheduleBuild(cause)) {
121114
LOGGER.info("SCM changes detected in " + job.getName() + ". Triggering " + name);
122115
} else {
123116
LOGGER.info("SCM changes detected in " + job.getName() + ". Job is already in the queue");

src/main/java/com/cloudbees/jenkins/GitHubRepositoryNameContributor.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,37 @@ public void parseAssociatedNames(AbstractProject<?, ?> job, Collection<GitHubRep
4848
* then puts them into the collection.
4949
*/
5050
public /*abstract*/ void parseAssociatedNames(Job<?, ?> job, Collection<GitHubRepositoryName> result) {
51-
if (Util.isOverridden(GitHubRepositoryNameContributor.class, getClass(),
52-
"parseAssociatedNames", AbstractProject.class, Collection.class) && job instanceof AbstractProject) {
51+
if (overriddenMethodHasDeprecatedSignature(job)) {
5352
parseAssociatedNames((AbstractProject) job, result);
5453
} else {
5554
throw new AbstractMethodError("you must override the new overload of parseAssociatedNames");
5655
}
5756
}
5857

58+
/**
59+
* To select backward compatible method with old extensions
60+
* with overridden {@link #parseAssociatedNames(AbstractProject, Collection)}
61+
*
62+
* @param job - parameter to check for old class
63+
*
64+
* @return true if overridden deprecated method
65+
*/
66+
private boolean overriddenMethodHasDeprecatedSignature(Job<?, ?> job) {
67+
return Util.isOverridden(
68+
GitHubRepositoryNameContributor.class,
69+
getClass(),
70+
"parseAssociatedNames",
71+
AbstractProject.class,
72+
Collection.class
73+
) && job instanceof AbstractProject;
74+
}
75+
5976
public static ExtensionList<GitHubRepositoryNameContributor> all() {
6077
return Jenkins.getInstance().getExtensionList(GitHubRepositoryNameContributor.class);
6178
}
6279

6380
/**
64-
* @deprecated Use {@link GitHubRepositoryNameContributor#parseAssociatedNames(Job)}
81+
* @deprecated Use {@link #parseAssociatedNames(Job)}
6582
*/
6683
@Deprecated
6784
public static Collection<GitHubRepositoryName> parseAssociatedNames(AbstractProject<?, ?> job) {
@@ -98,8 +115,7 @@ protected EnvVars buildEnv(Job<?, ?> job) {
98115
try {
99116
contributor.buildEnvironmentFor(job, env, TaskListener.NULL);
100117
} catch (Exception e) {
101-
LOGGER.debug(e.getMessage(), e);
102-
// ignore
118+
LOGGER.debug("{} failed to build env ({}), skipping", contributor.getClass(), e.getMessage(), e);
103119
}
104120
}
105121
return env;

src/main/java/org/jenkinsci/plugins/github/util/JobInfoHelpers.java

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
import com.cloudbees.jenkins.GitHubRepositoryNameContributor;
55
import com.google.common.base.Function;
66
import com.google.common.base.Predicate;
7+
import hudson.model.AbstractProject;
78
import hudson.model.Job;
89
import hudson.triggers.Trigger;
910
import jenkins.model.ParameterizedJobMixIn;
1011
import org.jenkinsci.plugins.github.extension.GHEventsSubscriber;
1112

13+
import javax.annotation.CheckForNull;
1214
import java.util.Collection;
1315

1416
import static org.jenkinsci.plugins.github.extension.GHEventsSubscriber.isApplicableFor;
@@ -34,18 +36,7 @@ private JobInfoHelpers() {
3436
public static Predicate<Job> withTrigger(final Class<? extends Trigger> clazz) {
3537
return new Predicate<Job>() {
3638
public boolean apply(Job job) {
37-
if (job instanceof ParameterizedJobMixIn.ParameterizedJob) {
38-
ParameterizedJobMixIn.ParameterizedJob pJob = (ParameterizedJobMixIn.ParameterizedJob) job;
39-
// TODO use standard method in 1.621+
40-
for (Trigger trigger : pJob.getTriggers().values()) {
41-
if (clazz.isInstance(trigger)) {
42-
return true;
43-
}
44-
}
45-
return false;
46-
} else {
47-
return false;
48-
}
39+
return triggerFrom(job, clazz) != null;
4940
}
5041
};
5142
}
@@ -88,5 +79,46 @@ public boolean apply(Job job) {
8879
}
8980
};
9081
}
82+
83+
/**
84+
* @param job job to search trigger in
85+
* @param tClass trigger with class which we want to receive from job
86+
* @param <T> type of trigger
87+
*
88+
* @return Trigger instance with required class or null
89+
* TODO use standard method in 1.621+
90+
*/
91+
@CheckForNull
92+
public static <T extends Trigger> T triggerFrom(Job<?, ?> job, Class<T> tClass) {
93+
if (job instanceof ParameterizedJobMixIn.ParameterizedJob) {
94+
ParameterizedJobMixIn.ParameterizedJob pJob = (ParameterizedJobMixIn.ParameterizedJob) job;
95+
96+
for (Trigger candidate : pJob.getTriggers().values()) {
97+
if (tClass.isInstance(candidate)) {
98+
return tClass.cast(candidate);
99+
}
100+
}
101+
}
102+
return null;
103+
}
104+
105+
/**
106+
* Converts any child class of {@link Job} (such as {@link AbstractProject}
107+
* to {@link ParameterizedJobMixIn} to use it for workflow
108+
*
109+
* @param job to wrap
110+
* @param <T> any child type of Job
111+
*
112+
* @return ParameterizedJobMixIn
113+
* TODO use standard method in 1.621+
114+
*/
115+
public static <T extends Job> ParameterizedJobMixIn asParameterizedJobMixIn(final T job) {
116+
return new ParameterizedJobMixIn() {
117+
@Override
118+
protected Job asJob() {
119+
return job;
120+
}
121+
};
122+
}
91123
}
92124

src/main/java/org/jenkinsci/plugins/github/webhook/subscriber/DefaultPushGHEventSubscriber.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88
import hudson.Extension;
99
import hudson.model.Job;
1010
import hudson.security.ACL;
11-
import hudson.triggers.Trigger;
1211
import jenkins.model.Jenkins;
13-
import jenkins.model.ParameterizedJobMixIn;
1412
import net.sf.json.JSONObject;
1513
import org.jenkinsci.plugins.github.extension.GHEventsSubscriber;
1614
import org.kohsuke.github.GHEvent;
@@ -22,6 +20,7 @@
2220
import java.util.regex.Pattern;
2321

2422
import static com.google.common.collect.Sets.immutableEnumSet;
23+
import static org.jenkinsci.plugins.github.util.JobInfoHelpers.triggerFrom;
2524
import static org.jenkinsci.plugins.github.util.JobInfoHelpers.withTrigger;
2625
import static org.kohsuke.github.GHEvent.PUSH;
2726

@@ -86,17 +85,7 @@ protected void onEvent(GHEvent event, String payload) {
8685
@Override
8786
public void run() {
8887
for (Job<?, ?> job : Jenkins.getInstance().getAllItems(Job.class)) {
89-
GitHubTrigger trigger = null;
90-
if (job instanceof ParameterizedJobMixIn.ParameterizedJob) {
91-
ParameterizedJobMixIn.ParameterizedJob pJob = (ParameterizedJobMixIn.ParameterizedJob) job;
92-
// TODO use standard method in 1.621+
93-
for (Trigger candidate : pJob.getTriggers().values()) {
94-
if (candidate instanceof GitHubTrigger) {
95-
trigger = (GitHubTrigger) candidate;
96-
break;
97-
}
98-
}
99-
}
88+
GitHubTrigger trigger = triggerFrom(job, GitHubPushTrigger.class);
10089
if (trigger != null) {
10190
LOGGER.debug("Considering to poke {}", job.getFullDisplayName());
10291
if (GitHubRepositoryNameContributor.parseAssociatedNames(job).contains(changedRepository)) {
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.cloudbees.jenkins;
2+
3+
import hudson.plugins.git.util.Build;
4+
import hudson.plugins.git.util.BuildData;
5+
import org.eclipse.jgit.lib.ObjectId;
6+
import org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventListenerTest;
7+
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
8+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
9+
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
10+
import org.junit.Rule;
11+
import org.junit.Test;
12+
import org.jvnet.hudson.test.Issue;
13+
import org.jvnet.hudson.test.JenkinsRule;
14+
15+
import java.util.HashMap;
16+
import java.util.concurrent.TimeUnit;
17+
18+
import static com.cloudbees.jenkins.GitHubWebHookFullTest.classpath;
19+
import static org.hamcrest.MatcherAssert.assertThat;
20+
import static org.hamcrest.Matchers.is;
21+
import static org.jenkinsci.plugins.github.webhook.subscriber.DefaultPushGHEventListenerTest.TRIGGERED_BY_USER_FROM_RESOURCE;
22+
23+
/**
24+
* @author lanwen (Merkushev Kirill)
25+
*/
26+
public class GitHubPushTriggerTest {
27+
28+
@Rule
29+
public JenkinsRule jRule = new JenkinsRule();
30+
31+
/**
32+
* This test requires internet access to get real git revision
33+
*/
34+
@Test
35+
@Issue("JENKINS-27136")
36+
public void shouldStartWorkflowByTrigger() throws Exception {
37+
WorkflowJob job = jRule.getInstance().createProject(WorkflowJob.class, "test-workflow-job");
38+
GitHubPushTrigger trigger = new GitHubPushTrigger();
39+
trigger.start(job, false);
40+
job.addTrigger(trigger);
41+
job.setDefinition(
42+
new CpsFlowDefinition(classpath(DefaultPushGHEventListenerTest.class, "workflow-definition.groovy"))
43+
);
44+
45+
// Trigger the build once to register SCMs
46+
WorkflowRun lastRun = jRule.assertBuildStatusSuccess(job.scheduleBuild2(0));
47+
// Testing hack! This will make the polling believe that there was remote changes to build
48+
BuildData buildData = lastRun.getActions(BuildData.class).get(0);
49+
buildData.buildsByBranchName = new HashMap<String, Build>();
50+
buildData.getLastBuiltRevision().setSha1(ObjectId.zeroId());
51+
52+
trigger.onPost(TRIGGERED_BY_USER_FROM_RESOURCE);
53+
54+
TimeUnit.SECONDS.sleep(job.getQuietPeriod());
55+
jRule.waitUntilNoActivity();
56+
57+
assertThat("should be 2 build after hook", job.getLastBuild().getNumber(), is(2));
58+
}
59+
}

src/test/java/com/cloudbees/jenkins/GitHubWebHookFullTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,12 @@ public Header eventHeader(String event) {
140140
}
141141

142142
public static String classpath(String path) throws IOException {
143-
return IOUtils.toString(GitHubWebHookFullTest.class.getClassLoader().getResourceAsStream(
144-
GitHubWebHookFullTest.class.getName().replace(PACKAGE_SEPARATOR, File.separator) + File.separator + path
143+
return classpath(GitHubWebHookFullTest.class, path);
144+
}
145+
146+
public static String classpath(Class<?> clazz, String path) throws IOException {
147+
return IOUtils.toString(clazz.getClassLoader().getResourceAsStream(
148+
clazz.getName().replace(PACKAGE_SEPARATOR, File.separator) + File.separator + path
145149
), Charsets.UTF_8);
146150
}
147151
}

src/test/java/org/jenkinsci/plugins/github/util/JobInfoHelpersTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
import com.cloudbees.jenkins.GitHubPushTrigger;
44
import hudson.model.FreeStyleProject;
5+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
56
import org.junit.ClassRule;
67
import org.junit.Test;
78
import org.jvnet.hudson.test.JenkinsRule;
89

910
import static org.hamcrest.Matchers.is;
11+
import static org.hamcrest.Matchers.nullValue;
1012
import static org.jenkinsci.plugins.github.util.JobInfoHelpers.isAlive;
1113
import static org.jenkinsci.plugins.github.util.JobInfoHelpers.isBuildable;
14+
import static org.jenkinsci.plugins.github.util.JobInfoHelpers.triggerFrom;
1215
import static org.jenkinsci.plugins.github.util.JobInfoHelpers.withTrigger;
1316
import static org.junit.Assert.assertThat;
1417

@@ -59,4 +62,30 @@ public void shouldSeeProjectWithoutTriggerIsNotAliveForCleaner() throws Exceptio
5962

6063
assertThat("without trigger", isAlive().apply(prj), is(false));
6164
}
65+
66+
@Test
67+
public void shouldGetTriggerFromAbstractProject() throws Exception {
68+
GitHubPushTrigger trigger = new GitHubPushTrigger();
69+
70+
FreeStyleProject prj = jenkins.createFreeStyleProject();
71+
prj.addTrigger(trigger);
72+
73+
assertThat("with trigger in free style job", triggerFrom(prj, GitHubPushTrigger.class), is(trigger));
74+
}
75+
76+
@Test
77+
public void shouldGetTriggerFromWorkflow() throws Exception {
78+
GitHubPushTrigger trigger = new GitHubPushTrigger();
79+
WorkflowJob job = jenkins.getInstance().createProject(WorkflowJob.class, "Test Workflow");
80+
job.addTrigger(trigger);
81+
82+
assertThat("with trigger in workflow", triggerFrom(job, GitHubPushTrigger.class), is(trigger));
83+
}
84+
85+
@Test
86+
public void shouldNotGetTriggerWhenNoOne() throws Exception {
87+
FreeStyleProject prj = jenkins.createFreeStyleProject();
88+
89+
assertThat("without trigger in project", triggerFrom(prj, GitHubPushTrigger.class), nullValue());
90+
}
6291
}

src/test/java/org/jenkinsci/plugins/github/webhook/subscriber/DefaultPushGHEventListenerTest.java

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
package org.jenkinsci.plugins.github.webhook.subscriber;
22

33
import com.cloudbees.jenkins.GitHubPushTrigger;
4-
import com.cloudbees.jenkins.GitHubWebHookFullTest;
54
import hudson.model.FreeStyleProject;
65
import hudson.plugins.git.GitSCM;
6+
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
7+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
78
import org.junit.Rule;
89
import org.junit.Test;
10+
import org.jvnet.hudson.test.Issue;
911
import org.jvnet.hudson.test.JenkinsRule;
1012
import org.kohsuke.github.GHEvent;
1113

14+
import static com.cloudbees.jenkins.GitHubWebHookFullTest.classpath;
1215
import static org.hamcrest.MatcherAssert.assertThat;
1316
import static org.hamcrest.Matchers.is;
1417
import static org.mockito.Mockito.mock;
18+
import static org.mockito.Mockito.never;
1519
import static org.mockito.Mockito.verify;
1620

1721
/**
@@ -41,14 +45,46 @@ public void shouldBeApplicableForProjectWithTrigger() throws Exception {
4145
@Test
4246
public void shouldParsePushPayload() throws Exception {
4347
GitHubPushTrigger trigger = mock(GitHubPushTrigger.class);
44-
48+
4549
FreeStyleProject prj = jenkins.createFreeStyleProject();
4650
prj.addTrigger(trigger);
4751
prj.setScm(GIT_SCM_FROM_RESOURCE);
48-
52+
53+
new DefaultPushGHEventSubscriber()
54+
.onEvent(GHEvent.PUSH, classpath("payloads/push.json"));
55+
56+
verify(trigger).onPost(TRIGGERED_BY_USER_FROM_RESOURCE);
57+
}
58+
59+
@Test
60+
@Issue("JENKINS-27136")
61+
public void shouldReceivePushHookOnWorkflow() throws Exception {
62+
WorkflowJob job = jenkins.getInstance().createProject(WorkflowJob.class, "test-workflow-job");
63+
64+
GitHubPushTrigger trigger = mock(GitHubPushTrigger.class);
65+
job.addTrigger(trigger);
66+
job.setDefinition(new CpsFlowDefinition(classpath(getClass(), "workflow-definition.groovy")));
67+
// Trigger the build once to register SCMs
68+
jenkins.assertBuildStatusSuccess(job.scheduleBuild2(0));
69+
4970
new DefaultPushGHEventSubscriber()
50-
.onEvent(GHEvent.PUSH, GitHubWebHookFullTest.classpath("payloads/push.json"));
51-
71+
.onEvent(GHEvent.PUSH, classpath("payloads/push.json"));
72+
5273
verify(trigger).onPost(TRIGGERED_BY_USER_FROM_RESOURCE);
5374
}
75+
76+
@Test
77+
@Issue("JENKINS-27136")
78+
public void shouldNotReceivePushHookOnWorkflowWithNoBuilds() throws Exception {
79+
WorkflowJob job = jenkins.getInstance().createProject(WorkflowJob.class, "test-workflow-job");
80+
81+
GitHubPushTrigger trigger = mock(GitHubPushTrigger.class);
82+
job.addTrigger(trigger);
83+
job.setDefinition(new CpsFlowDefinition(classpath(getClass(), "workflow-definition.groovy")));
84+
85+
new DefaultPushGHEventSubscriber()
86+
.onEvent(GHEvent.PUSH, classpath("payloads/push.json"));
87+
88+
verify(trigger, never()).onPost(TRIGGERED_BY_USER_FROM_RESOURCE);
89+
}
5490
}

0 commit comments

Comments
 (0)