Skip to content

Commit a3f0dad

Browse files
authored
Merge branch 'main' into erichaagdev/display-potential-build-time-savings
2 parents 9e73951 + 322d555 commit a3f0dad

File tree

7 files changed

+148
-107
lines changed

7 files changed

+148
-107
lines changed

buildSrc/build.gradle.kts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ plugins {
55
kotlin {
66
jvmToolchain {
77
languageVersion.set(JavaLanguageVersion.of(8))
8-
9-
// Azul has been chosen due to its wide range of supported platforms for
10-
// Java 8, including arm64 for macOS.
11-
// See: https://foojay.io/almanac/jdk-8
128
vendor.set(JvmVendorSpec.AZUL)
139
}
1410
}

components/capture-build-scan-url-maven-extension/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ description = "Maven extension to capture the build scan URL"
1717
java {
1818
toolchain {
1919
languageVersion.set(JavaLanguageVersion.of(8))
20+
vendor.set(JvmVendorSpec.AZUL)
2021
}
2122
}
2223

components/fetch-build-scan-data-cmdline-tool/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ dependencies {
3030
java {
3131
toolchain {
3232
languageVersion.set(JavaLanguageVersion.of(8))
33+
vendor.set(JvmVendorSpec.AZUL)
3334
}
3435
}
3536

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

Lines changed: 136 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import org.gradle.util.GradleVersion
2-
import java.nio.charset.StandardCharsets;
3-
4-
if (GradleVersion.current() < GradleVersion.version("5.0")) {
5-
throw new IllegalStateException("The Gradle Enterprise Build Validation Scripts are not supported with Gradle ${GradleVersion.current()}. Please upgrade your project's build to Gradle 5 or newer.")
6-
}
2+
import java.nio.charset.StandardCharsets
73

84
// note that there is no mechanism to share code between the initscript{} block and the main script, so some logic is duplicated
95

@@ -14,21 +10,35 @@ initscript {
1410
return
1511
}
1612

17-
def enableGradleEnterprise = Boolean.getBoolean("com.gradle.enterprise.build_validation.enableGradleEnterprise")
13+
def getInputParam = { String name ->
14+
def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_')
15+
return System.getProperty(name) ?: System.getenv(envVarName)
16+
}
17+
18+
def pluginRepositoryUrl = getInputParam('com.gradle.enterprise.build_validation.gradle.plugin-repository.url')
19+
def gePluginVersion = getInputParam('com.gradle.enterprise.build_validation.gradle-enterprise.plugin.version')
20+
def ccudPluginVersion = getInputParam('com.gradle.enterprise.build_validation.ccud.plugin.version')
21+
22+
def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0')
23+
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
1824

19-
def gePluginVersion = enableGradleEnterprise ? "3.12.4" : null
20-
def ccudPluginVersion = enableGradleEnterprise ? "1.9" : null
25+
if (gePluginVersion || ccudPluginVersion && atLeastGradle4) {
26+
pluginRepositoryUrl = pluginRepositoryUrl ?: 'https://plugins.gradle.org/m2'
27+
logger.quiet("Gradle Enterprise plugins resolution: $pluginRepositoryUrl")
2128

22-
repositories {
23-
gradlePluginPortal()
29+
repositories {
30+
maven { url pluginRepositoryUrl }
31+
}
2432
}
2533

2634
dependencies {
2735
if (gePluginVersion) {
28-
classpath "com.gradle:gradle-enterprise-gradle-plugin:$gePluginVersion"
36+
classpath atLeastGradle5 ?
37+
"com.gradle:gradle-enterprise-gradle-plugin:$gePluginVersion" :
38+
"com.gradle:build-scan-plugin:1.16"
2939
}
3040

31-
if (ccudPluginVersion) {
41+
if (ccudPluginVersion && atLeastGradle4) {
3242
classpath "com.gradle:common-custom-user-data-gradle-plugin:$ccudPluginVersion"
3343
}
3444
}
@@ -49,94 +59,152 @@ if (!isTopLevelBuild) {
4959
return
5060
}
5161

52-
def enableGradleEnterprise = Boolean.getBoolean("com.gradle.enterprise.build_validation.enableGradleEnterprise")
53-
def isScanDump = System.properties.containsKey("scan.dump")
62+
def getInputParam = { String name ->
63+
def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_')
64+
return System.getProperty(name) ?: System.getenv(envVarName)
65+
}
5466

55-
clearWarnings()
67+
def geUrl = getInputParam('com.gradle.enterprise.build_validation.gradle-enterprise.url')
68+
def geAllowUntrustedServer = Boolean.parseBoolean(getInputParam('com.gradle.enterprise.build_validation.gradle-enterprise.allow-untrusted-server'))
69+
def gePluginVersion = getInputParam('com.gradle.enterprise.build_validation.gradle-enterprise.plugin.version')
70+
def ccudPluginVersion = getInputParam('com.gradle.enterprise.build_validation.ccud.plugin.version')
5671

57-
// define a buildScanPublished listener that captures the build scan data and appends to a file
58-
def buildScanPublishedAction = { def buildScan ->
59-
if (buildScan.metaClass.respondsTo(buildScan, 'buildScanPublished', Action)) {
60-
def scanFile = new File(experimentDir, "build-scans.csv")
61-
buildScan.buildScanPublished { publishedBuildScan ->
62-
def buildScanUri = publishedBuildScan.buildScanUri
63-
def buildScanId = publishedBuildScan.buildScanId
64-
def port = (buildScanUri.port != -1) ? ":" + buildScanUri.port : ""
65-
def baseUrl = "${buildScanUri.scheme}://${buildScanUri.host}${port}"
66-
scanFile.append("${baseUrl},${buildScanUri},${buildScanId}\n")
67-
}
68-
def errorFile = new File(experimentDir, "build-scan-publish-error.txt")
69-
buildScan.onError { error ->
70-
errorFile.text = error
71-
}
72+
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
73+
74+
// finish early if configuration parameters passed in via system properties are not valid/supported
75+
if (ccudPluginVersion && isNotAtLeast(ccudPluginVersion, '1.7')) {
76+
logger.warn("Common Custom User Data Gradle plugin must be at least 1.7. Configured version is $ccudPluginVersion.")
77+
return
78+
}
79+
80+
// register build scan listeners to capture build scan URL/id and to track publishing errors
81+
def registerBuildScanActions = { def buildScan ->
82+
def scanFile = new File(experimentDir, 'build-scans.csv')
83+
buildScan.buildScanPublished { publishedBuildScan ->
84+
def buildScanUri = publishedBuildScan.buildScanUri
85+
def buildScanId = publishedBuildScan.buildScanId
86+
def port = (buildScanUri.port != -1) ? ':' + buildScanUri.port : ''
87+
def baseUrl = "${buildScanUri.scheme}://${buildScanUri.host}${port}"
88+
scanFile.append("${baseUrl},${buildScanUri},${buildScanId}\n")
89+
}
90+
91+
def errorFile = new File(experimentDir, 'build-scan-publish-error.txt')
92+
buildScan.onError { error ->
93+
errorFile.text = error
7294
}
7395
}
7496

75-
// register buildScanPublished listener and optionally apply the GE / Build Scan plugin
97+
// configure build scan publishing behavior
98+
def configureBuildScanPublishing = { def buildScan ->
99+
buildScan.publishAlways()
100+
// buildScan.captureTaskInputFiles = true // too late to be set here for Gradle 5, set via sys prop
101+
if (buildScan.metaClass.respondsTo(buildScan, 'setUploadInBackground', Boolean)) buildScan.uploadInBackground = false // uploadInBackground not available for build-scan-plugin 1.16
102+
}
103+
104+
// add custom data identifying the experiment
105+
def addBuildScanCustomData = { def buildScan ->
106+
def projectProperties = gradle.startParameter.projectProperties
107+
108+
def expId = projectProperties.get("com.gradle.enterprise.build_validation.expId")
109+
addCustomValueAndSearchLink(buildScan, "Experiment id", expId)
110+
buildScan.tag(expId)
111+
112+
def runId = projectProperties.get("com.gradle.enterprise.build_validation.runId")
113+
addCustomValueAndSearchLink(buildScan, "Experiment run id", runId)
114+
}
115+
116+
// configure build scan behavior and optionally apply the GE / Build Scan / CCUD plugin
76117
if (GradleVersion.current() < GradleVersion.version('6.0')) {
118+
//noinspection GroovyAssignabilityCheck
77119
rootProject {
78120
buildscript.configurations.getByName("classpath").incoming.afterResolve { ResolvableDependencies incoming ->
79121
def resolutionResult = incoming.resolutionResult
80122

81123
def scanPluginComponent = resolutionResult.allComponents.find {
82124
it.moduleVersion.with { group == "com.gradle" && (name == "build-scan-plugin" || name == "gradle-enterprise-gradle-plugin") }
83125
}
84-
if (!scanPluginComponent) {
85-
if (enableGradleEnterprise) {
126+
127+
if (gePluginVersion) {
128+
if (!scanPluginComponent) {
129+
logger.quiet("Applying $BUILD_SCAN_PLUGIN_CLASS via init script")
130+
logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
86131
pluginManager.apply(initscript.classLoader.loadClass(BUILD_SCAN_PLUGIN_CLASS))
87-
} else {
132+
if (geUrl) buildScan.server = geUrl
133+
if (geAllowUntrustedServer) buildScan.allowUntrustedServer = geAllowUntrustedServer
134+
}
135+
} else {
136+
if (!scanPluginComponent) {
88137
throw new IllegalStateException("The com.gradle.build-scan plugin is missing from the project.\n" +
89-
"Either apply it directly (see https://docs.gradle.com/enterprise/gradle-plugin/#gradle_5_x),\n" +
90-
"or use `--enable-gradle-enterprise` when running the build validation script.")
138+
"Either apply it directly (see https://docs.gradle.com/enterprise/gradle-plugin/#gradle_5_x) to the project,\n" +
139+
"or use `--enable-gradle-enterprise` when running the build validation script.")
91140
}
92141
}
93142

94143
def ccudPluginComponent = resolutionResult.allComponents.find {
95144
it.moduleVersion.with { group == "com.gradle" && name == "common-custom-user-data-gradle-plugin" }
96145
}
97-
if (!ccudPluginComponent) {
98-
if (enableGradleEnterprise) {
146+
147+
if (ccudPluginVersion && atLeastGradle4) {
148+
if (!ccudPluginComponent) {
149+
logger.quiet("Applying $CCUD_PLUGIN_CLASS via init script")
99150
pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
100-
} else {
151+
}
152+
} else {
153+
if (!ccudPluginComponent) {
101154
logWarningMissingCommonCustomUserDataGradlePlugin()
102155
}
103156
}
104157
}
105158

106159
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
107-
buildScanPublishedAction(buildScan)
108-
}
109-
}
160+
afterEvaluate {
161+
if (geUrl) buildScan.server = geUrl
162+
if (geAllowUntrustedServer) buildScan.allowUntrustedServer = geAllowUntrustedServer
110163

111-
if (!isScanDump) {
112-
projectsEvaluated { gradle ->
113-
configureGradleEnterprise(gradle.rootProject.extensions["gradleEnterprise"])
164+
registerBuildScanActions(buildScan)
165+
addBuildScanCustomData(buildScan)
166+
configureBuildScanPublishing(buildScan)
167+
}
114168
}
115169
}
116170
} else {
117171
gradle.settingsEvaluated { settings ->
118-
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID)) {
119-
if (enableGradleEnterprise) {
172+
if (gePluginVersion) {
173+
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID)) {
174+
logger.quiet("Applying $GRADLE_ENTERPRISE_PLUGIN_CLASS via init script")
175+
logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
120176
settings.pluginManager.apply(initscript.classLoader.loadClass(GRADLE_ENTERPRISE_PLUGIN_CLASS))
121-
} else {
177+
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
178+
if (geUrl) ext.server = geUrl
179+
if (geAllowUntrustedServer) ext.allowUntrustedServer = geAllowUntrustedServer
180+
}
181+
}
182+
} else {
183+
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID)) {
122184
throw new IllegalStateException("The com.gradle.enterprise plugin is missing from the project.\n" +
123-
"Either apply it directly (see https://docs.gradle.com/enterprise/gradle-plugin/#gradle_6_x_and_later),\n" +
124-
"or use `--enable-gradle-enterprise` when running the build validation script.")
185+
"Either apply it directly (see https://docs.gradle.com/enterprise/gradle-plugin/#gradle_6_x_and_later),\n" +
186+
"or use `--enable-gradle-enterprise` when running the build validation script.")
125187
}
126188
}
127-
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
128-
if (enableGradleEnterprise) {
189+
190+
if (ccudPluginVersion) {
191+
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
192+
logger.quiet("Applying $CCUD_PLUGIN_CLASS via init script")
129193
settings.pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
130-
} else {
194+
}
195+
} else {
196+
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
131197
logWarningMissingCommonCustomUserDataGradlePlugin()
132198
}
133199
}
134200

135201
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
136-
if (!isScanDump) {
137-
configureGradleEnterprise(ext)
138-
}
139-
buildScanPublishedAction(ext.buildScan)
202+
if (geUrl) ext.server = geUrl
203+
if (geAllowUntrustedServer) ext.allowUntrustedServer = geAllowUntrustedServer
204+
205+
registerBuildScanActions(ext.buildScan)
206+
addBuildScanCustomData(ext.buildScan)
207+
configureBuildScanPublishing(ext.buildScan)
140208
}
141209
}
142210
}
@@ -145,48 +213,25 @@ static def extensionsWithPublicType(def container, String publicType) {
145213
container.extensions.extensionsSchema.elements.findAll { it.publicType.concreteClass.name == publicType }
146214
}
147215

