Skip to content

Commit c6168d2

Browse files
Handle scenario when no GE server URL is specified in Maven experiment more gracefully (#374)
* Handle scenario when no GE server URL is specified in Maven experiment more gracefully * Add newline --------- Co-authored-by: Eric Haag <[email protected]>
1 parent c0932e8 commit c6168d2

File tree

5 files changed

+150
-114
lines changed

5 files changed

+150
-114
lines changed

components/capture-build-scan-url-maven-extension/src/main/java/com/gradle/CaptureBuildScansListener.java

Lines changed: 0 additions & 93 deletions
This file was deleted.
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package com.gradle;
2+
3+
import com.gradle.maven.extension.api.GradleEnterpriseApi;
4+
import com.gradle.maven.extension.api.GradleEnterpriseListener;
5+
import com.gradle.maven.extension.api.scan.BuildScanApi;
6+
import org.apache.maven.execution.MavenSession;
7+
import org.codehaus.plexus.logging.Logger;
8+
9+
import javax.inject.Inject;
10+
import java.io.File;
11+
import java.io.IOException;
12+
import java.io.UnsupportedEncodingException;
13+
import java.net.URI;
14+
import java.net.URLEncoder;
15+
import java.nio.charset.StandardCharsets;
16+
import java.nio.file.Files;
17+
18+
import static java.lang.Boolean.parseBoolean;
19+
import static java.nio.file.StandardOpenOption.*;
20+
21+
@SuppressWarnings("unused")
22+
public class ConfigureGradleEnterprise implements GradleEnterpriseListener {
23+
24+
private static final String EXPERIMENT_DIR = System.getProperty("com.gradle.enterprise.build-validation.expDir");
25+
26+
private final Logger logger;
27+
28+
@Inject
29+
public ConfigureGradleEnterprise(Logger logger) {
30+
this.logger = logger;
31+
}
32+
33+
@Override
34+
public void configure(GradleEnterpriseApi api, MavenSession session) {
35+
logger.debug("Configuring build scan published event...");
36+
37+
BuildScanApi buildScan = api.getBuildScan();
38+
39+
String geUrl = System.getProperty("gradle.enterprise.url");
40+
String geAllowUntrustedServer = System.getProperty("gradle.enterprise.allowUntrustedServer");
41+
42+
if (geUrl != null && !geUrl.isEmpty()) {
43+
buildScan.setServer(geUrl);
44+
}
45+
if (geAllowUntrustedServer != null && !geAllowUntrustedServer.isEmpty()) {
46+
buildScan.setAllowUntrustedServer(Boolean.parseBoolean(geAllowUntrustedServer));
47+
}
48+
49+
registerBuildScanActions(buildScan);
50+
configureBuildScanPublishing(buildScan);
51+
}
52+
53+
private static void registerBuildScanActions(BuildScanApi buildScan) {
54+
buildScan.buildFinished(buildResult -> {
55+
// communicate via error file that no GE server is set
56+
boolean omitServerUrlValidation = parseBoolean(System.getProperty("com.gradle.enterprise.build-validation.omitServerUrlValidation"));
57+
if (buildScan.getServer() == null && !omitServerUrlValidation) {
58+
buildScan.publishAlwaysIf(false); // disable publishing, otherwise scans.gradle.com will be used
59+
File errorFile = new File(EXPERIMENT_DIR, "errors.txt");
60+
append(errorFile, "The Gradle Enterprise server URL has not been configured in the project or on the command line.");
61+
}
62+
});
63+
64+
buildScan.buildFinished(buildResult -> {
65+
String expId = System.getProperty("com.gradle.enterprise.build-validation.expId");
66+
addCustomValueAndSearchLink(buildScan, "Experiment id", expId);
67+
buildScan.tag(expId);
68+
69+
String runId = System.getProperty("com.gradle.enterprise.build-validation.runId");
70+
addCustomValueAndSearchLink(buildScan, "Experiment run id", runId);
71+
72+
String scriptsVersion = System.getProperty("com.gradle.enterprise.build-validation.scriptsVersion");
73+
buildScan.value("Build validation scripts", scriptsVersion);
74+
});
75+
76+
buildScan.buildScanPublished(scan -> {
77+
String runNum = System.getProperty("com.gradle.enterprise.build-validation.runNum");
78+
URI buildScanUri = scan.getBuildScanUri();
79+
String buildScanId = scan.getBuildScanId();
80+
String port = buildScanUri.getPort() != -1 ? ":" + buildScanUri.getPort() : "";
81+
String baseUrl = String.format("%s://%s%s", buildScanUri.getScheme(), buildScanUri.getHost(), port);
82+
83+
File scanFile = new File(EXPERIMENT_DIR, "build-scans.csv");
84+
append(scanFile, String.format("%s,%s,%s,%s\n", runNum, baseUrl, buildScanUri, buildScanId));
85+
});
86+
}
87+
88+
private static void configureBuildScanPublishing(BuildScanApi buildScan) {
89+
buildScan.publishAlways();
90+
buildScan.capture(t -> t.setGoalInputFiles(true)); // also set via sys prop
91+
buildScan.setUploadInBackground(false);
92+
}
93+
94+
private static void addCustomValueAndSearchLink(BuildScanApi buildScan, String label, String value) {
95+
buildScan.value(label, value);
96+
if (buildScan.getServer() != null) {
97+
String server = buildScan.getServer();
98+
String searchParams = "search.names=" + urlEncode(label) + "&search.values=" + urlEncode(value);
99+
String url = appendIfMissing(server, "/") + "scans?" + searchParams + "#selection.buildScanB=" + urlEncode("{SCAN_ID}");
100+
buildScan.link(label + " build scans", url);
101+
}
102+
}
103+
104+
private static String appendIfMissing(String str, String suffix) {
105+
return str.endsWith(suffix) ? str : str + suffix;
106+
}
107+
108+
private static String urlEncode(String str) {
109+
try {
110+
return URLEncoder.encode(str, StandardCharsets.UTF_8.name());
111+
} catch (UnsupportedEncodingException e) {
112+
throw new RuntimeException(e);
113+
}
114+
}
115+
116+
private static void append(File file, String text) {
117+
try {
118+
Files.write(file.toPath(), text.getBytes(), CREATE, WRITE, APPEND);
119+
} catch (IOException e) {
120+
throw new RuntimeException(String.format("Unable to write to file %s: %s", file.getName(), e.getMessage()), e);
121+
}
122+
}
123+
124+
}

components/capture-build-scan-url-maven-extension/src/main/resources/META-INF/plexus/components.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
<components>
33
<component>
44
<role>com.gradle.maven.extension.api.GradleEnterpriseListener</role>
5-
<role-hint>capture-build-scan-url</role-hint>
6-
<implementation>com.gradle.CaptureBuildScansListener</implementation>
7-
<description>Captures the build scan URL from Maven builds</description>
5+
<role-hint>configure-gradle-enterprise</role-hint>
6+
<implementation>com.gradle.ConfigureGradleEnterprise</implementation>
7+
<description>Configures Gradle Enterprise</description>
88
<isolated-realm>false</isolated-realm>
99
</component>
1010
</components>

components/scripts/gradle/gradle-init-scripts/configure-gradle-enterprise.gradle

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import org.gradle.util.GradleVersion
22
import java.nio.charset.StandardCharsets
33

4+
import static java.lang.Boolean.parseBoolean
5+
46
// note that there is no mechanism to share code between the initscript{} block and the main script, so some logic is duplicated
57

68
// conditionally apply the GE / Build Scan plugin to the classpath so it can be applied to the build further down in this script
@@ -73,15 +75,15 @@ def getInputParam = { String name ->
7375
// the following local variables do not change between the build invocations of the same experiment run
7476
// thus, reading their values in way that the configuration cache does not track them is acceptable
7577
def geUrl = getInputParam('com.gradle.enterprise.build-validation.gradle-enterprise.url')
76-
def geAllowUntrustedServer = Boolean.parseBoolean(getInputParam('com.gradle.enterprise.build-validation.gradle-enterprise.allow-untrusted-server'))
78+
def geAllowUntrustedServer = getInputParam('com.gradle.enterprise.build-validation.gradle-enterprise.allow-untrusted-server')
7779
def gePluginVersion = getInputParam('com.gradle.enterprise.build-validation.gradle-enterprise.plugin.version')
7880
def ccudPluginVersion = getInputParam('com.gradle.enterprise.build-validation.ccud.plugin.version')
7981

8082
def expDir = getInputParam('com.gradle.enterprise.build-validation.expDir')
8183
def expId = getInputParam('com.gradle.enterprise.build-validation.expId')
8284
def runId = getInputParam('com.gradle.enterprise.build-validation.runId')
8385
def scriptsVersion = getInputParam('com.gradle.enterprise.build-validation.scriptsVersion')
84-
def omitServerUrlValidation = Boolean.parseBoolean(getInputParam('com.gradle.enterprise.build-validation.omitServerUrlValidation'))
86+
def omitServerUrlValidation = parseBoolean(getInputParam('com.gradle.enterprise.build-validation.omitServerUrlValidation'))
8587

8688
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
8789

@@ -171,7 +173,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
171173
logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
172174
pluginManager.apply(initscript.classLoader.loadClass(BUILD_SCAN_PLUGIN_CLASS))
173175
if (geUrl) buildScan.server = geUrl
174-
if (geAllowUntrustedServer) buildScan.allowUntrustedServer = geAllowUntrustedServer
176+
if (geAllowUntrustedServer) buildScan.allowUntrustedServer = parseBoolean(geAllowUntrustedServer)
175177
}
176178
} else {
177179
if (!scanPluginComponent) {
@@ -201,7 +203,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
201203
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
202204
afterEvaluate {
203205
if (geUrl) buildScan.server = geUrl
204-
if (geAllowUntrustedServer) buildScan.allowUntrustedServer = geAllowUntrustedServer
206+
if (geAllowUntrustedServer) buildScan.allowUntrustedServer = parseBoolean(geAllowUntrustedServer)
205207

206208
if (!buildScan.server && !omitServerUrlValidation) {
207209
logErrorMissingGradleEnterpriseServerURL()
@@ -211,8 +213,8 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
211213
}
212214

213215
registerBuildScanActions(buildScan)
214-
addBuildScanCustomData(buildScan)
215216
configureBuildScanPublishing(buildScan)
217+
addBuildScanCustomData(buildScan)
216218
}
217219
}
218220
}
@@ -225,7 +227,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
225227
settings.pluginManager.apply(initscript.classLoader.loadClass(GRADLE_ENTERPRISE_PLUGIN_CLASS))
226228
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
227229
if (geUrl) ext.server = geUrl
228-
if (geAllowUntrustedServer) ext.allowUntrustedServer = geAllowUntrustedServer
230+
if (geAllowUntrustedServer) ext.allowUntrustedServer = parseBoolean(geAllowUntrustedServer)
229231
}
230232
}
231233
} else {
@@ -250,7 +252,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
250252

251253
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
252254
if (geUrl) ext.server = geUrl
253-
if (geAllowUntrustedServer) ext.allowUntrustedServer = geAllowUntrustedServer
255+
if (geAllowUntrustedServer) ext.allowUntrustedServer = parseBoolean(geAllowUntrustedServer)
254256

255257
if (!ext.server && !omitServerUrlValidation) {
256258
logErrorMissingGradleEnterpriseServerURL()
@@ -260,8 +262,8 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
260262
}
261263

262264
registerBuildScanActions(ext.buildScan)
263-
addBuildScanCustomData(ext.buildScan)
264265
configureBuildScanPublishing(ext.buildScan)
266+
addBuildScanCustomData(ext.buildScan)
265267
}
266268
}
267269
}

