Skip to content

Commit c6d6970

Browse files
authored
Merge pull request #264 from gradle/erichaagdev/init-script-cleanup
Gradle init script improvements
2 parents b60e6d6 + 687a9c3 commit c6d6970

File tree

4 files changed

+205
-166
lines changed

4 files changed

+205
-166
lines changed

components/scripts/gradle/gradle-init-scripts/capture-published-build-scan.gradle

Lines changed: 0 additions & 51 deletions
This file was deleted.

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

Lines changed: 197 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,237 @@
11
import org.gradle.util.GradleVersion
2-
import java.nio.charset.StandardCharsets;
2+
import java.nio.charset.StandardCharsets
33

4+
// note that there is no mechanism to share code between the initscript{} block and the main script, so some logic is duplicated
5+
6+
// conditionally apply the GE / Build Scan plugin to the classpath so it can be applied to the build further down in this script
47
initscript {
5-
def gradleEnterprisePluginVersion = "3.12.4"
8+
def isTopLevelBuild = !gradle.parent
9+
if (!isTopLevelBuild) {
10+
return
11+
}
612

7-
repositories {
8-
gradlePluginPortal()
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')
24+
25+
if (gePluginVersion || ccudPluginVersion && atLeastGradle4) {
26+
pluginRepositoryUrl = pluginRepositoryUrl ?: 'https://plugins.gradle.org/m2'
27+
logger.quiet("Gradle Enterprise plugins resolution: $pluginRepositoryUrl")
28+
29+
repositories {
30+
maven { url pluginRepositoryUrl }
31+
}
932
}
1033

1134
dependencies {
12-
classpath("com.gradle:gradle-enterprise-gradle-plugin:${gradleEnterprisePluginVersion}")
35+
if (gePluginVersion) {
36+
classpath atLeastGradle5 ?
37+
"com.gradle:gradle-enterprise-gradle-plugin:$gePluginVersion" :
38+
"com.gradle:build-scan-plugin:1.16"
39+
}
40+
41+
if (ccudPluginVersion && atLeastGradle4) {
42+
classpath "com.gradle:common-custom-user-data-gradle-plugin:$ccudPluginVersion"
43+
}
1344
}
1445
}
1546

16-
// Don't run against the included builds (if the main build has any).
17-
def isTopLevelBuild = gradle.getParent() == null
18-
if (isTopLevelBuild) {
19-
def version = GradleVersion.current().baseVersion
20-
def atLeastGradle5 = version >= GradleVersion.version("5.0")
21-
def atLeastGradle6 = version >= GradleVersion.version("6.0")
22-
def isScanDump = System.properties.containsKey("scan.dump")
47+
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
48+
def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin'
49+
50+
def GRADLE_ENTERPRISE_PLUGIN_ID = 'com.gradle.enterprise'
51+
def GRADLE_ENTERPRISE_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin'
52+
def GRADLE_ENTERPRISE_EXTENSION_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterpriseExtension'
53+
54+
def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin'
55+
def CCUD_PLUGIN_CLASS = 'com.gradle.CommonCustomUserDataGradlePlugin'
56+
57+
def isTopLevelBuild = !gradle.parent
58+
if (!isTopLevelBuild) {
59+
return
60+
}
61+
62+
def getInputParam = { String name ->
63+
def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_')
64+
return System.getProperty(name) ?: System.getenv(envVarName)
65+
}
66+
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')
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
94+
}
95+
}
96+
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
117+
if (GradleVersion.current() < GradleVersion.version('6.0')) {
118+
//noinspection GroovyAssignabilityCheck
119+
rootProject {
120+
buildscript.configurations.getByName("classpath").incoming.afterResolve { ResolvableDependencies incoming ->
121+
def resolutionResult = incoming.resolutionResult
23122

24-
clearWarnings()
123+
def scanPluginComponent = resolutionResult.allComponents.find {
124+
it.moduleVersion.with { group == "com.gradle" && (name == "build-scan-plugin" || name == "gradle-enterprise-gradle-plugin") }
125+
}
25126

26-
if (atLeastGradle6) {
27-
settingsEvaluated { settings ->
28-
if (!settings.pluginManager.hasPlugin("com.gradle.enterprise")) {
29-
throw new IllegalStateException("The com.gradle.enterprise plugin is missing from the project (see https://docs.gradle.com/enterprise/gradle-plugin/#gradle_6_x_and_later).")
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")
131+
pluginManager.apply(initscript.classLoader.loadClass(BUILD_SCAN_PLUGIN_CLASS))
132+
if (geUrl) buildScan.server = geUrl
133+
if (geAllowUntrustedServer) buildScan.allowUntrustedServer = geAllowUntrustedServer
134+
}
135+
} else {
136+
if (!scanPluginComponent) {
137+
throw new IllegalStateException("The com.gradle.build-scan plugin is missing from the project.\n" +
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.")
140+
}
30141
}
31-
if (!settings.pluginManager.hasPlugin("com.gradle.common-custom-user-data-gradle-plugin")) {
32-
logWarningMissingCommonCustomUserDataGradlePlugin()
142+
143+
def ccudPluginComponent = resolutionResult.allComponents.find {
144+
it.moduleVersion.with { group == "com.gradle" && name == "common-custom-user-data-gradle-plugin" }
33145
}
34-
if (!isScanDump) {
35-
configureGradleEnterprise(settings.extensions["gradleEnterprise"])
146+
147+
if (ccudPluginVersion && atLeastGradle4) {
148+
if (!ccudPluginComponent) {
149+
logger.quiet("Applying $CCUD_PLUGIN_CLASS via init script")
150+
pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
151+
}
152+
} else {
153+
if (!ccudPluginComponent) {
154+
logWarningMissingCommonCustomUserDataGradlePlugin()
155+
}
36156
}
37157
}
38-
} else if (atLeastGradle5) {
39-
projectsEvaluated { gradle ->
40-
if (!gradle.rootProject.pluginManager.hasPlugin("com.gradle.build-scan")) {
41-
throw new IllegalStateException("The com.gradle.build-scan plugin is missing from the project (see https://docs.gradle.com/enterprise/gradle-plugin/#gradle_5_x).")
158+
159+
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
160+
afterEvaluate {
161+
if (geUrl) buildScan.server = geUrl
162+
if (geAllowUntrustedServer) buildScan.allowUntrustedServer = geAllowUntrustedServer
163+
164+
registerBuildScanActions(buildScan)
165+
addBuildScanCustomData(buildScan)
166+
configureBuildScanPublishing(buildScan)
42167
}
43-
if (!gradle.rootProject.pluginManager.hasPlugin("com.gradle.common-custom-user-data-gradle-plugin")) {
44-
logWarningMissingCommonCustomUserDataGradlePlugin()
168+
}
169+
}
170+
} else {
171+
gradle.settingsEvaluated { settings ->
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")
176+
settings.pluginManager.apply(initscript.classLoader.loadClass(GRADLE_ENTERPRISE_PLUGIN_CLASS))
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+
}
45181
}
46-
if (!isScanDump) {
47-
configureGradleEnterprise(gradle.rootProject.extensions["gradleEnterprise"])
182+
} else {
183+
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID)) {
184+
throw new IllegalStateException("The com.gradle.enterprise plugin is missing from the project.\n" +
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.")
48187
}
49188
}
50-
} else {
51-
throw new IllegalStateException("Build validation not supported for Gradle ${GradleVersion.current()}. Upgrade your project's build to Gradle 5 or newer.")
52-
}
53-
}
54189

55-
void configureGradleEnterprise(gradleEnterprise) {
56-
gradleEnterprise.with {
57-
buildScan {
58-
def projectProperties = gradle.startParameter.projectProperties
59-
if (projectProperties.containsKey("com.gradle.enterprise.build_validation.server")) {
60-
server = projectProperties.get("com.gradle.enterprise.build_validation.server")
190+
if (ccudPluginVersion) {
191+
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
192+
logger.quiet("Applying $CCUD_PLUGIN_CLASS via init script")
193+
settings.pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
61194
}
62-
63-
if (!server) {
64-
throw new IllegalStateException("A Gradle Enterprise server URL has not been configured.", null)
195+
} else {
196+
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
197+
logWarningMissingCommonCustomUserDataGradlePlugin()
65198
}
199+
}
200+
201+
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
202+
if (geUrl) ext.server = geUrl
203+
if (geAllowUntrustedServer) ext.allowUntrustedServer = geAllowUntrustedServer
66204

67-
// captureTaskInputFiles = true (too late to be set here for Gradle 5, set via sys prop)
68-
uploadInBackground = false
69-
publishAlways()
205+
registerBuildScanActions(ext.buildScan)
206+
addBuildScanCustomData(ext.buildScan)
207+
configureBuildScanPublishing(ext.buildScan)
70208
}
71-
addCustomData(buildScan)
72209
}
73210
}
74211

75-
void addCustomData(buildScan) {
76-
def projectProperties = gradle.startParameter.projectProperties
77-
78-
def expId = projectProperties.get("com.gradle.enterprise.build_validation.expId")
79-
addCustomValueAndSearchLink(buildScan, "Experiment id", expId)
80-
buildScan.tag(expId)
212+
static def extensionsWithPublicType(def container, String publicType) {
213+
container.extensions.extensionsSchema.elements.findAll { it.publicType.concreteClass.name == publicType }
214+
}
81215

82-
def runId = projectProperties.get("com.gradle.enterprise.build_validation.runId")
83-
addCustomValueAndSearchLink(buildScan, "Experiment run id", runId)
216+
static boolean isNotAtLeast(String versionUnderTest, String referenceVersion) {
217+
GradleVersion.version(versionUnderTest) < GradleVersion.version(referenceVersion)
84218
}
85219

86-
void addCustomValueAndSearchLink(buildScan, String label, String value) {
220+
static void addCustomValueAndSearchLink(buildScan, String label, String value) {
87221
buildScan.value(label, value)
88-
String server = buildScan.server
89-
String searchParams = "search.names=" + urlEncode(label) + "&search.values=" + urlEncode(value)
90-
String url = appendIfMissing(server, "/") + "scans?" + searchParams + "#selection.buildScanB=" + urlEncode("{SCAN_ID}")
91-
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+
}
92228
}
93229

94-
String appendIfMissing(String str, String suffix) {
230+
static String appendIfMissing(String str, String suffix) {
95231
return str.endsWith(suffix) ? str : str + suffix
96232
}
97233

98-
String urlEncode(String str) {
234+
static String urlEncode(String str) {
99235
return URLEncoder.encode(str, StandardCharsets.UTF_8.name())
100236
}
101237

@@ -108,11 +244,6 @@ void logWarning(String warning) {
108244
warningFile.append(warning + "\n")
109245
}
110246

111-
void clearWarnings() {
112-
def warningFile = new File(experimentDir, "warnings.txt")
113-
warningFile.delete()
114-
}
115-
116247
File getExperimentDir() {
117248
def projectProperties = gradle.startParameter.projectProperties
118249
new File(projectProperties.get("com.gradle.enterprise.build_validation.experimentDir"))

0 commit comments

Comments
 (0)