Compare commits

...

19 Commits

Author SHA1 Message Date
daz
42452daeb5 Add explicit process.exit() to avoid wait for hanging promises
When using the `@actions/cache` library to save cache entries, it seems that one
or more Promises remain unresolved after the save completes.
With Node20 this causes a delay when exiting the process: the default behaviour
now wait for these Promises to complete. Adding an explicit `Process.exit()`
removes the delay, returning to the Node 16 behaviour.

Fixes #1038
2024-01-16 18:01:46 -07:00
daz
346645706f Don't overwrite dependency-graph env vars
This allows these vars to be explicitly set, which is required for
testing (and could prove useful for debugging).
2024-01-16 09:43:56 -07:00
daz
5516b39940 Fix docs for dependency-graph param 2024-01-13 12:55:55 -07:00
Daz DeBoer
7099569988 Improve dependency graph failure handling (#1036)
One goal for the original dependency-graph support was to minimize it's
impact on existing workflows, by operating transparently and not
impacting the build outcome. This meant that any failures in
dependency-graph generation or submission were logged as warnings, but
did not cause the workflow to fail.

However, in some cases the primary purpose of a workflow is to generate
and submit a dependency graph: in these cases it is desirable to have
the workflow fail when this process breaks.

This PR introduces a new `dependency-graph-continue-on-failure`
parameter, which when `false` will enable the latter behaviour. It also
adds test coverage for different failures in dependency graph generation
and submission.

Fixes #1034 
Fixes #997
2024-01-13 15:32:28 +01:00
daz
610728fa8c Build outputs 2024-01-13 07:21:40 -07:00
daz
a835cbb991 Use latest release of dependency-graph plugin 2024-01-13 07:21:40 -07:00
daz
ee4d92bb22 Document 'dependency-graph-continue-on-error' 2024-01-13 07:21:40 -07:00
daz
173b6ae553 Improve testing for dependency graph failures
- Update test to use input param
- Rename Job to indicate expected failure
2024-01-13 07:21:08 -07:00
daz
a01f794d92 Add dependency-graph-continue-on-failure input param
- Translate to env var for init-script support
- Use when deciding whether to log or rethrow errors
- Add a custom error type to trigger failure in post action
2024-01-13 07:20:45 -07:00
daz
369fcc54d8 Add tests for dependency graph failures 2024-01-13 07:20:45 -07:00
daz
6523a87c8f Update supported Gradle versions to match plugin 2024-01-12 13:33:42 -07:00
daz
11693a1169 Run npm tasks concurrently 2024-01-12 07:22:24 -07:00
daz
0e6b90783e Fix dependency-graph with configuration-cache
When state is reused from the configuration cache, no dependencies are resolved.
This fix prevents the action from submitting an empty dependency graph in this case.
2024-01-11 21:25:29 -07:00
Iurii Ignatko
932abbbe13 Update GE injection script for Develocity rename
- Rename all env vars expected by init-script: `s/GRADLE_ENTERPRISE/DEVELOCITY`
- Update README for changes
- Use `Develocity` consistently in tests
2024-01-10 20:30:40 -07:00
Daz DeBoer
1a18d0b2d3 Update description of cache key 2024-01-09 20:10:49 -07:00
Daz DeBoer
7af89832c5 Further improvements to Merge Queue docs 2024-01-08 13:00:48 -07:00
Daz DeBoer
b5ebb0cc96 Document caching with merge-queue 2024-01-08 12:58:38 -07:00
daz
3a75647ad4 Remove 'gradle-executable' input param 2024-01-04 13:53:16 -07:00
daz
4dda5928c7 Update CodeQL config to latest default 2024-01-04 13:03:33 -07:00
29 changed files with 1690 additions and 446 deletions

View File

@@ -1,22 +1,10 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: CI-codeql name: CI-codeql
on: on:
push: push:
branches: [ main ] branches: [ "main" ]
pull_request: pull_request:
# The branches below must be a subset of the branches above branches: [ "main" ]
branches: [ main ]
schedule: schedule:
- cron: '25 23 * * 2' - cron: '25 23 * * 2'
@@ -32,9 +20,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: [ 'javascript' ] language: [ 'javascript-typescript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps: steps:
- name: Checkout repository - name: Checkout repository
@@ -45,26 +31,9 @@ jobs:
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. config: |
# By default, queries listed here will override any specified in a config file. paths:
# Prefix the list here with "+" to use these queries and those in the config file. - src
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v3

View File

@@ -36,6 +36,11 @@ jobs:
with: with:
cache-key-prefix: ${{github.run_number}}- cache-key-prefix: ${{github.run_number}}-
dependency-graph-failures:
uses: ./.github/workflows/integ-test-dependency-graph-failures.yml
with:
cache-key-prefix: ${{github.run_number}}-
execution-with-caching: execution-with-caching:
uses: ./.github/workflows/integ-test-execution-with-caching.yml uses: ./.github/workflows/integ-test-execution-with-caching.yml
with: with:
@@ -46,12 +51,12 @@ jobs:
with: with:
cache-key-prefix: ${{github.run_number}}- cache-key-prefix: ${{github.run_number}}-
gradle-enterprise-injection: develocity-injection:
uses: ./.github/workflows/integ-test-inject-gradle-enterprise.yml uses: ./.github/workflows/integ-test-inject-develocity.yml
with: with:
cache-key-prefix: ${{github.run_number}}- cache-key-prefix: ${{github.run_number}}-
secrets: secrets:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }} DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
provision-gradle-versions: provision-gradle-versions:
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml uses: ./.github/workflows/integ-test-provision-gradle-versions.yml

View File

@@ -59,6 +59,13 @@ jobs:
runner-os: '["ubuntu-latest"]' runner-os: '["ubuntu-latest"]'
download-dist: true download-dist: true
dependency-graph-failures:
needs: build-distribution
uses: ./.github/workflows/integ-test-dependency-graph-failures.yml
with:
runner-os: '["ubuntu-latest"]'
download-dist: true
execution-with-caching: execution-with-caching:
needs: build-distribution needs: build-distribution
uses: ./.github/workflows/integ-test-execution-with-caching.yml uses: ./.github/workflows/integ-test-execution-with-caching.yml
@@ -73,14 +80,14 @@ jobs:
runner-os: '["ubuntu-latest"]' runner-os: '["ubuntu-latest"]'
download-dist: true download-dist: true
gradle-enterprise-injection: develocity-injection:
needs: build-distribution needs: build-distribution
uses: ./.github/workflows/integ-test-inject-gradle-enterprise.yml uses: ./.github/workflows/integ-test-inject-develocity.yml
with: with:
runner-os: '["ubuntu-latest"]' runner-os: '["ubuntu-latest"]'
download-dist: true download-dist: true
secrets: secrets:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }} DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
provision-gradle-versions: provision-gradle-versions:
needs: build-distribution needs: build-distribution

View File

@@ -0,0 +1,103 @@
name: Test dependency graph
on:
workflow_call:
inputs:
cache-key-prefix:
type: string
runner-os:
type: string
default: '["ubuntu-latest"]'
download-dist:
type: boolean
default: false
env:
DOWNLOAD_DIST: ${{ inputs.download-dist }}
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-graph-${{ inputs.cache-key-prefix }}
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
jobs:
unsupported-gradle-version-warning:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
gradle-version: 7.0.1
dependency-graph: generate
dependency-graph-continue-on-failure: true
- name: Run with unsupported Gradle version
working-directory: .github/workflow-samples/groovy-dsl
run: |
if gradle help | grep -q 'warning::Dependency Graph is not supported for Gradle 7.0.1. No dependency snapshot will be generated.';
then
echo "Got the expected warning"
else
echo "Did not get the expected warning"
exit 1
fi
unsupported-gradle-version-failure:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
gradle-version: 7.0.1
dependency-graph: generate
dependency-graph-continue-on-failure: false
- name: Run with unsupported Gradle version
working-directory: .github/workflow-samples/groovy-dsl
run: |
if gradle help; then
echo "Expected build to fail with Gradle 7.0.1"
exit 1
fi
insufficient-permissions-warning:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
dependency-graph: generate-and-submit
dependency-graph-continue-on-failure: true
- name: Run with insufficient permissions
working-directory: .github/workflow-samples/groovy-dsl
run: ./gradlew help
# This test is primarily for demonstration: it's unclear how to check for warnings emitted in the post-action
SHOULD_FAIL-insufficient-permissions-failure:
runs-on: ubuntu-latest
permissions:
contents: read
continue-on-error: true
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
dependency-graph: generate-and-submit
dependency-graph-continue-on-failure: false
- name: Run with insufficient permissions
working-directory: .github/workflow-samples/groovy-dsl
run: ./gradlew help
# This test is primarily for demonstration: it's unclear how to check for a failure in the post-action

View File

@@ -90,11 +90,15 @@ jobs:
- id: gradle-build - id: gradle-build
run: ./gradlew build run: ./gradlew build
working-directory: .github/workflow-samples/groovy-dsl working-directory: .github/workflow-samples/groovy-dsl
- id: gradle-build-again
run: ./gradlew build
working-directory: .github/workflow-samples/groovy-dsl
- name: Check generated dependency graphs - name: Check generated dependency graphs
shell: bash shell: bash
run: | run: |
echo "gradle-assemble report file: ${{ steps.gradle-assemble.outputs.dependency-graph-file }}" echo "gradle-assemble report file: ${{ steps.gradle-assemble.outputs.dependency-graph-file }}"
echo "gradle-build report file: ${{ steps.gradle-build.outputs.dependency-graph-file }}" echo "gradle-build report file: ${{ steps.gradle-build.outputs.dependency-graph-file }}"
echo "gradle-build-again report file: ${{ steps.gradle-build-again.outputs.dependency-graph-file }}"
ls -l dependency-graph-reports ls -l dependency-graph-reports
if [ ! -e "${{ steps.gradle-assemble.outputs.dependency-graph-file }}" ]; then if [ ! -e "${{ steps.gradle-assemble.outputs.dependency-graph-file }}" ]; then
echo "Did not find gradle-assemble dependency graph file" echo "Did not find gradle-assemble dependency graph file"
@@ -104,3 +108,41 @@ jobs:
echo "Did not find gradle-build dependency graph files" echo "Did not find gradle-build dependency graph files"
exit 1 exit 1
fi fi
if [ ! -e "${{ steps.gradle-build-again.outputs.dependency-graph-file }}" ]; then
echo "Did not find gradle-build-again dependency graph files"
exit 1
fi
config-cache:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v4
- name: Download distribution if required
uses: ./.github/actions/download-dist
- name: Setup Gradle for dependency-graph generate
uses: ./
with:
dependency-graph: generate-and-submit
- id: config-cache-store
run: ./gradlew assemble --configuration-cache
working-directory: .github/workflow-samples/groovy-dsl
- name: Check and delete generated dependency graph
shell: bash
run: |
if [ ! -e "${{ steps.config-cache-store.outputs.dependency-graph-file }}" ]; then
echo "Did not find config-cache-store dependency graph files"
exit 1
fi
rm ${{ steps.config-cache-store.outputs.dependency-graph-file }}
- id: config-cache-reuse
run: ./gradlew assemble --configuration-cache
working-directory: .github/workflow-samples/groovy-dsl
- name: Check no dependency graph is generated
shell: bash
run: |
if [ ! -z "$(ls -A dependency-graph-reports)" ]; then
echo "Expected no dependency graph files to be generated"
ls -l dependency-graph-reports
exit 1
fi

