Skip to content

Add support for Jenkins Pipeline. #110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package stashpullrequestbuilder.stashpullrequestbuilder;

import hudson.Extension;
import hudson.model.AbstractBuild;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.model.listeners.RunListener;

Expand All @@ -12,25 +12,25 @@
* Created by Nathan McCarthy
*/
@Extension
public class StashBuildListener extends RunListener<AbstractBuild> {
public class StashBuildListener extends RunListener<Run<?, ?>> {
private static final Logger logger = Logger.getLogger(StashBuildTrigger.class.getName());

@Override
public void onStarted(AbstractBuild abstractBuild, TaskListener listener) {
public void onStarted(Run<?, ?> run, TaskListener listener) {
logger.info("BuildListener onStarted called.");
StashBuildTrigger trigger = StashBuildTrigger.getTrigger(abstractBuild.getProject());
StashBuildTrigger trigger = StashBuildTrigger.getTrigger(run.getParent());
if (trigger == null) {
return;
}
trigger.getBuilder().getBuilds().onStarted(abstractBuild);
trigger.getBuilder().getBuilds().onStarted(run);
}

@Override
public void onCompleted(AbstractBuild abstractBuild, @Nonnull TaskListener listener) {
StashBuildTrigger trigger = StashBuildTrigger.getTrigger(abstractBuild.getProject());
public void onCompleted(Run<?, ?> run, @Nonnull TaskListener listener) {
StashBuildTrigger trigger = StashBuildTrigger.getTrigger(run.getParent());
if (trigger == null) {
return;
}
trigger.getBuilder().getBuilds().onCompleted(abstractBuild, listener);
trigger.getBuilder().getBuilds().onCompleted(run, listener);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.Extension;
import hudson.model.AbstractProject;
import hudson.model.Build;
import hudson.model.Cause;
import hudson.model.CauseAction;
import hudson.model.Item;
import hudson.model.Job;
import hudson.model.ParameterDefinition;
import hudson.model.ParameterValue;
import hudson.model.ParametersAction;
Expand All @@ -26,7 +27,9 @@
import hudson.triggers.TriggerDescriptor;
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import jenkins.model.ParameterizedJobMixIn;
import net.sf.json.JSONObject;
import org.acegisecurity.Authentication;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
Expand All @@ -47,7 +50,7 @@
* Created by Nathan McCarthy
*/
@SuppressFBWarnings({"WMI_WRONG_MAP_ITERATOR", "NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE"})
public class StashBuildTrigger extends Trigger<AbstractProject<?, ?>> {
public class StashBuildTrigger extends Trigger<Job<?, ?>> {
private static final Logger logger = Logger.getLogger(StashBuildTrigger.class.getName());
private final String projectPath;
private final String cron;
Expand Down Expand Up @@ -130,11 +133,15 @@ public String getcredentialsId() {
}

private StandardUsernamePasswordCredentials getCredentials() {
Authentication defaultAuth = null;
if (job instanceof Queue.Task) {
defaultAuth = Tasks.getDefaultAuthenticationOf((Queue.Task)this.job);
}
return CredentialsMatchers.firstOrNull(
CredentialsProvider.lookupCredentials(
StandardUsernamePasswordCredentials.class,
this.job,
Tasks.getDefaultAuthenticationOf(this.job),
defaultAuth,
URIRequirementBuilder.fromUri(stashHost).build()
),
CredentialsMatchers.allOf(CredentialsMatchers.withId(credentialsId)));
Expand Down Expand Up @@ -189,21 +196,27 @@ public boolean isCancelOutdatedJobsEnabled() {
}

@Override
public void start(AbstractProject<?, ?> project, boolean newInstance) {
public void start(Job<?, ?> job, boolean newInstance) {
try {
this.stashPullRequestsBuilder = StashPullRequestsBuilder.getBuilder();
this.stashPullRequestsBuilder.setProject(project);
this.stashPullRequestsBuilder.setJob(job);
this.stashPullRequestsBuilder.setTrigger(this);
this.stashPullRequestsBuilder.setupBuilder();
} catch(IllegalStateException e) {
logger.log(Level.SEVERE, "Can't start trigger", e);
return;
}
super.start(project, newInstance);
super.start(job, newInstance);
}

public static StashBuildTrigger getTrigger(AbstractProject project) {
Trigger trigger = project.getTrigger(StashBuildTrigger.class);
public static StashBuildTrigger getTrigger(Job job) {
if (!(job instanceof ParameterizedJobMixIn.ParameterizedJob)) {
return null;
}

ParameterizedJobMixIn.ParameterizedJob pjob = (ParameterizedJobMixIn.ParameterizedJob) job;

Trigger trigger = pjob.getTriggers().get(descriptor);
return (StashBuildTrigger)trigger;
}

Expand Down Expand Up @@ -235,9 +248,13 @@ public QueueTaskFuture<?> startJob(StashCause cause) {
cancelPreviousJobsInQueueThatMatch(cause);
abortRunningJobsThatMatch(cause);
}

return this.job.scheduleBuild2(0, cause, new ParametersAction(values));


return new ParameterizedJobMixIn() {
@Override
protected Job asJob() {
return StashBuildTrigger.this.job;
}
}.scheduleBuild2(0, new ParametersAction(values), new CauseAction(cause));
}

private void cancelPreviousJobsInQueueThatMatch(@Nonnull StashCause stashCause) {
Expand Down Expand Up @@ -292,10 +309,10 @@ private List<ParameterValue> getDefaultParameters() {

@Override
public void run() {
if(this.getBuilder().getProject().isDisabled()) {
logger.info(format("Build Skip (%s).", getBuilder().getProject().getName()));
if(!this.getBuilder().getJob().isBuildable()) {
logger.info(format("Build Skip (%s).", getBuilder().getJob().getName()));
} else {
logger.info(format("Build started (%s).", getBuilder().getProject().getName()));
logger.info(format("Build started (%s).", getBuilder().getJob().getName()));
this.stashPullRequestsBuilder.run();
}
this.getDescriptor().save();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package stashpullrequestbuilder.stashpullrequestbuilder;

import hudson.model.AbstractBuild;
import hudson.model.Cause;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import jenkins.model.JenkinsLocationConfiguration;

Expand All @@ -23,61 +23,61 @@ public StashBuilds(StashBuildTrigger trigger, StashRepository repository) {
this.repository = repository;
}

public StashCause getCause(AbstractBuild build) {
Cause cause = build.getCause(StashCause.class);
public StashCause getCause(Run run) {
Cause cause = run.getCause(StashCause.class);
if (cause == null || !(cause instanceof StashCause)) {
return null;
}
return (StashCause) cause;
}

public void onStarted(AbstractBuild build) {
StashCause cause = this.getCause(build);
public void onStarted(Run run) {
StashCause cause = this.getCause(run);
if (cause == null) {
return;
}
try {
build.setDescription(cause.getShortDescription());
run.setDescription(cause.getShortDescription());
} catch (IOException e) {
logger.log(Level.SEVERE, "Can't update build description", e);
}
}

public void onCompleted(AbstractBuild build, TaskListener listener) {
StashCause cause = this.getCause(build);
public void onCompleted(Run run, TaskListener listener) {
StashCause cause = this.getCause(run);
if (cause == null) {
return;
}
Result result = build.getResult();
Result result = run.getResult();
JenkinsLocationConfiguration globalConfig = new JenkinsLocationConfiguration();
String rootUrl = globalConfig.getUrl();
String buildUrl = "";
if (rootUrl == null) {
buildUrl = " PLEASE SET JENKINS ROOT URL FROM GLOBAL CONFIGURATION " + build.getUrl();
buildUrl = " PLEASE SET JENKINS ROOT URL FROM GLOBAL CONFIGURATION " + run.getUrl();
}
else {
buildUrl = rootUrl + build.getUrl();
buildUrl = rootUrl + run.getUrl();
}
repository.deletePullRequestComment(cause.getPullRequestId(), cause.getBuildStartCommentId());

String additionalComment = "";

StashPostBuildCommentAction comments = build.getAction(StashPostBuildCommentAction.class);
StashPostBuildCommentAction comments = run.getAction(StashPostBuildCommentAction.class);
if(comments != null) {
String buildComment = result == Result.SUCCESS ? comments.getBuildSuccessfulComment() : comments.getBuildFailedComment();

if(buildComment != null && !buildComment.isEmpty()) {
additionalComment = "\n\n" + buildComment;
}
}
String duration = build.getDurationString();
String duration = run.getDurationString();
repository.postFinishedComment(cause.getPullRequestId(), cause.getSourceCommitHash(),
cause.getDestinationCommitHash(), result, buildUrl,
build.getNumber(), additionalComment, duration);
run.getNumber(), additionalComment, duration);

//Merge PR
StashBuildTrigger trig = StashBuildTrigger.getTrigger(build.getProject());
if(trig.getMergeOnSuccess() && build.getResult() == Result.SUCCESS) {
StashBuildTrigger trig = StashBuildTrigger.getTrigger(run.getParent());
if(trig.getMergeOnSuccess() && run.getResult() == Result.SUCCESS) {
boolean mergeStat = repository.mergePullRequest(cause.getPullRequestId(), cause.getPullRequestVersion());
if(mergeStat == true)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;

// TODO: Make available in Jenkins Pipeline
public class StashPostBuildComment extends Notifier {
private static final Logger logger = Logger.getLogger(StashBuildTrigger.class.getName());
private String buildSuccessfulComment;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import static java.lang.String.format;

import hudson.model.Job;
import stashpullrequestbuilder.stashpullrequestbuilder.stash.StashPullRequestResponseValue;
import hudson.model.AbstractProject;

import java.util.Collection;
import java.util.logging.Logger;
Expand All @@ -13,7 +13,7 @@
*/
public class StashPullRequestsBuilder {
private static final Logger logger = Logger.getLogger(StashBuildTrigger.class.getName());
private AbstractProject<?, ?> project;
private Job<?, ?> job;
private StashBuildTrigger trigger;
private StashRepository repository;
private StashBuilds builds;
Expand All @@ -27,31 +27,31 @@ public void stop() {
}

public void run() {
logger.info(format("Build Start (%s).", project.getName()));
logger.info(format("Build Start (%s).", job.getName()));
this.repository.init();
Collection<StashPullRequestResponseValue> targetPullRequests = this.repository.getTargetPullRequests();
this.repository.addFutureBuildTasks(targetPullRequests);
}

public StashPullRequestsBuilder setupBuilder() {
if (this.project == null || this.trigger == null) {
if (this.job == null || this.trigger == null) {
throw new IllegalStateException();
}
this.repository = new StashRepository(this.trigger.getProjectPath(), this);
this.builds = new StashBuilds(this.trigger, this.repository);
return this;
}

public void setProject(AbstractProject<?, ?> project) {
this.project = project;
public void setJob(Job<?, ?> job) {
this.job = job;
}

public void setTrigger(StashBuildTrigger trigger) {
this.trigger = trigger;
}

public AbstractProject<?, ?> getProject() {
return this.project;
public Job<?, ?> getJob() {
return this.job;
}

public StashBuildTrigger getTrigger() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void init() {
}

public Collection<StashPullRequestResponseValue> getTargetPullRequests() {
logger.info(format("Fetch PullRequests (%s).", builder.getProject().getName()));
logger.info(format("Fetch PullRequests (%s).", builder.getJob().getName()));
List<StashPullRequestResponseValue> pullRequests = client.getPullRequests();
List<StashPullRequestResponseValue> targetPullRequests = new ArrayList<StashPullRequestResponseValue>();
for(StashPullRequestResponseValue pullRequest : pullRequests) {
Expand All @@ -80,11 +80,11 @@ public Collection<StashPullRequestResponseValue> getTargetPullRequests() {
}

public String postBuildStartCommentTo(StashPullRequestResponseValue pullRequest) {
String sourceCommit = pullRequest.getFromRef().getLatestCommit();
String destinationCommit = pullRequest.getToRef().getLatestCommit();
String comment = format(BUILD_START_MARKER, builder.getProject().getDisplayName(), sourceCommit, destinationCommit);
StashPullRequestComment commentResponse = this.client.postPullRequestComment(pullRequest.getId(), comment);
return commentResponse.getCommentId().toString();
String sourceCommit = pullRequest.getFromRef().getLatestCommit();
String destinationCommit = pullRequest.getToRef().getLatestCommit();
String comment = format(BUILD_START_MARKER, builder.getJob().getDisplayName(), sourceCommit, destinationCommit);
StashPullRequestComment commentResponse = this.client.postPullRequestComment(pullRequest.getId(), comment);
return commentResponse.getCommentId().toString();
}

public static AbstractMap.SimpleEntry<String,String> getParameter(String content){
Expand Down Expand Up @@ -192,7 +192,7 @@ private String getMessageForBuildResult(Result result) {

public void postFinishedComment(String pullRequestId, String sourceCommit, String destinationCommit, Result buildResult, String buildUrl, int buildNumber, String additionalComment, String duration) {
String message = getMessageForBuildResult(buildResult);
String comment = format(BUILD_FINISH_SENTENCE, builder.getProject().getDisplayName(), sourceCommit, destinationCommit, message, buildUrl, buildNumber, duration);
String comment = format(BUILD_FINISH_SENTENCE, builder.getJob().getDisplayName(), sourceCommit, destinationCommit, message, buildUrl, buildNumber, duration);

comment = comment.concat(additionalComment);

Expand Down Expand Up @@ -233,7 +233,7 @@ private void deletePreviousBuildFinishedComments(StashPullRequestResponseValue p
continue;
}

String project_build_finished = format(BUILD_FINISH_REGEX, builder.getProject().getDisplayName());
String project_build_finished = format(BUILD_FINISH_REGEX, builder.getJob().getDisplayName());
Matcher finishMatcher = Pattern.compile(project_build_finished, Pattern.CASE_INSENSITIVE).matcher(content);

if (finishMatcher.find()) {
Expand Down Expand Up @@ -289,7 +289,7 @@ private boolean isBuildTarget(StashPullRequestResponseValue pullRequest) {
}

//These will match any start or finish message -- need to check commits
String escapedBuildName = Pattern.quote(builder.getProject().getDisplayName());
String escapedBuildName = Pattern.quote(builder.getJob().getDisplayName());
String project_build_start = String.format(BUILD_START_REGEX, escapedBuildName);
String project_build_finished = String.format(BUILD_FINISH_REGEX, escapedBuildName);
Matcher startMatcher = Pattern.compile(project_build_start, Pattern.CASE_INSENSITIVE).matcher(content);
Expand Down