From 97d9c134b7036253faa0cda5b89f304b2fc25abd Mon Sep 17 00:00:00 2001 From: daz Date: Sun, 20 Aug 2023 13:57:18 -0600 Subject: [PATCH] Add init-script for Gradle Enterprise injection Adds a new init-script which can enable and configure the Gradle Enterprise plugin(s) for a build, without needing to modify the settings script for the project. The functionality is enabled and configured via environment variables or system properties. Not yet wired into `gradle-build-action`. --- .../inject-gradle-enterprise.init.gradle | 192 +++++++++ .../BaseInitScriptTest.groovy | 30 +- .../TestGradleEnterpriseInjection.groovy | 401 ++++++++++++++++++ 3 files changed, 613 insertions(+), 10 deletions(-) create mode 100644 src/resources/init-scripts/inject-gradle-enterprise.init.gradle create mode 100644 test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestGradleEnterpriseInjection.groovy diff --git a/src/resources/init-scripts/inject-gradle-enterprise.init.gradle b/src/resources/init-scripts/inject-gradle-enterprise.init.gradle new file mode 100644 index 0000000..5e0227e --- /dev/null +++ b/src/resources/init-scripts/inject-gradle-enterprise.init.gradle @@ -0,0 +1,192 @@ +import org.gradle.util.GradleVersion + +// note that there is no mechanism to share code between the initscript{} block and the main script, so some logic is duplicated + +// conditionally apply the GE / Build Scan plugin to the classpath so it can be applied to the build further down in this script +initscript { + def isTopLevelBuild = !gradle.parent + if (!isTopLevelBuild) { + return + } + + def getInputParam = { String name -> + def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_') + return System.getProperty(name) ?: System.getenv(envVarName) + } + + // finish early if injection is disabled + def gradleInjectionEnabled = getInputParam("gradle-enterprise-injection.enabled") + if (gradleInjectionEnabled != "true") { + return + } + + def pluginRepositoryUrl = getInputParam('gradle-enterprise-injection.plugin-repository-url') + def gePluginVersion = getInputParam('gradle-enterprise-injection.ge-plugin-version') + def ccudPluginVersion = getInputParam('gradle-enterprise-injection.ccud-plugin-version') + + def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0') + def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0') + + if (gePluginVersion || ccudPluginVersion && atLeastGradle4) { + pluginRepositoryUrl = pluginRepositoryUrl ?: 'https://plugins.gradle.org/m2' + logger.quiet("Gradle Enterprise plugins resolution: $pluginRepositoryUrl") + + repositories { + maven { url pluginRepositoryUrl } + } + } + + dependencies { + if (gePluginVersion) { + classpath atLeastGradle5 ? + "com.gradle:gradle-enterprise-gradle-plugin:$gePluginVersion" : + "com.gradle:build-scan-plugin:1.16" + } + + if (ccudPluginVersion && atLeastGradle4) { + classpath "com.gradle:common-custom-user-data-gradle-plugin:$ccudPluginVersion" + } + } +} + +def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan' +def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin' + +def GRADLE_ENTERPRISE_PLUGIN_ID = 'com.gradle.enterprise' +def GRADLE_ENTERPRISE_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin' +def GRADLE_ENTERPRISE_EXTENSION_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterpriseExtension' +def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection' +def CI_AUTO_INJECTION_CUSTOM_VALUE_VALUE = 'gradle-build-action' +def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin' +def CCUD_PLUGIN_CLASS = 'com.gradle.CommonCustomUserDataGradlePlugin' + +def isTopLevelBuild = !gradle.parent +if (!isTopLevelBuild) { + return +} + +def getInputParam = { String name -> + def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_') + return System.getProperty(name) ?: System.getenv(envVarName) +} + +// finish early if injection is disabled +def gradleInjectionEnabled = getInputParam("gradle-enterprise-injection.enabled") +if (gradleInjectionEnabled != "true") { + return +} + +def geUrl = getInputParam('gradle-enterprise-injection.server-url') +def geAllowUntrustedServer = Boolean.parseBoolean(getInputParam('gradle-enterprise-injection.allow-untrusted-server')) +def geEnforceUrl = Boolean.parseBoolean(getInputParam('gradle-enterprise-injection.enforce-server-url')) +def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('gradle-enterprise-injection.build-scan-upload-in-background')) +def gePluginVersion = getInputParam('gradle-enterprise-injection.ge-plugin-version') +def ccudPluginVersion = getInputParam('gradle-enterprise-injection.ccud-plugin-version') + +def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0') + +// finish early if configuration parameters passed in via system properties are not valid/supported +if (ccudPluginVersion && isNotAtLeast(ccudPluginVersion, '1.7')) { + logger.warn("Common Custom User Data Gradle plugin must be at least 1.7. Configured version is $ccudPluginVersion.") + return +} + +// register buildScanPublished listener and optionally apply the GE / Build Scan plugin +if (GradleVersion.current() < GradleVersion.version('6.0')) { + rootProject { + buildscript.configurations.getByName("classpath").incoming.afterResolve { ResolvableDependencies incoming -> + def resolutionResult = incoming.resolutionResult + + if (gePluginVersion) { + def scanPluginComponent = resolutionResult.allComponents.find { + it.moduleVersion.with { group == "com.gradle" && (name == "build-scan-plugin" || name == "gradle-enterprise-gradle-plugin") } + } + if (!scanPluginComponent) { + logger.quiet("Applying $BUILD_SCAN_PLUGIN_CLASS via init script") + logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") + applyPluginExternally(pluginManager, BUILD_SCAN_PLUGIN_CLASS) + buildScan.server = geUrl + buildScan.allowUntrustedServer = geAllowUntrustedServer + buildScan.publishAlways() + if (buildScan.metaClass.respondsTo(buildScan, 'setUploadInBackground', Boolean)) buildScan.uploadInBackground = buildScanUploadInBackground // uploadInBackground not available for build-scan-plugin 1.16 + buildScan.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, CI_AUTO_INJECTION_CUSTOM_VALUE_VALUE + } + + if (geUrl && geEnforceUrl) { + pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) { + afterEvaluate { + logger.quiet("Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") + buildScan.server = geUrl + buildScan.allowUntrustedServer = geAllowUntrustedServer + } + } + } + } + + if (ccudPluginVersion && atLeastGradle4) { + def ccudPluginComponent = resolutionResult.allComponents.find { + it.moduleVersion.with { group == "com.gradle" && name == "common-custom-user-data-gradle-plugin" } + } + if (!ccudPluginComponent) { + logger.quiet("Applying $CCUD_PLUGIN_CLASS via init script") + pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS)) + } + } + } + } +} else { + gradle.settingsEvaluated { settings -> + if (gePluginVersion) { + if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID)) { + logger.quiet("Applying $GRADLE_ENTERPRISE_PLUGIN_CLASS via init script") + logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") + applyPluginExternally(settings.pluginManager, GRADLE_ENTERPRISE_PLUGIN_CLASS) + extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext -> + ext.server = geUrl + ext.allowUntrustedServer = geAllowUntrustedServer + ext.buildScan.publishAlways() + ext.buildScan.uploadInBackground = buildScanUploadInBackground + ext.buildScan.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, CI_AUTO_INJECTION_CUSTOM_VALUE_VALUE + } + } + + if (geUrl && geEnforceUrl) { + extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext -> + logger.quiet("Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") + ext.server = geUrl + ext.allowUntrustedServer = geAllowUntrustedServer + } + } + } + + if (ccudPluginVersion) { + if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) { + logger.quiet("Applying $CCUD_PLUGIN_CLASS via init script") + settings.pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS)) + } + } + } +} + +void applyPluginExternally(PluginManager pluginManager, String pluginClassName) { + def externallyApplied = 'gradle.enterprise.externally-applied' + def oldValue = System.getProperty(externallyApplied) + System.setProperty(externallyApplied, 'true') + try { + pluginManager.apply(initscript.classLoader.loadClass(pluginClassName)) + } finally { + if (oldValue == null) { + System.clearProperty(externallyApplied) + } else { + System.setProperty(externallyApplied, oldValue) + } + } +} + +static def extensionsWithPublicType(def container, String publicType) { + container.extensions.extensionsSchema.elements.findAll { it.publicType.concreteClass.name == publicType } +} + +static boolean isNotAtLeast(String versionUnderTest, String referenceVersion) { + GradleVersion.version(versionUnderTest) < GradleVersion.version(referenceVersion) +} \ No newline at end of file diff --git a/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/BaseInitScriptTest.groovy b/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/BaseInitScriptTest.groovy index 02bc1fb..fcb7b05 100644 --- a/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/BaseInitScriptTest.groovy +++ b/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/BaseInitScriptTest.groovy @@ -16,6 +16,8 @@ import java.nio.file.Files import java.util.zip.GZIPOutputStream class BaseInitScriptTest extends Specification { + static final String GE_PLUGIN_VERSION = '3.14.1' + static final String CCUD_PLUGIN_VERSION = '1.11.1' static final TestGradleVersion GRADLE_3_X = new TestGradleVersion(GradleVersion.version('3.5.1'), 7, 9) static final TestGradleVersion GRADLE_4_X = new TestGradleVersion(GradleVersion.version('4.10.3'), 7, 10) @@ -126,12 +128,17 @@ class BaseInitScriptTest extends Specification { buildFile << '' } - def declareGePluginApplication(GradleVersion gradleVersion) { - settingsFile.text = maybeAddPluginsToSettings(gradleVersion) + settingsFile.text - buildFile.text = maybeAddPluginsToRootProject(gradleVersion) + buildFile.text + def declareGePluginApplication(GradleVersion gradleVersion, URI serverUrl = mockScansServer.address) { + settingsFile.text = maybeAddPluginsToSettings(gradleVersion, null, serverUrl) + settingsFile.text + buildFile.text = maybeAddPluginsToRootProject(gradleVersion, null, serverUrl) + buildFile.text } - String maybeAddPluginsToSettings(GradleVersion gradleVersion) { + def declareGePluginAndCcudPluginApplication(GradleVersion gradleVersion, URI serverUrl = mockScansServer.address) { + settingsFile.text = maybeAddPluginsToSettings(gradleVersion, CCUD_PLUGIN_VERSION, serverUrl) + settingsFile.text + buildFile.text = maybeAddPluginsToRootProject(gradleVersion, CCUD_PLUGIN_VERSION, serverUrl) + buildFile.text + } + + String maybeAddPluginsToSettings(GradleVersion gradleVersion, String ccudPluginVersion, URI serverUri) { if (gradleVersion < GradleVersion.version('5.0')) { '' // applied in build.gradle } else if (gradleVersion < GradleVersion.version('6.0')) { @@ -139,10 +146,11 @@ class BaseInitScriptTest extends Specification { } else { """ plugins { - id 'com.gradle.enterprise' version '3.14.1' + id 'com.gradle.enterprise' version '${GE_PLUGIN_VERSION}' + ${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""} } gradleEnterprise { - server = '$mockScansServer.address' + server = '$serverUri' buildScan { publishAlways() } @@ -151,24 +159,26 @@ class BaseInitScriptTest extends Specification { } } - String maybeAddPluginsToRootProject(GradleVersion gradleVersion) { + String maybeAddPluginsToRootProject(GradleVersion gradleVersion, String ccudPluginVersion, URI serverUrl) { if (gradleVersion < GradleVersion.version('5.0')) { """ plugins { id 'com.gradle.build-scan' version '1.16' + ${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""} } buildScan { - server = '$mockScansServer.address' + server = '$serverUrl' publishAlways() } """ } else if (gradleVersion < GradleVersion.version('6.0')) { """ plugins { - id 'com.gradle.build-scan' version '3.14.1' + id 'com.gradle.build-scan' version '${GE_PLUGIN_VERSION}' + ${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""} } gradleEnterprise { - server = '$mockScansServer.address' + server = '$serverUrl' buildScan { publishAlways() } diff --git a/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestGradleEnterpriseInjection.groovy b/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestGradleEnterpriseInjection.groovy new file mode 100644 index 0000000..95fef7a --- /dev/null +++ b/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestGradleEnterpriseInjection.groovy @@ -0,0 +1,401 @@ +package com.gradle.gradlebuildaction + +import org.gradle.testkit.runner.BuildResult +import org.gradle.util.GradleVersion + +import static org.junit.Assume.assumeTrue + +class TestGradleEnterpriseInjection extends BaseInitScriptTest { + static final List CCUD_COMPATIBLE_VERSIONS = ALL_VERSIONS - [GRADLE_3_X] + + def initScript = 'inject-gradle-enterprise.init.gradle' + + private static final GradleVersion GRADLE_6 = GradleVersion.version('6.0') + + def "does not apply GE plugins when not requested"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def result = run([], initScript, testGradleVersion.gradleVersion) + + then: + outputMissesGePluginApplicationViaInitScript(result) + outputMissesCcudPluginApplicationViaInitScript(result) + + where: + testGradleVersion << ALL_VERSIONS + } + + def "does not override GE plugin when already defined in project"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + given: + declareGePluginApplication(testGradleVersion.gradleVersion) + + when: + def result = run(testGradleVersion, testConfig()) + + then: + outputMissesGePluginApplicationViaInitScript(result) + outputMissesCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << ALL_VERSIONS + } + + def "applies GE plugin via init script when not defined in project"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def result = run(testGradleVersion, testConfig()) + + then: + outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) + outputMissesCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << ALL_VERSIONS + } + + def "applies GE and CCUD plugins via init script when not defined in project"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def result = run(testGradleVersion, testConfig().withCCUDPlugin()) + + then: + outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) + outputContainsCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << CCUD_COMPATIBLE_VERSIONS + } + + def "applies CCUD plugin via init script where GE plugin already applied"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + given: + declareGePluginApplication(testGradleVersion.gradleVersion) + + when: + def result = run(testGradleVersion, testConfig().withCCUDPlugin()) + + then: + outputMissesGePluginApplicationViaInitScript(result) + outputContainsCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << CCUD_COMPATIBLE_VERSIONS + } + + def "does not override CCUD plugin when already defined in project"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + given: + declareGePluginAndCcudPluginApplication(testGradleVersion.gradleVersion) + + when: + def result = run(testGradleVersion, testConfig().withCCUDPlugin()) + + then: + outputMissesGePluginApplicationViaInitScript(result) + outputMissesCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << CCUD_COMPATIBLE_VERSIONS + } + + def "ignores GE URL and allowUntrustedServer when GE plugin is not applied by the init script"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + given: + declareGePluginApplication(testGradleVersion.gradleVersion) + + when: + def config = testConfig().withServer(URI.create('https://ge-server.invalid')) + def result = run(testGradleVersion, config) + + then: + outputMissesGePluginApplicationViaInitScript(result) + outputMissesCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << ALL_VERSIONS + } + + def "configures GE URL and allowUntrustedServer when GE plugin is applied by the init script"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def config = testConfig().withServer(mockScansServer.address) + def result = run(testGradleVersion, config) + + then: + outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) + outputContainsGeConnectionInfo(result, mockScansServer.address.toString(), true) + outputMissesCcudPluginApplicationViaInitScript(result) + outputContainsPluginRepositoryInfo(result, 'https://plugins.gradle.org/m2') + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << ALL_VERSIONS + } + + def "enforces GE URL and allowUntrustedServer in project if enforce url parameter is enabled"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + given: + declareGePluginApplication(testGradleVersion.gradleVersion, URI.create('https://ge-server.invalid')) + + when: + def config = testConfig().withServer(mockScansServer.address, true) + def result = run(testGradleVersion, config) + + then: + outputMissesGePluginApplicationViaInitScript(result) + outputMissesCcudPluginApplicationViaInitScript(result) + + and: + outputEnforcesGeUrl(result, mockScansServer.address.toString(), true) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << ALL_VERSIONS + } + + def "can configure alternative repository for plugins when GE plugin is applied by the init script"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def config = testConfig().withPluginRepository(new URI('https://plugins.grdev.net/m2')) + def result = run(testGradleVersion, config) + + then: + outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) + outputContainsGeConnectionInfo(result, mockScansServer.address.toString(), true) + outputMissesCcudPluginApplicationViaInitScript(result) + outputContainsPluginRepositoryInfo(result, 'https://plugins.grdev.net/m2') + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << ALL_VERSIONS + } + + def "stops gracefully when requested CCUD plugin version is <1.7"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def config = testConfig().withCCUDPlugin("1.6.6") + def result = run(testGradleVersion, config) + + then: + outputMissesGePluginApplicationViaInitScript(result) + outputMissesCcudPluginApplicationViaInitScript(result) + result.output.contains('Common Custom User Data Gradle plugin must be at least 1.7. Configured version is 1.6.6.') + + where: + testGradleVersion << ALL_VERSIONS + } + + def "can configure GE via CCUD system property overrides when CCUD plugin is inject via init script"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def config = testConfig().withCCUDPlugin().withServer(URI.create('https://ge-server.invalid')) + def result = run(testGradleVersion, config, ["help", "-Dgradle.enterprise.url=${mockScansServer.address}".toString()]) + + then: + outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) + outputContainsCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << CCUD_COMPATIBLE_VERSIONS + } + + def "init script is configuration cache compatible"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def config = testConfig().withCCUDPlugin() + def result = run(testGradleVersion, config, ["help", "--configuration-cache"]) + + then: + outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) + outputContainsCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + when: + result = run(testGradleVersion, config, ["help", "--configuration-cache"]) + + then: + outputMissesGePluginApplicationViaInitScript(result) + outputMissesCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << CONFIGURATION_CACHE_VERSIONS + } + + void outputContainsBuildScanUrl(BuildResult result) { + def message = "Publishing build scan...\n${mockScansServer.address}s/$PUBLIC_BUILD_SCAN_ID" + assert result.output.contains(message) + assert 1 == result.output.count(message) + } + + void outputContainsGePluginApplicationViaInitScript(BuildResult result, GradleVersion gradleVersion) { + def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script" + def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script" + if (gradleVersion < GRADLE_6) { + assert result.output.contains(pluginApplicationLogMsgGradle4And5) + assert 1 == result.output.count(pluginApplicationLogMsgGradle4And5) + assert !result.output.contains(pluginApplicationLogMsgGradle6AndHigher) + } else { + assert result.output.contains(pluginApplicationLogMsgGradle6AndHigher) + assert 1 == result.output.count(pluginApplicationLogMsgGradle6AndHigher) + assert !result.output.contains(pluginApplicationLogMsgGradle4And5) + } + } + + void outputMissesGePluginApplicationViaInitScript(BuildResult result) { + def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script" + def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script" + assert !result.output.contains(pluginApplicationLogMsgGradle4And5) + assert !result.output.contains(pluginApplicationLogMsgGradle6AndHigher) + } + + void outputContainsCcudPluginApplicationViaInitScript(BuildResult result) { + def pluginApplicationLogMsg = "Applying com.gradle.CommonCustomUserDataGradlePlugin via init script" + assert result.output.contains(pluginApplicationLogMsg) + assert 1 == result.output.count(pluginApplicationLogMsg) + } + + void outputMissesCcudPluginApplicationViaInitScript(BuildResult result) { + def pluginApplicationLogMsg = "Applying com.gradle.CommonCustomUserDataGradlePlugin via init script" + assert !result.output.contains(pluginApplicationLogMsg) + } + + void outputContainsGeConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer) { + def geConnectionInfo = "Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer" + assert result.output.contains(geConnectionInfo) + assert 1 == result.output.count(geConnectionInfo) + } + + void outputContainsPluginRepositoryInfo(BuildResult result, String gradlePluginRepositoryUrl) { + def repositoryInfo = "Gradle Enterprise plugins resolution: ${gradlePluginRepositoryUrl}" + assert result.output.contains(repositoryInfo) + assert 1 == result.output.count(repositoryInfo) + } + + void outputEnforcesGeUrl(BuildResult result, String geUrl, boolean geAllowUntrustedServer) { + def enforceUrl = "Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer" + assert result.output.contains(enforceUrl) + assert 1 == result.output.count(enforceUrl) + } + + private BuildResult run(TestGradleVersion testGradleVersion, TestConfig config, List args = ["help"]) { + if (testKitSupportsEnvVars(testGradleVersion.gradleVersion)) { + return run(args, initScript, testGradleVersion.gradleVersion, [], config.envVars) + } else { + return run(args, initScript, testGradleVersion.gradleVersion, config.jvmArgs, [:]) + } + } + + private boolean testKitSupportsEnvVars(GradleVersion gradleVersion) { + // TestKit supports env vars for Gradle 3.5+, except on M1 Mac where only 6.9+ is supported + def isM1Mac = System.getProperty("os.arch") == "aarch64" + if (isM1Mac) { + return gradleVersion >= GRADLE_6_X.gradleVersion + } else { + return gradleVersion >= GRADLE_3_X.gradleVersion + } + } + + private TestConfig testConfig() { + new TestConfig() + } + + class TestConfig { + String serverUrl = mockScansServer.address.toString() + boolean enforceUrl = false + String ccudPluginVersion = null + String pluginRepositoryUrl = null + + TestConfig withCCUDPlugin(String version = CCUD_PLUGIN_VERSION) { + ccudPluginVersion = version + return this + } + + TestConfig withServer(URI url, boolean enforceUrl = false) { + serverUrl = url.toASCIIString() + this.enforceUrl = enforceUrl + return this + } + + TestConfig withPluginRepository(URI pluginRepositoryUrl) { + this.pluginRepositoryUrl = pluginRepositoryUrl + return this + } + + def getEnvVars() { + Map envVars = [ + GRADLE_ENTERPRISE_INJECTION_ENABLED: "true", + GRADLE_ENTERPRISE_INJECTION_SERVER_URL: serverUrl, + GRADLE_ENTERPRISE_INJECTION_ALLOW_UNTRUSTED_SERVER: "true", + GRADLE_ENTERPRISE_INJECTION_GE_PLUGIN_VERSION: GE_PLUGIN_VERSION, + GRADLE_ENTERPRISE_INJECTION_BUILD_SCAN_UPLOAD_IN_BACKGROUND: "true" // Need to upload in background since our Mock server doesn't cope with foreground upload + ] + if (enforceUrl) envVars.put("GRADLE_ENTERPRISE_INJECTION_ENFORCE_SERVER_URL", "true") + if (ccudPluginVersion != null) envVars.put("GRADLE_ENTERPRISE_INJECTION_CCUD_PLUGIN_VERSION", ccudPluginVersion) + if (pluginRepositoryUrl != null) envVars.put("GRADLE_ENTERPRISE_INJECTION_PLUGIN_REPOSITORY_URL", pluginRepositoryUrl) + + return envVars + } + + def getJvmArgs() { + List jvmArgs = [ + "-Dgradle-enterprise-injection.enabled=true", + "-Dgradle-enterprise-injection.server-url=$serverUrl", + "-Dgradle-enterprise-injection.allow-untrusted-server=true", + "-Dgradle-enterprise-injection.ge-plugin-version=$GE_PLUGIN_VERSION", + "-Dgradle-enterprise-injection.build-scan-upload-in-background=true" + ] + + if (enforceUrl) jvmArgs.add("-Dgradle-enterprise-injection.enforce-server-url=true") + if (ccudPluginVersion != null) jvmArgs.add("-Dgradle-enterprise-injection.ccud-plugin-version=$ccudPluginVersion") + if (pluginRepositoryUrl != null) jvmArgs.add("-Dgradle-enterprise-injection.plugin-repository-url=$pluginRepositoryUrl") + + return jvmArgs.collect { it.toString() } // Convert from GStrings + } + } +}