Compare commits

...

36 Commits

Author SHA1 Message Date
bigdaz
31ae3562f6 [bot] Update dist directory 2024-06-15 03:19:11 +00:00
Daz DeBoer
719985db3d Simplify requesting short-lived Develocity access tokens (#259)
- Always fetch a token for every hostname in the access key
- Use any tokens that are successfully fetched
- Retain access key if no tokens can be fetched
2024-06-14 21:18:08 -06:00
bigdaz
b53238971c [bot] Update dist directory 2024-06-14 22:45:05 +00:00
Inaki Villar
5f1c5827bf handle missing access token 2024-06-14 16:44:06 -06:00
bigdaz
d9336dac04 [bot] Update dist directory 2024-06-13 19:36:18 +00:00
daz
8dbe9a3802 Update DV access key regex to be more selective
This should address the code-scanning alert
  https://github.com/gradle/actions/security/code-scanning/1
2024-06-13 13:35:19 -06:00
bigdaz
9c3430720d [bot] Update dist directory 2024-06-13 19:32:23 +00:00
daz
30c82f0068 Fail on invalid boolean for Develocity inputs 2024-06-13 13:31:25 -06:00
daz
e3bc05f224 Run CodeQL on PRs 2024-06-13 13:15:23 -06:00
daz
485ea107b7 Run CodeQL on dev/* branches 2024-06-13 13:01:56 -06:00
bigdaz
c1091c9c8e [bot] Update dist directory 2024-06-13 18:43:53 +00:00
Iñaki Villar
d0a116fff5 Adding Develocity input actions (#244)
Adding Develocity input actions. 

If an input is configured in the action, it will generate the environment variable, example:

```yaml
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@v3
      with:
        develocity-injection-enabled: true
        develocity-url: https://develocity.your-server.com
        develocity-plugin-version: 3.17.4

    - name: Run a Gradle build with Develocity injection enabled from input actions
      run: ./gradlew build
```

This configuration will create the environment variables:
```
DEVELOCITY_INJECTION_ENABLED=true
DEVELOCITY_URL=https://develocity.your-server.com
DEVELOCITY_PLUGIN_VERSION=3.17.4
```

Relation variable-input available:

| Variable | Input |

|--------------------------------------|--------------------------------------|
| DEVELOCITY_INJECTION_ENABLED | develocity-injection-enabled |
| DEVELOCITY_URL | develocity-url |
| DEVELOCITY_ALLOW_UNTRUSTED_SERVER | develocity-allow-untrusted-server
|
| DEVELOCITY_CAPTURE_FILE_FINGERPRINTS |
develocity-capture-file-fingerprints |
| DEVELOCITY_ENFORCE_URL | develocity-enforce-url |
| DEVELOCITY_PLUGIN_VERSION | develocity-plugin-version |
| DEVELOCITY_CCUD_PLUGIN_VERSION | develocity-ccud-plugin-version |
| GRADLE_PLUGIN_REPOSITORY_URL | gradle-plugin-repository-url |
| GRADLE_PLUGIN_REPOSITORY_USERNAME | gradle-plugin-repository-username
|
| GRADLE_PLUGIN_REPOSITORY_PASSWORD | gradle-plugin-repository-password
|
2024-06-13 12:42:47 -06:00
bigdaz
e238a7ad22 [bot] Update dist directory 2024-06-13 16:01:59 +00:00
bot-githubaction
1d2ea6e5a8 Bump references to Develocity Gradle plugin from 3.17.4 to 3.17.5 2024-06-13 10:01:04 -06:00
dependabot[bot]
114c1c234e Bump braces from 3.0.2 to 3.0.3 in /sources
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-13 09:10:17 -06:00
daz
2db3ae936e Update to Gradle 8.8 2024-06-13 09:03:40 -06:00
dependabot[bot]
a68381d359 Bump com.google.guava:guava in /.github/workflow-samples/kotlin-dsl
Bumps [com.google.guava:guava](https://github.com/google/guava) from 33.2.0-jre to 33.2.1-jre.
- [Release notes](https://github.com/google/guava/releases)
- [Commits](https://github.com/google/guava/commits)

---
updated-dependencies:
- dependency-name: com.google.guava:guava
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-13 07:41:41 -06:00
bigdaz
52ae27f7bb [bot] Update dist directory 2024-06-13 13:41:01 +00:00
bigdaz
d1cd62d80a Update known wrapper checksums 2024-06-13 07:40:03 -06:00
Anton Mostovoy
af6e576724 add missing permission for downloading dependency graph artifact
per https://docs.github.com/en/rest/actions/artifacts?apiVersion=2022-11-28#list-workflow-run-artifacts, `actions: read` is required. Without it the action fails after logging `Fetching artifact list for workflow ` due to `Error: HttpError: Resource not accessible by integration`
2024-05-23 09:09:36 -06:00
bigdaz
775b4d10d7 [bot] Update dist directory 2024-05-23 14:57:08 +00:00
Bot Githubaction
30610bc983 Bump references to Develocity Gradle plugin from 3.17.3 to 3.17.4 (#236)
This PR bumps references to Develocity Gradle plugin from 3.17.3 to 3.17.4.

---------

Co-authored-by: Eric Haag <ehaag@gradle.com>
2024-05-23 08:56:09 -06:00
bigdaz
d4d72c9934 [bot] Update dist directory 2024-05-17 21:08:44 +00:00
Alexis Tual
96b9cb4988 Set both DEVELOCITY_ACCESS_KEY and GRADLE_ENTERPRISE_ACCESS_KEY env vars (#225)
Follow up of https://github.com/gradle/actions/pull/224, we now attempt to set both old and new access key env variables to a short lived token.
If a short-lived token cannot be obtained, then:
- DEVELOCITY_ACCESS_KEY is set to an empty string, preventing this from being used.
- GRADLE_ENTERPRISE_ACCESS_KEY is left intact, with a deprecation warning being issued.
2024-05-17 15:07:50 -06:00
Bot Githubaction
db270b9337 Update develocity-injection init script to v1.0
Updates the develocity-injection init script to the latest reference script content
from https://github.com/gradle/develocity-ci-injection.
2024-05-17 14:18:19 -06:00
Bot Githubaction
d91e2960eb Update develocity-injection init script to v0.5.1
Updates the develocity-injection init script to the latest reference script content
from https://github.com/gradle/develocity-ci-injection.
2024-05-17 11:10:27 -06:00
bigdaz
0498421560 Update develocity-injection init script to v0.5.0 2024-05-17 07:27:33 -06:00
bigdaz
edb13383f3 Update develocity-injection init script to v0.4.0 2024-05-15 16:56:41 -06:00
bigdaz
cd560aa3ad [bot] Update dist directory 2024-05-15 22:50:56 +00:00
Alexis Tual
500e0ee5b3 Add support for short-lived tokens (#224)
The setup-gradle action tries to get a short-lived access token given the supplied Develocity access key.
This key can be passed either with the `DEVELOCITY_ACCESS_KEY` env var or via the  `develocity-access-key` input parameter.
If a token can be retrieved, then the `DEVELOCITY_ACCESS_KEY` env var will be set to the token. 
Otherwise the `DEVELOCITY_ACCESS_KEY` will be set to a blank string, to avoid a leak.

---------

Co-authored-by: daz <daz@gradle.com>
2024-05-15 16:49:55 -06:00
bigdaz
eb13cf7170 [bot] Update dist directory 2024-05-11 13:46:41 +00:00
Daz DeBoer
ea14aa9caf Dependency updates (#222)
- Bump to com.gradle.develocity plugin v3.17.3
- Bump JVM dependencies in sample projects
2024-05-11 07:45:47 -06:00
lokalpage-safe
063cfaf0eb Update dependency-submission.md
fix: Fixed document typo (additonal -> additional)
2024-05-09 15:54:39 -06:00
Maxim Mironyuk
35f9242e22 Update setup-gradle.md
repsitory -> repository
2024-05-09 15:54:08 -06:00
bigdaz
90f1de0556 [bot] Update dist directory 2024-04-28 14:50:56 +00:00
bigdaz
da512b52a5 Update known wrapper checksums 2024-04-28 15:49:59 +01:00
45 changed files with 2221 additions and 558 deletions

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,5 +1,5 @@
plugins {
id "com.gradle.develocity" version "3.17.2"
id "com.gradle.develocity" version "3.17.5"
id "com.gradle.common-custom-user-data-gradle-plugin" version "2.0.1"
}

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -8,7 +8,7 @@ repositories {
dependencies {
api("org.apache.commons:commons-math3:3.6.1")
implementation("com.google.guava:guava:33.1.0-jre")
implementation("com.google.guava:guava:33.2.1-jre")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
}

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,5 +1,5 @@
plugins {
id("com.gradle.develocity") version "3.17.2"
id("com.gradle.develocity") version "3.17.5"
id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.1"
}

View File

@@ -1,5 +1,5 @@
plugins {
id "com.gradle.develocity" version "3.17.2"
id "com.gradle.develocity" version "3.17.5"
}
develocity {

View File

@@ -1,5 +1,5 @@
plugins {
id "com.gradle.develocity" version "3.17.2"
id "com.gradle.develocity" version "3.17.5"
}
develocity {

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,5 +1,5 @@
plugins {
id "com.gradle.develocity" version "3.17.2"
id "com.gradle.develocity" version "3.17.5"
}
develocity {

View File

@@ -5,6 +5,12 @@ on:
branches:
- 'main'
- 'release/**'
- 'dev/**' # Allow running Code QL on dev branches without a PR
paths-ignore:
- 'dist/**'
pull_request:
branches:
- 'main'
paths-ignore:
- 'dist/**'
schedule:

View File

@@ -26,14 +26,19 @@ jobs:
DEVELOCITY_URL: https://ge.solutions-team.gradle.com
DEVELOCITY_PLUGIN_VERSION: ${{ matrix.plugin-version }}
DEVELOCITY_CCUD_PLUGIN_VERSION: '2.0'
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} # required to test against GE plugin 3.16.2
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
${{matrix.accessKeyEnv}}: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
strategy:
fail-fast: false
matrix:
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
os: ${{fromJSON(inputs.runner-os)}}
plugin-version: [3.16.2, 3.17.2]
plugin-version: [3.16.2, 3.17.4]
include:
- plugin-version: 3.16.2
accessKeyEnv: GRADLE_ENTERPRISE_ACCESS_KEY
- plugin-version: 3.17.4
accessKeyEnv: DEVELOCITY_ACCESS_KEY
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
@@ -62,3 +67,135 @@ jobs:
with:
script: |
core.setFailed('No Build Scan detected')
- name: Check short lived token (DEVELOCITY_ACCESS_KEY)
run: "[ ${#DEVELOCITY_ACCESS_KEY} -gt 500 ] || (echo 'DEVELOCITY_ACCESS_KEY does not look like a short lived token'; exit 1)"
- name: Check short lived token (GRADLE_ENTERPRISE_ACCESS_KEY)
run: "[ ${#GRADLE_ENTERPRISE_ACCESS_KEY} -gt 500 ] || (echo 'GRADLE_ENTERPRISE_ACCESS_KEY does not look like a short lived token'; exit 1)"
inject-develocity-with-access-key:
env:
DEVELOCITY_INJECTION_ENABLED: true
DEVELOCITY_URL: 'https://ge.solutions-team.gradle.com'
DEVELOCITY_PLUGIN_VERSION: ${{ matrix.plugin-version }}
DEVELOCITY_CCUD_PLUGIN_VERSION: '2.0'
strategy:
fail-fast: false
matrix:
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
os: ${{fromJSON(inputs.runner-os)}}
plugin-version: [3.16.2, 3.17.4]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Initialize integ-test
uses: ./.github/actions/init-integ-test
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
- name: Setup Gradle
id: setup-gradle
uses: ./setup-gradle
with:
cache-read-only: false # For testing, allow writing cache entries on non-default branches
gradle-version: ${{ matrix.gradle }}
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
develocity-token-expiry: 1
- name: Run Gradle build
id: gradle
working-directory: .github/workflow-samples/no-ge
run: gradle help
- name: Check short lived token (DEVELOCITY_ACCESS_KEY)
run: "[ ${#DEVELOCITY_ACCESS_KEY} -gt 500 ] || (echo 'DEVELOCITY_ACCESS_KEY does not look like a short lived token'; exit 1)"
- name: Check short lived token (GRADLE_ENTERPRISE_ACCESS_KEY)
run: "[ ${#GRADLE_ENTERPRISE_ACCESS_KEY} -gt 500 ] || (echo 'GRADLE_ENTERPRISE_ACCESS_KEY does not look like a short lived token'; exit 1)"
- name: Check Build Scan url
if: ${{ !steps.gradle.outputs.build-scan-url }}
uses: actions/github-script@v7
with:
script: |
core.setFailed('No Build Scan detected')
inject-develocity-short-lived-token-failed:
env:
DEVELOCITY_INJECTION_ENABLED: true
DEVELOCITY_URL: 'https://localhost:3333/'
DEVELOCITY_PLUGIN_VERSION: ${{ matrix.plugin-version }}
DEVELOCITY_CCUD_PLUGIN_VERSION: '2.0'
# Access key also set as an env var, we want to check it does not leak
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
strategy:
fail-fast: false
matrix:
gradle: [ current, 7.6.2, 6.9.4, 5.6.4 ]
os: ${{fromJSON(inputs.runner-os)}}
plugin-version: [ 3.16.2, 3.17.4 ]
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Initialize integ-test
uses: ./.github/actions/init-integ-test
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
- name: Setup Gradle
id: setup-gradle
uses: ./setup-gradle
with:
cache-read-only: false # For testing, allow writing cache entries on non-default branches
develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
- name: Run Gradle build
id: gradle
working-directory: .github/workflow-samples/no-ge
run: gradle help
- name: Check access key is not blank (DEVELOCITY_ACCESS_KEY)
run: "[ \"${DEVELOCITY_ACCESS_KEY}\" != \"\" ] || (echo 'using DEVELOCITY_ACCESS_KEY!'; exit 1)"
- name: Check access key is not blank (GRADLE_ENTERPRISE_ACCESS_KEY)
run: "[ \"${GRADLE_ENTERPRISE_ACCESS_KEY}\" != \"\" ] || (echo 'GRADLE_ENTERPRISE_ACCESS_KEY is still supported in v3!'; exit 1)"
inject-develocity-with-access-key-from-input-actions:
env:
DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }}
strategy:
fail-fast: false
matrix:
gradle: [ current, 7.6.2, 6.9.4, 5.6.4 ]
os: ${{fromJSON(inputs.runner-os)}}
plugin-version: [ 3.16.2, 3.17.4 ]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Initialize integ-test
uses: ./.github/actions/init-integ-test
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8
- name: Setup Gradle
id: setup-gradle
uses: ./setup-gradle
with:
cache-read-only: false # For testing, allow writing cache entries on non-default branches
gradle-version: ${{ matrix.gradle }}
develocity-injection-enabled: true
develocity-url: 'https://ge.solutions-team.gradle.com'
develocity-plugin-version: ${{ matrix.plugin-version }}
- 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@v7
with:
script: |
core.setFailed('No Build Scan detected')

8
build
View File

@@ -16,12 +16,18 @@ case "$1" in
# Run act
$@
# Revert the changes to the dist directory
git co -- dist
git checkout -- dist
;;
init-scripts)
cd test/init-scripts
./gradlew check
;;
dist)
npm install
npm run build
cd ..
cp -r sources/dist .
;;
*)
npm install
npm run build

View File

@@ -125,6 +125,14 @@ inputs:
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
required: false
develocity-access-key:
description: Develocity access key. Should be set to a secret containing the Develocity Access key.
required: false
develocity-token-expiry:
description: The Develocity short-lived access tokens expiry in hours. Default is 2 hours.
required: false
# DEPRECATED ACTION INPUTS
build-scan-terms-of-service-url:
description: The URL to the Build Scan® terms of use. This input must be set to 'https://gradle.com/terms-of-service'.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -95,7 +95,7 @@ In some cases, the default action configuration will not be sufficient, and addi
dependency-resolution-task: myDependencyResolutionTask
# Additional arguments that should be passed to execute Gradle
additonal-arguments: --no-configuration-cache
additional-arguments: --no-configuration-cache
# Enable configuration-cache reuse for this build.
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
@@ -367,6 +367,7 @@ on:
types: [completed]
permissions:
actions: read
contents: write
jobs:

View File

@@ -101,7 +101,7 @@ The exact syntax depends on whether or not your project is configured with the [
- name: Setup Gradle for a non-wrapper project
uses: gradle/actions/setup-gradle@v3
with:
gradle-version: 8.7
gradle-version: 8.8
- name: Assemble the project
run: gradle assemble
@@ -143,3 +143,8 @@ to this:
build-scan-terms-of-use-agree: "yes"
```
These deprecated build-scan parameters are scheduled to be removed in `setup-gradle@v4` and `dependency-submission@v4`.
## The GRADLE_ENTERPRISE_ACCESS_KEY env var is deprecated
Gradle Enterprise has been renamed to Develocity starting from Gradle plugin 3.17 and Develocity server 2024.1.
In v4 release of the action, it will require setting the access key with the `develocity-access-key` input and Develocity 2024.1 at least to generate short-lived tokens.
If those requirements are not met, the `GRADLE_ENTERPRISE_ACCESS_KEY` env var will be cleared out and build scan publication or other authenticated Develocity operations won't be possible.

View File

@@ -198,7 +198,7 @@ jobs:
```
> [!IMPORTANT]
> The configuration cache cannot be saved or restored in workflows triggered by a pull requests from a repsitory fork.
> The configuration cache cannot be saved or restored in workflows triggered by a pull requests from a repository fork.
> This is because [GitHub secrets are not passed to workflows triggered by PRs from forks](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#using-secrets-in-a-workflow).
> This prevents a malicious PR from reading the configuration-cache data, which may encode secrets read by Gradle.
@@ -708,27 +708,49 @@ The same auto-injection behavior is available for the Common Custom User Data Gr
## Enabling Develocity injection
To enable Develocity injection for your build, you must provide the required configuration via environment variables.
To enable Develocity injection for your build, you must provide the required configuration via inputs.
Here's a minimal example:
```yaml
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
develocity-injection-enabled: true
develocity-url: https://develocity.your-server.com
develocity-plugin-version: 3.17.5
- name: Run a Gradle build with Develocity injection enabled
run: ./gradlew build
```
This configuration will automatically apply `v3.17.5` of the [Develocity Gradle plugin](https://docs.gradle.com/develocity/gradle-plugin/), and publish build scans to https://develocity.your-server.com.
This example assumes that the `develocity.your-server.com` server allows anonymous publishing of build scans.
In the likely scenario that your Develocity server requires authentication, you will also need to pass a valid [Develocity access key](https://docs.gradle.com/develocity/gradle-plugin/#via_environment_variable) taken from a secret:
```yaml
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
develocity-access-key: ${{ secrets.MY_DEVELOCITY_ACCESS_KEY }}
- name: Run a Gradle build with Develocity injection enabled
run: ./gradlew build
env:
DEVELOCITY_INJECTION_ENABLED: true
DEVELOCITY_URL: https://develocity.your-server.com
DEVELOCITY_PLUGIN_VERSION: 3.17.2
DEVELOCITY_PLUGIN_VERSION: 3.17
```
This configuration will automatically apply `v3.17.2` of the [Develocity Gradle plugin](https://docs.gradle.com/develocity/gradle-plugin/), and publish build scans to https://develocity.your-server.com.
This access key will be used during the action execution to get a short-lived token and set it to the DEVELOCITY_ACCESS_KEY environment variable.
This example assumes that the `develocity.your-server.com` server allows anonymous publishing of build scans.
In the likely scenario that your Develocity server requires authentication, you will also need to configure an additional environment variable
with a valid [Develocity access key](https://docs.gradle.com/develocity/gradle-plugin/#via_environment_variable).
### Short-lived access tokens
Develocity access keys are long-lived, creating risks if they are leaked. To avoid this, users can use short-lived access tokens to authenticate with Develocity. Access tokens can be used wherever an access key would be used. Access tokens are only valid for the Develocity instance that created them.
If a short-lived token fails to be retrieved (for example, if the Develocity server version is lower than `2024.1`):
- if a `GRADLE_ENTERPRISE_ACCESS_KEY` env var has been set, we're falling back to it with a deprecation warning
- otherwise no access key env var will be set. In that case Develocity authenticated operations like build cache read/write and build scan publication will fail without failing the build.
For more information on short-lived tokens, see [Develocity API documentation](https://docs.gradle.com/develocity/api-manual/#short_lived_access_tokens).
## Configuring Develocity injection
@@ -736,16 +758,46 @@ The `init-script` supports several additional configuration parameters that you
| 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/develocity/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 |
| 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/develocity/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 |
The input parameters can be expressed as environment variables following the relationships outlined in the table below:
| Input | Environment Variable |
|--------------------------------------|--------------------------------------|
| develocity-injection-enabled | DEVELOCITY_INJECTION_ENABLED |
| develocity-url | DEVELOCITY_URL |
| develocity-allow-untrusted-server | DEVELOCITY_ALLOW_UNTRUSTED_SERVER |
| develocity-capture-file-fingerprints | DEVELOCITY_CAPTURE_FILE_FINGERPRINTS |
| develocity-enforce-url | DEVELOCITY_ENFORCE_URL |
| develocity-plugin-version | DEVELOCITY_PLUGIN_VERSION |
| develocity-ccud-plugin-version | DEVELOCITY_CCUD_PLUGIN_VERSION |
| gradle-plugin-repository-url | GRADLE_PLUGIN_REPOSITORY_URL |
| gradle-plugin-repository-username | GRADLE_PLUGIN_REPOSITORY_USERNAME |
| gradle-plugin-repository-password | GRADLE_PLUGIN_REPOSITORY_PASSWORD |
Here's an example using the env vars:
```yaml
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- name: Run a Gradle build with Develocity injection enabled with environment variables
run: ./gradlew build
env:
DEVELOCITY_INJECTION_ENABLED: true
DEVELOCITY_URL: https://develocity.your-server.com
DEVELOCITY_PLUGIN_VERSION: 3.17.5
```
## Publishing to scans.gradle.com

View File

@@ -100,6 +100,54 @@ inputs:
description: Indicate that you agree to the Build Scan® terms of use. This input value must be "yes".
required: false
develocity-access-key:
description: Develocity access key. Should be set to a secret containing the Develocity Access key.
required: false
develocity-token-expiry:
description: The Develocity short-lived access tokens expiry in hours. Default is 2 hours.
required: false
develocity-injection-enabled:
description: Enables Develocity injection.
required: false
develocity-url:
description: The URL for the Develocity server.
required: false
develocity-allow-untrusted-server:
description: Allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed.
required: false
develocity-capture-file-fingerprints:
description: Enables capturing the paths and content hashes of each individual input file.
required: false
develocity-enforce-url:
description: 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.
required: false
develocity-plugin-version:
description: The version of the Develocity Gradle plugin to apply.
required: false
develocity-ccud-plugin-version:
description: The version of the Common Custom User Data Gradle plugin to apply, if any.
required: false
gradle-plugin-repository-url:
description: The URL of the repository to use when resolving the Develocity and CCUD plugins; the Gradle Plugin Portal is used by default.
required: false
gradle-plugin-repository-username:
description: The username for the repository URL to use when resolving the Develocity and CCUD.
required: false
gradle-plugin-repository-password:
description: 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.
required: false
# Wrapper validation configuration
validate-wrappers:
description: |

View File

@@ -1,3 +1,3 @@
# Configuration file for asdf version manager
nodejs 20.10.0
gradle 8.7
gradle 8.8

View File

@@ -3316,12 +3316,12 @@
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -4736,9 +4736,9 @@
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -11628,12 +11628,12 @@
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
"fill-range": "^7.1.1"
}
},
"browserslist": {
@@ -12659,9 +12659,9 @@
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"

View File

@@ -1,20 +0,0 @@
import * as core from '@actions/core'
import {BuildScanConfig} from './configuration'
export function setup(config: BuildScanConfig): void {
maybeExportVariable('DEVELOCITY_INJECTION_INIT_SCRIPT_NAME', 'gradle-actions.inject-develocity.init.gradle')
maybeExportVariable('DEVELOCITY_AUTO_INJECTION_CUSTOM_VALUE', 'gradle-actions')
if (config.getBuildScanPublishEnabled()) {
maybeExportVariable('DEVELOCITY_INJECTION_ENABLED', 'true')
maybeExportVariable('DEVELOCITY_PLUGIN_VERSION', '3.17.2')
maybeExportVariable('DEVELOCITY_CCUD_PLUGIN_VERSION', '2.0')
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_URL', config.getBuildScanTermsOfUseUrl())
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_AGREE', config.getBuildScanTermsOfUseAgree())
}
}
function maybeExportVariable(variableName: string, value: unknown): void {
if (!process.env[variableName]) {
core.exportVariable(variableName, value)
}
}

View File

@@ -188,6 +188,9 @@ export enum JobSummaryOption {
}
export class BuildScanConfig {
static DevelocityAccessKeyEnvVar = 'DEVELOCITY_ACCESS_KEY'
static GradleEnterpriseAccessKeyEnvVar = 'GRADLE_ENTERPRISE_ACCESS_KEY'
getBuildScanPublishEnabled(): boolean {
return getBooleanInput('build-scan-publish') && this.verifyTermsOfUseAgreement()
}
@@ -200,6 +203,59 @@ export class BuildScanConfig {
return this.getTermsOfUseProp('build-scan-terms-of-use-agree', 'build-scan-terms-of-service-agree')
}
getDevelocityAccessKey(): string {
return (
core.getInput('develocity-access-key') ||
process.env[BuildScanConfig.DevelocityAccessKeyEnvVar] ||
process.env[BuildScanConfig.GradleEnterpriseAccessKeyEnvVar] ||
''
)
}
getDevelocityTokenExpiry(): string {
return core.getInput('develocity-token-expiry')
}
getDevelocityInjectionEnabled(): boolean | undefined {
return getOptionalBooleanInput('develocity-injection-enabled')
}
getDevelocityUrl(): string {
return core.getInput('develocity-url')
}
getDevelocityAllowUntrustedServer(): boolean | undefined {
return getOptionalBooleanInput('develocity-allow-untrusted-server')
}
getDevelocityCaptureFileFingerprints(): boolean | undefined {
return getOptionalBooleanInput('develocity-capture-file-fingerprints')
}
getDevelocityEnforceUrl(): boolean | undefined {
return getOptionalBooleanInput('develocity-enforce-url')
}
getDevelocityPluginVersion(): string {
return core.getInput('develocity-plugin-version')
}
getDevelocityCcudPluginVersion(): string {
return core.getInput('develocity-ccud-plugin-version')
}
getGradlePluginRepositoryUrl(): string {
return core.getInput('gradle-plugin-repository-url')
}
getGradlePluginRepositoryUsername(): string {
return core.getInput('gradle-plugin-repository-username')
}
getGradlePluginRepositoryPassword(): string {
return core.getInput('gradle-plugin-repository-password')
}
private verifyTermsOfUseAgreement(): boolean {
if (
(this.getBuildScanTermsOfUseUrl() !== 'https://gradle.com/terms-of-service' &&
@@ -313,3 +369,11 @@ function getBooleanInput(paramName: string, paramDefault = false): boolean {
}
throw TypeError(`The value '${paramValue} is not valid for '${paramName}. Valid values are: [true, false]`)
}
function getOptionalBooleanInput(paramName: string): boolean | undefined {
const paramValue = core.getInput(paramName)
if (paramValue === '') {
return undefined
}
return getBooleanInput(paramName)
}

View File

@@ -0,0 +1,39 @@
import * as core from '@actions/core'
import {BuildScanConfig} from '../configuration'
import {setupToken} from './short-lived-token'
export async function setup(config: BuildScanConfig): Promise<void> {
maybeExportVariable('DEVELOCITY_INJECTION_INIT_SCRIPT_NAME', 'gradle-actions.inject-develocity.init.gradle')
maybeExportVariable('DEVELOCITY_AUTO_INJECTION_CUSTOM_VALUE', 'gradle-actions')
if (config.getBuildScanPublishEnabled()) {
maybeExportVariable('DEVELOCITY_INJECTION_ENABLED', 'true')
maybeExportVariable('DEVELOCITY_PLUGIN_VERSION', '3.17.5')
maybeExportVariable('DEVELOCITY_CCUD_PLUGIN_VERSION', '2.0')
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_URL', config.getBuildScanTermsOfUseUrl())
maybeExportVariable('DEVELOCITY_TERMS_OF_USE_AGREE', config.getBuildScanTermsOfUseAgree())
}
maybeExportVariableNotEmpty('DEVELOCITY_INJECTION_ENABLED', config.getDevelocityInjectionEnabled())
maybeExportVariableNotEmpty('DEVELOCITY_URL', config.getDevelocityUrl())
maybeExportVariableNotEmpty('DEVELOCITY_ALLOW_UNTRUSTED_SERVER', config.getDevelocityAllowUntrustedServer())
maybeExportVariableNotEmpty('DEVELOCITY_CAPTURE_FILE_FINGERPRINTS', config.getDevelocityCaptureFileFingerprints())
maybeExportVariableNotEmpty('DEVELOCITY_ENFORCE_URL', config.getDevelocityEnforceUrl())
maybeExportVariableNotEmpty('DEVELOCITY_PLUGIN_VERSION', config.getDevelocityPluginVersion())
maybeExportVariableNotEmpty('GRADLE_PLUGIN_REPOSITORY_URL', config.getGradlePluginRepositoryUrl())
maybeExportVariableNotEmpty('GRADLE_PLUGIN_REPOSITORY_USERNAME', config.getGradlePluginRepositoryUsername())
maybeExportVariableNotEmpty('GRADLE_PLUGIN_REPOSITORY_PASSWORD', config.getGradlePluginRepositoryPassword())
setupToken(config.getDevelocityAccessKey(), config.getDevelocityTokenExpiry())
}
function maybeExportVariable(variableName: string, value: unknown): void {
if (!process.env[variableName]) {
core.exportVariable(variableName, value)
}
}
function maybeExportVariableNotEmpty(variableName: string, value: unknown): void {
if (value !== null && value !== undefined && value !== '') {
maybeExportVariable(variableName, value)
}
}

View File

@@ -0,0 +1,160 @@
import * as httpm from 'typed-rest-client/HttpClient'
import * as core from '@actions/core'
import {BuildScanConfig} from '../configuration'
import {recordDeprecation} from '../deprecation-collector'
export async function setupToken(develocityAccessKey: string, develocityTokenExpiry: string): Promise<void> {
if (develocityAccessKey) {
try {
core.debug('Fetching short-lived token...')
const tokens = await getToken(develocityAccessKey, develocityTokenExpiry)
if (tokens != null && !tokens.isEmpty()) {
core.debug(`Got token(s), setting the access key env vars`)
const token = tokens.raw()
core.setSecret(token)
exportAccessKeyEnvVars(token)
} else {
handleMissingAccessToken()
}
} catch (e) {
handleMissingAccessToken()
core.warning(`Failed to fetch short-lived token, reason: ${e}`)
}
}
}
function exportAccessKeyEnvVars(value: string): void {
;[BuildScanConfig.DevelocityAccessKeyEnvVar, BuildScanConfig.GradleEnterpriseAccessKeyEnvVar].forEach(key =>
core.exportVariable(key, value)
)
}
function handleMissingAccessToken(): void {
core.warning(`Failed to fetch short-lived token for Develocity`)
if (process.env[BuildScanConfig.GradleEnterpriseAccessKeyEnvVar]) {
// We do not clear the GRADLE_ENTERPRISE_ACCESS_KEY env var in v3, to let the users upgrade to DV 2024.1
recordDeprecation(`The ${BuildScanConfig.GradleEnterpriseAccessKeyEnvVar} env var is deprecated`)
}
if (process.env[BuildScanConfig.DevelocityAccessKeyEnvVar]) {
core.warning(`The ${BuildScanConfig.DevelocityAccessKeyEnvVar} env var should be mapped to a short-lived token`)
}
}
export async function getToken(accessKey: string, expiry: string): Promise<DevelocityAccessCredentials | null> {
const empty: Promise<DevelocityAccessCredentials | null> = new Promise(r => r(null))
const develocityAccessKey = DevelocityAccessCredentials.parse(accessKey)
const shortLivedTokenClient = new ShortLivedTokenClient()
if (develocityAccessKey == null) {
return empty
}
const tokens = new Array<HostnameAccessKey>()
for (const k of develocityAccessKey.keys) {
try {
core.info(`Requesting short-lived Develocity access token for ${k.hostname}`)
const token = await shortLivedTokenClient.fetchToken(`https://${k.hostname}`, k, expiry)
tokens.push(token)
} catch (e) {
// Ignore failure to obtain token
core.info(`Failed to obtain short-lived Develocity access token for ${k.hostname}: ${e}`)
}
}
if (tokens.length > 0) {
return DevelocityAccessCredentials.of(tokens)
}
return empty
}
class ShortLivedTokenClient {
httpc = new httpm.HttpClient('gradle/actions/setup-gradle')
maxRetries = 3
retryInterval = 1000
async fetchToken(serverUrl: string, accessKey: HostnameAccessKey, expiry: string): Promise<HostnameAccessKey> {
const queryParams = expiry ? `?expiresInHours${expiry}` : ''
const sanitizedServerUrl = !serverUrl.endsWith('/') ? `${serverUrl}/` : serverUrl
const headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessKey.key}`
}
let attempts = 0
while (attempts < this.maxRetries) {
try {
const requestUrl = `${sanitizedServerUrl}api/auth/token${queryParams}`
core.debug(`Attempt ${attempts} to fetch short lived token at ${requestUrl}`)
const response = await this.httpc.post(requestUrl, '', headers)
if (response.message.statusCode === 200) {
const text = await response.readBody()
return new Promise<HostnameAccessKey>(resolve => resolve({hostname: accessKey.hostname, key: text}))
}
// This should be only 404
attempts++
if (attempts === this.maxRetries) {
return new Promise((resolve, reject) =>
reject(
new Error(
`Develocity short lived token request failed ${serverUrl} with status code ${response.message.statusCode}`
)
)
)
}
} catch (error) {
attempts++
if (attempts === this.maxRetries) {
return new Promise((resolve, reject) => reject(error))
}
}
await new Promise(resolve => setTimeout(resolve, this.retryInterval))
}
return new Promise((resolve, reject) => reject(new Error('Illegal state')))
}
}
type HostnameAccessKey = {
hostname: string
key: string
}
export class DevelocityAccessCredentials {
static readonly accessKeyRegexp = /^([^;=\s]+=\w+)(;[^;=\s]+=\w+)*$/
readonly keys: HostnameAccessKey[]
private constructor(allKeys: HostnameAccessKey[]) {
this.keys = allKeys
}
static of(allKeys: HostnameAccessKey[]): DevelocityAccessCredentials {
return new DevelocityAccessCredentials(allKeys)
}
private static readonly keyDelimiter = ';'
private static readonly hostDelimiter = '='
static parse(rawKey: string): DevelocityAccessCredentials | null {
if (!this.isValid(rawKey)) {
return null
}
return new DevelocityAccessCredentials(
rawKey.split(this.keyDelimiter).map(hostKey => {
const pair = hostKey.split(this.hostDelimiter)
return {hostname: pair[0], key: pair[1]}
})
)
}
isEmpty(): boolean {
return this.keys.length === 0
}
raw(): string {
return this.keys
.map(k => `${k.hostname}${DevelocityAccessCredentials.hostDelimiter}${k.key}`)
.join(DevelocityAccessCredentials.keyDelimiter)
}
private static isValid(allKeys: string): boolean {
return this.accessKeyRegexp.test(allKeys)
}
}

View File

@@ -1,16 +1,20 @@
/*
* Initscript for injection of Develocity into Gradle builds.
* Version: v1.0
*/
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 Develocity plugin to the classpath so it can be applied to the build further down in this script
initscript {
// NOTE: there is no mechanism to share code between the initscript{} block and the main script, so some logic is duplicated
def isTopLevelBuild = !gradle.parent
if (!isTopLevelBuild) {
return
}
def getInputParam = { String name ->
def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_')
def ENV_VAR_PREFIX = ''
def envVarName = ENV_VAR_PREFIX + name.toUpperCase().replace('.', '_').replace('-', '_')
return System.getProperty(name) ?: System.getenv(envVarName)
}
@@ -20,9 +24,9 @@ initscript {
return
}
// finish early if injection is disabled
def gradleInjectionEnabled = getInputParam("develocity.injection-enabled")
if (gradleInjectionEnabled != "true") {
// Plugin loading is only required for Develocity injection. Abort early if not enabled.
def develocityInjectionEnabled = Boolean.parseBoolean(getInputParam("develocity.injection-enabled"))
if (!develocityInjectionEnabled) {
return
}
@@ -75,29 +79,17 @@ initscript {
}
}
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 DEVELOCITY_PLUGIN_ID = 'com.gradle.develocity'
def DEVELOCITY_PLUGIN_CLASS = 'com.gradle.develocity.agent.gradle.DevelocityPlugin'
def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection'
def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin'
def CCUD_PLUGIN_CLASS = 'com.gradle.CommonCustomUserDataGradlePlugin'
static getInputParam(String name) {
def ENV_VAR_PREFIX = ''
def envVarName = ENV_VAR_PREFIX + name.toUpperCase().replace('.', '_').replace('-', '_')
return System.getProperty(name) ?: System.getenv(envVarName)
}
def isTopLevelBuild = !gradle.parent
if (!isTopLevelBuild) {
return
}
def getInputParam = { String name ->
def envVarName = name.toUpperCase().replace('.', '_').replace('-', '_')
return System.getProperty(name) ?: System.getenv(envVarName)
}
def requestedInitScriptName = getInputParam('develocity.injection.init-script-name')
def initScriptName = buildscript.sourceFile.name
if (requestedInitScriptName != initScriptName) {
@@ -105,205 +97,226 @@ if (requestedInitScriptName != initScriptName) {
return
}
// finish early if injection is disabled
def gradleInjectionEnabled = getInputParam("develocity.injection-enabled")
if (gradleInjectionEnabled != "true") {
return
def develocityInjectionEnabled = Boolean.parseBoolean(getInputParam("develocity.injection-enabled"))
if (develocityInjectionEnabled) {
enableDevelocityInjection()
}
def develocityUrl = getInputParam('develocity.url')
def develocityAllowUntrustedServer = Boolean.parseBoolean(getInputParam('develocity.allow-untrusted-server'))
def develocityEnforceUrl = Boolean.parseBoolean(getInputParam('develocity.enforce-url'))
def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('develocity.build-scan.upload-in-background'))
def develocityCaptureFileFingerprints = getInputParam('develocity.capture-file-fingerprints') ? Boolean.parseBoolean(getInputParam('develocity.capture-file-fingerprints')) : true
def develocityPluginVersion = getInputParam('develocity.plugin.version')
def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version')
def buildScanTermsOfUseUrl = getInputParam('develocity.terms-of-use.url')
def buildScanTermsOfUseAgree = getInputParam('develocity.terms-of-use.agree')
def ciAutoInjectionCustomValueValue = getInputParam('develocity.auto-injection.custom-value')
// To enable build-scan capture, a `captureBuildScanLink(String)` method must be added to `BuildScanCollector`.
def buildScanCollector = new BuildScanCollector()
def buildScanCaptureEnabled = buildScanCollector.metaClass.respondsTo(buildScanCollector, 'captureBuildScanLink', String)
if (buildScanCaptureEnabled) {
enableBuildScanLinkCapture(buildScanCollector)
}
def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0')
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
def shouldApplyDevelocityPlugin = atLeastGradle5 && develocityPluginVersion && isAtLeast(develocityPluginVersion, '3.17')
void enableDevelocityInjection() {
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin'
def dvOrGe = { def dvValue, def geValue ->
if (shouldApplyDevelocityPlugin) {
return dvValue instanceof Closure<?> ? dvValue() : dvValue
def GRADLE_ENTERPRISE_PLUGIN_ID = 'com.gradle.enterprise'
def GRADLE_ENTERPRISE_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin'
def DEVELOCITY_PLUGIN_ID = 'com.gradle.develocity'
def DEVELOCITY_PLUGIN_CLASS = 'com.gradle.develocity.agent.gradle.DevelocityPlugin'
def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection'
def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin'
def CCUD_PLUGIN_CLASS = 'com.gradle.CommonCustomUserDataGradlePlugin'
def develocityUrl = getInputParam('develocity.url')
def develocityAllowUntrustedServer = Boolean.parseBoolean(getInputParam('develocity.allow-untrusted-server'))
def develocityEnforceUrl = Boolean.parseBoolean(getInputParam('develocity.enforce-url'))
def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('develocity.build-scan.upload-in-background'))
def develocityCaptureFileFingerprints = getInputParam('develocity.capture-file-fingerprints') ? Boolean.parseBoolean(getInputParam('develocity.capture-file-fingerprints')) : true
def develocityPluginVersion = getInputParam('develocity.plugin.version')
def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version')
def buildScanTermsOfUseUrl = getInputParam('develocity.terms-of-use.url')
def buildScanTermsOfUseAgree = getInputParam('develocity.terms-of-use.agree')
def ciAutoInjectionCustomValueValue = getInputParam('develocity.auto-injection.custom-value')
def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0')
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
def shouldApplyDevelocityPlugin = atLeastGradle5 && develocityPluginVersion && isAtLeast(develocityPluginVersion, '3.17')
def dvOrGe = { def dvValue, def geValue ->
if (shouldApplyDevelocityPlugin) {
return dvValue instanceof Closure<?> ? dvValue() : dvValue
}
return geValue instanceof Closure<?> ? geValue() : geValue
}
return geValue instanceof Closure<?> ? geValue() : geValue
}
// 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
}
// 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 Develocity plugin
if (GradleVersion.current() < GradleVersion.version('6.0')) {
rootProject {
buildscript.configurations.getByName("classpath").incoming.afterResolve { ResolvableDependencies incoming ->
def resolutionResult = incoming.resolutionResult
// Conditionally apply and configure the Develocity plugin
if (GradleVersion.current() < GradleVersion.version('6.0')) {
rootProject {
buildscript.configurations.getByName("classpath").incoming.afterResolve { ResolvableDependencies incoming ->
def resolutionResult = incoming.resolutionResult
if (develocityPluginVersion) {
def scanPluginComponent = resolutionResult.allComponents.find {
it.moduleVersion.with { group == "com.gradle" && ['build-scan-plugin', 'gradle-enterprise-gradle-plugin', 'develocity-gradle-plugin'].contains(name) }
}
if (!scanPluginComponent) {
def pluginClass = dvOrGe(DEVELOCITY_PLUGIN_CLASS, BUILD_SCAN_PLUGIN_CLASS)
logger.lifecycle("Applying $pluginClass via init script")
applyPluginExternally(pluginManager, pluginClass)
def rootExtension = dvOrGe(
if (develocityPluginVersion) {
def scanPluginComponent = resolutionResult.allComponents.find {
it.moduleVersion.with { group == "com.gradle" && ['build-scan-plugin', 'gradle-enterprise-gradle-plugin', 'develocity-gradle-plugin'].contains(name) }
}
if (!scanPluginComponent) {
def pluginClass = dvOrGe(DEVELOCITY_PLUGIN_CLASS, BUILD_SCAN_PLUGIN_CLASS)
logger.lifecycle("Applying $pluginClass via init script")
applyPluginExternally(pluginManager, pluginClass)
def rootExtension = dvOrGe(
{ develocity },
{ buildScan }
)
def buildScanExtension = dvOrGe(
)
def buildScanExtension = dvOrGe(
{ rootExtension.buildScan },
{ rootExtension }
)
if (develocityUrl) {
logger.lifecycle("Connection to Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
rootExtension.server = develocityUrl
rootExtension.allowUntrustedServer = develocityAllowUntrustedServer
}
if (!shouldApplyDevelocityPlugin) {
// Develocity plugin publishes scans by default
buildScanExtension.publishAlways()
}
// uploadInBackground not available for build-scan-plugin 1.16
if (buildScanExtension.metaClass.respondsTo(buildScanExtension, 'setUploadInBackground', Boolean)) buildScanExtension.uploadInBackground = buildScanUploadInBackground
buildScanExtension.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, ciAutoInjectionCustomValueValue
if (isAtLeast(develocityPluginVersion, '2.1') && atLeastGradle5) {
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
if (isAtLeast(develocityPluginVersion, '3.17')) {
buildScanExtension.capture.fileFingerprints.set(develocityCaptureFileFingerprints)
} else if (isAtLeast(develocityPluginVersion, '3.7')) {
buildScanExtension.capture.taskInputFiles = develocityCaptureFileFingerprints
} else {
buildScanExtension.captureTaskInputFiles = develocityCaptureFileFingerprints
)
if (develocityUrl) {
logger.lifecycle("Connection to Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
rootExtension.server = develocityUrl
rootExtension.allowUntrustedServer = develocityAllowUntrustedServer
}
if (!shouldApplyDevelocityPlugin) {
// Develocity plugin publishes scans by default
buildScanExtension.publishAlways()
}
// uploadInBackground not available for build-scan-plugin 1.16
if (buildScanExtension.metaClass.respondsTo(buildScanExtension, 'setUploadInBackground', Boolean)) buildScanExtension.uploadInBackground = buildScanUploadInBackground
buildScanExtension.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, ciAutoInjectionCustomValueValue
if (isAtLeast(develocityPluginVersion, '2.1') && atLeastGradle5) {
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
if (isAtLeast(develocityPluginVersion, '3.17')) {
buildScanExtension.capture.fileFingerprints.set(develocityCaptureFileFingerprints)
} else if (isAtLeast(develocityPluginVersion, '3.7')) {
buildScanExtension.capture.taskInputFiles = develocityCaptureFileFingerprints
} else {
buildScanExtension.captureTaskInputFiles = develocityCaptureFileFingerprints
}
}
}
if (develocityUrl && develocityEnforceUrl) {
logger.lifecycle("Enforcing Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
}
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
// Only execute if develocity plugin isn't applied.
if (gradle.rootProject.extensions.findByName("develocity")) return
afterEvaluate {
if (develocityUrl && develocityEnforceUrl) {
buildScan.server = develocityUrl
buildScan.allowUntrustedServer = develocityAllowUntrustedServer
}
}
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
buildScan.termsOfServiceUrl = buildScanTermsOfUseUrl
buildScan.termsOfServiceAgree = buildScanTermsOfUseAgree
}
}
pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
afterEvaluate {
if (develocityUrl && develocityEnforceUrl) {
develocity.server = develocityUrl
develocity.allowUntrustedServer = develocityAllowUntrustedServer
}
}
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
develocity.buildScan.termsOfUseUrl = buildScanTermsOfUseUrl
develocity.buildScan.termsOfUseAgree = buildScanTermsOfUseAgree
}
}
}
if (ccudPluginVersion && atLeastGradle4) {
def ccudPluginComponent = resolutionResult.allComponents.find {
it.moduleVersion.with { group == "com.gradle" && name == "common-custom-user-data-gradle-plugin" }
}
if (!ccudPluginComponent) {
logger.lifecycle("Applying $CCUD_PLUGIN_CLASS via init script")
pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
}
}
}
}
} else {
gradle.settingsEvaluated { settings ->
if (develocityPluginVersion) {
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID) && !settings.pluginManager.hasPlugin(DEVELOCITY_PLUGIN_ID)) {
def pluginClass = dvOrGe(DEVELOCITY_PLUGIN_CLASS, GRADLE_ENTERPRISE_PLUGIN_CLASS)
logger.lifecycle("Applying $pluginClass via init script")
applyPluginExternally(settings.pluginManager, pluginClass)
if (develocityUrl) {
logger.lifecycle("Connection to Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
eachDevelocitySettingsExtension(settings) { ext ->
ext.server = develocityUrl
ext.allowUntrustedServer = develocityAllowUntrustedServer
}
}
eachDevelocitySettingsExtension(settings) { ext ->
ext.buildScan.uploadInBackground = buildScanUploadInBackground
ext.buildScan.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, ciAutoInjectionCustomValueValue
}
eachDevelocitySettingsExtension(settings,
{ develocity ->
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
develocity.buildScan.capture.fileFingerprints = develocityCaptureFileFingerprints
},
{ gradleEnterprise ->
gradleEnterprise.buildScan.publishAlways()
if (isAtLeast(develocityPluginVersion, '2.1')) {
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
if (isAtLeast(develocityPluginVersion, '3.7')) {
gradleEnterprise.buildScan.capture.taskInputFiles = develocityCaptureFileFingerprints
} else {
gradleEnterprise.buildScan.captureTaskInputFiles = develocityCaptureFileFingerprints
}
}
}
)
}
if (develocityUrl && develocityEnforceUrl) {
logger.lifecycle("Enforcing Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
}
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
// Only execute if develocity plugin isn't applied.
if (gradle.rootProject.extensions.findByName("develocity")) return
afterEvaluate {
if (develocityUrl && develocityEnforceUrl) {
buildScan.server = develocityUrl
buildScan.allowUntrustedServer = develocityAllowUntrustedServer
}
}
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
buildScan.termsOfServiceUrl = buildScanTermsOfUseUrl
buildScan.termsOfServiceAgree = buildScanTermsOfUseAgree
}
}
pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
afterEvaluate {
eachDevelocitySettingsExtension(settings,
{ develocity ->
if (develocityUrl && develocityEnforceUrl) {
develocity.server = develocityUrl
develocity.allowUntrustedServer = develocityAllowUntrustedServer
}
}
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
develocity.buildScan.termsOfUseUrl = buildScanTermsOfUseUrl
develocity.buildScan.termsOfUseAgree = buildScanTermsOfUseAgree
}
}
}
if (ccudPluginVersion && atLeastGradle4) {
def ccudPluginComponent = resolutionResult.allComponents.find {
it.moduleVersion.with { group == "com.gradle" && name == "common-custom-user-data-gradle-plugin" }
}
if (!ccudPluginComponent) {
logger.lifecycle("Applying $CCUD_PLUGIN_CLASS via init script")
pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
}
}
}
}
} else {
gradle.settingsEvaluated { settings ->
if (develocityPluginVersion) {
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID) && !settings.pluginManager.hasPlugin(DEVELOCITY_PLUGIN_ID)) {
def pluginClass = dvOrGe(DEVELOCITY_PLUGIN_CLASS, GRADLE_ENTERPRISE_PLUGIN_CLASS)
logger.lifecycle("Applying $pluginClass via init script")
applyPluginExternally(settings.pluginManager, pluginClass)
if (develocityUrl) {
logger.lifecycle("Connection to Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
eachDevelocitySettingsExtension(settings) { ext ->
ext.server = develocityUrl
ext.allowUntrustedServer = develocityAllowUntrustedServer
}
}
eachDevelocitySettingsExtension(settings) { ext ->
ext.buildScan.uploadInBackground = buildScanUploadInBackground
ext.buildScan.value CI_AUTO_INJECTION_CUSTOM_VALUE_NAME, ciAutoInjectionCustomValueValue
}
eachDevelocitySettingsExtension(settings,
{ develocity ->
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
develocity.buildScan.capture.fileFingerprints = develocityCaptureFileFingerprints
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
develocity.buildScan.termsOfUseUrl = buildScanTermsOfUseUrl
develocity.buildScan.termsOfUseAgree = buildScanTermsOfUseAgree
}
},
{ gradleEnterprise ->
gradleEnterprise.buildScan.publishAlways()
if (isAtLeast(develocityPluginVersion, '2.1')) {
logger.lifecycle("Setting captureFileFingerprints: $develocityCaptureFileFingerprints")
if (isAtLeast(develocityPluginVersion, '3.7')) {
gradleEnterprise.buildScan.capture.taskInputFiles = develocityCaptureFileFingerprints
} else {
gradleEnterprise.buildScan.captureTaskInputFiles = develocityCaptureFileFingerprints
}
if (develocityUrl && develocityEnforceUrl) {
gradleEnterprise.server = develocityUrl
gradleEnterprise.allowUntrustedServer = develocityAllowUntrustedServer
}
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
gradleEnterprise.buildScan.termsOfServiceUrl = buildScanTermsOfUseUrl
gradleEnterprise.buildScan.termsOfServiceAgree = buildScanTermsOfUseAgree
}
}
)
}
if (develocityUrl && develocityEnforceUrl) {
logger.lifecycle("Enforcing Develocity: $develocityUrl, allowUntrustedServer: $develocityAllowUntrustedServer, captureFileFingerprints: $develocityCaptureFileFingerprints")
}
eachDevelocitySettingsExtension(settings,
{ develocity ->
if (develocityUrl && develocityEnforceUrl) {
develocity.server = develocityUrl
develocity.allowUntrustedServer = develocityAllowUntrustedServer
}
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
develocity.buildScan.termsOfUseUrl = buildScanTermsOfUseUrl
develocity.buildScan.termsOfUseAgree = buildScanTermsOfUseAgree
}
},
{ gradleEnterprise ->
if (develocityUrl && develocityEnforceUrl) {
gradleEnterprise.server = develocityUrl
gradleEnterprise.allowUntrustedServer = develocityAllowUntrustedServer
}
if (buildScanTermsOfUseUrl && buildScanTermsOfUseAgree) {
gradleEnterprise.buildScan.termsOfServiceUrl = buildScanTermsOfUseUrl
gradleEnterprise.buildScan.termsOfServiceAgree = buildScanTermsOfUseAgree
}
if (ccudPluginVersion) {
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
logger.lifecycle("Applying $CCUD_PLUGIN_CLASS via init script")
settings.pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
}
)
}
if (ccudPluginVersion) {
if (!settings.pluginManager.hasPlugin(CCUD_PLUGIN_ID)) {
logger.lifecycle("Applying $CCUD_PLUGIN_CLASS via init script")
settings.pluginManager.apply(initscript.classLoader.loadClass(CCUD_PLUGIN_CLASS))
}
}
}
@@ -361,3 +374,41 @@ static boolean isAtLeast(String versionUnderTest, String referenceVersion) {
static boolean isNotAtLeast(String versionUnderTest, String referenceVersion) {
!isAtLeast(versionUnderTest, referenceVersion)
}
void enableBuildScanLinkCapture(BuildScanCollector collector) {
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
def DEVELOCITY_PLUGIN_ID = 'com.gradle.develocity'
// Conditionally apply and configure the Develocity plugin
if (GradleVersion.current() < GradleVersion.version('6.0')) {
rootProject {
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
// Only execute if develocity plugin isn't applied.
if (gradle.rootProject.extensions.findByName("develocity")) return
buildScanPublishedAction(buildScan, collector)
}
pluginManager.withPlugin(DEVELOCITY_PLUGIN_ID) {
buildScanPublishedAction(develocity.buildScan, collector)
}
}
} else {
gradle.settingsEvaluated { settings ->
eachDevelocitySettingsExtension(settings) { ext ->
buildScanPublishedAction(ext.buildScan, collector)
}
}
}
}
// Action will only be called if a `BuildScanCollector.captureBuildScanLink` method is present.
// Add `void captureBuildScanLink(String) {}` to the `BuildScanCollector` class to respond to buildScanPublished events
static buildScanPublishedAction(def buildScanExtension, BuildScanCollector collector) {
if (buildScanExtension.metaClass.respondsTo(buildScanExtension, 'buildScanPublished', Action)) {
buildScanExtension.buildScanPublished { scan ->
collector.captureBuildScanLink(scan.buildScanUri.toString())
}
}
}
class BuildScanCollector {}

View File

@@ -4,7 +4,7 @@ import * as path from 'path'
import * as os from 'os'
import * as caches from './caching/caches'
import * as jobSummary from './job-summary'
import * as buildScan from './build-scan'
import * as buildScan from './develocity/build-scan'
import {loadBuildResults, markBuildResultsProcessed} from './build-results'
import {CacheListener, generateCachingReport} from './caching/cache-reporting'
@@ -41,7 +41,7 @@ export async function setup(cacheConfig: CacheConfig, buildScanConfig: BuildScan
core.saveState(CACHE_LISTENER, cacheListener.stringify())
buildScan.setup(buildScanConfig)
await buildScan.setup(buildScanConfig)
return true
}

View File

@@ -1,4 +1,16 @@
[
{
"version": "8.8",
"checksum": "cb0da6751c2b753a16ac168bb354870ebb1e162e9083f116729cec9c781156b8"
},
{
"version": "8.8-rc-2",
"checksum": "cb0da6751c2b753a16ac168bb354870ebb1e162e9083f116729cec9c781156b8"
},
{
"version": "8.8-rc-1",
"checksum": "cb0da6751c2b753a16ac168bb354870ebb1e162e9083f116729cec9c781156b8"
},
{
"version": "8.7",
"checksum": "cb0da6751c2b753a16ac168bb354870ebb1e162e9083f116729cec9c781156b8"

View File

@@ -20,7 +20,7 @@ dependencies {
testImplementation ('io.ratpack:ratpack-groovy-test:1.9.0') {
exclude group: 'org.codehaus.groovy', module: 'groovy-all'
}
testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.17.0'
testImplementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-smile:2.17.1'
}
test {

View File

@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@@ -1,5 +1,5 @@
plugins {
id "com.gradle.develocity" version "3.17.2"
id "com.gradle.develocity" version "3.17.5"
id "com.gradle.common-custom-user-data-gradle-plugin" version "2.0.1"
}

View File

@@ -16,7 +16,7 @@ import java.nio.file.Files
import java.util.zip.GZIPOutputStream
class BaseInitScriptTest extends Specification {
static final String DEVELOCITY_PLUGIN_VERSION = '3.17.2'
static final String DEVELOCITY_PLUGIN_VERSION = '3.17.5'
static final String CCUD_PLUGIN_VERSION = '2.0.1'
static final TestGradleVersion GRADLE_3_X = new TestGradleVersion(GradleVersion.version('3.5.1'), 7, 9)

View File

@@ -190,7 +190,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
when:
settingsFile.text = """
plugins {
id 'com.gradle.develocity' version '3.17.2' apply(false)
id 'com.gradle.develocity' version '3.17.5' apply(false)
}
gradle.settingsEvaluated {
apply plugin: 'com.gradle.develocity'

View File

@@ -1,4 +1,5 @@
import * as exec from '@actions/exec'
import * as core from '@actions/core'
import fs from 'fs'
import path from 'path'
import {CacheCleaner} from '../../src/caching/cache-cleaner'
@@ -23,13 +24,13 @@ test('will cleanup unused dependency jars and build-cache entries', async () =>
expect(fs.existsSync(commonsMath31)).toBe(true)
expect(fs.existsSync(commonsMath311)).toBe(true)
expect(fs.readdirSync(buildCacheDir).length).toBe(6)
expect(fs.readdirSync(buildCacheDir).length).toBe(4) // gc.properties, build-cache-1.lock, and 2 task entries
await cacheCleaner.forceCleanup()
expect(fs.existsSync(commonsMath31)).toBe(false)
expect(fs.existsSync(commonsMath311)).toBe(true)
expect(fs.readdirSync(buildCacheDir).length).toBe(5)
expect(fs.readdirSync(buildCacheDir).length).toBe(3) // 1 task entry has been cleaned up
})
test('will cleanup unused gradle versions', async () => {
@@ -49,7 +50,7 @@ test('will cleanup unused gradle versions', async () => {
const gradle802 = path.resolve(gradleUserHome, "caches/8.0.2")
const wrapper802 = path.resolve(gradleUserHome, "wrapper/dists/gradle-8.0.2-bin")
const gradleCurrent = path.resolve(gradleUserHome, "caches/8.7")
const gradleCurrent = path.resolve(gradleUserHome, "caches/8.8")
expect(fs.existsSync(gradle802)).toBe(true)
expect(fs.existsSync(wrapper802)).toBe(true)

View File

@@ -0,0 +1,117 @@
import {DevelocityAccessCredentials, getToken} from "../../src/develocity/short-lived-token";
import nock from "nock";
describe('short lived tokens', () => {
it('parse valid access key should return an object', async () => {
let develocityAccessCredentials = DevelocityAccessCredentials.parse('some-host.local=key1;host2=key2');
expect(develocityAccessCredentials).toStrictEqual(DevelocityAccessCredentials.of([
{hostname: 'some-host.local', key: 'key1'},
{hostname: 'host2', key: 'key2'}])
)
})
it('parse wrong access key should return null', async () => {
let develocityAccessCredentials = DevelocityAccessCredentials.parse('random;foo');
expect(develocityAccessCredentials).toBeNull()
})
it('parse empty access key should return null', async () => {
let develocityAccessCredentials = DevelocityAccessCredentials.parse('');
expect(develocityAccessCredentials).toBeNull()
})
it('access key as raw string', async () => {
let develocityAccessCredentials = DevelocityAccessCredentials.parse('host1=key1;host2=key2');
expect(develocityAccessCredentials?.raw()).toBe('host1=key1;host2=key2')
})
it('get short lived token fails when cannot connect', async () => {
nock('http://localhost:3333')
.post('/api/auth/token')
.times(3)
.replyWithError({
message: 'connect ECONNREFUSED 127.0.0.1:3333',
code: 'ECONNREFUSED'
})
await expect(getToken('localhost=key0', ''))
.resolves
.toBeNull()
})
it('get short lived token is null when request fails', async () => {
nock('http://dev:3333')
.post('/api/auth/token')
.times(3)
.reply(500, 'Internal error')
expect.assertions(1)
await expect(getToken('dev=xyz', ''))
.resolves
.toBeNull()
})
it('get short lived token returns null when access key is empty', async () => {
expect.assertions(1)
await expect(getToken('', ''))
.resolves
.toBeNull()
})
it('get short lived token succeeds when single key is set', async () => {
nock('https://dev')
.post('/api/auth/token')
.reply(200, 'token')
expect.assertions(1)
await expect(getToken('dev=key1', ''))
.resolves
.toEqual({"keys": [{"hostname": "dev", "key": "token"}]})
})
it('get short lived token succeeds when multiple keys are set', async () => {
nock('https://dev')
.post('/api/auth/token')
.reply(200, 'token1')
nock('https://prod')
.post('/api/auth/token')
.reply(200, 'token2')
expect.assertions(1)
await expect(getToken('dev=key1;prod=key2', ''))
.resolves
.toEqual({"keys": [{"hostname": "dev", "key": "token1"}, {"hostname": "prod", "key": "token2"}]})
})
it('get short lived token succeeds when multiple keys are set and one is failing', async () => {
nock('https://dev')
.post('/api/auth/token')
.reply(200, 'token1')
nock('https://bogus')
.post('/api/auth/token')
.times(3)
.reply(500, 'Internal Error')
nock('https://prod')
.post('/api/auth/token')
.reply(200, 'token2')
expect.assertions(1)
await expect(getToken('dev=key1;bogus=key0;prod=key2', ''))
.resolves
.toEqual({"keys": [{"hostname": "dev", "key": "token1"}, {"hostname": "prod", "key": "token2"}]})
})
it('get short lived token is null when multiple keys are set and all are failing', async () => {
nock('https://dev')
.post('/api/auth/token')
.times(3)
.reply(500, 'Internal Error')
nock('https://bogus')
.post('/api/auth/token')
.times(3)
.reply(500, 'Internal Error')
expect.assertions(1)
await expect(getToken('dev=key1;bogus=key0', ''))
.resolves
.toBeNull()
})
})