Merge pull request #857 from gradle/dd/inject-ge

Add support for Gradle Enterprise injection into Gradle Builds
This commit is contained in:
Daz DeBoer 2023-08-21 01:38:14 +02:00 committed by GitHub
commit e3426b1f20
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 760 additions and 31 deletions

View file

@ -0,0 +1 @@
// Required to keep dependabot happy

View file

@ -0,0 +1 @@
rootProject.name = 'no-ge'

View file

@ -44,6 +44,11 @@ jobs:
with: with:
cache-key-prefix: ${{github.run_number}}- cache-key-prefix: ${{github.run_number}}-
gradle-enterprise-injection:
uses: ./github/workflows/integ-test-inject-gradle-enterprise.yml
with:
cache-key-prefix: ${{github.run_number}}-
provision-gradle-versions: provision-gradle-versions:
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml uses: ./.github/workflows/integ-test-provision-gradle-versions.yml
with: with:

View file

@ -71,6 +71,13 @@ jobs:
runner-os: '["ubuntu-latest"]' runner-os: '["ubuntu-latest"]'
download-dist: true download-dist: true
gradle-enterprise-injection:
needs: build-distribution
uses: ./github/workflows/integ-test-inject-gradle-enterprise.yml
with:
runner-os: '["ubuntu-latest"]'
download-dist: true
provision-gradle-versions: provision-gradle-versions:
needs: build-distribution needs: build-distribution
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml uses: ./.github/workflows/integ-test-provision-gradle-versions.yml

View file

@ -0,0 +1,57 @@
name: Test gradle enterprise injection
on:
workflow_call:
inputs:
cache-key-prefix:
type: string
runner-os:
type: string
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
download-dist:
type: boolean
default: false
env:
DOWNLOAD_DIST: ${{ inputs.download-dist }}
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }}
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
GRADLE_ENTERPRISE_INJECTION_ENABLED: true
GRADLE_ENTERPRISE_INJECTION_SERVER_URL: https://ge.solutions-team.gradle.com
GRADLE_ENTERPRISE_INJECTION_GE_PLUGIN_VERSION: 3.14.1
GRADLE_ENTERPRISE_INJECTION_CCUD_PLUGIN_VERSION: 1.11.1
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
jobs:
inject-gradle-enterprise:
strategy:
matrix:
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
os: ${{fromJSON(inputs.runner-os)}}
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v3
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 8
- name: Setup Gradle
id: setup-gradle
uses: ./
with:
cache-read-only: false # For testing, allow writing cache entries on non-default branches
gradle-version: ${{ matrix.gradle }}
- name: Run Gradle build
id: gradle
working-directory: .github/workflow-samples/no-ge
run: gradle help
- name: Check Build Scan url
if: ${{ !steps.gradle.outputs.build-scan-url }}
uses: actions/github-script@v6
with:
script: |
core.setFailed('No Build Scan detected')

View file

@ -725,3 +725,55 @@ limited to Gradle "8.1.0" and later:
To use this plugin with versions of Gradle older than "8.1.0", you'll need to invoke Gradle with the To use this plugin with versions of Gradle older than "8.1.0", you'll need to invoke Gradle with the
configuration-cache disabled. configuration-cache disabled.
# Gradle Enterprise plugin injection
The `gradle-build-action` provides support for injecting and configuring the Gradle Enterprise Gradle plugin into any Gradle build, without any modification to the project sources.
This is achieved via an init-script installed into Gradle User Home, which is enabled and parameterized via environment variables.
The same auto-injection behavior is available for the Common Custom User Data Gradle plugin, which enriches any build scans published with additional useful information.
## Enabling Gradle Enterprise injection
In order to enable Gradle Enterprise for your build, you must provide the required configuration via environment variables.
Here's a minimal example:
```yaml
name: Run build with Gradle Enterprise injection
env:
GRADLE_ENTERPRISE_INJECTION_ENABLED: true
GRADLE_ENTERPRISE_INJECTION_SERVER_URL: https://ge.gradle.org
GRADLE_ENTERPRISE_INJECTION_GE_PLUGIN_VERSION: 3.14.1
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_KEY }} # Required to publish scans to ge.gradle.org
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Run a Gradle build with Gradle Enterprise injection enabled
run: ./gradlew build
```
This configuration will automatically apply `v3.14.1` of the [Gradle Enterprise Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/), and publish build scans to https://ge.gradle.org.
Note that the `ge.gradle.org` server requires authentication in order to publish scans. The provided `GRADLE_ENTERPRISE_ACCESS_KEY` isn't required by the Gradle Enterprise injection script,
but will be used by the GE plugin in order to authenticate with the server.
## Configuring Gradle Enterprise injection
The `init-script` supports a number of additional configuration parameters that you may fine useful. All configuration options (required and optional) are detailed below:
| Variable | Required | Description |
| --- | --- | --- |
| GRADLE_ENTERPRISE_INJECTION_ENABLED | :white_check_mark: | enables Gradle Enterprise injection |
| GRADLE_ENTERPRISE_INJECTION_SERVER_URL | :white_check_mark: | the URL of the Gradle Enterprise server |
| GRADLE_ENTERPRISE_INJECTION_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Gradle Enterprise instance is using a self-signed certificate |
| GRADLE_ENTERPRISE_INJECTION_ENFORCE_SERVER_URL | | enforce the configured Gradle Enterprise URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Gradle Enterprise URL |
| GRADLE_ENTERPRISE_INJECTION_GE_PLUGIN_VERSION | :white_check_mark: | the version of the [Gradle Enterprise Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/) to apply |
| GRADLE_ENTERPRISE_INJECTION_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_ENTERPRISE_INJECTION_PLUGIN_REPOSITORY_URL | | the URL of the repository to use when resolving the GE and CCUD plugins; the Gradle Plugin Portal is used by default |

