|
1 | 1 | package com.cloudbees.jenkins;
|
2 | 2 |
|
| 3 | +import edu.umd.cs.findbugs.annotations.NonNull; |
3 | 4 | import hudson.Extension;
|
4 | 5 | import hudson.FilePath;
|
5 | 6 | import hudson.Launcher;
|
6 |
| -import hudson.Util; |
7 | 7 | import hudson.model.AbstractProject;
|
8 | 8 | import hudson.model.Result;
|
9 | 9 | import hudson.model.Run;
|
|
14 | 14 | import hudson.tasks.Publisher;
|
15 | 15 | import hudson.util.ListBoxModel;
|
16 | 16 | import jenkins.tasks.SimpleBuildStep;
|
17 |
| -import org.eclipse.jgit.lib.ObjectId; |
18 | 17 | import org.jenkinsci.plugins.github.common.ExpandableMessage;
|
19 |
| -import org.jenkinsci.plugins.github.util.BuildDataHelper; |
| 18 | +import org.jenkinsci.plugins.github.extension.status.StatusErrorHandler; |
| 19 | +import org.jenkinsci.plugins.github.status.GitHubCommitStatusSetter; |
| 20 | +import org.jenkinsci.plugins.github.status.err.ChangingBuildStatusErrorHandler; |
| 21 | +import org.jenkinsci.plugins.github.status.err.ShallowAnyErrorHandler; |
| 22 | +import org.jenkinsci.plugins.github.status.sources.AnyDefinedRepositorySource; |
| 23 | +import org.jenkinsci.plugins.github.status.sources.BuildDataRevisionShaSource; |
| 24 | +import org.jenkinsci.plugins.github.status.sources.ConditionalStatusResultSource; |
| 25 | +import org.jenkinsci.plugins.github.status.sources.DefaultCommitContextSource; |
| 26 | +import org.jenkinsci.plugins.github.status.sources.DefaultStatusResultSource; |
20 | 27 | import org.kohsuke.accmod.Restricted;
|
21 | 28 | import org.kohsuke.accmod.restrictions.NoExternalUse;
|
22 | 29 | import org.kohsuke.github.GHCommitState;
|
23 |
| -import org.kohsuke.github.GHRepository; |
24 | 30 | import org.kohsuke.stapler.DataBoundConstructor;
|
25 | 31 | import org.kohsuke.stapler.DataBoundSetter;
|
26 | 32 | import org.slf4j.Logger;
|
27 | 33 | import org.slf4j.LoggerFactory;
|
28 | 34 |
|
29 | 35 | import javax.annotation.Nonnull;
|
30 |
| -import java.io.FileNotFoundException; |
31 | 36 | import java.io.IOException;
|
| 37 | +import java.util.Collections; |
32 | 38 |
|
33 | 39 | import static com.cloudbees.jenkins.Messages.GitHubCommitNotifier_DisplayName;
|
34 |
| -import static com.cloudbees.jenkins.Messages.GitHubCommitNotifier_SettingCommitStatus; |
35 |
| -import static com.coravy.hudson.plugins.github.GithubProjectProperty.displayNameFor; |
36 | 40 | import static com.google.common.base.Objects.firstNonNull;
|
37 | 41 | import static hudson.model.Result.FAILURE;
|
38 | 42 | import static hudson.model.Result.SUCCESS;
|
39 | 43 | import static hudson.model.Result.UNSTABLE;
|
40 |
| -import static java.lang.String.format; |
41 |
| -import static org.apache.commons.lang3.StringUtils.defaultIfEmpty; |
| 44 | +import static java.util.Arrays.asList; |
| 45 | +import static org.apache.commons.lang3.StringUtils.isNotBlank; |
42 | 46 | import static org.apache.commons.lang3.StringUtils.trimToEmpty;
|
| 47 | +import static org.jenkinsci.plugins.github.status.sources.misc.AnyBuildResult.onAnyResult; |
| 48 | +import static org.jenkinsci.plugins.github.status.sources.misc.BetterThanOrEqualBuildResult.betterThanOrEqualTo; |
43 | 49 |
|
44 | 50 | /**
|
45 | 51 | * Create commit status notifications on the commits based on the outcome of the build.
|
@@ -107,105 +113,41 @@ public BuildStepMonitor getRequiredMonitorService() {
|
107 | 113 | }
|
108 | 114 |
|
109 | 115 | @Override
|
110 |
| - public void perform(Run<?, ?> build, |
111 |
| - FilePath ws, |
112 |
| - Launcher launcher, |
113 |
| - TaskListener listener) throws InterruptedException, IOException { |
114 |
| - try { |
115 |
| - updateCommitStatus(build, listener); |
116 |
| - } catch (IOException error) { |
117 |
| - final Result buildResult = getEffectiveResultOnFailure(); |
118 |
| - if (buildResult.equals(FAILURE)) { |
119 |
| - throw error; |
120 |
| - } else { |
121 |
| - listener.error(format("[GitHub Commit Notifier] - %s", error.getMessage())); |
122 |
| - listener.getLogger().println( |
123 |
| - format("[GitHub Commit Notifier] - Build result will be set to %s", buildResult) |
124 |
| - ); |
125 |
| - build.setResult(buildResult); |
126 |
| - } |
127 |
| - } |
128 |
| - } |
129 |
| - |
130 |
| - private void updateCommitStatus(@Nonnull Run<?, ?> build, |
131 |
| - @Nonnull TaskListener listener) throws InterruptedException, IOException { |
132 |
| - final String sha1 = ObjectId.toString(BuildDataHelper.getCommitSHA1(build)); |
133 |
| - |
134 |
| - StatusResult status = statusFrom(build); |
135 |
| - String message = defaultIfEmpty(firstNonNull(statusMessage, DEFAULT_MESSAGE) |
136 |
| - .expandAll(build, listener), status.getMsg()); |
137 |
| - String contextName = displayNameFor(build.getParent()); |
138 |
| - |
139 |
| - for (GitHubRepositoryName name : GitHubRepositoryNameContributor.parseAssociatedNames(build.getParent())) { |
140 |
| - for (GHRepository repository : name.resolve()) { |
141 |
| - |
142 |
| - listener.getLogger().println( |
143 |
| - GitHubCommitNotifier_SettingCommitStatus(repository.getHtmlUrl() + "/commit/" + sha1) |
144 |
| - ); |
145 |
| - |
146 |
| - try { |
147 |
| - repository.createCommitStatus( |
148 |
| - sha1, status.getState(), build.getAbsoluteUrl(), |
149 |
| - message, |
150 |
| - contextName |
151 |
| - ); |
152 |
| - } catch (FileNotFoundException e) { |
153 |
| - // PR builds and other merge activities can create a merge commit that |
154 |
| - // doesn't exist in the upstream. Don't let the build fail |
155 |
| - // TODO: ideally we'd like other plugins to designate a commit to put the status update to |
156 |
| - LOGGER.debug("Failed to update commit status", e); |
157 |
| - listener.getLogger() |
158 |
| - .format("Commit doesn't exist in %s. Status is not set%n", repository.getFullName()); |
159 |
| - } |
160 |
| - } |
161 |
| - } |
162 |
| - } |
163 |
| - |
164 |
| - private static StatusResult statusFrom(@Nonnull Run<?, ?> build) { |
165 |
| - Result result = build.getResult(); |
166 |
| - |
167 |
| - // We do not use `build.getDurationString()` because it appends 'and counting' (build is still running) |
168 |
| - String duration = Util.getTimeSpanString(System.currentTimeMillis() - build.getTimeInMillis()); |
169 |
| - |
170 |
| - if (result == null) { // Build is ongoing |
171 |
| - return new StatusResult( |
172 |
| - GHCommitState.PENDING, |
173 |
| - Messages.CommitNotifier_Pending(build.getDisplayName()) |
174 |
| - ); |
175 |
| - } else if (result.isBetterOrEqualTo(SUCCESS)) { |
176 |
| - return new StatusResult( |
177 |
| - GHCommitState.SUCCESS, |
178 |
| - Messages.CommitNotifier_Success(build.getDisplayName(), duration) |
179 |
| - ); |
180 |
| - } else if (result.isBetterOrEqualTo(UNSTABLE)) { |
181 |
| - return new StatusResult( |
182 |
| - GHCommitState.
10000
FAILURE, |
183 |
| - Messages.CommitNotifier_Unstable(build.getDisplayName(), duration) |
184 |
| - ); |
| 116 | + public void perform(@NonNull Run<?, ?> build, |
| 117 | + @NonNull FilePath ws, |
| 118 | + @NonNull Launcher launcher, |
| 119 | + @NonNull TaskListener listener) throws InterruptedException, IOException { |
| 120 | + |
| 121 | + GitHubCommitStatusSetter setter = new GitHubCommitStatusSetter(); |
| 122 | + setter.setReposSource(new AnyDefinedRepositorySource()); |
| 123 | + setter.setCommitShaSource(new BuildDataRevisionShaSource()); |
| 124 | + setter.setContextSource(new DefaultCommitContextSource()); |
| 125 | + |
| 126 | + |
| 127 | + String content = firstNonNull(statusMessage, DEFAULT_MESSAGE).getContent(); |
| 128 | + |
| 129 | + if (isNotBlank(content)) { |
| 130 | + setter.setStatusResultSource(new ConditionalStatusResultSource( |
| 131 | + asList( |
| 132 | + betterThanOrEqualTo(SUCCESS, GHCommitState.SUCCESS, content), |
| 133 | + betterThanOrEqualTo(UNSTABLE, GHCommitState.FAILURE, content), |
| 134 | + betterThanOrEqualTo(FAILURE, GHCommitState.ERROR, content), |
| 135 | + onAnyResult(GHCommitState.PENDING, content) |
| 136 | + ))); |
185 | 137 | } else {
|
186 |
| - return new StatusResult( |
187 |
| - GHCommitState.ERROR, |
188 |
| - Messages.CommitNotifier_Failed(build.getDisplayName(), duration) |
189 |
| - ); |
| 138 | + setter.setStatusResultSource(new DefaultStatusResultSource()); |
190 | 139 | }
|
191 |
| - } |
192 | 140 |
|
193 |
| - private static class StatusResult { |
194 |
| - private GHCommitState state; |
195 |
| - private String msg; |
196 |
| - |
197 |
| - public StatusResult(GHCommitState state, String msg) { |
198 |
| - this.state = state; |
199 |
| - this.msg = msg; |
200 |
| - } |
201 |
| - |
202 |
| - public GHCommitState getState() { |
203 |
| - return state; |
| 141 | + if (getEffectiveResultOnFailure().equals(SUCCESS)) { |
| 142 | + setter.setErrorHandlers(Collections.<StatusErrorHandler>singletonList(new ShallowAnyErrorHandler())); |
| 143 | + } else if (resultOnFailure == null) { |
| 144 | + setter.setErrorHandlers(null); |
| 145 | + } else { |
| 146 | + setter.setErrorHandlers(Collections.<StatusErrorHandler>singletonList( |
| 147 | + new ChangingBuildStatusErrorHandler(getEffectiveResultOnFailure().toString()))); |
204 | 148 | }
|
205 | 149 |
|
206 |
| - public String getMsg() { |
207 |
| - return msg; |
208 |
| - } |
| 150 | + setter.perform(build, ws, launcher, listener); |
209 | 151 | }
|
210 | 152 |
|
211 | 153 | @Extension
|
|
0 commit comments