package org.jenkinsci.plugins.ghprb.extensions.status; import hudson.Extension; import hudson.Util; import hudson.matrix.MatrixProject; import hudson.model.Job; import hudson.model.Run; import hudson.model.TaskListener; import jenkins.model.Jenkins; import org.apache.commons.lang.StringUtils; import org.jenkinsci.plugins.ghprb.Ghprb; import org.jenkinsci.plugins.ghprb.GhprbCause; import org.jenkinsci.plugins.ghprb.GhprbTrigger; import org.jenkinsci.plugins.ghprb.extensions.GhprbCommitStatus; import org.jenkinsci.plugins.ghprb.extensions.GhprbCommitStatusException; import org.jenkinsci.plugins.ghprb.extensions.GhprbExtension; import org.jenkinsci.plugins.ghprb.extensions.GhprbExtensionDescriptor; import org.jenkinsci.plugins.ghprb.extensions.GhprbGlobalDefault; import org.jenkinsci.plugins.ghprb.extensions.GhprbGlobalExtension; import org.jenkinsci.plugins.ghprb.extensions.GhprbProjectExtension; import org.jenkinsci.plugins.ghprb.extensions.comments.GhprbBuildResultMessage; import org.jenkinsci.plugins.ghprb.manager.GhprbBuildManager; import org.jenkinsci.plugins.ghprb.manager.configuration.JobConfiguration; import org.jenkinsci.plugins.ghprb.manager.factory.GhprbBuildManagerFactoryUtil; import org.kohsuke.github.GHCommitState; import org.kohsuke.github.GHRepository; import org.kohsuke.stapler.DataBoundConstructor; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; public class GhprbSimpleStatus extends GhprbExtension implements GhprbCommitStatus, GhprbGlobalExtension, GhprbProjectExtension, GhprbGlobalDefault { @Extension public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); private final String commitStatusContext; private final Boolean showMatrixStatus; private final String triggeredStatus; private final String startedStatus; private final String statusUrl; private final Boolean addTestResults; private final List<GhprbBuildResultMessage> completedStatus; public GhprbSimpleStatus() { this(null); } public GhprbSimpleStatus(String commitStatusContext) { this(false, commitStatusContext, null, null, null, false, new ArrayList<GhprbBuildResultMessage>(0)); } @DataBoundConstructor public GhprbSimpleStatus(Boolean showMatrixStatus, String commitStatusContext, String statusUrl, String triggeredStatus, String startedStatus, Boolean addTestResults, List<GhprbBuildResultMessage> completedStatus) { this.showMatrixStatus = showMatrixStatus; this.statusUrl = statusUrl; this.commitStatusContext = commitStatusContext == null ? "" : commitStatusContext; this.triggeredStatus = triggeredStatus; this.startedStatus = startedStatus; this.addTestResults = addTestResults; this.completedStatus = completedStatus; } public String getStatusUrl() { return statusUrl == null ? "" : statusUrl; } public boolean getShowMatrixStatus() { return showMatrixStatus == null ? false: showMatrixStatus; } public String getCommitStatusContext() { return commitStatusContext == null ? "" : commitStatusContext; } public String getStartedStatus() { return startedStatus == null ? "" : startedStatus; } public String getTriggeredStatus() { return triggeredStatus == null ? "" : triggeredStatus; } public Boolean getAddTestResults() { return addTestResults == null ? Boolean.valueOf(false) : addTestResults; } public List<GhprbBuildResultMessage> getCompletedStatus() { return completedStatus == null ? new ArrayList<GhprbBuildResultMessage>(0) : completedStatus; } public boolean addIfMissing() { return true; } public void onBuildTriggered(Job<?, ?> project, String commitSha, boolean isMergeable, int prId, GHRepository ghRepository) throws GhprbCommitStatusException { StringBuilder sb = new StringBuilder(); GHCommitState state = GHCommitState.PENDING; String triggeredStatus = getDescriptor().getTriggeredStatusDefault(this); // check if we even need to update if (StringUtils.equals(triggeredStatus, "--none--")) { return; } String statusUrl = getDescriptor().getStatusUrlDefault(this); String commitStatusContext = getDescriptor().getCommitStatusContextDefault(this); String context = Util.fixEmpty(commitStatusContext); context = Ghprb.replaceMacros(project, context); if (!StringUtils.isEmpty(triggeredStatus)) { sb.append(Ghprb.replaceMacros(project, triggeredStatus)); } else { sb.append("Build triggered."); if (isMergeable) { sb.append(" sha1 is merged."); } else { sb.append(" sha1 is original commit."); } } String url = Ghprb.replaceMacros(project, statusUrl); if (StringUtils.equals(statusUrl, "--none--")) { url = ""; } String message = sb.toString(); try { ghRepository.createCommitStatus(commitSha, state, url, message, context); } catch (IOException e) { throw new GhprbCommitStatusException(e, state, message, prId); } } public void onEnvironmentSetup(Run<?, ?> build, TaskListener listener, GHRepository repo) throws GhprbCommitStatusException { // no need to create a commit here -- the onBuildStart() event will fire // soon and will respect's the user's settings for startedStatus. } public void onBuildStart(Run<?, ?> build, TaskListener listener, GHRepository repo) throws GhprbCommitStatusException { String startedStatus = getDescriptor().getStartedStatusDefault(this); // If the showMatrixStatus checkbox is selected and the job is not a Matrix Job (Children // nodes), then don't post statuses boolean showMatrixStatus = getDescriptor().getShowMatrixStatusDefault(this); if(showMatrixStatus && !(build.getParent() instanceof MatrixProject)){ return; } // check if we even need to update if (StringUtils.equals(startedStatus, "--none--")) { return; } GhprbCause c = Ghprb.getCause(build); StringBuilder sb = new StringBuilder(); if (StringUtils.isEmpty(startedStatus)) { sb.append("Build started"); if (c != null) { sb.append(c.isMerged() ? " sha1 is merged." : " sha1 is original commit."); } } else { sb.append(Ghprb.replaceMacros(build, listener, startedStatus)); } createCommitStatus(build, listener, sb.toString(), repo, GHCommitState.PENDING); } public void onBuildComplete(Run<?, ?> build, TaskListener listener, GHRepository repo) throws GhprbCommitStatusException { List<GhprbBuildResultMessage> completedStatus = getDescriptor().getCompletedStatusDefault(this); boolean showMatrixStatus = getDescriptor().getShowMatrixStatusDefault(this); // If the showMatrixStatus checkbox is selected and the job is not a Matrix Job (Children // nodes), then don't post statuses if(showMatrixStatus && !(build.getParent() instanceof MatrixProject)) { return; } GHCommitState state = Ghprb.getState(build); StringBuilder sb = new StringBuilder(); if (completedStatus == null || completedStatus.isEmpty()) { sb.append("Build finished."); } else { for (GhprbBuildResultMessage buildStatus : completedStatus) { sb.append(buildStatus.postBuildComment(build, listener)); } if (StringUtils.equals(sb.toString(), "--none--")) { return; } } sb.append(" "); GhprbTrigger trigger = Ghprb.extractTrigger(build); if (trigger == null) { listener.getLogger().println("Unable to get pull request builder trigger!!"); } else { JobConfiguration jobConfiguration = JobConfiguration.builder() .printStackTrace(trigger.getDisplayBuildErrorsOnDownstreamBuilds()).build(); GhprbBuildManager buildManager = GhprbBuildManagerFactoryUtil.getBuildManager(build, jobConfiguration); if (getAddTestResults()) { listener.getLogger().println("Adding one-line test results to commit status..."); sb.append(buildManager.getOneLineTestResults()); } } createCommitStatus(build, listener, sb.toString(), repo, state); } private void createCommitStatus(Run<?, ?> build, TaskListener listener, String message, GHRepository repo, GHCommitState state) throws GhprbCommitStatusException { Map<String, String> envVars = Ghprb.getEnvVars(build, listener); String sha1 = envVars.get("ghprbActualCommit"); Integer pullId = Integer.parseInt(envVars.get("ghprbPullId")); String url = envVars.get("BUILD_URL"); if (StringUtils.isEmpty(url)) { url = envVars.get("JOB_URL"); } if (StringUtils.isEmpty(url)) { url = Jenkins.getInstance().getRootUrl() + build.getUrl(); } if (StringUtils.equals(statusUrl, "--none--")) { url = ""; } else if (!StringUtils.isEmpty(statusUrl)) { url = Ghprb.replaceMacros(build, listener, statusUrl); } String context = Util.fixEmpty(commitStatusContext); context = Ghprb.replaceMacros(build, listener, context); listener.getLogger().println(String.format("Setting status of %s to %s with url %s and message: '%s'", sha1, state, url, message)); if (context != null) { listener.getLogger().println(String.format("Using context: " + context)); } try { repo.createCommitStatus(sha1, state, url, message, context); } catch (IOException e) { throw new GhprbCommitStatusException(e, state, message, pullId); } } @Override public DescriptorImpl getDescriptor() { return DESCRIPTOR; } public static final class DescriptorImpl extends GhprbExtensionDescriptor implements GhprbGlobalExtension, GhprbProjectExtension { @Override public String getDisplayName() { return "Update commit status during build"; } public String getTriggeredStatusDefault(GhprbSimpleStatus local) { return Ghprb.getDefaultValue(local, GhprbSimpleStatus.class, "getTriggeredStatus"); } public String getStatusUrlDefault(GhprbSimpleStatus local) { return Ghprb.getDefaultValue(local, GhprbSimpleStatus.class, "getStatusUrl"); } public String getStartedStatusDefault(GhprbSimpleStatus local) { return Ghprb.getDefaultValue(local, GhprbSimpleStatus.class, "getStartedStatus"); } public Boolean getAddTestResultsDefault(GhprbSimpleStatus local) { return Ghprb.getDefaultValue(local, GhprbSimpleStatus.class, "getAddTestResults"); } public List<GhprbBuildResultMessage> getCompletedStatusDefault(GhprbSimpleStatus local) { return Ghprb.getDefaultValue(local, GhprbSimpleStatus.class, "getCompletedStatus"); } public String getCommitStatusContextDefault(GhprbSimpleStatus local) { return Ghprb.getDefaultValue(local, GhprbSimpleStatus.class, "getCommitStatusContext"); } public Boolean getShowMatrixStatusDefault(GhprbSimpleStatus local){ return Ghprb.getDefaultValue(local,GhprbSimpleStatus.class, "getShowMatrixStatus"); } public boolean addIfMissing() { return false; } } }