9
dist/main/index.js vendored
View file

@ -72982,10 +72982,11 @@ org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME
`); `);
} }
const initScriptFilenames = [ const initScriptFilenames = [
'build-result-capture.init.gradle', 'gradle-build-action.build-result-capture.init.gradle',
'build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
'github-dependency-graph.init.gradle', 'gradle-build-action.github-dependency-graph.init.gradle',
'github-dependency-graph-gradle-plugin-apply.groovy' 'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy',
'gradle-build-action.inject-gradle-enterprise.init.gradle'
]; ];
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readInitScriptAsString(initScriptFilename); const initScriptContent = this.readInitScriptAsString(initScriptFilename);

File diff suppressed because one or more lines are too long

9
dist/post/index.js vendored
View file

@ -72982,10 +72982,11 @@ org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME
`); `);
} }
const initScriptFilenames = [ const initScriptFilenames = [
'build-result-capture.init.gradle', 'gradle-build-action.build-result-capture.init.gradle',
'build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
'github-dependency-graph.init.gradle', 'gradle-build-action.github-dependency-graph.init.gradle',
'github-dependency-graph-gradle-plugin-apply.groovy' 'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy',
'gradle-build-action.inject-gradle-enterprise.init.gradle'
]; ];
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readInitScriptAsString(initScriptFilename); const initScriptContent = this.readInitScriptAsString(initScriptFilename);

File diff suppressed because one or more lines are too long

View file

@ -189,10 +189,11 @@ org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME
// Copy init scripts from src/resources // Copy init scripts from src/resources
const initScriptFilenames = [ const initScriptFilenames = [
'build-result-capture.init.gradle', 'gradle-build-action.build-result-capture.init.gradle',
'build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
'github-dependency-graph.init.gradle', 'gradle-build-action.github-dependency-graph.init.gradle',
'github-dependency-graph-gradle-plugin-apply.groovy' 'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy',
'gradle-build-action.inject-gradle-enterprise.init.gradle'
] ]
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readInitScriptAsString(initScriptFilename) const initScriptContent = this.readInitScriptAsString(initScriptFilename)

View file

