Skip to content

Commit 77ccda4

Browse files
authored
[JENKINS-61020] Add configurable commit status identifier (#75)
* [JENKINS-61020] Add configurable commit status identifier * GitLabPipelineStatusNotifier: Move status name generation to own method, mark some instances as final
1 parent b420cce commit 77ccda4

File tree

6 files changed

+148
-19
lines changed

6 files changed

+148
-19
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package io.jenkins.plugins.gitlabbranchsource;
2+
3+
import edu.umd.cs.findbugs.annotations.NonNull;
4+
import hudson.Extension;
5+
import jenkins.scm.api.SCMSource;
6+
import jenkins.scm.api.trait.SCMSourceContext;
7+
import jenkins.scm.api.trait.SCMSourceTrait;
8+
import jenkins.scm.api.trait.SCMSourceTraitDescriptor;
9+
import org.jenkinsci.Symbol;
10+
import org.kohsuke.stapler.DataBoundConstructor;
11+
import org.kohsuke.stapler.DataBoundSetter;
12+
13+
public class BuildStatusNameCustomPartTrait extends SCMSourceTrait {
14+
15+
@NonNull
16+
private String buildStatusNameCustomPart = "";
17+
18+
/**
19+
* Constructor for stapler.
20+
*/
21+
@DataBoundConstructor
22+
public BuildStatusNameCustomPartTrait() {
23+
// empty
24+
}
25+
26+
/**
27+
* Setter for stapler to set the buildStatusNameCustomPart of the build status
28+
*/
29+
@DataBoundSetter
30+
public void setBuildStatusNameCustomPart(@NonNull String buildStatusNameCustomPart) {
31+
this.buildStatusNameCustomPart = buildStatusNameCustomPart;
32+
}
33+
34+
@Override
35+
protected void decorateContext(SCMSourceContext<?, ?> context) {
36+
if (context instanceof GitLabSCMSourceContext) {
37+
GitLabSCMSourceContext ctx = (GitLabSCMSourceContext) context;
38+
ctx.withBuildStatusNameCustomPart(getBuildStatusNameCustomPart());
39+
}
40+
}
41+
42+
/**
43+
* Getter method for the build status context prefix
44+
*
45+
* @return build status context prefix
46+
*/
47+
@NonNull
48+
public String getBuildStatusNameCustomPart() {
49+
return buildStatusNameCustomPart;
50+
}
51+
52+
/**
53+
* Our descriptor.
54+
*/
55+
@Extension
56+
@Symbol("buildStatusNameCustomPart")
57+
public static class DescriptorImpl extends SCMSourceTraitDescriptor {
58+
59+
@NonNull
60+
@Override
61+
public String getDisplayName() {
62+
return Messages.BuildStatusNameCustomPartTrait_displayName();
63+
}
64+
65+
@Override
66+
public Class<? extends SCMSourceContext> getContextClass() {
67+
return GitLabSCMSourceContext.class;
68+
}
69+
70+
@Override
71+
public Class<? extends SCMSource> getSourceClass() {
72+
return GitLabSCMSource.class;
73+
}
74+
}
75+
}

src/main/java/io/jenkins/plugins/gitlabbranchsource/GitLabSCMSourceContext.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public class GitLabSCMSourceContext
4545

4646
private boolean projectAvatarDisabled;
4747

48+
private String buildStatusNameCustomPart = "";
49+
4850
public GitLabSCMSourceContext(@CheckForNull SCMSourceCriteria criteria,
4951
@NonNull SCMHeadObserver observer) {
5052
super(criteria, observer);
@@ -118,6 +120,10 @@ public final String getCommentBody() {
118120
return commentBody;
119121
}
120122

123+
public final String getBuildStatusNameCustomPart() {
124+
return buildStatusNameCustomPart;
125+
}
126+
121127
@NonNull
122128
public GitLabSCMSourceContext wantBranches(boolean include) {
123129
wantBranches = wantBranches || include;
@@ -208,6 +214,12 @@ public final GitLabSCMSourceContext withCommentBody(String commentBody) {
208214
return this;
209215
}
210216

217+
@NonNull
218+
public final GitLabSCMSourceContext withBuildStatusNameCustomPart(final String buildStatusNameCustomPart) {
219+
this.buildStatusNameCustomPart = Util.fixNull(buildStatusNameCustomPart);
220+
return this;
221+
}
222+
211223
@NonNull
212224
@Override
213225
public GitLabSCMSourceRequest newRequest(@NonNull SCMSource source,

src/main/java/io/jenkins/plugins/gitlabbranchsource/helpers/GitLabPipelineStatusNotifier.java

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ public class GitLabPipelineStatusNotifier {
5353
private static final Logger LOGGER = Logger
5454
.getLogger(GitLabPipelineStatusNotifier.class.getName());
5555

56+
private static final String GITLAB_PIPELINE_STATUS_PREFIX = "jenkinsci";
57+
58+
private static final String GITLAB_PIPELINE_STATUS_DELIMITER = "/";
59+
5660
private static String getRootUrl(Run<?, ?> build) {
5761
try {
5862
return DisplayURLProvider.get().getRunURL(build);
@@ -75,12 +79,41 @@ private static GitLabSCMSource getSource(Run<?, ?> build) {
7579
return null;
7680
}
7781

78-
private static String getMrBuildName(String buildName) {
79-
String suffix = "jenkinsci/";
80-
if (buildName.contains("merge")) {
81-
return suffix + "mr-merge";
82+
private static String getStatusName(final GitLabSCMSourceContext sourceContext, final Run<?, ?> build, final SCMRevision revision) {
83+
return getStatusName(sourceContext, build.getFullDisplayName(), revision);
84+
}
85+
86+
private static String getStatusName(final GitLabSCMSourceContext sourceContext, final Job<?, ?> job, final SCMRevision revision) {
87+
return getStatusName(sourceContext, job.getFullDisplayName(), revision);
88+
}
89+
90+
private static String getStatusName(final GitLabSCMSourceContext sourceContext, final String fullDisplayName, final SCMRevision revision) {
91+
final String type;
92+
if (revision instanceof BranchSCMRevision) {
93+
type = "branch";
94+
} else if (revision instanceof MergeRequestSCMRevision) {
95+
type = getMrBuildName(fullDisplayName);
96+
} else if (revision instanceof GitTagSCMRevision) {
97+
type = "tag";
98+
} else {
99+
type = "UNKNOWN";
100+
LOGGER.log(Level.WARNING, () -> "Unknown SCMRevision implementation "
101+
+ revision.getClass().getName() + ", append" + type + " to status name");
102+
}
103+
104+
String customPrefix = sourceContext.getBuildStatusNameCustomPart();
105+
if (!customPrefix.isEmpty())
106+
{
107+
customPrefix = customPrefix + GITLAB_PIPELINE_STATUS_DELIMITER;
82108
}
83-
return suffix + "mr-head";
109+
110+
final String statusName = GITLAB_PIPELINE_STATUS_PREFIX + GITLAB_PIPELINE_STATUS_DELIMITER + customPrefix + type;
111+
LOGGER.log(Level.FINEST, () -> "Retrieved status name is: " + statusName);
112+
return statusName;
113+
}
114+
115+
private static String getMrBuildName(final String buildName) {
116+
return (buildName.contains("merge") ? "mr-merge" : "mr-head");
84117
}
85118

86119
/**
@@ -130,26 +163,24 @@ private static void logComment(Run<?, ?> build, TaskListener listener) {
130163
if (!sudoUsername.isEmpty()) {
131164
gitLabApi.sudo(sudoUsername);
132165
}
133-
String hash;
166+
final String buildName = "**" + getStatusName(sourceContext, build, revision) + ":** ";
167+
final String hash;
134168
if (revision instanceof BranchSCMRevision) {
135169
hash = ((BranchSCMRevision) revision).getHash();
136-
String buildName = "**jenkinsci/branch:** ";
137170
gitLabApi.getCommitsApi().addComment(
138171
source.getProjectPath(),
139172
hash,
140173
symbol + buildName + note + suffix
141174
);
142175
} else if (revision instanceof MergeRequestSCMRevision) {
143176
MergeRequestSCMHead head = (MergeRequestSCMHead) revision.getHead();
144-
String buildName = "**" + getMrBuildName(build.getFullDisplayName()) + "**: ";
145177
gitLabApi.getNotesApi().createMergeRequestNote(
146178
source.getProjectPath(),
147179
Integer.valueOf(head.getId()),
148180
symbol + buildName + note + suffix
149181
);
150182
} else if (revision instanceof GitTagSCMRevision) {
151183
hash = ((GitTagSCMRevision) revision).getHash();
152-
String buildName = "**jenkinsci/tag:** ";
153184
gitLabApi.getCommitsApi().addComment(
154185
source.getProjectPath(),
155186
hash,
@@ -212,30 +243,29 @@ private static void sendNotifications(Run<?, ?> build, TaskListener listener) {
212243
state = Constants.CommitBuildState.RUNNING;
213244
}
214245

215-
SCMRevision revision = SCMRevisionAction.getRevision(source, build);
246+
final SCMRevision revision = SCMRevisionAction.getRevision(source, build);
216247
String hash;
217248
if (revision instanceof BranchSCMRevision) {
218249
listener.getLogger()
219250
.format("[GitLab Pipeline Status] Notifying branch build status: %s %s%n",
220251
status.getStatus(), status.getDescription());
221252
hash = ((BranchSCMRevision) revision).getHash();
222-
status.setName("jenkinsci/branch");
223253
} else if (revision instanceof MergeRequestSCMRevision) {
224254
listener.getLogger()
225255
.format("[GitLab Pipeline Status] Notifying merge request build status: %s %s%n",
226256
status.getStatus(), status.getDescription());
227257
hash = ((MergeRequestSCMRevision) revision).getOrigin().getHash();
228-
status.setName(getMrBuildName(build.getFullDisplayName()));
229258
} else if (revision instanceof GitTagSCMRevision) {
230259
listener.getLogger()
231260
.format("[GitLab Pipeline Status] Notifying tag build status: %s %s%n",
232261
status.getStatus(), status.getDescription());
233262
hash = ((GitTagSCMRevision) revision).getHash();
234-
status.setName("jenkinsci/tag");
235263
} else {
236264
return;
237265
}
238-
JobScheduledListener jsl = ExtensionList.lookup(QueueListener.class)
266+
status.setName(getStatusName(sourceContext, build, revision));
267+
268+
final JobScheduledListener jsl = ExtensionList.lookup(QueueListener.class)
239269
.get(JobScheduledListener.class);
240270
if (jsl != null) {
241271
// we are setting the status, so don't let the queue listener background thread change it to pending
@@ -295,28 +325,27 @@ public void onEnterWaiting(final Queue.WaitingItem wi) {
295325
// prevent delays in the queue when updating GitLab
296326
Computer.threadPoolForRemoting.submit(() -> {
297327
try (ACLContext ctx = ACL.as(Tasks.getAuthenticationOf(wi.task))) {
298-
SCMRevision revision = source
328+
final SCMRevision revision = source
299329
.fetch(head, new LogTaskListener(LOGGER, Level.INFO));
300330
String hash;
301-
CommitStatus status = new CommitStatus();
331+
final CommitStatus status = new CommitStatus();
302332
if (revision instanceof BranchSCMRevision) {
303333
LOGGER.log(Level.INFO, "Notifying branch pending build {0}",
304334
job.getFullName());
305335
hash = ((BranchSCMRevision) revision).getHash();
306-
status.setName("jenkinsci/branch");
307336
} else if (revision instanceof MergeRequestSCMRevision) {
308337
LOGGER.log(Level.INFO, "Notifying merge request pending build {0}",
309338
job.getFullName());
310339
hash = ((MergeRequestSCMRevision) revision).getOrigin().getHash();
311-
status.setName(getMrBuildName(job.getFullDisplayName()));
312340
} else if (revision instanceof GitTagSCMRevision) {
313341
LOGGER.log(Level.INFO, "Notifying tag pending build {0}",
314342
job.getFullName());
315343
hash = ((GitTagSCMRevision) revision).getHash();
316-
status.setName("jenkinsci/tag");
317344
} else {
318345
return;
319346
}
347+
status.setName(getStatusName(sourceContext, job, revision));
348+
320349
String url;
321350
try {
322351
url = DisplayURLProvider.get().getJobURL(job);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?jelly escape-by-default='true'?>
2+
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">
3+
<f:entry title="${%Build status name custom part}" field="buildStatusNameCustomPart">
4+
<f:textbox/>
5+
</f:entry>
6+
</j:jelly>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<div>
2+
Enter a string to customize the status/context name for status updates published to GitLab.
3+
For a branch build the default name would be 'jenkinsci/branch'. With the buildStatusNameCustomPart
4+
'custom' the name would be 'jenkinsci/custom/branch'.
5+
This allows to have multiple GitLab-Branch-Sources for the same GitLab-project configured.
6+
</div>

src/main/resources/io/jenkins/plugins/gitlabbranchsource/Messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ BranchDiscoveryTrait.authorityDisplayName=Trust origin branches
44
BranchDiscoveryTrait.displayName=Discover branches
55
BranchDiscoveryTrait.excludeMRs=Only branches that are not also filed as MRs
66
BranchDiscoveryTrait.onlyMRs=Only branches that are also filed as MRs
7+
BuildStatusNameCustomPartTrait.displayName=Customize GitLab build status name
78
ForkMergeRequestDiscoveryTrait.displayName=Discover merge requests from forks
89
ForkMergeRequestDiscoveryTrait.headAndMerge=Both the current merge request revision and the merge request merged with \
910
the current target branch revision

0 commit comments

Comments
 (0)