View File

@@ -46,12 +46,6 @@ jobs:
gradle-version: release-candidate gradle-version: release-candidate
build-root-directory: .github/workflow-samples/no-wrapper build-root-directory: .github/workflow-samples/no-wrapper
arguments: help arguments: help
- name: Test use defined Gradle executable
uses: ./
with:
gradle-executable: .github/workflow-samples/groovy-dsl/gradlew${{ matrix.script-suffix }}
build-root-directory: .github/workflow-samples/no-wrapper
arguments: help
gradle-versions: gradle-versions:
strategy: strategy:

View File

@@ -1,4 +1,4 @@
name: Test gradle enterprise injection name: Test develocity injection
on: on:
workflow_call: workflow_call:
@@ -12,21 +12,21 @@ on:
type: boolean type: boolean
default: false default: false
secrets: secrets:
GRADLE_ENTERPRISE_ACCESS_KEY: DEVELOCITY_ACCESS_KEY:
required: true required: true
env: env:
DOWNLOAD_DIST: ${{ inputs.download-dist }} DOWNLOAD_DIST: ${{ inputs.download-dist }}
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }} GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }}
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
GRADLE_ENTERPRISE_INJECTION_ENABLED: true DEVELOCITY_INJECTION_ENABLED: true
GRADLE_ENTERPRISE_URL: https://ge.solutions-team.gradle.com DEVELOCITY_URL: https://ge.solutions-team.gradle.com
GRADLE_ENTERPRISE_PLUGIN_VERSION: 3.16.1 DEVELOCITY_PLUGIN_VERSION: 3.16.1
GRADLE_ENTERPRISE_CCUD_PLUGIN_VERSION: 1.12.1 DEVELOCITY_CCUD_PLUGIN_VERSION: 1.12.1
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} # This env var has not (yet) been renamed/aliased in GE plugin 3.16.1
jobs: jobs:
inject-gradle-enterprise: inject-develocity:
strategy: strategy:
matrix: matrix:
gradle: [current, 7.6.2, 6.9.4, 5.6.4] gradle: [current, 7.6.2, 6.9.4, 5.6.4]

112
README.md
View File