components/scripts/lib/maven.sh

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,13 @@ invoke_maven() {
4646
done
4747
fi
4848

49-
if [ "$build_scan_publishing_mode" == "on" ]; then
50-
args+=("-Dscan")
51-
else
49+
if [ -n "${ge_server}" ]; then
50+
args+=("-Dgradle.enterprise.url=${ge_server}")
51+
args+=("-Dgradle.enterprise.allowUntrustedServer=false")
52+
fi
53+
54+
if [[ "${build_scan_publishing_mode}" == "off" ]]; then
55+
args+=("-Dcom.gradle.enterprise.build-validation.omitServerUrlValidation=true")
5256
args+=("-Dscan.dump")
5357
fi
5458

@@ -62,10 +66,6 @@ invoke_maven() {
6266
-Dgradle.scan.captureGoalInputFiles=true
6367
)
6468

65-
if [ -n "${ge_server}" ]; then
66-
args+=("-Dgradle.enterprise.url=${ge_server}")
67-
fi
68-
6969
# https://stackoverflow.com/a/31485948
7070
while IFS= read -r -d ''; do
7171
local extra_arg="$REPLY"
@@ -76,8 +76,11 @@ invoke_maven() {
7676

7777
args+=("$@")
7878

79+
rm -f "${EXP_DIR}/errors.txt"
80+
7981
debug "Current directory: $(pwd)"
8082
debug "${mvn}" "${args[@]}"
83+
8184
if ${mvn} "${args[@]}"; then
8285
build_outcomes+=("SUCCESSFUL")
8386
else
@@ -87,12 +90,12 @@ invoke_maven() {
8790
if [ -f "${EXP_DIR}/errors.txt" ]; then
8891
print_bl
8992
die "ERROR: Experiment aborted due to a non-recoverable failure: $(cat "${EXP_DIR}/errors.txt")"
90-
fi
93+
fi
9194

92-
if [[ "${build_scan_publishing_mode}" == "on" ]] && is_build_scan_metadata_missing "$run_num"; then
95+
if [[ "${build_scan_publishing_mode}" == "on" ]] && is_build_scan_metadata_missing "$run_num"; then
9396
print_bl
9497
die "ERROR: Experiment aborted due to a non-recoverable failure: No Build Scan was published."
95-
fi
98+
fi
9699

97100
# defined in git.sh
98101
read_git_metadata_from_current_repo

0 commit comments

Comments
 (0)