Skip to content

Commit ea4a885

Browse files
committed
WIP: Add support for Jenkins pipeline
Pipelines don't use AbstractProject and AbstractBuild. Instead, they use WorkflowJob and WorkflowRun. The common ancestors are Job and Run. There are some common interfaces implemented by freestyle projects and pipelines, which allows us to retain most of the functionality when operating in a pipeline. Custom messages for post-build-comments are not implemented yet. Original patch by Robert Hencke <[email protected]>
1 parent 20aced1 commit ea4a885

File tree

5 files changed

+82
-53
lines changed

5 files changed

+82
-53
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package stashpullrequestbuilder.stashpullrequestbuilder;
22

33
import hudson.Extension;
4-
import hudson.model.AbstractBuild;
4+
import hudson.model.Run;
55
import hudson.model.TaskListener;
66
import hudson.model.listeners.RunListener;
77
import java.lang.invoke.MethodHandles;
@@ -10,26 +10,26 @@
1010

1111
/** Created by Nathan McCarthy */
1212
@Extension
13-
public class StashBuildListener extends RunListener<AbstractBuild> {
13+
public class StashBuildListener extends RunListener<Run<?, ?>> {
1414
private static final Logger logger =
1515
Logger.getLogger(MethodHandles.lookup().lookupClass().getName());
1616

1717
@Override
18-
public void onStarted(AbstractBuild abstractBuild, TaskListener listener) {
18+
public void onStarted(Run<?, ?> run, TaskListener listener) {
1919
logger.info("BuildListener onStarted called.");
20-
StashBuildTrigger trigger = StashBuildTrigger.getTrigger(abstractBuild.getProject());
20+
StashBuildTrigger trigger = StashBuildTrigger.getTrigger(run.getParent());
2121
if (trigger == null) {
2222
return;
2323
}
24-
trigger.getBuilder().getBuilds().onStarted(abstractBuild);
24+
trigger.getBuilder().getBuilds().onStarted(run);
2525
}
2626

2727
@Override
28-
public void onCompleted(AbstractBuild abstractBuild, @Nonnull TaskListener listener) {
29-
StashBuildTrigger trigger = StashBuildTrigger.getTrigger(abstractBuild.getProject());
28+
public void onCompleted(Run<?, ?> run, @Nonnull TaskListener listener) {
29+
StashBuildTrigger trigger = StashBuildTrigger.getTrigger(run.getParent());
3030
if (trigger == null) {
3131
return;
3232
}
33-
trigger.getBuilder().getBuilds().onCompleted(abstractBuild, listener);
33+
trigger.getBuilder().getBuilds().onCompleted(run, listener);
3434
}
3535
}

src/main/java/stashpullrequestbuilder/stashpullrequestbuilder/StashBuildTrigger.java

+42-13
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder;
1111
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
1212
import hudson.Extension;
13-
import hudson.model.AbstractProject;
1413
import hudson.model.Build;
1514
import hudson.model.Cause;
15+
import hudson.model.CauseAction;
1616
import hudson.model.Item;
17+
import hudson.model.Job;
1718
import hudson.model.ParameterDefinition;
1819
import hudson.model.ParameterValue;
1920
import hudson.model.ParametersAction;
@@ -37,7 +38,9 @@
3738
import javax.annotation.Nonnull;
3839
import javax.annotation.Nullable;
3940
import jenkins.model.Jenkins;
41+
import jenkins.model.ParameterizedJobMixIn;
4042
import net.sf.json.JSONObject;
43+
import org.acegisecurity.Authentication;
4144
import org.apache.commons.lang.StringUtils;
4245
import org.kohsuke.stapler.AncestorInPath;
4346
import org.kohsuke.stapler.DataBoundConstructor;
@@ -47,7 +50,7 @@
4750

4851
/** Created by Nathan McCarthy */
4952
@SuppressFBWarnings({"WMI_WRONG_MAP_ITERATOR", "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"})
50-
public class StashBuildTrigger extends Trigger<AbstractProject<?, ?>> {
53+
public class StashBuildTrigger extends Trigger<Job<?, ?>> {
5154
private static final Logger logger =
5255
Logger.getLogger(MethodHandles.lookup().lookupClass().getName());
5356
private final String projectPath;
@@ -138,11 +141,16 @@ public String getcredentialsId() {
138141
}
139142

140143
private StandardUsernamePasswordCredentials getCredentials() {
144+
Authentication defaultAuth = null;
145+
if (job instanceof Queue.Task) {
146+
defaultAuth = Tasks.getDefaultAuthenticationOf((Queue.Task) job);
147+
}
148+
141149
return CredentialsMatchers.firstOrNull(
142150
CredentialsProvider.lookupCredentials(
143151
StandardUsernamePasswordCredentials.class,
144152
this.job,
145-
Tasks.getDefaultAuthenticationOf(this.job),
153+
defaultAuth,
146154
URIRequirementBuilder.fromUri(stashHost).build()),
147155
CredentialsMatchers.allOf(CredentialsMatchers.withId(credentialsId)));
148156
}
@@ -196,19 +204,26 @@ public boolean isCancelOutdatedJobsEnabled() {
196204
}
197205

198206
@Override
199-
public void start(AbstractProject<?, ?> project, boolean newInstance) {
207+
public void start(Job<?, ?> job, boolean newInstance) {
200208
try {
201-
Objects.requireNonNull(project, "project is null");
202-
this.stashPullRequestsBuilder = new StashPullRequestsBuilder(project, this);
209+
Objects.requireNonNull(job, "job is null");
210+
this.stashPullRequestsBuilder = new StashPullRequestsBuilder(job, this);
203211
} catch (NullPointerException e) {
204212
logger.log(Level.SEVERE, "Can't start trigger", e);
205213
return;
206214
}
207-
super.start(project, newInstance);
215+
super.start(job, newInstance);
208216
}
209217

210-
public static StashBuildTrigger getTrigger(AbstractProject project) {
211-
Trigger trigger = project.getTrigger(StashBuildTrigger.class);
218+
public static StashBuildTrigger getTrigger(Job job) {
219+
if (!(job instanceof ParameterizedJobMixIn.ParameterizedJob)) {
220+
return null;
221+
}
222+
223+
ParameterizedJobMixIn.ParameterizedJob parameterizedJob =
224+
(ParameterizedJobMixIn.ParameterizedJob) job;
225+
226+
Trigger trigger = parameterizedJob.getTriggers().get(descriptor);
212227
return (StashBuildTrigger) trigger;
213228
}
214229

@@ -231,7 +246,21 @@ public QueueTaskFuture<?> startJob(StashCause cause) {
231246
abortRunningJobsThatMatch(cause);
232247
}
233248

234-
return job.scheduleBuild2(job.getQuietPeriod(), cause, new ParametersAction(values));
249+
ParameterizedJobMixIn jobMixIn =
250+
new ParameterizedJobMixIn() {
251+
@Override
252+
protected Job asJob() {
253+
return StashBuildTrigger.this.job;
254+
}
255+
};
256+
257+
int quietPeriod = Jenkins.getInstance().getQuietPeriod();
258+
if (job instanceof ParameterizedJobMixIn.ParameterizedJob) {
259+
quietPeriod = ((ParameterizedJobMixIn.ParameterizedJob) job).getQuietPeriod();
260+
}
261+
262+
return jobMixIn.scheduleBuild2(
263+
quietPeriod, new CauseAction(cause), new ParametersAction(values));
235264
}
236265

237266
private void cancelPreviousJobsInQueueThatMatch(@Nonnull StashCause stashCause) {
@@ -300,9 +329,9 @@ public void run() {
300329
return;
301330
}
302331

303-
AbstractProject project = stashPullRequestsBuilder.getProject();
304-
if (project.isDisabled()) {
305-
logger.fine(format("Project disabled, skipping build (%s).", project.getName()));
332+
Job<?, ?> job = stashPullRequestsBuilder.getJob();
333+
if (job.isBuildable()) {
334+
logger.fine(format("Project disabled, skipping build (%s).", job.getName()));
306335
return;
307336
}
308337

src/main/java/stashpullrequestbuilder/stashpullrequestbuilder/StashBuilds.java

+20-16
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package stashpullrequestbuilder.stashpullrequestbuilder;
22

33
import hudson.Util;
4-
import hudson.model.AbstractBuild;
4+
import hudson.model.AbstractProject;
5+
import hudson.model.Job;
56
import hudson.model.Result;
7+
import hudson.model.Run;
68
import hudson.model.TaskListener;
79
import java.io.IOException;
810
import java.lang.invoke.MethodHandles;
@@ -22,40 +24,43 @@ public StashBuilds(StashBuildTrigger trigger, StashRepository repository) {
2224
this.repository = repository;
2325
}
2426

25-
public void onStarted(AbstractBuild<?, ?> build) {
26-
StashCause cause = build.getCause(StashCause.class);
27+
public void onStarted(Run<?, ?> run) {
28+
StashCause cause = run.getCause(StashCause.class);
2729
if (cause == null) {
2830
return;
2931
}
3032
try {
31-
build.setDescription(cause.getShortDescription());
33+
run.setDescription(cause.getShortDescription());
3234
} catch (IOException e) {
3335
logger.log(Level.SEVERE, "Can't update build description", e);
3436
}
3537
}
3638

37-
public void onCompleted(AbstractBuild<?, ?> build, TaskListener listener) {
38-
StashCause cause = build.getCause(StashCause.class);
39+
public void onCompleted(Run<?, ?> run, TaskListener listener) {
40+
StashCause cause = run.getCause(StashCause.class);
3941
if (cause == null) {
4042
return;
4143
}
42-
Result result = build.getResult();
44+
Result result = run.getResult();
4345
// Note: current code should no longer use "new JenkinsLocationConfiguration()"
4446
// as only one instance per runtime is really supported by the current core.
4547
JenkinsLocationConfiguration globalConfig = JenkinsLocationConfiguration.get();
4648
String rootUrl = globalConfig == null ? null : globalConfig.getUrl();
4749
String buildUrl = "";
4850
if (rootUrl == null) {
49-
buildUrl = " PLEASE SET JENKINS ROOT URL FROM GLOBAL CONFIGURATION " + build.getUrl();
51+
buildUrl = " PLEASE SET JENKINS ROOT URL FROM GLOBAL CONFIGURATION " + run.getUrl();
5052
} else {
51-
buildUrl = rootUrl + build.getUrl();
53+
buildUrl = rootUrl + run.getUrl();
5254
}
5355
repository.deletePullRequestComment(cause.getPullRequestId(), cause.getBuildStartCommentId());
5456

5557
String additionalComment = "";
58+
StashPostBuildComment comments = null;
59+
Job<?, ?> job = run.getParent();
5660

57-
StashPostBuildComment comments =
58-
build.getProject().getPublishersList().get(StashPostBuildComment.class);
61+
if (job instanceof AbstractProject<?, ?>) {
62+
comments = ((AbstractProject<?, ?>) job).getPublishersList().get(StashPostBuildComment.class);
63+
}
5964

6065
if (comments != null) {
6166
String buildComment =
@@ -66,28 +71,27 @@ public void onCompleted(AbstractBuild<?, ?> build, TaskListener listener) {
6671
if (buildComment != null && !buildComment.isEmpty()) {
6772
String expandedComment;
6873
try {
69-
expandedComment =
70-
Util.fixEmptyAndTrim(build.getEnvironment(listener).expand(buildComment));
74+
expandedComment = Util.fixEmptyAndTrim(run.getEnvironment(listener).expand(buildComment));
7175
} catch (IOException | InterruptedException e) {
7276
expandedComment = "Exception while expanding '" + buildComment + "': " + e;
7377
}
7478

7579
additionalComment = "\n\n" + expandedComment;
7680
}
7781
}
78-
String duration = build.getDurationString();
82+
String duration = run.getDurationString();
7983
repository.postFinishedComment(
8084
cause.getPullRequestId(),
8185
cause.getSourceCommitHash(),
8286
cause.getDestinationCommitHash(),
8387
result,
8488
buildUrl,
85-
build.getNumber(),
89+
run.getNumber(),
8690
additionalComment,
8791
duration);
8892

8993
// Merge PR
90-
if (trigger.getMergeOnSuccess() && build.getResult() == Result.SUCCESS) {
94+
if (trigger.getMergeOnSuccess() && run.getResult() == Result.SUCCESS) {
9195
boolean mergeStat =
9296
repository.mergePullRequest(cause.getPullRequestId(), cause.getPullRequestVersion());
9397
if (mergeStat == true) {

src/main/java/stashpullrequestbuilder/stashpullrequestbuilder/StashPullRequestsBuilder.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import static java.lang.String.format;
44

5-
import hudson.model.AbstractProject;
5+
import hudson.model.Job;
66
import java.lang.invoke.MethodHandles;
77
import java.util.Collection;
88
import java.util.logging.Logger;
@@ -13,29 +13,28 @@
1313
public class StashPullRequestsBuilder {
1414
private static final Logger logger =
1515
Logger.getLogger(MethodHandles.lookup().lookupClass().getName());
16-
private AbstractProject<?, ?> project;
16+
private Job<?, ?> job;
1717
private StashBuildTrigger trigger;
1818
private StashRepository repository;
1919
private StashBuilds builds;
2020

21-
public StashPullRequestsBuilder(
22-
@Nonnull AbstractProject project, @Nonnull StashBuildTrigger trigger) {
23-
this.project = project;
21+
public StashPullRequestsBuilder(@Nonnull Job<?, ?> job, @Nonnull StashBuildTrigger trigger) {
22+
this.job = job;
2423
this.trigger = trigger;
2524
this.repository = new StashRepository(trigger.getProjectPath(), this);
2625
this.builds = new StashBuilds(trigger, repository);
2726
}
2827

2928
public void run() {
30-
logger.info(format("Build Start (%s).", project.getName()));
29+
logger.info(format("Build Start (%s).", job.getName()));
3130
this.repository.init();
3231
Collection<StashPullRequestResponseValue> targetPullRequests =
3332
this.repository.getTargetPullRequests();
3433
this.repository.addFutureBuildTasks(targetPullRequests);
3534
}
3635

37-
public AbstractProject<?, ?> getProject() {
38-
return this.project;
36+
public Job<?, ?> getJob() {
37+
return this.job;
3938
}
4039

4140
public StashBuildTrigger getTrigger() {

src/main/java/stashpullrequestbuilder/stashpullrequestbuilder/StashRepository.java

+5-8
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void init() {
7373
}
7474

7575
public Collection<StashPullRequestResponseValue> getTargetPullRequests() {
76-
logger.info(format("Fetch PullRequests (%s).", builder.getProject().getName()));
76+
logger.info(format("Fetch PullRequests (%s).", builder.getJob().getName()));
7777
List<StashPullRequestResponseValue> pullRequests = client.getPullRequests();
7878
List<StashPullRequestResponseValue> targetPullRequests =
7979
new ArrayList<StashPullRequestResponseValue>();
@@ -90,10 +90,7 @@ public String postBuildStartCommentTo(StashPullRequestResponseValue pullRequest)
9090
String destinationCommit = pullRequest.getToRef().getLatestCommit();
9191
String comment =
9292
format(
93-
BUILD_START_MARKER,
94-
builder.getProject().getDisplayName(),
95-
sourceCommit,
96-
destinationCommit);
93+
BUILD_START_MARKER, builder.getJob().getDisplayName(), sourceCommit, destinationCommit);
9794
StashPullRequestComment commentResponse =
9895
this.client.postPullRequestComment(pullRequest.getId(), comment);
9996
return commentResponse.getCommentId().toString();
@@ -216,7 +213,7 @@ public void postFinishedComment(
216213
String comment =
217214
format(
218215
BUILD_FINISH_SENTENCE,
219-
builder.getProject().getDisplayName(),
216+
builder.getJob().getDisplayName(),
220217
sourceCommit,
221218
destinationCommit,
222219
message,
@@ -292,7 +289,7 @@ private void deletePreviousBuildFinishedComments(StashPullRequestResponseValue p
292289
}
293290

294291
String project_build_finished =
295-
format(BUILD_FINISH_REGEX, builder.getProject().getDisplayName());
292+
format(BUILD_FINISH_REGEX, builder.getJob().getDisplayName());
296293
Matcher finishMatcher =
297294
Pattern.compile(project_build_finished, Pattern.CASE_INSENSITIVE).matcher(content);
298295

@@ -354,7 +351,7 @@ private boolean isBuildTarget(StashPullRequestResponseValue pullRequest) {
354351
}
355352

356353
// These will match any start or finish message -- need to check commits
357-
String escapedBuildName = Pattern.quote(builder.getProject().getDisplayName());
354+
String escapedBuildName = Pattern.quote(builder.getJob().getDisplayName());
358355
String project_build_start = String.format(BUILD_START_REGEX, escapedBuildName);
359356
String project_build_finished = String.format(BUILD_FINISH_REGEX, escapedBuildName);
360357
Matcher startMatcher =

0 commit comments

Comments
 (0)