@@ -120,7 +120,7 @@ cache-disabled: true
By default, the `gradle-build-action` will only write to the cache from Jobs on the default (`main`/`master`) branch. By default, the `gradle-build-action` will only write to the cache from Jobs on the default (`main`/`master`) branch.
Jobs on other branches will read entries from the cache but will not write updated entries. Jobs on other branches will read entries from the cache but will not write updated entries.
See [Optimizing cache effectiveness](#optimizing-cache-effectiveness) for a more detailed explanation. See [Optimizing cache effectiveness](#select-which-branches-should-write-to-the-cache) for a more detailed explanation.
In some circumstances it makes sense to change this default, and to configure a workflow Job to read existing cache entries but not to write changes back. In some circumstances it makes sense to change this default, and to configure a workflow Job to read existing cache entries but not to write changes back.
@@ -247,11 +247,11 @@ For this reason, it's very difficult to create a cache key that will determinist
The Gradle User Home cache key is composed of: The Gradle User Home cache key is composed of:
- The current operating system (`RUNNER_OS`) - The current operating system (`RUNNER_OS`)
- The workflow name and Job ID - The Job id
- A hash of the Job matrix parameters - A hash of the Job matrix parameters and the workflow name
- The git SHA for the latest commit - The git SHA for the latest commit
Specifically, the cache key is: `${cache-protocol}-gradle|${runner-os}|${workflow-name}-${job-id}[${hash-of-job-matrix}]-${git-sha}` Specifically, the cache key is: `${cache-protocol}-gradle|${runner-os}|${job-id}[${hash-of-job-matrix-and-workflow-name}]-${git-sha}`
As such, the cache key is likely to change on each subsequent run of GitHub actions. As such, the cache key is likely to change on each subsequent run of GitHub actions.
This allows the most recent state to always be available in the GitHub actions cache. This allows the most recent state to always be available in the GitHub actions cache.
@@ -259,8 +259,8 @@ This allows the most recent state to always be available in the GitHub actions c
### Finding a matching cache entry ### Finding a matching cache entry
In most cases, no exact match will exist for the cache key. Instead, the Gradle User Home will be restored for the closest matching cache entry, using a set of "restore keys". The entries will be matched with the following precedence: In most cases, no exact match will exist for the cache key. Instead, the Gradle User Home will be restored for the closest matching cache entry, using a set of "restore keys". The entries will be matched with the following precedence:
- An exact match on OS, workflow name, job id, matrix and Git SHA - An exact match on OS, job id, workflow name, matrix and Git SHA
- The most recent entry saved for the same OS, workflow name, job id and matrix values - The most recent entry saved for the same OS, job id, workflow name and matrix values
- The most recent entry saved for the same OS and job id - The most recent entry saved for the same OS and job id
- The most recent entry saved for the same OS - The most recent entry saved for the same OS
@@ -314,20 +314,23 @@ There are some techniques that can be used to avoid/mitigate this issue:
### Select which branches should write to the cache ### Select which branches should write to the cache
GitHub cache entries are not shared between builds on different branches. GitHub cache entries are not shared between builds on different branches.
This means that each PR branch will have it's own Gradle User Home cache, and will not benefit from cache entries written by other PR branches. Workflow runs can restore caches created in either the current branch or the default branch (usually main).
An exception to this is that cache entries written in parent and upstream branches are visible to child branches, and cache entries for the default (`master`/`main`) branch can be read by actions invoked for any other branch. This means that each branch will have it's own Gradle User Home cache scope, and will not benefit from cache entries written for other (non-default) branches.
By default, the `gradle-build-action` will only _write_ to the cache for builds run on the default (`master`/`main`) branch. By default, the `gradle-build-action` will only _write_ to the cache for builds run on the default (`master`/`main`) branch.
Jobs run on other branches will only read from the cache. In most cases, this is the desired behaviour, Jobs run on other branches will only read from the cache. In most cases, this is the desired behavior.
because Jobs run against other branches will benefit from the cache Gradle User Home from `main`, This is because Jobs run on other branches will benefit from the cache Gradle User Home from `main`,
without writing private cache entries that could lead to evicting shared entries. without writing private cache entries that which could lead to evicting these shared entries.
If you have other long-lived development branches that would benefit from writing to the cache, If you have other long-lived development branches that would benefit from writing to the cache,
you can configure these by overriding the `cache-read-only` action parameter. you can configure this by disabling the `cache-read-only` action parameter for these branches.
See [Using the cache read-only](#using-the-cache-read-only) for more details. See [Using the cache read-only](#using-the-cache-read-only) for more details.
Similarly, you could use `cache-read-only` for certain jobs in the workflow, and instead have these jobs reuse the cache content from upstream jobs. Note there are some cases where writing cache entries is typically unhelpful (these are disabled by default):
- For `pull_request` triggered runs, the cache scope is limited to the merge ref (`refs/pull/.../merge`) and can only be restored by re-runs of the same pull request.
- For `merge_group` triggered runs, the cache scope is limited to a temporary branch with a special prefix created to validate pull request changes, and won't be available on subsequent Merge Queue executions.
### Exclude content from Gradle User Home cache ### Exclude content from Gradle User Home cache
As well as any wrapper distributions, the action will attempt to save and restore the `caches` and `notifications` directories from Gradle User Home. As well as any wrapper distributions, the action will attempt to save and restore the `caches` and `notifications` directories from Gradle User Home.
@@ -473,9 +476,10 @@ You enable GitHub Dependency Graph support by setting the `dependency-graph` act
| Option | Behaviour | | Option | Behaviour |
| --- | --- | | --- | --- |
| `disabled` | Do not generate a dependency graph for any build invocations.<p>This is the default. | | `disabled` | Do not generate a dependency graph for any build invocations.<p>This is the default. |
| `generate` | Generate a dependency graph snapshot for each build invocation, saving as a workflow artifact. | | `generate` | Generate a dependency graph snapshot for each build invocation. |
| `generate-and-submit` | As per `generate`, but any generated dependency graph snapshots will be submitted at the end of the job. | | `generate-and-submit` | Generate a dependency graph snapshot for each build invocation, and submit these via the Dependency Submission API on completion of the job. |
| `download-and-submit` | Download any previously saved dependency graph snapshots, submitting them via the Dependency Submission API. This can be useful to collect all snapshots in a matrix of builds and submit them in one step. | | `generate-and-upload` | Generate a dependency graph snapshot for each build invocation, saving as a workflow artifact. |
| `download-and-submit` | Download any previously saved dependency graph snapshots, and submit them via the Dependency Submission API. This can be useful to submit [dependency graphs for pull requests submitted from a repository forks](#dependency-graphs-for-pull-request-workflows). |
Example of a CI workflow that generates and submits a dependency graph: Example of a CI workflow that generates and submits a dependency graph:
```yaml ```yaml
@@ -509,6 +513,22 @@ Depending on [repository settings](https://docs.github.com/en/actions/security-g
> for a PR submitted from a forked repository. > for a PR submitted from a forked repository.
> For a configuration that supports this setup, see [Dependency Graphs for pull request workflows](#dependency-graphs-for-pull-request-workflows). > For a configuration that supports this setup, see [Dependency Graphs for pull request workflows](#dependency-graphs-for-pull-request-workflows).
### Making dependency graph failures cause Job failures
By default, if a failure is encountered when generating or submitting the dependency graph, the action will log the failure as a warning and continue.
This allows your workflow to be resilient to dependency graph failures, in case dependency graph production is a side-effect rather than the primary purpose of a workflow.
If instead you have a workflow that has a primary purpose to generate and submit a dependency graph, then it makes sense for this workflow to fail if the dependency
graph cannot be generated or submitted. You can enable this behaviour with the `dependency-graph-continue-on-failure` parameter, which defaults to `true`.
```yaml
# Ensure that the workflow Job will fail if the dependency graph cannot be submitted
- uses: gradle/gradle-build-action@v3
with:
dependency-graph: generate-and-submit
dependency-graph-continue-on-failure: false
```
### Using a custom plugin repository ### Using a custom plugin repository
By default, the action downloads the `github-dependency-graph-gradle-plugin` from the Gradle Plugin Portal (https://plugins.gradle.org). If your GitHub Actions environment does not have access to this URL, you can specify a custom plugin repository to use. By default, the action downloads the `github-dependency-graph-gradle-plugin` from the Gradle Plugin Portal (https://plugins.gradle.org). If your GitHub Actions environment does not have access to this URL, you can specify a custom plugin repository to use.
@@ -685,6 +705,9 @@ name: run-build-and-generate-dependency-snapshot
on: on:
pull_request: pull_request:
permissions:
contents: read
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -693,7 +716,7 @@ jobs:
- name: Setup Gradle to generate and submit dependency graphs - name: Setup Gradle to generate and submit dependency graphs
uses: gradle/gradle-build-action@v2 uses: gradle/gradle-build-action@v2
with: with:
dependency-graph: generate # Only generate in this job dependency-graph: generate-and-upload # Generate graphs and save as workflow artifacts
- name: Run a build, generating the dependency graph snapshot which will be submitted - name: Run a build, generating the dependency graph snapshot which will be submitted
run: ./gradlew build run: ./gradlew build
``` ```
@@ -707,6 +730,9 @@ on:
workflows: ['run-build-and-generate-dependency-snapshot'] workflows: ['run-build-and-generate-dependency-snapshot']
types: [completed] types: [completed]
permissions:
contents: write
jobs: jobs:
submit-dependency-graph: submit-dependency-graph:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -714,7 +740,7 @@ jobs:
- name: Retrieve dependency graph artifact and submit - name: Retrieve dependency graph artifact and submit
uses: gradle/gradle-build-action@v2 uses: gradle/gradle-build-action@v2
with: with:
dependency-graph: download-and-submit dependency-graph: download-and-submit # Download saved workflow artifacts and submit
``` ```
### Integrating `dependency-review-action` for pull request workflows ### Integrating `dependency-review-action` for pull request workflows
@@ -780,27 +806,26 @@ To reduce storage costs for these artifacts, you can set the `artifact-retention
# Gradle Enterprise plugin injection # Develocity plugin injection
The `gradle-build-action` provides support for injecting and configuring the Gradle Enterprise Gradle plugin into any Gradle build, without any modification to the project sources. The `gradle-build-action` provides support for injecting and configuring the Develocity Gradle plugin into any Gradle build, without any modification to the project sources.
This is achieved via an init-script installed into Gradle User Home, which is enabled and parameterized via environment variables. This is achieved via an init-script installed into Gradle User Home, which is enabled and parameterized via environment variables.
The same auto-injection behavior is available for the Common Custom User Data Gradle plugin, which enriches any build scans published with additional useful information. The same auto-injection behavior is available for the Common Custom User Data Gradle plugin, which enriches any build scans published with additional useful information.
## Enabling Gradle Enterprise injection ## Enabling Develocity injection
In order to enable Gradle Enterprise for your build, you must provide the required configuration via environment variables. In order to enable Develocity injection for your build, you must provide the required configuration via environment variables.
Here's a minimal example: Here's a minimal example:
```yaml ```yaml
name: Run build with Gradle Enterprise injection name: Run build with Develocity injection
env: env:
GRADLE_ENTERPRISE_INJECTION_ENABLED: true DEVELOCITY_INJECTION_ENABLED: true
GRADLE_ENTERPRISE_URL: https://ge.gradle.org DEVELOCITY_URL: https://develocity.your-server.com
GRADLE_ENTERPRISE_PLUGIN_VERSION: 3.16.1 DEVELOCITY_PLUGIN_VERSION: 3.16.1
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_KEY }} # Required to publish scans to ge.gradle.org
jobs: jobs:
build: build:
@@ -809,36 +834,37 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Gradle - name: Setup Gradle
uses: gradle/gradle-build-action@v2 uses: gradle/gradle-build-action@v2
- name: Run a Gradle build with Gradle Enterprise injection enabled - name: Run a Gradle build with Develocity injection enabled
run: ./gradlew build run: ./gradlew build
``` ```
This configuration will automatically apply `v3.16.1` of the [Gradle Enterprise Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/), and publish build scans to https://ge.gradle.org. This configuration will automatically apply `v3.16.1` of the [Develocity Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/), and publish build scans to https://develocity.your-server.com.
Note that the `ge.gradle.org` server requires authentication in order to publish scans. The provided `GRADLE_ENTERPRISE_ACCESS_KEY` isn't required by the Gradle Enterprise injection script, This example assumes that the `develocity.your-server.com` server allows anonymous publishing of build scans.
but will be used by the GE plugin in order to authenticate with the server. In the likely scenario that your Develocity server requires authentication, you will also need to configure an addition environment variable
with a valid [Develocity access key](https://docs.gradle.com/enterprise/gradle-plugin/#via_environment_variable).
## Configuring Gradle Enterprise injection ## Configuring Develocity injection
The `init-script` supports a number of additional configuration parameters that you may fine useful. All configuration options (required and optional) are detailed below: The `init-script` supports a number of additional configuration parameters that you may fine useful. All configuration options (required and optional) are detailed below:
| Variable | Required | Description | | Variable | Required | Description |
| --- | --- | --- | |-----------------------------------| --- | --- |
| GRADLE_ENTERPRISE_INJECTION_ENABLED | :white_check_mark: | enables Gradle Enterprise injection | | DEVELOCITY_INJECTION_ENABLED | :white_check_mark: | enables Develocity injection |
| GRADLE_ENTERPRISE_URL | :white_check_mark: | the URL of the Gradle Enterprise server | | DEVELOCITY_URL | :white_check_mark: | the URL of the Develocity server |
| GRADLE_ENTERPRISE_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Gradle Enterprise instance is using a self-signed certificate | | DEVELOCITY_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed certificate |
| GRADLE_ENTERPRISE_ENFORCE_URL | | enforce the configured Gradle Enterprise URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Gradle Enterprise URL | | 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 |
| GRADLE_ENTERPRISE_PLUGIN_VERSION | :white_check_mark: | the version of the [Gradle Enterprise Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/) to apply | | DEVELOCITY_PLUGIN_VERSION | :white_check_mark: | the version of the [Develocity Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/) to apply |
| GRADLE_ENTERPRISE_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 | | 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_ENTERPRISE_PLUGIN_REPOSITORY_URL | | the URL of the repository to use when resolving the GE and CCUD plugins; the Gradle Plugin Portal is used by default | | 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 |
## Publishing to scans.gradle.com ## Publishing to scans.gradle.com
Gradle Enterprise injection is designed to enable publishing of build scans to a Gradle Enterprise instance, Develocity injection is designed to enable publishing of build scans to a Develocity instance,
and is not suitable for publishing to the public Build Scans instance (https://scans.gradle.com). and is not suitable for publishing to the public Build Scans instance (https://scans.gradle.com).
In order to publish Build Scans to scans.gradle.com, you need to: In order to publish Build Scans to scans.gradle.com, you need to:
- Apply the Gradle Enterprise plugin to your build configuration ([see docs](https://docs.gradle.com/enterprise/get-started/#applying_the_plugin)) - Apply the Develocity plugin to your build configuration ([see docs](https://docs.gradle.com/enterprise/get-started/#applying_the_plugin))
- Programmatically accept the Terms of Service for scans.gradle.com ([see docs](https://docs.gradle.com/enterprise/gradle-plugin/#connecting_to_scans_gradle_com)) - Programmatically accept the Terms of Service for scans.gradle.com ([see docs](https://docs.gradle.com/enterprise/gradle-plugin/#connecting_to_scans_gradle_com))
- Execute the build with `--scan` or configure your build with `publishAlways()` ([see docs](https://docs.gradle.com/enterprise/get-started/#always_publishing_a_build_scan)) - Execute the build with `--scan` or configure your build with `publishAlways()` ([see docs](https://docs.gradle.com/enterprise/get-started/#always_publishing_a_build_scan))

View File

@@ -73,6 +73,11 @@ inputs:
required: false required: false
default: 'disabled' default: 'disabled'
dependency-graph-continue-on-failure:
description: When 'false' a failure to generate or submit a dependency graph will fail the Step or Job. When 'true' a warning will be emitted but no failure will result.
required: false
default: true
artifact-retention-days: artifact-retention-days:
description: Specifies the number of days to retain any artifacts generated by the action. If not set, the default retention settings for the repository will apply. description: Specifies the number of days to retain any artifacts generated by the action. If not set, the default retention settings for the repository will apply.
required: false required: false
@@ -88,11 +93,6 @@ inputs:
required: false required: false
deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step. See https://github.com/gradle/gradle-build-action?tab=readme-ov-file#use-the-action-to-setup-gradle. deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step. See https://github.com/gradle/gradle-build-action?tab=readme-ov-file#use-the-action-to-setup-gradle.
gradle-executable:
description: Path to the Gradle executable. If specified, this executable will be added to the PATH and used for invoking Gradle.
required: false
deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step. See https://github.com/gradle/gradle-build-action?tab=readme-ov-file#use-the-action-to-setup-gradle.
generate-job-summary: generate-job-summary:
description: When 'false', no Job Summary will be generated for the Job. description: When 'false', no Job Summary will be generated for the Job.
required: false required: false

84
dist/main/index.js vendored
View File

@@ -138736,7 +138736,7 @@ class GradleStateCache {
'gradle-build-action.build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
'gradle-build-action.github-dependency-graph.init.gradle', 'gradle-build-action.github-dependency-graph.init.gradle',
'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy', 'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy',
'gradle-build-action.inject-gradle-enterprise.init.gradle' 'gradle-build-action.inject-develocity.init.gradle'
]; ];
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename); const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename);
@@ -139971,6 +139971,7 @@ const request_error_1 = __nccwpck_require__(10537);
const path = __importStar(__nccwpck_require__(71017)); const path = __importStar(__nccwpck_require__(71017));
const fs_1 = __importDefault(__nccwpck_require__(57147)); const fs_1 = __importDefault(__nccwpck_require__(57147));
const layout = __importStar(__nccwpck_require__(28182)); const layout = __importStar(__nccwpck_require__(28182));
const errors_1 = __nccwpck_require__(36976);
const input_params_1 = __nccwpck_require__(23885); const input_params_1 = __nccwpck_require__(23885);
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_'; const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_';
function setup(option) { function setup(option) {
@@ -139983,16 +139984,22 @@ function setup(option) {
return; return;
} }
core.info('Enabling dependency graph generation'); core.info('Enabling dependency graph generation');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true'); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator()); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', (0, input_params_1.getDependencyGraphContinueOnFailure)());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext()); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory()); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext());
core.exportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports')); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory());
maybeExportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports'));
}); });
} }
exports.setup = setup; exports.setup = setup;
function maybeExportVariable(variableName, value) {
if (!process.env[variableName]) {
core.exportVariable(variableName, value);
}
}
function complete(option) { function complete(option) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
@@ -140009,7 +140016,7 @@ function complete(option) {
} }
} }
catch (e) { catch (e) {
core.warning(`Failed to ${option} dependency graph. Will continue. ${String(e)}`); warnOrFail(option, e);
} }
}); });
} }
@@ -140040,7 +140047,7 @@ function downloadAndSubmitDependencyGraphs() {
yield submitDependencyGraphs(yield downloadDependencyGraphs()); yield submitDependencyGraphs(yield downloadDependencyGraphs());
} }
catch (e) { catch (e) {
core.warning(`Download and submit dependency graph failed. Will continue. ${String(e)}`); warnOrFail(input_params_1.DependencyGraphOption.DownloadAndSubmit, e);
} }
}); });
} }
@@ -140052,7 +140059,7 @@ function submitDependencyGraphs(dependencyGraphFiles) {
} }
catch (error) { catch (error) {
if (error instanceof request_error_1.RequestError) { if (error instanceof request_error_1.RequestError) {
core.warning(buildWarningMessage(jsonFile, error)); throw new Error(translateErrorMessage(jsonFile, error));
} }
else { else {
throw error; throw error;
@@ -140061,9 +140068,9 @@ function submitDependencyGraphs(dependencyGraphFiles) {
} }
}); });
} }
function buildWarningMessage(jsonFile, error) { function translateErrorMessage(jsonFile, error) {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile); const relativeJsonFile = getRelativePathFromWorkspace(jsonFile);
const mainWarning = `Failed to submit dependency graph ${relativeJsonFile}.\n${String(error)}`; const mainWarning = `Dependency submission failed for ${relativeJsonFile}.\n${String(error)}`;
if (error.message === 'Resource not accessible by integration') { if (error.message === 'Resource not accessible by integration') {
return `${mainWarning} return `${mainWarning}
Please ensure that the 'contents: write' permission is available for the workflow job. Please ensure that the 'contents: write' permission is available for the workflow job.
@@ -140118,6 +140125,12 @@ function findDependencyGraphFiles(dir) {
return graphFiles; return graphFiles;
}); });
} }
function warnOrFail(option, error) {
if (!(0, input_params_1.getDependencyGraphContinueOnFailure)()) {
throw new errors_1.PostActionJobFailure(error);
}
core.warning(`Failed to ${option} dependency graph. Will continue.\n${String(error)}`);
}
function getOctokit() { function getOctokit() {
return github.getOctokit(getGithubToken()); return github.getOctokit(getGithubToken());
} }
@@ -140169,6 +140182,30 @@ function sanitize(value) {
} }
/***/ }),
/***/ 36976:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.PostActionJobFailure = void 0;
class PostActionJobFailure extends Error {
constructor(error) {
if (error instanceof Error) {
super(error.message);
this.name = error.name;
this.stack = error.stack;
}
else {
super(String(error));
}
}
}
exports.PostActionJobFailure = PostActionJobFailure;
/***/ }), /***/ }),
/***/ 23584: /***/ 23584:
@@ -140288,7 +140325,7 @@ function validateGradleWrapper(buildRootDirectory) {
} }
function verifyExists(file, description) { function verifyExists(file, description) {
if (!fs_1.default.existsSync(file)) { if (!fs_1.default.existsSync(file)) {
throw new Error(`Cannot locate ${description} at '${file}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.`); throw new Error(`Cannot locate ${description} at '${file}'. Specify 'gradle-version' for projects without Gradle wrapper configured.`);
} }
} }
function verifyIsExecutableScript(toExecute) { function verifyIsExecutableScript(toExecute) {
@@ -140332,7 +140369,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.JobSummaryOption = exports.DependencyGraphOption = exports.parseNumericInput = exports.getArtifactRetentionDays = exports.getDependencyGraphOption = exports.getPRCommentOption = exports.getJobSummaryOption = exports.isJobSummaryEnabled = exports.getGithubToken = exports.getJobMatrix = exports.getArguments = exports.getGradleExecutable = exports.getGradleVersion = exports.getBuildRootDirectory = exports.getCacheExcludes = exports.getCacheIncludes = exports.getCacheEncryptionKey = exports.isCacheCleanupEnabled = exports.isCacheDebuggingEnabled = exports.isCacheStrictMatch = exports.isCacheOverwriteExisting = exports.isCacheWriteOnly = exports.isCacheReadOnly = exports.isCacheDisabled = void 0; exports.JobSummaryOption = exports.DependencyGraphOption = exports.parseNumericInput = exports.getArtifactRetentionDays = exports.getDependencyGraphContinueOnFailure = exports.getDependencyGraphOption = exports.getPRCommentOption = exports.getJobSummaryOption = exports.isJobSummaryEnabled = exports.getGithubToken = exports.getJobMatrix = exports.getArguments = exports.getGradleVersion = exports.getBuildRootDirectory = exports.getCacheExcludes = exports.getCacheIncludes = exports.getCacheEncryptionKey = exports.isCacheCleanupEnabled = exports.isCacheDebuggingEnabled = exports.isCacheStrictMatch = exports.isCacheOverwriteExisting = exports.isCacheWriteOnly = exports.isCacheReadOnly = exports.isCacheDisabled = void 0;
const core = __importStar(__nccwpck_require__(42186)); const core = __importStar(__nccwpck_require__(42186));
const string_argv_1 = __nccwpck_require__(19663); const string_argv_1 = __nccwpck_require__(19663);
function isCacheDisabled() { function isCacheDisabled() {
@@ -140383,10 +140420,6 @@ function getGradleVersion() {
return core.getInput('gradle-version'); return core.getInput('gradle-version');
} }
exports.getGradleVersion = getGradleVersion; exports.getGradleVersion = getGradleVersion;
function getGradleExecutable() {
return core.getInput('gradle-executable');
}
exports.getGradleExecutable = getGradleExecutable;
function getArguments() { function getArguments() {
const input = core.getInput('arguments'); const input = core.getInput('arguments');
return (0, string_argv_1.parseArgsStringToArgv)(input); return (0, string_argv_1.parseArgsStringToArgv)(input);
@@ -140441,6 +140474,10 @@ function getDependencyGraphOption() {
throw TypeError(`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit]. The default value is 'disabled'.`); throw TypeError(`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit]. The default value is 'disabled'.`);
} }
exports.getDependencyGraphOption = getDependencyGraphOption; exports.getDependencyGraphOption = getDependencyGraphOption;
function getDependencyGraphContinueOnFailure() {
return getBooleanInput('dependency-graph-continue-on-failure', true);
}
exports.getDependencyGraphContinueOnFailure = getDependencyGraphContinueOnFailure;
function getArtifactRetentionDays() { function getArtifactRetentionDays() {
const val = core.getInput('artifact-retention-days'); const val = core.getInput('artifact-retention-days');
return parseNumericInput('artifact-retention-days', val, 0); return parseNumericInput('artifact-retention-days', val, 0);
@@ -140725,6 +140762,7 @@ function run() {
core.info(error.stack); core.info(error.stack);
} }
} }
process.exit();
}); });
} }
exports.run = run; exports.run = run;
@@ -140781,19 +140819,13 @@ const cache = __importStar(__nccwpck_require__(27799));
const toolCache = __importStar(__nccwpck_require__(27784)); const toolCache = __importStar(__nccwpck_require__(27784));
const gradlew = __importStar(__nccwpck_require__(32335)); const gradlew = __importStar(__nccwpck_require__(32335));
const params = __importStar(__nccwpck_require__(23885)); const params = __importStar(__nccwpck_require__(23885));
const layout = __importStar(__nccwpck_require__(28182));
const cache_utils_1 = __nccwpck_require__(41678); const cache_utils_1 = __nccwpck_require__(41678);
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'; const gradleVersionsBaseUrl = 'https://services.gradle.org/versions';
function provisionGradle() { function provisionGradle() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const gradleVersion = params.getGradleVersion(); const gradleVersion = params.getGradleVersion();
if (gradleVersion !== '' && gradleVersion !== 'wrapper') { if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
return addToPath(path.resolve(yield installGradle(gradleVersion))); return addToPath(yield installGradle(gradleVersion));
}
const gradleExecutable = params.getGradleExecutable();
if (gradleExecutable !== '') {
const workspaceDirectory = layout.workspaceDirectory();
return addToPath(path.resolve(workspaceDirectory, gradleExecutable));
} }
return undefined; return undefined;
}); });

