From e43d10f419a88bc2e3be5cd63a1ac282c3bb25bc Mon Sep 17 00:00:00 2001 From: Iurii Ignatko Date: Wed, 6 Mar 2024 17:53:10 +0200 Subject: [PATCH] Add an ability to capture task input files (#58) This PR adds an ability to enable/disable [capturing task input files](https://docs.gradle.com/enterprise/gradle-plugin/#capturing_task_input_files) in a build scan. --------- Co-authored-by: Eric Haag --- setup-gradle/README.md | 23 ++++----- ...adle-actions.inject-develocity.init.gradle | 44 +++++++++++++++-- .../TestDevelocityInjection.groovy | 47 +++++++++++++++---- 3 files changed, 88 insertions(+), 26 deletions(-) diff --git a/setup-gradle/README.md b/setup-gradle/README.md index 7e96a5f..6271758 100644 --- a/setup-gradle/README.md +++ b/setup-gradle/README.md @@ -663,17 +663,18 @@ with a valid [Develocity access key](https://docs.gradle.com/enterprise/gradle-p The `init-script` supports several additional configuration parameters that you may find useful. All configuration options (required and optional) are detailed below: -| Variable | Required | Description | -|-----------------------------------| --- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| DEVELOCITY_INJECTION_ENABLED | :white_check_mark: | enables Develocity injection | -| DEVELOCITY_URL | :white_check_mark: | the URL of the Develocity server | -| DEVELOCITY_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed certificate | -| DEVELOCITY_ENFORCE_URL | | enforce the configured Develocity URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Develocity URL | -| DEVELOCITY_PLUGIN_VERSION | :white_check_mark: | the version of the [Develocity Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/) to apply | -| DEVELOCITY_CCUD_PLUGIN_VERSION | | the version of the [Common Custom User Data Gradle plugin](https://github.com/gradle/common-custom-user-data-gradle-plugin) to apply, if any | -| GRADLE_PLUGIN_REPOSITORY_URL | | the URL of the repository to use when resolving the Develocity and CCUD plugins; the Gradle Plugin Portal is used by default | -| GRADLE_PLUGIN_REPOSITORY_USERNAME | | the username for the repository URL to use when resolving the Develocity and CCUD plugins | -| GRADLE_PLUGIN_REPOSITORY_PASSWORD | | the password for the repository URL to use when resolving the Develocity and CCUD plugins; Consider using secrets to pass the value to this variable | +| Variable | Required | Description | +|--------------------------------------| --- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| DEVELOCITY_INJECTION_ENABLED | :white_check_mark: | enables Develocity injection | +| DEVELOCITY_URL | :white_check_mark: | the URL of the Develocity server | +| DEVELOCITY_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed certificate | +| DEVELOCITY_CAPTURE_FILE_FINGERPRINTS | | enables capturing the paths and content hashes of each individual input file | +| DEVELOCITY_ENFORCE_URL | | enforce the configured Develocity URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Develocity URL | +| DEVELOCITY_PLUGIN_VERSION | :white_check_mark: | the version of the [Develocity Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/) to apply | +| DEVELOCITY_CCUD_PLUGIN_VERSION | | the version of the [Common Custom User Data Gradle plugin](https://github.com/gradle/common-custom-user-data-gradle-plugin) to apply, if any | +| GRADLE_PLUGIN_REPOSITORY_URL | | the URL of the repository to use when resolving the Develocity and CCUD plugins; the Gradle Plugin Portal is used by default | +| GRADLE_PLUGIN_REPOSITORY_USERNAME | | the username for the repository URL to use when resolving the Develocity and CCUD plugins | +| GRADLE_PLUGIN_REPOSITORY_PASSWORD | | the password for the repository URL to use when resolving the Develocity and CCUD plugins; Consider using secrets to pass the value to this variable | ## Publishing to scans.gradle.com diff --git a/sources/src/resources/init-scripts/gradle-actions.inject-develocity.init.gradle b/sources/src/resources/init-scripts/gradle-actions.inject-develocity.init.gradle index cf37e43..45eb18a 100644 --- a/sources/src/resources/init-scripts/gradle-actions.inject-develocity.init.gradle +++ b/sources/src/resources/init-scripts/gradle-actions.inject-develocity.init.gradle @@ -94,11 +94,13 @@ def geUrl = getInputParam('develocity.url') def geAllowUntrustedServer = Boolean.parseBoolean(getInputParam('develocity.allow-untrusted-server')) def geEnforceUrl = Boolean.parseBoolean(getInputParam('develocity.enforce-url')) def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('develocity.build-scan.upload-in-background')) +def geCaptureFileFingerprints = Boolean.parseBoolean(getInputParam('develocity.capture-file-fingerprints')) def gePluginVersion = getInputParam('develocity.plugin.version') def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version') def buildScanTermsOfServiceUrl = getInputParam('build-scan.terms-of-service.url') def buildScanTermsOfServiceAgree = getInputParam('build-scan.terms-of-service.agree') +def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0') def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0') // finish early if configuration parameters passed in via system properties are not valid/supported @@ -121,11 +123,18 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) { logger.lifecycle("Applying $BUILD_SCAN_PLUGIN_CLASS via init script") applyPluginExternally(pluginManager, BUILD_SCAN_PLUGIN_CLASS) if (geUrl) { - logger.lifecycle("Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") + logger.lifecycle("Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer, captureFileFingerprints: $geCaptureFileFingerprints") buildScan.server = geUrl buildScan.allowUntrustedServer = geAllowUntrustedServer } buildScan.publishAlways() + if (isAtLeast(gePluginVersion, '2.1') && atLeastGradle5) { + if (isAtLeast(gePluginVersion, '3.7')) { + buildScan.capture.taskInputFiles = geCaptureFileFingerprints + } else { + buildScan.captureTaskInputFiles = geCaptureFileFingerprints + } + } 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 } @@ -133,10 +142,17 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) { if (geUrl && geEnforceUrl) { pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) { afterEvaluate { - logger.lifecycle("Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") + logger.lifecycle("Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer, captureFileFingerprints: $geCaptureFileFingerprints") buildScan.server = geUrl buildScan.allowUntrustedServer = geAllowUntrustedServer } + if (isAtLeast(gePluginVersion, '2.1') && atLeastGradle5) { + if (isAtLeast(gePluginVersion, '3.7')) { + buildScan.capture.taskInputFiles = geCaptureFileFingerprints + } else { + buildScan.captureTaskInputFiles = geCaptureFileFingerprints + } + } } } @@ -165,21 +181,35 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) { applyPluginExternally(settings.pluginManager, DEVELOCITY_PLUGIN_CLASS) eachDevelocityExtension(settings, DEVELOCITY_EXTENSION_CLASS) { ext -> if (geUrl) { - logger.lifecycle("Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") + logger.lifecycle("Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer, captureFileFingerprints: $geCaptureFileFingerprints") ext.server = geUrl ext.allowUntrustedServer = geAllowUntrustedServer } ext.buildScan.publishAlways() ext.buildScan.uploadInBackground = buildScanUploadInBackground + if (isAtLeast(gePluginVersion, '2.1')) { + if (isAtLeast(gePluginVersion, '3.7')) { + ext.buildScan.capture.taskInputFiles = geCaptureFileFingerprints + } else { + ext.buildScan.captureTaskInputFiles = geCaptureFileFingerprints + } + } ext.buildScan.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, CI_AUTO_INJECTION_CUSTOM_VALUE_VALUE } } if (geUrl && geEnforceUrl) { eachDevelocityExtension(settings, DEVELOCITY_EXTENSION_CLASS) { ext -> - logger.lifecycle("Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") + logger.lifecycle("Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer, captureFileFingerprints: $geCaptureFileFingerprints") ext.server = geUrl ext.allowUntrustedServer = geAllowUntrustedServer + if (isAtLeast(gePluginVersion, '2.1')) { + if (isAtLeast(gePluginVersion, '3.7')) { + ext.buildScan.capture.taskInputFiles = geCaptureFileFingerprints + } else { + ext.buildScan.captureTaskInputFiles = geCaptureFileFingerprints + } + } } } @@ -221,5 +251,9 @@ static def eachDevelocityExtension(def settings, def publicType, def action) { } static boolean isNotAtLeast(String versionUnderTest, String referenceVersion) { - GradleVersion.version(versionUnderTest) < GradleVersion.version(referenceVersion) + !isAtLeast(versionUnderTest, referenceVersion) +} + +static boolean isAtLeast(String versionUnderTest, String referenceVersion) { + GradleVersion.version(versionUnderTest) >= GradleVersion.version(referenceVersion) } \ No newline at end of file diff --git a/sources/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestDevelocityInjection.groovy b/sources/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestDevelocityInjection.groovy index d74d6ff..03a2bb6 100644 --- a/sources/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestDevelocityInjection.groovy +++ b/sources/test/init-scripts/src/test/groovy/com/gradle/gradlebuildaction/TestDevelocityInjection.groovy @@ -225,6 +225,25 @@ class TestDevelocityInjection extends BaseInitScriptTest { testGradleVersion << ALL_VERSIONS } + def "can configure capturing file fingerprints when Develocity plugin is applied by the init script"() { + assumeTrue testGradleVersion.compatibleWithCurrentJvm + + when: + def config = testConfig().withCaptureFileFingerprints() + def result = run(testGradleVersion, config) + + then: + outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) + outputContainsDevelocityConnectionInfo(result, mockScansServer.address.toString(), true, true) + outputMissesCcudPluginApplicationViaInitScript(result) + + and: + outputContainsBuildScanUrl(result) + + where: + testGradleVersion << ALL_VERSIONS + } + def "stops gracefully when requested CCUD plugin version is <1.7"() { assumeTrue testGradleVersion.compatibleWithCurrentJvm @@ -325,8 +344,8 @@ class TestDevelocityInjection extends BaseInitScriptTest { assert !result.output.contains(pluginApplicationLogMsg) } - void outputContainsDevelocityConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer) { - def geConnectionInfo = "Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer" + void outputContainsDevelocityConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer, boolean geCaptureFileFingerprints = false) { + def geConnectionInfo = "Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer, captureFileFingerprints: $geCaptureFileFingerprints" assert result.output.contains(geConnectionInfo) assert 1 == result.output.count(geConnectionInfo) } @@ -376,8 +395,9 @@ class TestDevelocityInjection extends BaseInitScriptTest { boolean enforceUrl = false String ccudPluginVersion = null String pluginRepositoryUrl = null - String pluginRepoUsername = null - String pluginRepoPassword = null + String pluginRepositoryUsername = null + String pluginRepositoryPassword = null + boolean captureFileFingerprints = false TestConfig withCCUDPlugin(String version = CCUD_PLUGIN_VERSION) { ccudPluginVersion = version @@ -395,9 +415,14 @@ class TestDevelocityInjection extends BaseInitScriptTest { return this } + TestConfig withCaptureFileFingerprints() { + this.captureFileFingerprints = true + return this + } + TestConfig withPluginRepositoryCredentials(String pluginRepoUsername, String pluginRepoPassword) { - this.pluginRepoUsername = pluginRepoUsername - this.pluginRepoPassword = pluginRepoPassword + this.pluginRepositoryUsername = pluginRepoUsername + this.pluginRepositoryPassword = pluginRepoPassword return this } @@ -412,8 +437,9 @@ class TestDevelocityInjection extends BaseInitScriptTest { if (enforceUrl) envVars.put("DEVELOCITY_ENFORCE_URL", "true") if (ccudPluginVersion != null) envVars.put("DEVELOCITY_CCUD_PLUGIN_VERSION", ccudPluginVersion) if (pluginRepositoryUrl != null) envVars.put("GRADLE_PLUGIN_REPOSITORY_URL", pluginRepositoryUrl) - if (pluginRepoUsername != null) envVars.put("GRADLE_PLUGIN_REPOSITORY_USERNAME", pluginRepoUsername) - if (pluginRepoPassword != null) envVars.put("GRADLE_PLUGIN_REPOSITORY_PASSWORD", pluginRepoPassword) + if (pluginRepositoryUsername != null) envVars.put("GRADLE_PLUGIN_REPOSITORY_USERNAME", pluginRepositoryUsername) + if (pluginRepositoryPassword != null) envVars.put("GRADLE_PLUGIN_REPOSITORY_PASSWORD", pluginRepositoryPassword) + if (captureFileFingerprints) envVars.put("DEVELOCITY_CAPTURE_FILE_FINGERPRINTS", "true") return envVars } @@ -430,8 +456,9 @@ class TestDevelocityInjection extends BaseInitScriptTest { if (enforceUrl) jvmArgs.add("-Ddevelocity.enforce-url=true") if (ccudPluginVersion != null) jvmArgs.add("-Ddevelocity.ccud-plugin.version=$ccudPluginVersion") if (pluginRepositoryUrl != null) jvmArgs.add("-Dgradle.plugin-repository.url=$pluginRepositoryUrl") - if (pluginRepoUsername != null) jvmArgs.add("-Dgradle.plugin-repository.username=$pluginRepoUsername") - if (pluginRepoPassword != null) jvmArgs.add("-Dgradle.plugin-repository.password=$pluginRepoPassword") + if (pluginRepositoryUsername != null) jvmArgs.add("-Dgradle.plugin-repository.username=$pluginRepositoryUsername") + if (pluginRepositoryPassword != null) jvmArgs.add("-Dgradle.plugin-repository.password=$pluginRepositoryPassword") + if (captureFileFingerprints) jvmArgs.add("-Ddevelocity.capture-file-fingerprints=true") return jvmArgs.collect { it.toString() } // Convert from GStrings }