@ -82,7 +82,7 @@ def captureUsingBuildFinished(gradle, invocationId) {
def captureUsingBuildService(settings, invocationId) { def captureUsingBuildService(settings, invocationId) {
gradle.ext.invocationId = invocationId gradle.ext.invocationId = invocationId
apply from: 'build-result-capture-service.plugin.groovy' apply from: 'gradle-build-action.build-result-capture-service.plugin.groovy'
} }
class BuildResults { class BuildResults {

View file

@ -31,7 +31,7 @@ if (isTopLevelBuild) {
println "Generating dependency graph into '${reportFile}'" println "Generating dependency graph into '${reportFile}'"
} }
apply from: 'github-dependency-graph-gradle-plugin-apply.groovy' apply from: 'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy'
/** /**
* Using the supplied jobCorrelator value: * Using the supplied jobCorrelator value:

View file

@ -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)
}

View file

@ -16,6 +16,8 @@ import java.nio.file.Files
import java.util.zip.GZIPOutputStream import java.util.zip.GZIPOutputStream
class BaseInitScriptTest extends Specification { 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_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) static final TestGradleVersion GRADLE_4_X = new TestGradleVersion(GradleVersion.version('4.10.3'), 7, 10)
@ -126,12 +128,17 @@ class BaseInitScriptTest extends Specification {
buildFile << '' buildFile << ''
} }
def declareGePluginApplication(GradleVersion gradleVersion) { def declareGePluginApplication(GradleVersion gradleVersion, URI serverUrl = mockScansServer.address) {
settingsFile.text = maybeAddPluginsToSettings(gradleVersion) + settingsFile.text settingsFile.text = maybeAddPluginsToSettings(gradleVersion, null, serverUrl) + settingsFile.text
buildFile.text = maybeAddPluginsToRootProject(gradleVersion) + buildFile.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')) { if (gradleVersion < GradleVersion.version('5.0')) {
'' // applied in build.gradle '' // applied in build.gradle
} else if (gradleVersion < GradleVersion.version('6.0')) { } else if (gradleVersion < GradleVersion.version('6.0')) {
@ -139,10 +146,11 @@ class BaseInitScriptTest extends Specification {
} else { } else {
""" """
plugins { 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 { gradleEnterprise {
server = '$mockScansServer.address' server = '$serverUri'
buildScan { buildScan {
publishAlways() 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')) { if (gradleVersion < GradleVersion.version('5.0')) {
""" """
plugins { plugins {
id 'com.gradle.build-scan' version '1.16' id 'com.gradle.build-scan' version '1.16'
${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""}
} }
buildScan { buildScan {
server = '$mockScansServer.address' server = '$serverUrl'
publishAlways() publishAlways()
} }
""" """
} else if (gradleVersion < GradleVersion.version('6.0')) { } else if (gradleVersion < GradleVersion.version('6.0')) {
""" """
plugins { 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 { gradleEnterprise {
server = '$mockScansServer.address' server = '$serverUrl'
buildScan { buildScan {
publishAlways() publishAlways()
} }

View file

@ -5,7 +5,7 @@ import groovy.json.JsonSlurper
import static org.junit.Assume.assumeTrue import static org.junit.Assume.assumeTrue
class TestBuildResultRecorder extends BaseInitScriptTest { class TestBuildResultRecorder extends BaseInitScriptTest {
def initScript = 'build-result-capture.init.gradle' def initScript = 'gradle-build-action.build-result-capture.init.gradle'
def "produces build results file for build with #testGradleVersion"() { def "produces build results file for build with #testGradleVersion"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm

View file

@ -3,7 +3,7 @@ package com.gradle.gradlebuildaction
import static org.junit.Assume.assumeTrue import static org.junit.Assume.assumeTrue
class TestDependencyGraph extends BaseInitScriptTest { class TestDependencyGraph extends BaseInitScriptTest {
def initScript = 'github-dependency-graph.init.gradle' def initScript = 'gradle-build-action.github-dependency-graph.init.gradle'
static final List<TestGradleVersion> NO_DEPENDENCY_GRAPH_VERSIONS = [GRADLE_3_X, GRADLE_4_X] static final List<TestGradleVersion> NO_DEPENDENCY_GRAPH_VERSIONS = [GRADLE_3_X, GRADLE_4_X]
static final List<TestGradleVersion> DEPENDENCY_GRAPH_VERSIONS = ALL_VERSIONS - NO_DEPENDENCY_GRAPH_VERSIONS static final List<TestGradleVersion> DEPENDENCY_GRAPH_VERSIONS = ALL_VERSIONS - NO_DEPENDENCY_GRAPH_VERSIONS
@ -32,20 +32,20 @@ class TestDependencyGraph extends BaseInitScriptTest {
assert gitHubOutputFile.text == "dependency-graph-file=${reportFile.absolutePath}\n" assert gitHubOutputFile.text == "dependency-graph-file=${reportFile.absolutePath}\n"
where: where:
testGradleVersion << GRADLE_8_X testGradleVersion << [GRADLE_8_X]
} }
// Dependency-graph plugin doesn't support config-cache for 8.0 of Gradle
def "produces dependency graph with configuration-cache on latest Gradle"() { def "produces dependency graph with configuration-cache on latest Gradle"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
when: when:
run(['help'], initScript, testGradleVersion.gradleVersion, [], envVars) run(['help', '--configuration-cache'], initScript, testGradleVersion.gradleVersion, [], envVars)
then: then:
assert reportFile.exists() assert reportFile.exists()
where: where:
// Dependency-graph plugin doesn't support config-cache for 8.0 of Gradle
testGradleVersion << [GRADLE_8_X] testGradleVersion << [GRADLE_8_X]
} }

View file

@ -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<TestGradleVersion> CCUD_COMPATIBLE_VERSIONS = ALL_VERSIONS - [GRADLE_3_X]
def initScript = 'gradle-build-action.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<String> 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<String, String> 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<String> 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
}
}
}