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
on:
push:
branches: [ main ]
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
branches: [ "main" ]
schedule:
- cron: '25 23 * * 2'
@@ -32,9 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
language: [ 'javascript-typescript' ]
steps:
- name: Checkout repository
@@ -45,26 +31,9 @@ jobs:
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# 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
config: |
paths:
- src
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

View File

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

View File

@@ -59,6 +59,13 @@ jobs:
runner-os: '["ubuntu-latest"]'
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:
needs: build-distribution
uses: ./.github/workflows/integ-test-execution-with-caching.yml
@@ -73,14 +80,14 @@ jobs:
runner-os: '["ubuntu-latest"]'
download-dist: true
gradle-enterprise-injection:
develocity-injection:
needs: build-distribution
uses: ./.github/workflows/integ-test-inject-gradle-enterprise.yml
uses: ./.github/workflows/integ-test-inject-develocity.yml
with:
runner-os: '["ubuntu-latest"]'
download-dist: true
secrets:
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
provision-gradle-versions:
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
run: ./gradlew build
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
shell: bash
run: |
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-again report file: ${{ steps.gradle-build-again.outputs.dependency-graph-file }}"
ls -l dependency-graph-reports
if [ ! -e "${{ steps.gradle-assemble.outputs.dependency-graph-file }}" ]; then
echo "Did not find gradle-assemble dependency graph file"
@@ -104,3 +108,41 @@ jobs:
echo "Did not find gradle-build dependency graph files"
exit 1
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
build-root-directory: .github/workflow-samples/no-wrapper
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:
strategy:

View File