File diff suppressed because one or more lines are too long

82
dist/post/index.js vendored
View File

@@ -136189,7 +136189,7 @@ class GradleStateCache {
'gradle-build-action.build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
'gradle-build-action.github-dependency-graph.init.gradle', 'gradle-build-action.github-dependency-graph.init.gradle',
'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy', 'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy',
'gradle-build-action.inject-gradle-enterprise.init.gradle' 'gradle-build-action.inject-develocity.init.gradle'
]; ];
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename); const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename);
@@ -137424,6 +137424,7 @@ const request_error_1 = __nccwpck_require__(10537);
const path = __importStar(__nccwpck_require__(71017)); const path = __importStar(__nccwpck_require__(71017));
const fs_1 = __importDefault(__nccwpck_require__(57147)); const fs_1 = __importDefault(__nccwpck_require__(57147));
const layout = __importStar(__nccwpck_require__(28182)); const layout = __importStar(__nccwpck_require__(28182));
const errors_1 = __nccwpck_require__(36976);
const input_params_1 = __nccwpck_require__(23885); const input_params_1 = __nccwpck_require__(23885);
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_'; const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_';
function setup(option) { function setup(option) {
@@ -137436,16 +137437,22 @@ function setup(option) {
return; return;
} }
core.info('Enabling dependency graph generation'); core.info('Enabling dependency graph generation');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true'); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator()); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', (0, input_params_1.getDependencyGraphContinueOnFailure)());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext()); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory()); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext());
core.exportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports')); maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory());
maybeExportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports'));
}); });
} }
exports.setup = setup; exports.setup = setup;
function maybeExportVariable(variableName, value) {
if (!process.env[variableName]) {
core.exportVariable(variableName, value);
}
}
function complete(option) { function complete(option) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
@@ -137462,7 +137469,7 @@ function complete(option) {
} }
} }
catch (e) { catch (e) {
core.warning(`Failed to ${option} dependency graph. Will continue. ${String(e)}`); warnOrFail(option, e);
} }
}); });
} }
@@ -137493,7 +137500,7 @@ function downloadAndSubmitDependencyGraphs() {
yield submitDependencyGraphs(yield downloadDependencyGraphs()); yield submitDependencyGraphs(yield downloadDependencyGraphs());
} }
catch (e) { catch (e) {
core.warning(`Download and submit dependency graph failed. Will continue. ${String(e)}`); warnOrFail(input_params_1.DependencyGraphOption.DownloadAndSubmit, e);
} }
}); });
} }
@@ -137505,7 +137512,7 @@ function submitDependencyGraphs(dependencyGraphFiles) {
} }
catch (error) { catch (error) {
if (error instanceof request_error_1.RequestError) { if (error instanceof request_error_1.RequestError) {
core.warning(buildWarningMessage(jsonFile, error)); throw new Error(translateErrorMessage(jsonFile, error));
} }
else { else {
throw error; throw error;
@@ -137514,9 +137521,9 @@ function submitDependencyGraphs(dependencyGraphFiles) {
} }
}); });
} }
function buildWarningMessage(jsonFile, error) { function translateErrorMessage(jsonFile, error) {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile); const relativeJsonFile = getRelativePathFromWorkspace(jsonFile);
const mainWarning = `Failed to submit dependency graph ${relativeJsonFile}.\n${String(error)}`; const mainWarning = `Dependency submission failed for ${relativeJsonFile}.\n${String(error)}`;
if (error.message === 'Resource not accessible by integration') { if (error.message === 'Resource not accessible by integration') {
return `${mainWarning} return `${mainWarning}
Please ensure that the 'contents: write' permission is available for the workflow job. Please ensure that the 'contents: write' permission is available for the workflow job.
@@ -137571,6 +137578,12 @@ function findDependencyGraphFiles(dir) {
return graphFiles; return graphFiles;
}); });
} }
function warnOrFail(option, error) {
if (!(0, input_params_1.getDependencyGraphContinueOnFailure)()) {
throw new errors_1.PostActionJobFailure(error);
}
core.warning(`Failed to ${option} dependency graph. Will continue.\n${String(error)}`);
}
function getOctokit() { function getOctokit() {
return github.getOctokit(getGithubToken()); return github.getOctokit(getGithubToken());
} }
@@ -137622,6 +137635,30 @@ function sanitize(value) {
} }
/***/ }),
/***/ 36976:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.PostActionJobFailure = void 0;
class PostActionJobFailure extends Error {
constructor(error) {
if (error instanceof Error) {
super(error.message);
this.name = error.name;
this.stack = error.stack;
}
else {
super(String(error));
}
}
}
exports.PostActionJobFailure = PostActionJobFailure;
/***/ }), /***/ }),
/***/ 23885: /***/ 23885:
@@ -137653,7 +137690,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.JobSummaryOption = exports.DependencyGraphOption = exports.parseNumericInput = exports.getArtifactRetentionDays = exports.getDependencyGraphOption = exports.getPRCommentOption = exports.getJobSummaryOption = exports.isJobSummaryEnabled = exports.getGithubToken = exports.getJobMatrix = exports.getArguments = exports.getGradleExecutable = exports.getGradleVersion = exports.getBuildRootDirectory = exports.getCacheExcludes = exports.getCacheIncludes = exports.getCacheEncryptionKey = exports.isCacheCleanupEnabled = exports.isCacheDebuggingEnabled = exports.isCacheStrictMatch = exports.isCacheOverwriteExisting = exports.isCacheWriteOnly = exports.isCacheReadOnly = exports.isCacheDisabled = void 0; exports.JobSummaryOption = exports.DependencyGraphOption = exports.parseNumericInput = exports.getArtifactRetentionDays = exports.getDependencyGraphContinueOnFailure = exports.getDependencyGraphOption = exports.getPRCommentOption = exports.getJobSummaryOption = exports.isJobSummaryEnabled = exports.getGithubToken = exports.getJobMatrix = exports.getArguments = exports.getGradleVersion = exports.getBuildRootDirectory = exports.getCacheExcludes = exports.getCacheIncludes = exports.getCacheEncryptionKey = exports.isCacheCleanupEnabled = exports.isCacheDebuggingEnabled = exports.isCacheStrictMatch = exports.isCacheOverwriteExisting = exports.isCacheWriteOnly = exports.isCacheReadOnly = exports.isCacheDisabled = void 0;
const core = __importStar(__nccwpck_require__(42186)); const core = __importStar(__nccwpck_require__(42186));
const string_argv_1 = __nccwpck_require__(19663); const string_argv_1 = __nccwpck_require__(19663);
function isCacheDisabled() { function isCacheDisabled() {
@@ -137704,10 +137741,6 @@ function getGradleVersion() {
return core.getInput('gradle-version'); return core.getInput('gradle-version');
} }
exports.getGradleVersion = getGradleVersion; exports.getGradleVersion = getGradleVersion;
function getGradleExecutable() {
return core.getInput('gradle-executable');
}
exports.getGradleExecutable = getGradleExecutable;
function getArguments() { function getArguments() {
const input = core.getInput('arguments'); const input = core.getInput('arguments');
return (0, string_argv_1.parseArgsStringToArgv)(input); return (0, string_argv_1.parseArgsStringToArgv)(input);
@@ -137762,6 +137795,10 @@ function getDependencyGraphOption() {
throw TypeError(`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit]. The default value is 'disabled'.`); throw TypeError(`The value '${val}' is not valid for 'dependency-graph'. Valid values are: [disabled, generate, generate-and-submit, generate-and-upload, download-and-submit]. The default value is 'disabled'.`);
} }
exports.getDependencyGraphOption = getDependencyGraphOption; exports.getDependencyGraphOption = getDependencyGraphOption;
function getDependencyGraphContinueOnFailure() {
return getBooleanInput('dependency-graph-continue-on-failure', true);
}
exports.getDependencyGraphContinueOnFailure = getDependencyGraphContinueOnFailure;
function getArtifactRetentionDays() { function getArtifactRetentionDays() {
const val = core.getInput('artifact-retention-days'); const val = core.getInput('artifact-retention-days');
return parseNumericInput('artifact-retention-days', val, 0); return parseNumericInput('artifact-retention-days', val, 0);
@@ -138025,6 +138062,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.run = void 0; exports.run = void 0;
const core = __importStar(__nccwpck_require__(42186)); const core = __importStar(__nccwpck_require__(42186));
const setupGradle = __importStar(__nccwpck_require__(18652)); const setupGradle = __importStar(__nccwpck_require__(18652));
const errors_1 = __nccwpck_require__(36976);
process.on('uncaughtException', e => handleFailure(e)); process.on('uncaughtException', e => handleFailure(e));
function run() { function run() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
@@ -138032,8 +138070,14 @@ function run() {
yield setupGradle.complete(); yield setupGradle.complete();
} }
catch (error) { catch (error) {
handleFailure(error); if (error instanceof errors_1.PostActionJobFailure) {
core.setFailed(String(error));
}
else {
handleFailure(error);
}
} }
process.exit();
}); });
} }
exports.run = run; exports.run = run;