148-
void configureGradleEnterprise(gradleEnterprise) {
149-
gradleEnterprise.with {
150-
def serverOverride = System.getProperty("com.gradle.enterprise.build_validation.server")
151-
if (serverOverride) {
152-
server = serverOverride
153-
} else if (!server) {
154-
throw new IllegalStateException("A Gradle Enterprise server URL has not been configured.", null)
155-
}
156-
157-
buildScan {
158-
// captureTaskInputFiles = true (too late to be set here for Gradle 5, set via sys prop)
159-
uploadInBackground = false
160-
publishAlways()
161-
}
162-
addCustomData(buildScan)
163-
}
164-
}
165-
166-
void addCustomData(buildScan) {
167-
def projectProperties = gradle.startParameter.projectProperties
168-
169-
def expId = projectProperties.get("com.gradle.enterprise.build_validation.expId")
170-
addCustomValueAndSearchLink(buildScan, "Experiment id", expId)
171-
buildScan.tag(expId)
172-
173-
def runId = projectProperties.get("com.gradle.enterprise.build_validation.runId")
174-
addCustomValueAndSearchLink(buildScan, "Experiment run id", runId)
216+
static boolean isNotAtLeast(String versionUnderTest, String referenceVersion) {
217+
GradleVersion.version(versionUnderTest) < GradleVersion.version(referenceVersion)
175218
}
176219

177-
void addCustomValueAndSearchLink(buildScan, String label, String value) {
220+
static void addCustomValueAndSearchLink(buildScan, String label, String value) {
178221
buildScan.value(label, value)
179-
String server = buildScan.server
180-
String searchParams = "search.names=" + urlEncode(label) + "&search.values=" + urlEncode(value)
181-
String url = appendIfMissing(server, "/") + "scans?" + searchParams + "#selection.buildScanB=" + urlEncode("{SCAN_ID}")
182-
buildScan.link(label + " build scans", url)
222+
if (buildScan.metaClass.respondsTo(buildScan, 'getServer')) { // required for Gradle 4.x / build-scan-plugin 1.16
223+
String server = buildScan.server
224+
String searchParams = "search.names=" + urlEncode(label) + "&search.values=" + urlEncode(value)
225+
String url = appendIfMissing(server, "/") + "scans?" + searchParams + "#selection.buildScanB=" + urlEncode("{SCAN_ID}")
226+
buildScan.link(label + " build scans", url)
227+
}
183228
}
184229

185-
String appendIfMissing(String str, String suffix) {
230+
static String appendIfMissing(String str, String suffix) {
186231
return str.endsWith(suffix) ? str : str + suffix
187232
}
188233

189-
String urlEncode(String str) {
234+
static String urlEncode(String str) {
190235
return URLEncoder.encode(str, StandardCharsets.UTF_8.name())
191236
}
192237

@@ -199,11 +244,6 @@ void logWarning(String warning) {
199244
warningFile.append(warning + "\n")
200245
}
201246

202-
void clearWarnings() {
203-
def warningFile = new File(experimentDir, "warnings.txt")
204-
warningFile.delete()
205-
}
206-
207247
File getExperimentDir() {
208248
def projectProperties = gradle.startParameter.projectProperties
209249
new File(projectProperties.get("com.gradle.enterprise.build_validation.experimentDir"))

components/scripts/lib/gradle.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ invoke_gradle() {
1313
args+=(--init-script "${INIT_SCRIPTS_DIR}/configure-gradle-enterprise.gradle")
1414

1515
if [ "$enable_ge" == "on" ]; then
16-
args+=("-Dcom.gradle.enterprise.build_validation.enableGradleEnterprise=true")
16+
args+=("-Dcom.gradle.enterprise.build_validation.gradle.plugin-repository.url=https://plugins.gradle.org/m2")
17+
args+=("-Dcom.gradle.enterprise.build_validation.gradle-enterprise.plugin.version=3.12.4")
18+
args+=("-Dcom.gradle.enterprise.build_validation.ccud.plugin.version=1.9")
1719
fi
1820

1921
if [ -n "${ge_server}" ]; then
20-
args+=("-Dcom.gradle.enterprise.build_validation.server=${ge_server}")
22+
args+=("-Dcom.gradle.enterprise.build_validation.gradle-enterprise.url=${ge_server}")
23+
args+=("-Dcom.gradle.enterprise.build_validation.gradle-enterprise.allow-untrusted-server=false")
2124
fi
2225

2326
if [[ "${build_scan_publishing_mode}" == "off" ]]; then

components/scripts/lib/info.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ print_performance_characteristics() {
152152
print_performance_characteristics_header() {
153153
print_bl
154154
info "Performance Characteristics"
155-
info "----------------------"
155+
info "---------------------------"
156156
}
157157

158158
print_realized_build_time_savings() {
@@ -241,7 +241,7 @@ print_serialization_factor() {
241241
# Do not print serialization factor at all if this value does not exist
242242
# This can happen since build-scan-support-tool does not yet support this field
243243
if [[ -n "${serialization_factors[0]}" ]]; then
244-
summary_row "Serialization factor:" "$(to_two_decimal_places "${serialization_factors[0]}")"
244+
summary_row "Serialization factor:" "$(to_two_decimal_places "${serialization_factors[0]}")x"
245245
fi
246246
}
247247

@@ -324,5 +324,5 @@ format_duration() {
324324
# Rounds the argument to two decimal places
325325
# See: https://unix.stackexchange.com/a/167059
326326
to_two_decimal_places() {
327-
echo "$1" | LC_ALL=C xargs printf "%.2f"
327+
LC_ALL=C printf "%.2f" "$1"
328328
}

0 commit comments

Comments
 (0)