@@ -1,4 +1,4 @@
name: Test gradle enterprise injection
name: Test develocity injection
on:
workflow_call:
@@ -12,21 +12,21 @@ on:
type: boolean
default: false
secrets:
GRADLE_ENTERPRISE_ACCESS_KEY:
DEVELOCITY_ACCESS_KEY:
required: true
env:
DOWNLOAD_DIST: ${{ inputs.download-dist }}
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }}
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
GRADLE_ENTERPRISE_INJECTION_ENABLED: true
GRADLE_ENTERPRISE_URL: https://ge.solutions-team.gradle.com
GRADLE_ENTERPRISE_PLUGIN_VERSION: 3.16.1
GRADLE_ENTERPRISE_CCUD_PLUGIN_VERSION: 1.12.1
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
DEVELOCITY_INJECTION_ENABLED: true
DEVELOCITY_URL: https://ge.solutions-team.gradle.com
DEVELOCITY_PLUGIN_VERSION: 3.16.1
DEVELOCITY_CCUD_PLUGIN_VERSION: 1.12.1
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} # This env var has not (yet) been renamed/aliased in GE plugin 3.16.1
jobs:
inject-gradle-enterprise:
inject-develocity:
strategy:
matrix:
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.
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.
@@ -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 current operating system (`RUNNER_OS`)
- The workflow name and Job ID
- A hash of the Job matrix parameters
- The Job id
- A hash of the Job matrix parameters and the workflow name
- 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.
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
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
- The most recent entry saved for the same OS, workflow name, job id and matrix values
- An exact match on OS, job id, workflow name, matrix and Git SHA
- 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
@@ -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
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.
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.
Workflow runs can restore caches created in either the current branch or the default branch (usually main).
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.
Jobs run on other branches will only read from the cache. In most cases, this is the desired behaviour,
because Jobs run against other branches will benefit from the cache Gradle User Home from `main`,
without writing private cache entries that could lead to evicting shared entries.
Jobs run on other branches will only read from the cache. In most cases, this is the desired behavior.
This is because Jobs run on other branches will benefit from the cache Gradle User Home from `main`,
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,
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.
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
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 |
| --- | --- |
| `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-and-submit` | As per `generate`, but any generated dependency graph snapshots will be submitted at the end 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` | Generate a dependency graph snapshot for each build invocation. |
| `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. |
| `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:
```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 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
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:
pull_request:
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
@@ -693,7 +716,7 @@ jobs:
- name: Setup Gradle to generate and submit dependency graphs
uses: gradle/gradle-build-action@v2
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
run: ./gradlew build
```
@@ -707,6 +730,9 @@ on:
workflows: ['run-build-and-generate-dependency-snapshot']
types: [completed]
permissions:
contents: write
jobs:
submit-dependency-graph:
runs-on: ubuntu-latest
@@ -714,7 +740,7 @@ jobs:
- name: Retrieve dependency graph artifact and submit
uses: gradle/gradle-build-action@v2
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
@@ -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.
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:
```yaml
name: Run build with Gradle Enterprise injection
name: Run build with Develocity injection
env:
GRADLE_ENTERPRISE_INJECTION_ENABLED: true
GRADLE_ENTERPRISE_URL: https://ge.gradle.org
GRADLE_ENTERPRISE_PLUGIN_VERSION: 3.16.1
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_KEY }} # Required to publish scans to ge.gradle.org
DEVELOCITY_INJECTION_ENABLED: true
DEVELOCITY_URL: https://develocity.your-server.com
DEVELOCITY_PLUGIN_VERSION: 3.16.1
jobs:
build:
@@ -809,36 +834,37 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Gradle
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
```
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,
but will be used by the GE plugin in order to authenticate with the server.
This example assumes that the `develocity.your-server.com` server allows anonymous publishing of build scans.
In the likely scenario that your Develocity server requires authentication, you will also need to configure an 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:
| Variable | Required | Description |
| --- | --- | --- |
| GRADLE_ENTERPRISE_INJECTION_ENABLED | :white_check_mark: | enables Gradle Enterprise injection |
| GRADLE_ENTERPRISE_URL | :white_check_mark: | the URL of the Gradle Enterprise 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 |
| 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 |
| GRADLE_ENTERPRISE_PLUGIN_VERSION | :white_check_mark: | the version of the [Gradle Enterprise 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 |
| 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 |
| Variable | Required | Description |
|-----------------------------------| --- | --- |
| DEVELOCITY_INJECTION_ENABLED | :white_check_mark: | enables Develocity injection |
| DEVELOCITY_URL | :white_check_mark: | the URL of the Develocity server |
| DEVELOCITY_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed certificate |
| DEVELOCITY_ENFORCE_URL | | enforce the configured Develocity URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Develocity URL |
| DEVELOCITY_PLUGIN_VERSION | :white_check_mark: | the version of the [Develocity Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/) to apply |
| DEVELOCITY_CCUD_PLUGIN_VERSION | | the version of the [Common Custom User Data Gradle plugin](https://github.com/gradle/common-custom-user-data-gradle-plugin) to apply, if any |
| GRADLE_PLUGIN_REPOSITORY_URL | | the URL of the repository to use when resolving the Develocity and CCUD plugins; the Gradle Plugin Portal is used by default |
## 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).
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))
- 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
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:
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
@@ -88,11 +93,6 @@ inputs:
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.
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:
description: When 'false', no Job Summary will be generated for the Job.
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.github-dependency-graph.init.gradle',
'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) {
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 fs_1 = __importDefault(__nccwpck_require__(57147));
const layout = __importStar(__nccwpck_require__(28182));
const errors_1 = __nccwpck_require__(36976);
const input_params_1 = __nccwpck_require__(23885);
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_';
function setup(option) {
@@ -139983,16 +139984,22 @@ function setup(option) {
return;
}
core.info('Enabling dependency graph generation');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory());
core.exportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports'));
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true');
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', (0, input_params_1.getDependencyGraphContinueOnFailure)());
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator());
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId);
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref);
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext());
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory());
maybeExportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports'));
});
}
exports.setup = setup;
function maybeExportVariable(variableName, value) {
if (!process.env[variableName]) {
core.exportVariable(variableName, value);
}
}
function complete(option) {
return __awaiter(this, void 0, void 0, function* () {
try {
@@ -140009,7 +140016,7 @@ function complete(option) {
}
}
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());
}
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) {
if (error instanceof request_error_1.RequestError) {
core.warning(buildWarningMessage(jsonFile, error));
throw new Error(translateErrorMessage(jsonFile, error));
}
else {
throw error;
@@ -140061,9 +140068,9 @@ function submitDependencyGraphs(dependencyGraphFiles) {
}
});
}
function buildWarningMessage(jsonFile, error) {
function translateErrorMessage(jsonFile, error) {
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') {
return `${mainWarning}
Please ensure that the 'contents: write' permission is available for the workflow job.
@@ -140118,6 +140125,12 @@ function findDependencyGraphFiles(dir) {
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() {
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:
@@ -140288,7 +140325,7 @@ function validateGradleWrapper(buildRootDirectory) {
}
function verifyExists(file, description) {
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) {
@@ -140332,7 +140369,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
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 string_argv_1 = __nccwpck_require__(19663);
function isCacheDisabled() {
@@ -140383,10 +140420,6 @@ function getGradleVersion() {
return core.getInput('gradle-version');
}
exports.getGradleVersion = getGradleVersion;
function getGradleExecutable() {
return core.getInput('gradle-executable');
}
exports.getGradleExecutable = getGradleExecutable;
function getArguments() {
const input = core.getInput('arguments');
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'.`);
}
exports.getDependencyGraphOption = getDependencyGraphOption;
function getDependencyGraphContinueOnFailure() {
return getBooleanInput('dependency-graph-continue-on-failure', true);
}
exports.getDependencyGraphContinueOnFailure = getDependencyGraphContinueOnFailure;
function getArtifactRetentionDays() {
const val = core.getInput('artifact-retention-days');
return parseNumericInput('artifact-retention-days', val, 0);
@@ -140725,6 +140762,7 @@ function run() {
core.info(error.stack);
}
}
process.exit();
});
}
exports.run = run;
@@ -140781,19 +140819,13 @@ const cache = __importStar(__nccwpck_require__(27799));
const toolCache = __importStar(__nccwpck_require__(27784));
const gradlew = __importStar(__nccwpck_require__(32335));
const params = __importStar(__nccwpck_require__(23885));
const layout = __importStar(__nccwpck_require__(28182));
const cache_utils_1 = __nccwpck_require__(41678);
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions';
function provisionGradle() {
return __awaiter(this, void 0, void 0, function* () {
const gradleVersion = params.getGradleVersion();
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
return addToPath(path.resolve(yield installGradle(gradleVersion)));
}
const gradleExecutable = params.getGradleExecutable();
if (gradleExecutable !== '') {
const workspaceDirectory = layout.workspaceDirectory();
return addToPath(path.resolve(workspaceDirectory, gradleExecutable));
return addToPath(yield installGradle(gradleVersion));
}
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.github-dependency-graph.init.gradle',
'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) {
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 fs_1 = __importDefault(__nccwpck_require__(57147));
const layout = __importStar(__nccwpck_require__(28182));
const errors_1 = __nccwpck_require__(36976);
const input_params_1 = __nccwpck_require__(23885);
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_';
function setup(option) {
@@ -137436,16 +137437,22 @@ function setup(option) {
return;
}
core.info('Enabling dependency graph generation');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true');
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref);
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext());
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory());
core.exportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports'));
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true');
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', (0, input_params_1.getDependencyGraphContinueOnFailure)());
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator());
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId);
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref);
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext());
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory());
maybeExportVariable('DEPENDENCY_GRAPH_REPORT_DIR', path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports'));
});
}
exports.setup = setup;
function maybeExportVariable(variableName, value) {
if (!process.env[variableName]) {
core.exportVariable(variableName, value);
}
}
function complete(option) {
return __awaiter(this, void 0, void 0, function* () {
try {
@@ -137462,7 +137469,7 @@ function complete(option) {
}
}
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());
}
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) {
if (error instanceof request_error_1.RequestError) {
core.warning(buildWarningMessage(jsonFile, error));
throw new Error(translateErrorMessage(jsonFile, error));
}
else {
throw error;
@@ -137514,9 +137521,9 @@ function submitDependencyGraphs(dependencyGraphFiles) {
}
});
}
function buildWarningMessage(jsonFile, error) {
function translateErrorMessage(jsonFile, error) {
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') {
return `${mainWarning}
Please ensure that the 'contents: write' permission is available for the workflow job.
@@ -137571,6 +137578,12 @@ function findDependencyGraphFiles(dir) {
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() {
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:
@@ -137653,7 +137690,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
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 string_argv_1 = __nccwpck_require__(19663);
function isCacheDisabled() {
@@ -137704,10 +137741,6 @@ function getGradleVersion() {
return core.getInput('gradle-version');
}
exports.getGradleVersion = getGradleVersion;
function getGradleExecutable() {
return core.getInput('gradle-executable');
}
exports.getGradleExecutable = getGradleExecutable;
function getArguments() {
const input = core.getInput('arguments');
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'.`);
}
exports.getDependencyGraphOption = getDependencyGraphOption;
function getDependencyGraphContinueOnFailure() {
return getBooleanInput('dependency-graph-continue-on-failure', true);
}
exports.getDependencyGraphContinueOnFailure = getDependencyGraphContinueOnFailure;
function getArtifactRetentionDays() {
const val = core.getInput('artifact-retention-days');
return parseNumericInput('artifact-retention-days', val, 0);
@@ -138025,6 +138062,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.run = void 0;
const core = __importStar(__nccwpck_require__(42186));
const setupGradle = __importStar(__nccwpck_require__(18652));
const errors_1 = __nccwpck_require__(36976);
process.on('uncaughtException', e => handleFailure(e));
function run() {
return __awaiter(this, void 0, void 0, function* () {
@@ -138032,8 +138070,14 @@ function run() {
yield setupGradle.complete();
}
catch (error) {
handleFailure(error);
if (error instanceof errors_1.PostActionJobFailure) {
core.setFailed(String(error));
}
else {
handleFailure(error);
}
}
process.exit();
});
}
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",
"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": "npm run compile-main && npm run compile-post",
"compile": "npm-run-all --parallel compile-*",
"check": "npm-run-all --parallel format lint",
"test": "jest",
"check": "npm run format && npm run lint",
"build": "npm run check && npm run compile",
"all": "npm run build && npm test"
},
@@ -53,6 +53,7 @@
"eslint-plugin-prettier": "5.1.2",
"jest": "29.7.0",
"js-yaml": "4.1.0",
"npm-run-all": "4.1.5",
"patch-package": "8.0.0",
"prettier": "3.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.github-dependency-graph.init.gradle',
'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) {
const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename)