File diff suppressed because one or more lines are too long

1298
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,9 +10,9 @@
"lint": "eslint src/**/*.ts", "lint": "eslint src/**/*.ts",
"compile-main": "ncc build src/main.ts --out dist/main --source-map --no-source-map-register", "compile-main": "ncc build src/main.ts --out dist/main --source-map --no-source-map-register",
"compile-post": "ncc build src/post.ts --out dist/post --source-map --no-source-map-register", "compile-post": "ncc build src/post.ts --out dist/post --source-map --no-source-map-register",
"compile": "npm run compile-main && npm run compile-post", "compile": "npm-run-all --parallel compile-*",
"check": "npm-run-all --parallel format lint",
"test": "jest", "test": "jest",
"check": "npm run format && npm run lint",
"build": "npm run check && npm run compile", "build": "npm run check && npm run compile",
"all": "npm run build && npm test" "all": "npm run build && npm test"
}, },
@@ -53,6 +53,7 @@
"eslint-plugin-prettier": "5.1.2", "eslint-plugin-prettier": "5.1.2",
"jest": "29.7.0", "jest": "29.7.0",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"npm-run-all": "4.1.5",
"patch-package": "8.0.0", "patch-package": "8.0.0",
"prettier": "3.1.1", "prettier": "3.1.1",
"ts-jest": "29.1.1", "ts-jest": "29.1.1",

View File

@@ -203,7 +203,7 @@ export class GradleStateCache {
'gradle-build-action.build-result-capture-service.plugin.groovy', 'gradle-build-action.build-result-capture-service.plugin.groovy',
'gradle-build-action.github-dependency-graph.init.gradle', 'gradle-build-action.github-dependency-graph.init.gradle',
'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy', 'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy',
'gradle-build-action.inject-gradle-enterprise.init.gradle' 'gradle-build-action.inject-develocity.init.gradle'
] ]
for (const initScriptFilename of initScriptFilenames) { for (const initScriptFilename of initScriptFilenames) {
const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename) const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename)

View File

@@ -10,7 +10,13 @@ import * as path from 'path'
import fs from 'fs' import fs from 'fs'
import * as layout from './repository-layout' import * as layout from './repository-layout'
import {DependencyGraphOption, getJobMatrix, getArtifactRetentionDays} from './input-params' import {PostActionJobFailure} from './errors'
import {
DependencyGraphOption,
getDependencyGraphContinueOnFailure,
getJobMatrix,
getArtifactRetentionDays
} from './input-params'
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_' const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_'
@@ -25,18 +31,25 @@ export async function setup(option: DependencyGraphOption): Promise<void> {
} }
core.info('Enabling dependency graph generation') core.info('Enabling dependency graph generation')
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true') maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator()) maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', getDependencyGraphContinueOnFailure())
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId) maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator())
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref) maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext()) maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory()) maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
core.exportVariable( maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory())
maybeExportVariable(
'DEPENDENCY_GRAPH_REPORT_DIR', 'DEPENDENCY_GRAPH_REPORT_DIR',
path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports') path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports')
) )
} }
function maybeExportVariable(variableName: string, value: unknown): void {
if (!process.env[variableName]) {
core.exportVariable(variableName, value)
}
}
export async function complete(option: DependencyGraphOption): Promise<void> { export async function complete(option: DependencyGraphOption): Promise<void> {
try { try {
switch (option) { switch (option) {
@@ -51,7 +64,7 @@ export async function complete(option: DependencyGraphOption): Promise<void> {
await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles()) await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles())
} }
} catch (e) { } catch (e) {
core.warning(`Failed to ${option} dependency graph. Will continue. ${String(e)}`) warnOrFail(option, e)
} }
} }
@@ -78,7 +91,7 @@ async function downloadAndSubmitDependencyGraphs(): Promise<void> {
try { try {
await submitDependencyGraphs(await downloadDependencyGraphs()) await submitDependencyGraphs(await downloadDependencyGraphs())
} catch (e) { } catch (e) {
core.warning(`Download and submit dependency graph failed. Will continue. ${String(e)}`) warnOrFail(DependencyGraphOption.DownloadAndSubmit, e)
} }
} }
@@ -88,7 +101,7 @@ async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<v
await submitDependencyGraphFile(jsonFile) await submitDependencyGraphFile(jsonFile)
} catch (error) { } catch (error) {
if (error instanceof RequestError) { if (error instanceof RequestError) {
core.warning(buildWarningMessage(jsonFile, error)) throw new Error(translateErrorMessage(jsonFile, error))
} else { } else {
throw error throw error
} }
@@ -96,9 +109,9 @@ async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<v
} }
} }
function buildWarningMessage(jsonFile: string, error: RequestError): string { function translateErrorMessage(jsonFile: string, error: RequestError): string {
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile) const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
const mainWarning = `Failed to submit dependency graph ${relativeJsonFile}.\n${String(error)}` const mainWarning = `Dependency submission failed for ${relativeJsonFile}.\n${String(error)}`
if (error.message === 'Resource not accessible by integration') { if (error.message === 'Resource not accessible by integration') {
return `${mainWarning} return `${mainWarning}
Please ensure that the 'contents: write' permission is available for the workflow job. Please ensure that the 'contents: write' permission is available for the workflow job.
@@ -160,6 +173,14 @@ async function findDependencyGraphFiles(dir: string): Promise<string[]> {
return graphFiles return graphFiles
} }
function warnOrFail(option: String, error: unknown): void {
if (!getDependencyGraphContinueOnFailure()) {
throw new PostActionJobFailure(error)
}
core.warning(`Failed to ${option} dependency graph. Will continue.\n${String(error)}`)
}
function getOctokit(): InstanceType<typeof GitHub> { function getOctokit(): InstanceType<typeof GitHub> {
return github.getOctokit(getGithubToken()) return github.getOctokit(getGithubToken())
} }

11
src/errors.ts Normal file
View File

@@ -0,0 +1,11 @@
export class PostActionJobFailure extends Error {
constructor(error: unknown) {
if (error instanceof Error) {
super(error.message)
this.name = error.name
this.stack = error.stack
} else {
super(String(error))
}
}
}

View File

@@ -28,7 +28,7 @@ function validateGradleWrapper(buildRootDirectory: string): void {
function verifyExists(file: string, description: string): void { function verifyExists(file: string, description: string): void {
if (!fs.existsSync(file)) { if (!fs.existsSync(file)) {
throw new Error( throw new Error(
`Cannot locate ${description} at '${file}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.` `Cannot locate ${description} at '${file}'. Specify 'gradle-version' for projects without Gradle wrapper configured.`
) )
} }
} }

View File

@@ -49,10 +49,6 @@ export function getGradleVersion(): string {
return core.getInput('gradle-version') return core.getInput('gradle-version')
} }
export function getGradleExecutable(): string {
return core.getInput('gradle-executable')
}
export function getArguments(): string[] { export function getArguments(): string[] {
const input = core.getInput('arguments') const input = core.getInput('arguments')
return parseArgsStringToArgv(input) return parseArgsStringToArgv(input)
@@ -111,6 +107,10 @@ export function getDependencyGraphOption(): DependencyGraphOption {
) )
} }
export function getDependencyGraphContinueOnFailure(): boolean {
return getBooleanInput('dependency-graph-continue-on-failure', true)
}
export function getArtifactRetentionDays(): number { export function getArtifactRetentionDays(): number {
const val = core.getInput('artifact-retention-days') const val = core.getInput('artifact-retention-days')
return parseNumericInput('artifact-retention-days', val, 0) return parseNumericInput('artifact-retention-days', val, 0)

View File

@@ -29,6 +29,9 @@ export async function run(): Promise<void> {
core.info(error.stack) core.info(error.stack)
} }
} }
// Explicit process.exit() to prevent waiting for hanging promises.
process.exit()
} }
run() run()

