package org.jenkinsci.plugins.github.status; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.AbstractProject; import hudson.model.Run; import hudson.model.TaskListener; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; import hudson.tasks.Publisher; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.plugins.github.common.CombineErrorHandler; import org.jenkinsci.plugins.github.extension.status.GitHubCommitShaSource; import org.jenkinsci.plugins.github.extension.status.GitHubReposSource; import org.jenkinsci.plugins.github.extension.status.GitHubStatusBackrefSource; import org.jenkinsci.plugins.github.extension.status.GitHubStatusContextSource; import org.jenkinsci.plugins.github.extension.status.GitHubStatusResultSource; import org.jenkinsci.plugins.github.extension.status.StatusErrorHandler; import org.jenkinsci.plugins.github.status.sources.AnyDefinedRepositorySource; import org.jenkinsci.plugins.github.status.sources.BuildDataRevisionShaSource; import org.jenkinsci.plugins.github.status.sources.BuildRefBackrefSource; import org.jenkinsci.plugins.github.status.sources.DefaultCommitContextSource; import org.jenkinsci.plugins.github.status.sources.DefaultStatusResultSource; import org.kohsuke.github.GHCommitState; import org.kohsuke.github.GHRepository; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; import static com.cloudbees.jenkins.Messages.GitHubCommitNotifier_SettingCommitStatus; /** * Create commit state notifications on the commits based on the outcome of the build. * * @author lanwen (Merkushev Kirill) * @since 1.19.0 */ public class GitHubCommitStatusSetter extends Notifier implements SimpleBuildStep { private GitHubCommitShaSource commitShaSource = new BuildDataRevisionShaSource(); private GitHubReposSource reposSource = new AnyDefinedRepositorySource(); private GitHubStatusContextSource contextSource = new DefaultCommitContextSource(); private GitHubStatusResultSource statusResultSource = new DefaultStatusResultSource(); private GitHubStatusBackrefSource statusBackrefSource = new BuildRefBackrefSource(); private List<StatusErrorHandler> errorHandlers = new ArrayList<>(); @DataBoundConstructor public GitHubCommitStatusSetter() { } @DataBoundSetter public void setCommitShaSource(GitHubCommitShaSource commitShaSource) { this.commitShaSource = commitShaSource; } @DataBoundSetter public void setReposSource(GitHubReposSource reposSource) { this.reposSource = reposSource; } @DataBoundSetter public void setContextSource(GitHubStatusContextSource contextSource) { this.contextSource = contextSource; } @DataBoundSetter public void setStatusResultSource(GitHubStatusResultSource statusResultSource) { this.statusResultSource = statusResultSource; } @DataBoundSetter public void setStatusBackrefSource(GitHubStatusBackrefSource statusBackrefSource) { this.statusBackrefSource = statusBackrefSource; } @DataBoundSetter public void setErrorHandlers(List<StatusErrorHandler> errorHandlers) { this.errorHandlers = errorHandlers; } /** * @return SHA provider */ public GitHubCommitShaSource getCommitShaSource() { return commitShaSource; } /** * @return Repository list provider */ public GitHubReposSource getReposSource() { return reposSource; } /** * @return Context provider */ public GitHubStatusContextSource getContextSource() { return contextSource; } /** * @return state + msg provider */ public GitHubStatusResultSource getStatusResultSource() { return statusResultSource; } /** * @return backref provider */ public GitHubStatusBackrefSource getStatusBackrefSource() { return statusBackrefSource; } /** * @return error handlers */ public List<StatusErrorHandler> getErrorHandlers() { return errorHandlers; } /** * Gets info from the providers and updates commit status */ @Override public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workspace, @Nonnull Launcher launcher, @Nonnull TaskListener listener) { try { String sha = getCommitShaSource().get(run, listener); List<GHRepository> repos = getReposSource().repos(run, listener); String contextName = getContextSource().context(run, listener); String backref = getStatusBackrefSource().get(run, listener); GitHubStatusResultSource.StatusResult result = getStatusResultSource().get(run, listener); String message = result.getMsg(); GHCommitState state = result.getState(); listener.getLogger().printf( "[%s] %s on repos %s (sha:%7.7s) with context:%s%n", getDescriptor().getDisplayName(), state, repos, sha, contextName ); for (GHRepository repo : repos) { listener.getLogger().println( GitHubCommitNotifier_SettingCommitStatus(repo.getHtmlUrl() + "/commit/" + sha) ); repo.createCommitStatus(sha, state, backref, message, contextName); } } catch (Exception e) { CombineErrorHandler.errorHandling().withHandlers(getErrorHandlers()).handle(e, run, listener); } } @Override public BuildStepMonitor getRequiredMonitorService() { return BuildStepMonitor.NONE; } public Object readResolve() { if (getStatusBackrefSource() == null) { setStatusBackrefSource(new BuildRefBackrefSource()); } return this; } @Extension public static class GitHubCommitStatusSetterDescr extends BuildStepDescriptor<Publisher> { @Override public boolean isApplicable(Class<? extends AbstractProject> jobType) { return true; } @Override public String getDisplayName() { return "Set GitHub commit status (universal)"; } } }