View File

@@ -10,7 +10,13 @@ import * as path from 'path'
import fs from 'fs'
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_'
@@ -25,18 +31,25 @@ export async function setup(option: DependencyGraphOption): Promise<void> {
}
core.info('Enabling dependency graph generation')
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator())
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory())
core.exportVariable(
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', getDependencyGraphContinueOnFailure())
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator())
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory())
maybeExportVariable(
'DEPENDENCY_GRAPH_REPORT_DIR',
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> {
try {
switch (option) {
@@ -51,7 +64,7 @@ export async function complete(option: DependencyGraphOption): Promise<void> {
await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles())
}
} 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 {
await submitDependencyGraphs(await downloadDependencyGraphs())
} 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)
} catch (error) {
if (error instanceof RequestError) {
core.warning(buildWarningMessage(jsonFile, error))
throw new Error(translateErrorMessage(jsonFile, error))
} else {
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 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') {
return `${mainWarning}
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
}
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> {
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 {
if (!fs.existsSync(file)) {
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')
}
export function getGradleExecutable(): string {
return core.getInput('gradle-executable')
}
export function getArguments(): string[] {
const input = core.getInput('arguments')
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 {
const val = core.getInput('artifact-retention-days')
return parseNumericInput('artifact-retention-days', val, 0)

View File

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

View File

@@ -1,5 +1,6 @@
import * as core from '@actions/core'
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
// @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 {
await setupGradle.complete()
} 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 {

View File

@@ -8,7 +8,6 @@ import * as toolCache from '@actions/tool-cache'
import * as gradlew from './gradlew'
import * as params from './input-params'
import * as layout from './repository-layout'
import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
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> {
const gradleVersion = params.getGradleVersion()
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
return addToPath(path.resolve(await installGradle(gradleVersion)))
}
const gradleExecutable = params.getGradleExecutable()
if (gradleExecutable !== '') {
const workspaceDirectory = layout.workspaceDirectory()
return addToPath(path.resolve(workspaceDirectory, gradleExecutable))
return addToPath(await installGradle(gradleVersion))
}
return undefined

View File

@@ -9,7 +9,7 @@ buildscript {
maven { url pluginRepositoryUrl }
}
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

View File

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

View File

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

View File

@@ -16,7 +16,7 @@ import java.nio.file.Files
import java.util.zip.GZIPOutputStream
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 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_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_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_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)
@@ -146,7 +147,7 @@ class BaseInitScriptTest extends Specification {
} else {
"""
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'" : ""}
}
gradleEnterprise {
@@ -174,7 +175,7 @@ class BaseInitScriptTest extends Specification {
} else if (gradleVersion < GradleVersion.version('6.0')) {
"""
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'" : ""}
}
gradleEnterprise {

View File

@@ -1,11 +1,16 @@
package com.gradle.gradlebuildaction
import org.gradle.util.GradleVersion
import static org.junit.Assume.assumeTrue
class TestDependencyGraph extends BaseInitScriptTest {
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
def "does not produce dependency graph when not enabled"() {
@@ -29,7 +34,6 @@ class TestDependencyGraph extends BaseInitScriptTest {
then:
assert reportFile.exists()
assert gitHubOutputFile.text == "dependency-graph-file=${reportFile.absolutePath}\n"
where:
testGradleVersion << [GRADLE_8_X]
@@ -57,7 +61,23 @@ class TestDependencyGraph extends BaseInitScriptTest {
then:
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:
testGradleVersion << NO_DEPENDENCY_GRAPH_VERSIONS
@@ -110,13 +130,13 @@ class TestDependencyGraph extends BaseInitScriptTest {
def getEnvVars() {
return [
GITHUB_DEPENDENCY_GRAPH_ENABLED: "true",
GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE: "true",
GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR: "CORRELATOR",
GITHUB_DEPENDENCY_GRAPH_JOB_ID: "1",
GITHUB_DEPENDENCY_GRAPH_REF: "main",
GITHUB_DEPENDENCY_GRAPH_SHA: "123456",
GITHUB_DEPENDENCY_GRAPH_WORKSPACE: testProjectDir.absolutePath,
DEPENDENCY_GRAPH_REPORT_DIR: reportsDir.absolutePath,
GITHUB_OUTPUT: gitHubOutputFile.absolutePath
]
}
@@ -127,8 +147,4 @@ class TestDependencyGraph extends BaseInitScriptTest {
def getReportFile() {
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
class TestGradleEnterpriseInjection extends BaseInitScriptTest {
class TestDevelocityInjection extends BaseInitScriptTest {
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')
def "does not apply GE plugins when not requested"() {
def "does not apply Develocity plugins when not requested"() {
assumeTrue testGradleVersion.compatibleWithCurrentJvm
when:
def result = run([], initScript, testGradleVersion.gradleVersion)
then:
outputMissesGePluginApplicationViaInitScript(result)
outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result)
where:
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
given:
@@ -36,7 +36,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, testConfig())
then:
outputMissesGePluginApplicationViaInitScript(result)
outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result)
and:
@@ -46,14 +46,14 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
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
when:
def result = run(testGradleVersion, testConfig())
then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputMissesCcudPluginApplicationViaInitScript(result)
and:
@@ -63,14 +63,14 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
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
when:
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsCcudPluginApplicationViaInitScript(result)
and:
@@ -80,7 +80,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
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
given:
@@ -90,7 +90,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
then:
outputMissesGePluginApplicationViaInitScript(result)
outputMissesDevelocityPluginApplicationViaInitScript(result)
outputContainsCcudPluginApplicationViaInitScript(result)
and:
@@ -110,7 +110,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
then:
outputMissesGePluginApplicationViaInitScript(result)
outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result)
and:
@@ -120,18 +120,18 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
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
given:
declareGePluginApplication(testGradleVersion.gradleVersion)
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)
then:
outputMissesGePluginApplicationViaInitScript(result)
outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result)
and:
@@ -141,7 +141,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
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
when:
@@ -149,8 +149,8 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, config)
then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsGeConnectionInfo(result, mockScansServer.address.toString(), true)
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsDevelocityConnectionInfo(result, mockScansServer.address.toString(), true)
outputMissesCcudPluginApplicationViaInitScript(result)
outputContainsPluginRepositoryInfo(result, 'https://plugins.gradle.org/m2')
@@ -161,22 +161,22 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
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
given:
declareGePluginApplication(testGradleVersion.gradleVersion, URI.create('https://ge-server.invalid'))
declareGePluginApplication(testGradleVersion.gradleVersion, URI.create('https://develocity-server.invalid'))
when:
def config = testConfig().withServer(mockScansServer.address, true)
def result = run(testGradleVersion, config)
then:
outputMissesGePluginApplicationViaInitScript(result)
outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result)
and:
outputEnforcesGeUrl(result, mockScansServer.address.toString(), true)
outputEnforcesDevelocityUrl(result, mockScansServer.address.toString(), true)
and:
outputContainsBuildScanUrl(result)
@@ -185,7 +185,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
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
when:
@@ -193,8 +193,8 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, config)
then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsGeConnectionInfo(result, mockScansServer.address.toString(), true)
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsDevelocityConnectionInfo(result, mockScansServer.address.toString(), true)
outputMissesCcudPluginApplicationViaInitScript(result)
outputContainsPluginRepositoryInfo(result, 'https://plugins.grdev.net/m2')
@@ -213,7 +213,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, config)
then:
outputMissesGePluginApplicationViaInitScript(result)
outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result)
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
}
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
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()])
then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsCcudPluginApplicationViaInitScript(result)
and:
@@ -247,7 +247,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def result = run(testGradleVersion, config, ["help", "--configuration-cache"])
then:
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
outputContainsCcudPluginApplicationViaInitScript(result)
and:
@@ -257,7 +257,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
result = run(testGradleVersion, config, ["help", "--configuration-cache"])
then:
outputMissesGePluginApplicationViaInitScript(result)
outputMissesDevelocityPluginApplicationViaInitScript(result)
outputMissesCcudPluginApplicationViaInitScript(result)
and:
@@ -273,7 +273,7 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
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 pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script"
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 pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script"
assert !result.output.contains(pluginApplicationLogMsgGradle4And5)
@@ -305,20 +305,20 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
assert !result.output.contains(pluginApplicationLogMsg)
}
void outputContainsGeConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
def geConnectionInfo = "Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
void outputContainsDevelocityConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
def geConnectionInfo = "Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
assert result.output.contains(geConnectionInfo)
assert 1 == result.output.count(geConnectionInfo)
}
void outputContainsPluginRepositoryInfo(BuildResult result, String gradlePluginRepositoryUrl) {
def repositoryInfo = "Gradle Enterprise plugins resolution: ${gradlePluginRepositoryUrl}"
def repositoryInfo = "Develocity plugins resolution: ${gradlePluginRepositoryUrl}"
assert result.output.contains(repositoryInfo)
assert 1 == result.output.count(repositoryInfo)
}
void outputEnforcesGeUrl(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
def enforceUrl = "Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
void outputEnforcesDevelocityUrl(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
def enforceUrl = "Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
assert result.output.contains(enforceUrl)
assert 1 == result.output.count(enforceUrl)
}
@@ -369,31 +369,31 @@ class TestGradleEnterpriseInjection extends BaseInitScriptTest {
def getEnvVars() {
Map<String, String> envVars = [
GRADLE_ENTERPRISE_INJECTION_ENABLED: "true",
GRADLE_ENTERPRISE_URL: serverUrl,
GRADLE_ENTERPRISE_ALLOW_UNTRUSTED_SERVER: "true",
GRADLE_ENTERPRISE_PLUGIN_VERSION: GE_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_INJECTION_ENABLED: "true",
DEVELOCITY_URL: serverUrl,
DEVELOCITY_ALLOW_UNTRUSTED_SERVER: "true",
DEVELOCITY_PLUGIN_VERSION: DEVELOCITY_PLUGIN_VERSION,
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 (ccudPluginVersion != null) envVars.put("GRADLE_ENTERPRISE_CCUD_PLUGIN_VERSION", ccudPluginVersion)
if (pluginRepositoryUrl != null) envVars.put("GRADLE_ENTERPRISE_PLUGIN_REPOSITORY_URL", pluginRepositoryUrl)
if (enforceUrl) envVars.put("DEVELOCITY_ENFORCE_URL", "true")
if (ccudPluginVersion != null) envVars.put("DEVELOCITY_CCUD_PLUGIN_VERSION", ccudPluginVersion)
if (pluginRepositoryUrl != null) envVars.put("GRADLE_PLUGIN_REPOSITORY_URL", pluginRepositoryUrl)
return envVars
}
def getJvmArgs() {
List<String> jvmArgs = [
"-Dgradle-enterprise.injection-enabled=true",
"-Dgradle-enterprise.url=$serverUrl",
"-Dgradle-enterprise.allow-untrusted-server=true",
"-Dgradle-enterprise.plugin.version=$GE_PLUGIN_VERSION",
"-Dgradle-enterprise.build-scan.upload-in-background=true"
"-Ddevelocity.injection-enabled=true",
"-Ddevelocity.url=$serverUrl",
"-Ddevelocity.allow-untrusted-server=true",
"-Ddevelocity.plugin.version=$DEVELOCITY_PLUGIN_VERSION",
"-Ddevelocity.build-scan.upload-in-background=true"
]
if (enforceUrl) jvmArgs.add("-Dgradle-enterprise.enforce-url=true")
if (ccudPluginVersion != null) jvmArgs.add("-Dgradle-enterprise.ccud-plugin.version=$ccudPluginVersion")
if (pluginRepositoryUrl != null) jvmArgs.add("-Dgradle-enterprise.plugin-repository.url=$pluginRepositoryUrl")
if (enforceUrl) jvmArgs.add("-Ddevelocity.enforce-url=true")
if (ccudPluginVersion != null) jvmArgs.add("-Ddevelocity.ccud-plugin.version=$ccudPluginVersion")
if (pluginRepositoryUrl != null) jvmArgs.add("-Dgradle.plugin-repository.url=$pluginRepositoryUrl")
return jvmArgs.collect { it.toString() } // Convert from GStrings
}