View File

@@ -1,5 +1,6 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import * as setupGradle from './setup-gradle' import * as setupGradle from './setup-gradle'
import {PostActionJobFailure} from './errors'
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in // Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to // @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
@@ -13,8 +14,15 @@ export async function run(): Promise<void> {
try { try {
await setupGradle.complete() await setupGradle.complete()
} catch (error) { } catch (error) {
handleFailure(error) if (error instanceof PostActionJobFailure) {
core.setFailed(String(error))
} else {
handleFailure(error)
}
} }
// Explicit process.exit() to prevent waiting for promises left hanging by `@actions/cache` on save.
process.exit()
} }
function handleFailure(error: unknown): void { function handleFailure(error: unknown): void {

View File

@@ -8,7 +8,6 @@ import * as toolCache from '@actions/tool-cache'
import * as gradlew from './gradlew' import * as gradlew from './gradlew'
import * as params from './input-params' import * as params from './input-params'
import * as layout from './repository-layout'
import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils' import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions' const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
@@ -20,13 +19,7 @@ const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
export async function provisionGradle(): Promise<string | undefined> { export async function provisionGradle(): Promise<string | undefined> {
const gradleVersion = params.getGradleVersion() const gradleVersion = params.getGradleVersion()
if (gradleVersion !== '' && gradleVersion !== 'wrapper') { if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
return addToPath(path.resolve(await installGradle(gradleVersion))) return addToPath(await installGradle(gradleVersion))
}
const gradleExecutable = params.getGradleExecutable()
if (gradleExecutable !== '') {
const workspaceDirectory = layout.workspaceDirectory()
return addToPath(path.resolve(workspaceDirectory, gradleExecutable))
} }
return undefined return undefined

View File

@@ -9,7 +9,7 @@ buildscript {
maven { url pluginRepositoryUrl } maven { url pluginRepositoryUrl }
} }
dependencies { dependencies {
classpath "org.gradle:github-dependency-graph-gradle-plugin:1.0.0" classpath "org.gradle:github-dependency-graph-gradle-plugin:1.1.1"
} }
} }
apply plugin: org.gradle.github.GitHubDependencyGraphPlugin apply plugin: org.gradle.github.GitHubDependencyGraphPlugin

View File

@@ -6,8 +6,13 @@ if (getVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED') != "true") {
} }
// Do not run for unsupported versions of Gradle // Do not run for unsupported versions of Gradle
if (GradleVersion.current().baseVersion < GradleVersion.version("5.0")) { def gradleVersion = GradleVersion.current().baseVersion
println "::warning::Dependency Graph is not supported for Gradle versions < 5.0. No dependency snapshot will be generated." if (gradleVersion < GradleVersion.version("5.2") ||
(gradleVersion >= GradleVersion.version("7.0") && gradleVersion < GradleVersion.version("7.1"))) {
if (getVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE') != "true") {
throw new GradleException("Dependency Graph is not supported for ${gradleVersion}. No dependency snapshot will be generated.")
}
println "::warning::Dependency Graph is not supported for ${gradleVersion}. No dependency snapshot will be generated."
return return
} }
@@ -22,11 +27,6 @@ if (isTopLevelBuild) {
return return
} }
def githubOutput = System.getenv("GITHUB_OUTPUT")
if (githubOutput) {
new File(githubOutput) << "dependency-graph-file=${reportFile.absolutePath}\n"
}
println "Generating dependency graph into '${reportFile}'" println "Generating dependency graph into '${reportFile}'"
} }

View File

