mirror of
https://github.com/gradle/actions.git
synced 2025-11-26 17:09:10 +08:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbbdc275be | ||
|
|
ae74429826 | ||
|
|
bdc7162ff9 | ||
|
|
31ae3562f6 | ||
|
|
719985db3d | ||
|
|
b53238971c | ||
|
|
5f1c5827bf | ||
|
|
d9336dac04 | ||
|
|
8dbe9a3802 | ||
|
|
9c3430720d | ||
|
|
30c82f0068 | ||
|
|
e3bc05f224 | ||
|
|
485ea107b7 | ||
|
|
c1091c9c8e | ||
|
|
d0a116fff5 | ||
|
|
e238a7ad22 | ||
|
|
1d2ea6e5a8 | ||
|
|
114c1c234e | ||
|
|
2db3ae936e | ||
|
|
a68381d359 | ||
|
|
52ae27f7bb | ||
|
|
d1cd62d80a | ||
|
|
af6e576724 | ||
|
|
775b4d10d7 | ||
|
|
30610bc983 | ||
|
|
d4d72c9934 | ||
|
|
96b9cb4988 | ||
|
|
db270b9337 | ||
|
|
d91e2960eb | ||
|
|
0498421560 | ||
|
|
edb13383f3 | ||
|
|
cd560aa3ad | ||
|
|
500e0ee5b3 | ||
|
|
eb13cf7170 | ||
|
|
ea14aa9caf | ||
|
|
063cfaf0eb | ||
|
|
35f9242e22 | ||
|
|
90f1de0556 | ||
|
|
da512b52a5 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.develocity" version "3.17.2"
|
||||
id "com.gradle.develocity" version "3.17.5"
|
||||
}
|
||||
|
||||
develocity {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.develocity" version "3.17.2"
|
||||
id "com.gradle.develocity" version "3.17.5"
|
||||
}
|
||||
|
||||
develocity {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id "com.gradle.develocity" version "3.17.2"
|
||||
id "com.gradle.develocity" version "3.17.5"
|
||||
}
|
||||
|
||||
develocity {
|
||||
|
||||
6
.github/workflows/ci-codeql.yml
vendored
6
.github/workflows/ci-codeql.yml
vendored
@@ -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:
|
||||
|
||||
143
.github/workflows/integ-test-inject-develocity.yml
vendored
143
.github/workflows/integ-test-inject-develocity.yml
vendored
@@ -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
8
build
@@ -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
|
||||
|
||||
@@ -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'.
|
||||
|
||||
342
dist/dependency-submission/main/index.js
vendored
342
dist/dependency-submission/main/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/dependency-submission/main/index.js.map
vendored
2
dist/dependency-submission/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
342
dist/dependency-submission/post/index.js
vendored
342
dist/dependency-submission/post/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/dependency-submission/post/index.js.map
vendored
2
dist/dependency-submission/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
342
dist/setup-gradle/main/index.js
vendored
342
dist/setup-gradle/main/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/setup-gradle/main/index.js.map
vendored
2
dist/setup-gradle/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
342
dist/setup-gradle/post/index.js
vendored
342
dist/setup-gradle/post/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/setup-gradle/post/index.js.map
vendored
2
dist/setup-gradle/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
50
dist/wrapper-validation/main/index.js
vendored
50
dist/wrapper-validation/main/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/wrapper-validation/main/index.js.map
vendored
2
dist/wrapper-validation/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Configuration file for asdf version manager
|
||||
nodejs 20.10.0
|
||||
gradle 8.7
|
||||
gradle 8.8
|
||||
|
||||
28
sources/package-lock.json
generated
28
sources/package-lock.json
generated
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
39
sources/src/develocity/build-scan.ts
Normal file
39
sources/src/develocity/build-scan.ts
Normal 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())
|
||||
|
||||
return 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)
|
||||
}
|
||||
}
|
||||
160
sources/src/develocity/short-lived-token.ts
Normal file
160
sources/src/develocity/short-lived-token.ts
Normal 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)
|
||||
}
|
||||
}
|
||||
@@ -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,42 +97,62 @@ 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 ->
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// finish early if configuration parameters passed in via system properties are not valid/supported
|
||||
if (ccudPluginVersion && isNotAtLeast(ccudPluginVersion, '1.7')) {
|
||||
// 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')) {
|
||||
// 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
|
||||
@@ -231,7 +243,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
gradle.settingsEvaluated { settings ->
|
||||
if (develocityPluginVersion) {
|
||||
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID) && !settings.pluginManager.hasPlugin(DEVELOCITY_PLUGIN_ID)) {
|
||||
@@ -307,6 +319,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void applyPluginExternally(def pluginManager, String pluginClassName) {
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
117
sources/test/jest/short-lived-token.test.ts
Normal file
117
sources/test/jest/short-lived-token.test.ts
Normal 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()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user