Skip to content

Commit 709fc65

Browse files
committed
Add a custom value for the detected CI provider
Closes gh-77
1 parent e830ee8 commit 709fc65

File tree

3 files changed

+156
-59
lines changed

3 files changed

+156
-59
lines changed

src/main/java/io/spring/ge/conventions/gradle/BuildScanConventions.java

Lines changed: 15 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@
3535
*/
3636
class BuildScanConventions implements Action<BuildScanConfiguration> {
3737

38-
private static final String BAMBOO_RESULTS_ENV_VAR = "bamboo_resultsUrl";
39-
40-
private static final String CIRCLECI_BUILD_URL_ENV_VAR = "CIRCLE_BUILD_URL";
41-
4238
private final DevelocityConfiguration develocity;
4339

4440
private final ProcessRunner processRunner;
@@ -64,10 +60,11 @@ public void execute(BuildScanConfiguration buildScan) {
6460
buildScan.obfuscation((obfuscation) -> obfuscation
6561
.ipAddresses((addresses) -> addresses.stream().map((address) -> "0.0.0.0").collect(Collectors.toList())));
6662
configurePublishing(buildScan);
67-
tagBuildScan(buildScan);
63+
ContinuousIntegration ci = ContinuousIntegration.detect(this.env);
64+
tagBuildScan(buildScan, ci);
6865
buildScan.background(this::addGitMetadata);
69-
addCiMetadata(buildScan);
70-
buildScan.getUploadInBackground().set(!isCi());
66+
addCiMetadata(buildScan, ci);
67+
buildScan.getUploadInBackground().set(ci == null);
7168
buildScan.capture((settings) -> settings.getFileFingerprints().set(true));
7269
}
7370

@@ -82,41 +79,14 @@ protected void configurePublishing(BuildScanConfiguration buildScan) {
8279
this.develocity.getServer().set("https://ge.spring.io");
8380
}
8481

85-
private void tagBuildScan(BuildScanConfiguration buildScan) {
86-
tagCiOrLocal(buildScan);
82+
private void tagBuildScan(BuildScanConfiguration buildScan, ContinuousIntegration ci) {
83+
tagCiOrLocal(buildScan, ci);
8784
tagJdk(buildScan);
8885
tagOperatingSystem(buildScan);
8986
}
9087

91-
private void tagCiOrLocal(BuildScanConfiguration buildScan) {
92-
buildScan.tag(isCi() ? "CI" : "Local");
93-
}
94-
95-
private boolean isCi() {
96-
if (isBamboo() || isCircleCi() || isConcourse() || isJenkins() || isGitHubActions()) {
97-
return true;
98-
}
99-
return false;
100-
}
101-
102-
private boolean isBamboo() {
103-
return this.env.containsKey(BAMBOO_RESULTS_ENV_VAR);
104-
}
105-
106-
private boolean isCircleCi() {
107-
return this.env.containsKey(CIRCLECI_BUILD_URL_ENV_VAR);
108-
}
109-
110-
private boolean isConcourse() {
111-
return this.env.containsKey("CI");
112-
}
113-
114-
private boolean isJenkins() {
115-
return this.env.containsKey("JENKINS_URL");
116-
}
117-
118-
private boolean isGitHubActions() {
119-
return this.env.containsKey("GITHUB_ACTIONS");
88+
private void tagCiOrLocal(BuildScanConfiguration buildScan, ContinuousIntegration ci) {
89+
buildScan.tag((ci != null) ? "CI" : "Local");
12090
}
12191

12292
private void tagJdk(BuildScanConfiguration buildScan) {
@@ -151,25 +121,15 @@ private void addGitMetadata(BuildScanConfiguration buildScan) {
151121
});
152122
}
153123

154-
private void addCiMetadata(BuildScanConfiguration buildScan) {
155-
if (isBamboo()) {
156-
buildScan.link("CI build", this.env.get(BAMBOO_RESULTS_ENV_VAR));
157-
}
158-
else if (isJenkins()) {
159-
String buildUrl = this.env.get("BUILD_URL");
160-
if (hasText(buildUrl)) {
161-
buildScan.link("CI build", buildUrl);
162-
}
163-
}
164-
else if (isCircleCi()) {
165-
buildScan.link("CI build", this.env.get(CIRCLECI_BUILD_URL_ENV_VAR));
124+
private void addCiMetadata(BuildScanConfiguration buildScan, ContinuousIntegration ci) {
125+
if (ci == null) {
126+
return;
166127
}
167-
else if (isGitHubActions()) {
168-
String server = this.env.get("GITHUB_SERVER_URL");
169-
String repository = this.env.get("GITHUB_REPOSITORY");
170-
String runId = this.env.get("GITHUB_RUN_ID");
171-
buildScan.link("CI build", server + "/" + repository + "/actions/runs/" + runId);
128+
String buildUrl = ci.buildUrlFrom(this.env);
129+
if (hasText(buildUrl)) {
130+
buildScan.link("CI build", buildUrl);
172131
}
132+
buildScan.value("CI provider", ci.toString());
173133
}
174134

175135
private RunResult getBranch() {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.spring.ge.conventions.gradle;
18+
19+
import java.util.Map;
20+
import java.util.function.Function;
21+
22+
/**
23+
* Known continuous integration environments.
24+
*
25+
* @author Andy Wilkinson
26+
*/
27+
enum ContinuousIntegration {
28+
29+
BAMBOO("Bamboo", "bamboo_resultsUrl"),
30+
31+
CIRCLE_CI("CircleCI", "CIRCLE_BUILD_URL"),
32+
33+
CONCOURSE("Concourse", "CI", (env) -> null),
34+
35+
JENKINS("Jenkins", "JENKINS_URL", (env) -> env.get("BUILD_URL")),
36+
37+
GITHUB_ACTIONS("GitHub Actions", "GITHUB_ACTIONS", (env) -> {
38+
String server = env.get("GITHUB_SERVER_URL");
39+
String repository = env.get("GITHUB_REPOSITORY");
40+
String runId = env.get("GITHUB_RUN_ID");
41+
return server + "/" + repository + "/actions/runs/" + runId;
42+
});
43+
44+
private final String name;
45+
46+
private final String environmentVariable;
47+
48+
private final Function<Map<String, String>, String> buildUrl;
49+
50+
ContinuousIntegration(String name, String environmentVariable) {
51+
this(name, environmentVariable, (env) -> env.get(environmentVariable));
52+
}
53+
54+
ContinuousIntegration(String name, String environmentVariable, Function<Map<String, String>, String> buildUrl) {
55+
this.name = name;
56+
this.environmentVariable = environmentVariable;
57+
this.buildUrl = buildUrl;
58+
}
59+
60+
String buildUrlFrom(Map<String, String> env) {
61+
return this.buildUrl.apply(env);
62+
}
63+
64+
@Override
65+
public String toString() {
66+
return this.name;
67+
}
68+
69+
static ContinuousIntegration detect(Map<String, String> env) {
70+
for (ContinuousIntegration ci : values()) {
71+
if (env.containsKey(ci.environmentVariable)) {
72+
return ci;
73+
}
74+
}
75+
return null;
76+
}
77+
78+
}

src/test/java/io/spring/ge/conventions/gradle/BuildScanConventionsTests.java

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,22 @@ void whenBambooResultEnvVarIsPresentThenBuildScanHasACiBuildLinkToIt() {
9191
assertThat(this.buildScan.links).containsEntry("CI build", "https://bamboo.example.com");
9292
}
9393

94+
@Test
95+
void whenBambooResultEnvVarIsPresentThenBuildScanHasBambooAsTheCiProviderValue() {
96+
new BuildScanConventions(this.develocity, this.processRunner,
97+
Collections.singletonMap("bamboo_resultsUrl", "https://bamboo.example.com"))
98+
.execute(this.buildScan);
99+
assertThat(this.buildScan.values).containsEntry("CI provider", "Bamboo");
100+
}
101+
102+
@Test
103+
void whenCircleBuildUrlEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() {
104+
new BuildScanConventions(this.develocity, this.processRunner,
105+
Collections.singletonMap("CIRCLE_BUILD_URL", "https://circleci.example.com/gh/org/project/123"))
106+
.execute(this.buildScan);
107+
assertThat(this.buildScan.tags).contains("CI").doesNotContain("Local");
108+
}
109+
94110
@Test
95111
void whenCircleBuildUrlEnvVarIsPresentThenBuildScanHasACiBuildLinkToIt() {
96112
new BuildScanConventions(this.develocity, this.processRunner,
@@ -99,6 +115,22 @@ void whenCircleBuildUrlEnvVarIsPresentThenBuildScanHasACiBuildLinkToIt() {
99115
assertThat(this.buildScan.links).containsEntry("CI build", "https://circleci.example.com/gh/org/project/123");
100116
}
101117

118+
@Test
119+
void whenCircleBuildUrlEnvVarIsPresentThenBuildScanHasCircleCiAsTheCiProviderValue() {
120+
new BuildScanConventions(this.develocity, this.processRunner,
121+
Collections.singletonMap("CIRCLE_BUILD_URL", "https://circleci.example.com/gh/org/project/123"))
122+
.execute(this.buildScan);
123+
assertThat(this.buildScan.values).containsEntry("CI provider", "CircleCI");
124+
}
125+
126+
@Test
127+
void whenJenkinsUrlEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() {
128+
new BuildScanConventions(this.develocity, this.processRunner,
129+
Collections.singletonMap("JENKINS_URL", "https://jenkins.example.com"))
130+
.execute(this.buildScan);
131+
assertThat(this.buildScan.tags).contains("CI").doesNotContain("Local");
132+
}
133+
102134
@Test
103135
void whenJenkinsUrlAndBuildUrlEnvVarsArePresentThenBuildScanHasACiBuildLinkToBuildUrl() {
104136
Map<String, String> env = new HashMap<>();
@@ -108,6 +140,14 @@ void whenJenkinsUrlAndBuildUrlEnvVarsArePresentThenBuildScanHasACiBuildLinkToBui
108140
assertThat(this.buildScan.links).containsEntry("CI build", "https://jenkins.example.com/builds/123");
109141
}
110142

143+
@Test
144+
void whenJenkinsUrlEnvVarIsPresentThenBuildScanHasJenkinsAsTheCiProviderValue() {
145+
new BuildScanConventions(this.develocity, this.processRunner,
146+
Collections.singletonMap("JENKINS_URL", "https://jenkins.example.com"))
147+
.execute(this.buildScan);
148+
assertThat(this.buildScan.values).containsEntry("CI provider", "Jenkins");
149+
}
150+
111151
@Test
112152
void whenCiEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() {
113153
new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("CI", null))
@@ -116,11 +156,10 @@ void whenCiEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() {
116156
}
117157

118158
@Test
119-
void whenJenkinsUrlEnvVarIsPresentThenBuildScanIsTaggedWithCiNotLocal() {
120-
new BuildScanConventions(this.develocity, this.processRunner,
121-
Collections.singletonMap("JENKINS_URL", "https://jenkins.example.com"))
159+
void whenCiEnvVarIsPresentThenBuildScanHasConcourseAsTheCiProviderValue() {
160+
new BuildScanConventions(this.develocity, this.processRunner, Collections.singletonMap("CI", null))
122161
.execute(this.buildScan);
123-
assertThat(this.buildScan.tags).contains("CI").doesNotContain("Local");
162+
assertThat(this.buildScan.values).containsEntry("CI provider", "Concourse");
124163
}
125164

126165
@Test
@@ -143,12 +182,32 @@ void whenGitHubActionsEnvVarsArePresentThenBuildScanHasACiBuildLinkToIt() {
143182
"https://github.com/spring-projects/spring-boot/actions/runs/1234567890");
144183
}
145184

185+
@Test
186+
void whenGitHubActionsEnvVarIsPresentThenBuildScanHasGitHubActionsAsTheCiProviderValue() {
187+
new BuildScanConventions(this.develocity, this.processRunner,
188+
Collections.singletonMap("GITHUB_ACTIONS", "true"))
189+
.execute(this.buildScan);
190+
assertThat(this.buildScan.values).containsEntry("CI provider", "GitHub Actions");
191+
}
192+
146193
@Test
147194
void whenNoCiIndicatorsArePresentThenBuildScanIsTaggedWithLocalNotCi() {
148195
new BuildScanConventions(this.develocity, this.processRunner, Collections.emptyMap()).execute(this.buildScan);
149196
assertThat(this.buildScan.tags).contains("Local").doesNotContain("CI");
150197
}
151198

199+
@Test
200+
void whenNoCiIndicatorsArePresentThenBuildScanHasNoCiBuildLink() {
201+
new BuildScanConventions(this.develocity, this.processRunner, Collections.emptyMap()).execute(this.buildScan);
202+
assertThat(this.buildScan.links).doesNotContainKey("CI build");
203+
}
204+
205+
@Test
206+
void whenNoCiIndicatorsArePresentThenBuildScanHasNoCiProviderValue() {
207+
new BuildScanConventions(this.develocity, this.processRunner, Collections.emptyMap()).execute(this.buildScan);
208+
assertThat(this.buildScan.values).doesNotContainKey("CI provider");
209+
}
210+
152211
@Test
153212
void buildScanIsTaggedWithJdkVersion() {
154213
new BuildScanConventions(this.develocity, this.processRunner).execute(this.buildScan);

0 commit comments

Comments
 (0)