@@ -15,21 +15,21 @@ initscript {
} }
// finish early if injection is disabled // finish early if injection is disabled
def gradleInjectionEnabled = getInputParam("gradle-enterprise.injection-enabled") def gradleInjectionEnabled = getInputParam("develocity.injection-enabled")
if (gradleInjectionEnabled != "true") { if (gradleInjectionEnabled != "true") {
return return
} }
def pluginRepositoryUrl = getInputParam('gradle-enterprise.plugin-repository.url') def pluginRepositoryUrl = getInputParam('gradle.plugin-repository.url')
def gePluginVersion = getInputParam('gradle-enterprise.plugin.version') def gePluginVersion = getInputParam('develocity.plugin.version')
def ccudPluginVersion = getInputParam('gradle-enterprise.ccud-plugin.version') def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version')
def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0') def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0')
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0') def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
if (gePluginVersion || ccudPluginVersion && atLeastGradle4) { if (gePluginVersion || ccudPluginVersion && atLeastGradle4) {
pluginRepositoryUrl = pluginRepositoryUrl ?: 'https://plugins.gradle.org/m2' pluginRepositoryUrl = pluginRepositoryUrl ?: 'https://plugins.gradle.org/m2'
logger.quiet("Gradle Enterprise plugins resolution: $pluginRepositoryUrl") logger.quiet("Develocity plugins resolution: $pluginRepositoryUrl")
repositories { repositories {
maven { url pluginRepositoryUrl } maven { url pluginRepositoryUrl }
@@ -52,9 +52,9 @@ initscript {
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan' def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin' def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin'
def GRADLE_ENTERPRISE_PLUGIN_ID = 'com.gradle.enterprise' def DEVELOCITY_PLUGIN_ID = 'com.gradle.enterprise'
def GRADLE_ENTERPRISE_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin' def DEVELOCITY_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin'
def GRADLE_ENTERPRISE_EXTENSION_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterpriseExtension' def DEVELOCITY_EXTENSION_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterpriseExtension'
def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection' def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection'
def CI_AUTO_INJECTION_CUSTOM_VALUE_VALUE = 'gradle-build-action' def CI_AUTO_INJECTION_CUSTOM_VALUE_VALUE = 'gradle-build-action'
def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin' def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin'
@@ -71,17 +71,17 @@ def getInputParam = { String name ->
} }
// finish early if injection is disabled // finish early if injection is disabled
def gradleInjectionEnabled = getInputParam("gradle-enterprise.injection-enabled") def gradleInjectionEnabled = getInputParam("develocity.injection-enabled")
if (gradleInjectionEnabled != "true") { if (gradleInjectionEnabled != "true") {
return return
} }
def geUrl = getInputParam('gradle-enterprise.url') def geUrl = getInputParam('develocity.url')
def geAllowUntrustedServer = Boolean.parseBoolean(getInputParam('gradle-enterprise.allow-untrusted-server')) def geAllowUntrustedServer = Boolean.parseBoolean(getInputParam('develocity.allow-untrusted-server'))
def geEnforceUrl = Boolean.parseBoolean(getInputParam('gradle-enterprise.enforce-url')) def geEnforceUrl = Boolean.parseBoolean(getInputParam('develocity.enforce-url'))
def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('gradle-enterprise.build-scan.upload-in-background')) def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('develocity.build-scan.upload-in-background'))
def gePluginVersion = getInputParam('gradle-enterprise.plugin.version') def gePluginVersion = getInputParam('develocity.plugin.version')
def ccudPluginVersion = getInputParam('gradle-enterprise.ccud-plugin.version') def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version')
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0') def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
@@ -103,7 +103,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
} }
if (!scanPluginComponent) { if (!scanPluginComponent) {
logger.quiet("Applying $BUILD_SCAN_PLUGIN_CLASS via init script") logger.quiet("Applying $BUILD_SCAN_PLUGIN_CLASS via init script")
logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") logger.quiet("Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
applyPluginExternally(pluginManager, BUILD_SCAN_PLUGIN_CLASS) applyPluginExternally(pluginManager, BUILD_SCAN_PLUGIN_CLASS)
buildScan.server = geUrl buildScan.server = geUrl
buildScan.allowUntrustedServer = geAllowUntrustedServer buildScan.allowUntrustedServer = geAllowUntrustedServer
@@ -115,7 +115,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
if (geUrl && geEnforceUrl) { if (geUrl && geEnforceUrl) {
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) { pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
afterEvaluate { afterEvaluate {
logger.quiet("Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") logger.quiet("Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
buildScan.server = geUrl buildScan.server = geUrl
buildScan.allowUntrustedServer = geAllowUntrustedServer buildScan.allowUntrustedServer = geAllowUntrustedServer
} }
@@ -137,11 +137,11 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
} else { } else {
gradle.settingsEvaluated { settings -> gradle.settingsEvaluated { settings ->
if (gePluginVersion) { if (gePluginVersion) {
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID)) { if (!settings.pluginManager.hasPlugin(DEVELOCITY_PLUGIN_ID)) {
logger.quiet("Applying $GRADLE_ENTERPRISE_PLUGIN_CLASS via init script") logger.quiet("Applying $DEVELOCITY_PLUGIN_CLASS via init script")
logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") logger.quiet("Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
applyPluginExternally(settings.pluginManager, GRADLE_ENTERPRISE_PLUGIN_CLASS) applyPluginExternally(settings.pluginManager, DEVELOCITY_PLUGIN_CLASS)
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext -> extensionsWithPublicType(settings, DEVELOCITY_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
ext.server = geUrl ext.server = geUrl
ext.allowUntrustedServer = geAllowUntrustedServer ext.allowUntrustedServer = geAllowUntrustedServer
ext.buildScan.publishAlways() ext.buildScan.publishAlways()
@@ -151,8 +151,8 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
} }
if (geUrl && geEnforceUrl) { if (geUrl && geEnforceUrl) {
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext -> extensionsWithPublicType(settings, DEVELOCITY_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
logger.quiet("Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer") logger.quiet("Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
ext.server = geUrl ext.server = geUrl
ext.allowUntrustedServer = geAllowUntrustedServer ext.allowUntrustedServer = geAllowUntrustedServer
} }
@@ -169,7 +169,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
} }
void applyPluginExternally(def pluginManager, String pluginClassName) { void applyPluginExternally(def pluginManager, String pluginClassName) {
def externallyApplied = 'gradle.enterprise.externally-applied' def externallyApplied = 'develocity.externally-applied'
def oldValue = System.getProperty(externallyApplied) def oldValue = System.getProperty(externallyApplied)
System.setProperty(externallyApplied, 'true') System.setProperty(externallyApplied, 'true')
try { try {

View File

@@ -16,7 +16,7 @@ import java.nio.file.Files
import java.util.zip.GZIPOutputStream import java.util.zip.GZIPOutputStream
class BaseInitScriptTest extends Specification { class BaseInitScriptTest extends Specification {
static final String GE_PLUGIN_VERSION = '3.16.1' static final String DEVELOCITY_PLUGIN_VERSION = '3.16.1'
static final String CCUD_PLUGIN_VERSION = '1.12.1' static final String CCUD_PLUGIN_VERSION = '1.12.1'
static final TestGradleVersion GRADLE_3_X = new TestGradleVersion(GradleVersion.version('3.5.1'), 7, 9) static final TestGradleVersion GRADLE_3_X = new TestGradleVersion(GradleVersion.version('3.5.1'), 7, 9)
@@ -24,6 +24,7 @@ class BaseInitScriptTest extends Specification {
static final TestGradleVersion GRADLE_5_X = new TestGradleVersion(GradleVersion.version('5.6.4'), 8, 12) static final TestGradleVersion GRADLE_5_X = new TestGradleVersion(GradleVersion.version('5.6.4'), 8, 12)
static final TestGradleVersion GRADLE_6_NO_BUILD_SERVICE = new TestGradleVersion(GradleVersion.version('6.5.1'), 8, 14) static final TestGradleVersion GRADLE_6_NO_BUILD_SERVICE = new TestGradleVersion(GradleVersion.version('6.5.1'), 8, 14)
static final TestGradleVersion GRADLE_6_X = new TestGradleVersion(GradleVersion.version('6.9.4'), 8, 15) static final TestGradleVersion GRADLE_6_X = new TestGradleVersion(GradleVersion.version('6.9.4'), 8, 15)
static final TestGradleVersion GRADLE_7_1 = new TestGradleVersion(GradleVersion.version('7.6.2'), 8, 19)
static final TestGradleVersion GRADLE_7_X = new TestGradleVersion(GradleVersion.version('7.6.2'), 8, 19) static final TestGradleVersion GRADLE_7_X = new TestGradleVersion(GradleVersion.version('7.6.2'), 8, 19)
static final TestGradleVersion GRADLE_8_0 = new TestGradleVersion(GradleVersion.version('8.0.2'), 8, 19) static final TestGradleVersion GRADLE_8_0 = new TestGradleVersion(GradleVersion.version('8.0.2'), 8, 19)
static final TestGradleVersion GRADLE_8_X = new TestGradleVersion(GradleVersion.version('8.5'), 8, 19) static final TestGradleVersion GRADLE_8_X = new TestGradleVersion(GradleVersion.version('8.5'), 8, 19)
@@ -146,7 +147,7 @@ class BaseInitScriptTest extends Specification {
} else { } else {
""" """
plugins { plugins {
id 'com.gradle.enterprise' version '${GE_PLUGIN_VERSION}' id 'com.gradle.enterprise' version '${DEVELOCITY_PLUGIN_VERSION}'
${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""} ${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""}
} }
gradleEnterprise { gradleEnterprise {
@@ -174,7 +175,7 @@ class BaseInitScriptTest extends Specification {
} else if (gradleVersion < GradleVersion.version('6.0')) { } else if (gradleVersion < GradleVersion.version('6.0')) {
""" """
plugins { plugins {
id 'com.gradle.build-scan' version '${GE_PLUGIN_VERSION}' id 'com.gradle.build-scan' version '${DEVELOCITY_PLUGIN_VERSION}'
${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""} ${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""}
} }
gradleEnterprise { gradleEnterprise {

View File

@@ -1,11 +1,16 @@
package com.gradle.gradlebuildaction package com.gradle.gradlebuildaction
import org.gradle.util.GradleVersion
import static org.junit.Assume.assumeTrue import static org.junit.Assume.assumeTrue
class TestDependencyGraph extends BaseInitScriptTest { class TestDependencyGraph extends BaseInitScriptTest {
def initScript = 'gradle-build-action.github-dependency-graph.init.gradle' def initScript = 'gradle-build-action.github-dependency-graph.init.gradle'
static final List<TestGradleVersion> NO_DEPENDENCY_GRAPH_VERSIONS = [GRADLE_3_X, GRADLE_4_X] static final TestGradleVersion GRADLE_5_1 = new TestGradleVersion(GradleVersion.version('5.1.1'), 8, 12)
static final TestGradleVersion GRADLE_7_0 = new TestGradleVersion(GradleVersion.version('7.0.1'), 8, 12)
static final List<TestGradleVersion> NO_DEPENDENCY_GRAPH_VERSIONS = [GRADLE_3_X, GRADLE_4_X, GRADLE_5_1, GRADLE_7_0]
static final List<TestGradleVersion> DEPENDENCY_GRAPH_VERSIONS = ALL_VERSIONS - NO_DEPENDENCY_GRAPH_VERSIONS static final List<TestGradleVersion> DEPENDENCY_GRAPH_VERSIONS = ALL_VERSIONS - NO_DEPENDENCY_GRAPH_VERSIONS
def "does not produce dependency graph when not enabled"() { def "does not produce dependency graph when not enabled"() {
@@ -29,7 +34,6 @@ class TestDependencyGraph extends BaseInitScriptTest {
then: then:
assert reportFile.exists() assert reportFile.exists()
assert gitHubOutputFile.text == "dependency-graph-file=${reportFile.absolutePath}\n"
where: where:
testGradleVersion << [GRADLE_8_X] testGradleVersion << [GRADLE_8_X]
@@ -57,7 +61,23 @@ class TestDependencyGraph extends BaseInitScriptTest {
then: then:
assert !reportsDir.exists() assert !reportsDir.exists()
assert result.output.contains("::warning::Dependency Graph is not supported") assert result.output.contains("::warning::Dependency Graph is not supported for ${testGradleVersion}")
where:
testGradleVersion << NO_DEPENDENCY_GRAPH_VERSIONS
}
def "fails build when enabled for older Gradle versions if continue-on-failure is false"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm
when:
def vars = envVars
vars.put('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', 'false')
def result = runAndFail(['help'], initScript, testGradleVersion.gradleVersion, [], vars)
then:
assert !reportsDir.exists()
assert result.output.contains("Dependency Graph is not supported for ${testGradleVersion}")
where: where:
testGradleVersion << NO_DEPENDENCY_GRAPH_VERSIONS testGradleVersion << NO_DEPENDENCY_GRAPH_VERSIONS
@@ -110,13 +130,13 @@ class TestDependencyGraph extends BaseInitScriptTest {
def getEnvVars() { def getEnvVars() {
return [ return [
GITHUB_DEPENDENCY_GRAPH_ENABLED: "true", GITHUB_DEPENDENCY_GRAPH_ENABLED: "true",
GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE: "true",
GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR: "CORRELATOR", GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR: "CORRELATOR",
GITHUB_DEPENDENCY_GRAPH_JOB_ID: "1", GITHUB_DEPENDENCY_GRAPH_JOB_ID: "1",
GITHUB_DEPENDENCY_GRAPH_REF: "main", GITHUB_DEPENDENCY_GRAPH_REF: "main",
GITHUB_DEPENDENCY_GRAPH_SHA: "123456", GITHUB_DEPENDENCY_GRAPH_SHA: "123456",
GITHUB_DEPENDENCY_GRAPH_WORKSPACE: testProjectDir.absolutePath, GITHUB_DEPENDENCY_GRAPH_WORKSPACE: testProjectDir.absolutePath,
DEPENDENCY_GRAPH_REPORT_DIR: reportsDir.absolutePath, DEPENDENCY_GRAPH_REPORT_DIR: reportsDir.absolutePath,
GITHUB_OUTPUT: gitHubOutputFile.absolutePath
] ]
} }
@@ -127,8 +147,4 @@ class TestDependencyGraph extends BaseInitScriptTest {
def getReportFile() { def getReportFile() {
return new File(reportsDir, "CORRELATOR.json") return new File(reportsDir, "CORRELATOR.json")
} }
def getGitHubOutputFile() {
return new File(testProjectDir, "GITHUB_OUTPUT")
}
} }

View File

@@ -5,28 +5,28 @@ import org.gradle.util.GradleVersion
import static org.junit.Assume.assumeTrue import static org.junit.Assume.assumeTrue
class TestGradleEnterpriseInjection extends BaseInitScriptTest { class TestDevelocityInjection extends BaseInitScriptTest {
static final List<TestGradleVersion> CCUD_COMPATIBLE_VERSIONS = ALL_VERSIONS - [GRADLE_3_X] static final List<TestGradleVersion> CCUD_COMPATIBLE_VERSIONS = ALL_VERSIONS - [GRADLE_3_X]
def initScript = 'gradle-build-action.inject-gradle-enterprise.init.gradle' def initScript = 'gradle-build-action.inject-develocity.init.gradle'
private static final GradleVersion GRADLE_6 = GradleVersion.version('6.0') private static final GradleVersion GRADLE_6 = GradleVersion.version('6.0')
def "does not apply GE plugins when not requested"() { def "does not apply Develocity plugins when not requested"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
when: when:
def result = run([], initScript, testGradleVersion.gradleVersion) def result = run([], initScript, testGradleVersion.gradleVersion)
then: then:
outputMissesGePluginApplicationViaInitScript(result) outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
where: where:
testGradleVersion << ALL_VERSIONS testGradleVersion << ALL_VERSIONS
} }
def "does not override GE plugin when already defined in project"() { def "does not override Develocity plugin when already defined in project"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
given: given:
@@ -36,7 +36,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, testConfig()) def result = run(testGradleVersion, testConfig())
then: then:
outputMissesGePluginApplicationViaInitScript(result) outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
and: and:
@@ -46,14 +46,14 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
testGradleVersion << ALL_VERSIONS testGradleVersion << ALL_VERSIONS
} }
def "applies GE plugin via init script when not defined in project"() { def "applies Develocity plugin via init script when not defined in project"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
when: when:
def result = run(testGradleVersion, testConfig()) def result = run(testGradleVersion, testConfig())
then: then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
and: and:
@@ -63,14 +63,14 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
testGradleVersion << ALL_VERSIONS testGradleVersion << ALL_VERSIONS
} }
def "applies GE and CCUD plugins via init script when not defined in project"() { def "applies Develocity and CCUD plugins via init script when not defined in project"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
when: when:
def result = run(testGradleVersion, testConfig().withCCUDPlugin()) def result = run(testGradleVersion, testConfig().withCCUDPlugin())
then: then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsCcudPluginApplicationViaInitScript(result) outputContainsCcudPluginApplicationViaInitScript(result)
and: and:
@@ -80,7 +80,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
testGradleVersion << CCUD_COMPATIBLE_VERSIONS testGradleVersion << CCUD_COMPATIBLE_VERSIONS
} }
def "applies CCUD plugin via init script where GE plugin already applied"() { def "applies CCUD plugin via init script where Develocity plugin already applied"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
given: given:
@@ -90,7 +90,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, testConfig().withCCUDPlugin()) def result = run(testGradleVersion, testConfig().withCCUDPlugin())
then: then:
outputMissesGePluginApplicationViaInitScript(result) outputMissesDevelocityPluginApplicationViaInitScript(result)
outputContainsCcudPluginApplicationViaInitScript(result) outputContainsCcudPluginApplicationViaInitScript(result)
and: and:
@@ -110,7 +110,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, testConfig().withCCUDPlugin()) def result = run(testGradleVersion, testConfig().withCCUDPlugin())
then: then:
outputMissesGePluginApplicationViaInitScript(result) outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
and: and:
@@ -120,18 +120,18 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
testGradleVersion << CCUD_COMPATIBLE_VERSIONS testGradleVersion << CCUD_COMPATIBLE_VERSIONS
} }
def "ignores GE URL and allowUntrustedServer when GE plugin is not applied by the init script"() { def "ignores Develocity URL and allowUntrustedServer when Develocity plugin is not applied by the init script"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
given: given:
declareGePluginApplication(testGradleVersion.gradleVersion) declareGePluginApplication(testGradleVersion.gradleVersion)
when: when:
def config = testConfig().withServer(URI.create('https://ge-server.invalid')) def config = testConfig().withServer(URI.create('https://develocity-server.invalid'))
def result = run(testGradleVersion, config) def result = run(testGradleVersion, config)
then: then:
outputMissesGePluginApplicationViaInitScript(result) outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
and: and:
@@ -141,7 +141,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
testGradleVersion << ALL_VERSIONS testGradleVersion << ALL_VERSIONS
} }
def "configures GE URL and allowUntrustedServer when GE plugin is applied by the init script"() { def "configures Develocity URL and allowUntrustedServer when Develocity plugin is applied by the init script"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
when: when:
@@ -149,8 +149,8 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, config) def result = run(testGradleVersion, config)
then: then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsGeConnectionInfo(result, mockScansServer.address.toString(), true) outputContainsDevelocityConnectionInfo(result, mockScansServer.address.toString(), true)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
outputContainsPluginRepositoryInfo(result, 'https://plugins.gradle.org/m2') outputContainsPluginRepositoryInfo(result, 'https://plugins.gradle.org/m2')
@@ -161,22 +161,22 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
testGradleVersion << ALL_VERSIONS testGradleVersion << ALL_VERSIONS
} }
def "enforces GE URL and allowUntrustedServer in project if enforce url parameter is enabled"() { def "enforces Develocity URL and allowUntrustedServer in project if enforce url parameter is enabled"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
given: given:
declareGePluginApplication(testGradleVersion.gradleVersion, URI.create('https://ge-server.invalid')) declareGePluginApplication(testGradleVersion.gradleVersion, URI.create('https://develocity-server.invalid'))
when: when:
def config = testConfig().withServer(mockScansServer.address, true) def config = testConfig().withServer(mockScansServer.address, true)
def result = run(testGradleVersion, config) def result = run(testGradleVersion, config)
then: then:
outputMissesGePluginApplicationViaInitScript(result) outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
and: and:
outputEnforcesGeUrl(result, mockScansServer.address.toString(), true) outputEnforcesDevelocityUrl(result, mockScansServer.address.toString(), true)
and: and:
outputContainsBuildScanUrl(result) outputContainsBuildScanUrl(result)
@@ -185,7 +185,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
testGradleVersion << ALL_VERSIONS testGradleVersion << ALL_VERSIONS
} }
def "can configure alternative repository for plugins when GE plugin is applied by the init script"() { def "can configure alternative repository for plugins when Develocity plugin is applied by the init script"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
when: when:
@@ -193,8 +193,8 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, config) def result = run(testGradleVersion, config)
then: then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsGeConnectionInfo(result, mockScansServer.address.toString(), true) outputContainsDevelocityConnectionInfo(result, mockScansServer.address.toString(), true)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
outputContainsPluginRepositoryInfo(result, 'https://plugins.grdev.net/m2') outputContainsPluginRepositoryInfo(result, 'https://plugins.grdev.net/m2')
@@ -213,7 +213,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, config) def result = run(testGradleVersion, config)
then: then:
outputMissesGePluginApplicationViaInitScript(result) outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
result.output.contains('Common Custom User Data Gradle plugin must be at least 1.7. Configured version is 1.6.6.') result.output.contains('Common Custom User Data Gradle plugin must be at least 1.7. Configured version is 1.6.6.')
@@ -221,15 +221,15 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
testGradleVersion << ALL_VERSIONS testGradleVersion << ALL_VERSIONS
} }
def "can configure GE via CCUD system property overrides when CCUD plugin is inject via init script"() { def "can configure Develocity via CCUD system property overrides when CCUD plugin is inject via init script"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm assumeTrue testGradleVersion.compatibleWithCurrentJvm
when: when:
def config = testConfig().withCCUDPlugin().withServer(URI.create('https://ge-server.invalid')) def config = testConfig().withCCUDPlugin().withServer(URI.create('https://develocity-server.invalid'))
def result = run(testGradleVersion, config, ["help", "-Dgradle.enterprise.url=${mockScansServer.address}".toString()]) def result = run(testGradleVersion, config, ["help", "-Dgradle.enterprise.url=${mockScansServer.address}".toString()])
then: then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsCcudPluginApplicationViaInitScript(result) outputContainsCcudPluginApplicationViaInitScript(result)
and: and:
@@ -247,7 +247,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, config, ["help", "--configuration-cache"]) def result = run(testGradleVersion, config, ["help", "--configuration-cache"])
then: then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion) outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsCcudPluginApplicationViaInitScript(result) outputContainsCcudPluginApplicationViaInitScript(result)
and: and:
@@ -257,7 +257,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
result = run(testGradleVersion, config, ["help", "--configuration-cache"]) result = run(testGradleVersion, config, ["help", "--configuration-cache"])
then: then:
outputMissesGePluginApplicationViaInitScript(result) outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result) outputMissesCcudPluginApplicationViaInitScript(result)
and: and:
@@ -273,7 +273,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
assert 1 == result.output.count(message) assert 1 == result.output.count(message)
} }
void outputContainsGePluginApplicationViaInitScript(BuildResult result, GradleVersion gradleVersion) { void outputContainsDevelocityPluginApplicationViaInitScript(BuildResult result, GradleVersion gradleVersion) {
def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script" def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script"
def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script" def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script"
if (gradleVersion < GRADLE_6) { if (gradleVersion < GRADLE_6) {
@@ -287,7 +287,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
} }
} }
void outputMissesGePluginApplicationViaInitScript(BuildResult result) { void outputMissesDevelocityPluginApplicationViaInitScript(BuildResult result) {
def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script" def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script"
def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script" def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script"
assert !result.output.contains(pluginApplicationLogMsgGradle4And5) assert !result.output.contains(pluginApplicationLogMsgGradle4And5)
@@ -305,20 +305,20 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
assert !result.output.contains(pluginApplicationLogMsg) assert !result.output.contains(pluginApplicationLogMsg)
} }
void outputContainsGeConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer) { void outputContainsDevelocityConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
def geConnectionInfo = "Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer" def geConnectionInfo = "Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
assert result.output.contains(geConnectionInfo) assert result.output.contains(geConnectionInfo)
assert 1 == result.output.count(geConnectionInfo) assert 1 == result.output.count(geConnectionInfo)
} }
void outputContainsPluginRepositoryInfo(BuildResult result, String gradlePluginRepositoryUrl) { void outputContainsPluginRepositoryInfo(BuildResult result, String gradlePluginRepositoryUrl) {
def repositoryInfo = "Gradle Enterprise plugins resolution: ${gradlePluginRepositoryUrl}" def repositoryInfo = "Develocity plugins resolution: ${gradlePluginRepositoryUrl}"
assert result.output.contains(repositoryInfo) assert result.output.contains(repositoryInfo)
assert 1 == result.output.count(repositoryInfo) assert 1 == result.output.count(repositoryInfo)
} }
void outputEnforcesGeUrl(BuildResult result, String geUrl, boolean geAllowUntrustedServer) { void outputEnforcesDevelocityUrl(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
def enforceUrl = "Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer" def enforceUrl = "Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
assert result.output.contains(enforceUrl) assert result.output.contains(enforceUrl)
assert 1 == result.output.count(enforceUrl) assert 1 == result.output.count(enforceUrl)
} }
@@ -369,31 +369,31 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def getEnvVars() { def getEnvVars() {
Map<String, String> envVars = [ Map<String, String> envVars = [
GRADLE_ENTERPRISE_INJECTION_ENABLED: "true", DEVELOCITY_INJECTION_ENABLED: "true",
GRADLE_ENTERPRISE_URL: serverUrl, DEVELOCITY_URL: serverUrl,
GRADLE_ENTERPRISE_ALLOW_UNTRUSTED_SERVER: "true", DEVELOCITY_ALLOW_UNTRUSTED_SERVER: "true",
GRADLE_ENTERPRISE_PLUGIN_VERSION: GE_PLUGIN_VERSION, DEVELOCITY_PLUGIN_VERSION: DEVELOCITY_PLUGIN_VERSION,
GRADLE_ENTERPRISE_BUILD_SCAN_UPLOAD_IN_BACKGROUND: "true" // Need to upload in background since our Mock server doesn't cope with foreground upload DEVELOCITY_BUILD_SCAN_UPLOAD_IN_BACKGROUND: "true" // Need to upload in background since our Mock server doesn't cope with foreground upload
] ]
if (enforceUrl) envVars.put("GRADLE_ENTERPRISE_ENFORCE_URL", "true") if (enforceUrl) envVars.put("DEVELOCITY_ENFORCE_URL", "true")
if (ccudPluginVersion != null) envVars.put("GRADLE_ENTERPRISE_CCUD_PLUGIN_VERSION", ccudPluginVersion) if (ccudPluginVersion != null) envVars.put("DEVELOCITY_CCUD_PLUGIN_VERSION", ccudPluginVersion)
if (pluginRepositoryUrl != null) envVars.put("GRADLE_ENTERPRISE_PLUGIN_REPOSITORY_URL", pluginRepositoryUrl) if (pluginRepositoryUrl != null) envVars.put("GRADLE_PLUGIN_REPOSITORY_URL", pluginRepositoryUrl)
return envVars return envVars
} }
def getJvmArgs() { def getJvmArgs() {
List<String> jvmArgs = [ List<String> jvmArgs = [
"-Dgradle-enterprise.injection-enabled=true", "-Ddevelocity.injection-enabled=true",
"-Dgradle-enterprise.url=$serverUrl", "-Ddevelocity.url=$serverUrl",
"-Dgradle-enterprise.allow-untrusted-server=true", "-Ddevelocity.allow-untrusted-server=true",
"-Dgradle-enterprise.plugin.version=$GE_PLUGIN_VERSION", "-Ddevelocity.plugin.version=$DEVELOCITY_PLUGIN_VERSION",
"-Dgradle-enterprise.build-scan.upload-in-background=true" "-Ddevelocity.build-scan.upload-in-background=true"
] ]
if (enforceUrl) jvmArgs.add("-Dgradle-enterprise.enforce-url=true") if (enforceUrl) jvmArgs.add("-Ddevelocity.enforce-url=true")
if (ccudPluginVersion != null) jvmArgs.add("-Dgradle-enterprise.ccud-plugin.version=$ccudPluginVersion") if (ccudPluginVersion != null) jvmArgs.add("-Ddevelocity.ccud-plugin.version=$ccudPluginVersion")
if (pluginRepositoryUrl != null) jvmArgs.add("-Dgradle-enterprise.plugin-repository.url=$pluginRepositoryUrl") if (pluginRepositoryUrl != null) jvmArgs.add("-Dgradle.plugin-repository.url=$pluginRepositoryUrl")
return jvmArgs.collect { it.toString() } // Convert from GStrings return jvmArgs.collect { it.toString() } // Convert from GStrings
} }