mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-10-20 15:18:56 +08:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
915a66c096 | ||
|
8e5c8782a3 | ||
|
9f977db2d8 | ||
|
fa27d06744 | ||
|
a0fdbb009a | ||
|
f59a6d4310 | ||
|
b69de5f2a9 | ||
|
3c11eee5f9 | ||
|
4301451b53 | ||
|
295170c2ce | ||
|
ce999babab | ||
|
ce35ffa374 | ||
|
ad97b0f09e | ||
|
29c79cfd95 | ||
|
bd57605957 | ||
|
f464d5c9e5 | ||
|
cef72ff9e4 | ||
|
7a67f395d2 | ||
|
bc190ca89a | ||
|
f01b48d89d | ||
|
1e71bceb3f | ||
|
9a4d99b236 | ||
|
33f9bc031c | ||
|
437bff62b6 | ||
|
c0186c5832 | ||
|
ee7ca6ac9b | ||
|
063cc1c708 | ||
|
820b228f28 | ||
|
d0ffeaa089 | ||
|
4c9c435d2f | ||
|
a6ad1901be | ||
|
d7761f188f | ||
|
92c37aaab7 | ||
|
1a6aca96f3 | ||
|
90c9cfa90d | ||
|
35af09efd8 | ||
|
00309f16a9 | ||
|
3273b6ada1 | ||
|
f807993b34 | ||
|
bde650d6f1 |
@@ -12,6 +12,7 @@
|
|||||||
"import/no-namespace": "off",
|
"import/no-namespace": "off",
|
||||||
"i18n-text/no-en": "off",
|
"i18n-text/no-en": "off",
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
|
"no-shadow": "off",
|
||||||
"sort-imports": "off",
|
"sort-imports": "off",
|
||||||
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
|
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
|
||||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
"@typescript-eslint/no-misused-new": "error",
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
"@typescript-eslint/no-namespace": "error",
|
"@typescript-eslint/no-namespace": "error",
|
||||||
"@typescript-eslint/no-non-null-assertion": "off",
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"@typescript-eslint/no-shadow": "error",
|
||||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
"@typescript-eslint/no-useless-constructor": "error",
|
"@typescript-eslint/no-useless-constructor": "error",
|
||||||
|
15
.github/dependabot.yml
vendored
15
.github/dependabot.yml
vendored
@@ -10,12 +10,27 @@ updates:
|
|||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
|
groups:
|
||||||
|
github-actions:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
|
|
||||||
- package-ecosystem: "npm"
|
- package-ecosystem: "npm"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
ignore:
|
ignore:
|
||||||
- dependency-name: "@types/node"
|
- dependency-name: "@types/node"
|
||||||
|
groups:
|
||||||
|
runtime-dependencies:
|
||||||
|
patterns:
|
||||||
|
- "@actions/*"
|
||||||
|
- "@octokit/rest"
|
||||||
|
- "string-argv"
|
||||||
|
dev-dependencies:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
|
|
||||||
- package-ecosystem: "gradle"
|
- package-ecosystem: "gradle"
|
||||||
directory: ".github/workflow-samples/gradle-plugin"
|
directory: ".github/workflow-samples/gradle-plugin"
|
||||||
registries:
|
registries:
|
||||||
|
Binary file not shown.
@@ -1,7 +1,8 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=e111cb9948407e26351227dabce49822fb88c37ee72f1d1582a69c68af2e702f
|
distributionSha256Sum=03ec176d388f2aa99defcadc3ac6adf8dd2bce5145a129659537c0874dea5ad1
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@@ -130,10 +130,13 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
|
Binary file not shown.
@@ -1,7 +1,8 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=e111cb9948407e26351227dabce49822fb88c37ee72f1d1582a69c68af2e702f
|
distributionSha256Sum=03ec176d388f2aa99defcadc3ac6adf8dd2bce5145a129659537c0874dea5ad1
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
5
.github/workflow-samples/groovy-dsl/gradlew
vendored
5
.github/workflow-samples/groovy-dsl/gradlew
vendored
@@ -130,10 +130,13 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
|
Binary file not shown.
@@ -1,7 +1,8 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=e111cb9948407e26351227dabce49822fb88c37ee72f1d1582a69c68af2e702f
|
distributionSha256Sum=03ec176d388f2aa99defcadc3ac6adf8dd2bce5145a129659537c0874dea5ad1
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@@ -130,10 +130,13 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
|
Binary file not shown.
@@ -1,7 +1,8 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=e111cb9948407e26351227dabce49822fb88c37ee72f1d1582a69c68af2e702f
|
distributionSha256Sum=03ec176d388f2aa99defcadc3ac6adf8dd2bce5145a129659537c0874dea5ad1
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
5
.github/workflow-samples/kotlin-dsl/gradlew
vendored
5
.github/workflow-samples/kotlin-dsl/gradlew
vendored
@@ -130,10 +130,13 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
|
5
.github/workflows/ci-full-check.yml
vendored
5
.github/workflows/ci-full-check.yml
vendored
@@ -29,6 +29,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
|
dependency-graph:
|
||||||
|
uses: ./.github/workflows/integ-test-dependency-graph.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:
|
||||||
|
2
.github/workflows/ci-init-script-check.yml
vendored
2
.github/workflows/ci-init-script-check.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
|||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 8
|
java-version: 8
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v2.4.2 # Use a released version to avoid breakages
|
uses: gradle/gradle-build-action@v2.6.0 # Use a released version to avoid breakages
|
||||||
- name: Run integration tests
|
- name: Run integration tests
|
||||||
working-directory: test/init-scripts
|
working-directory: test/init-scripts
|
||||||
run: ./gradlew check
|
run: ./gradlew check
|
||||||
|
9
.github/workflows/ci-quick-check.yml
vendored
9
.github/workflows/ci-quick-check.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
- name: Configure Gradle as default for unit test
|
- name: Configure Gradle as default for unit test
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
gradle-version: 8.1.1
|
gradle-version: 8.2.1
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
npm install
|
npm install
|
||||||
@@ -50,6 +50,13 @@ jobs:
|
|||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
download-dist: true
|
download-dist: true
|
||||||
|
|
||||||
|
dependency-graph:
|
||||||
|
needs: build-distribution
|
||||||
|
uses: ./.github/workflows/integ-test-dependency-graph.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
|
||||||
|
98
.github/workflows/integ-test-dependency-graph.yml
vendored
Normal file
98
.github/workflows/integ-test-dependency-graph.yml
vendored
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
name: Test execution with caching
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
cache-key-prefix:
|
||||||
|
type: string
|
||||||
|
runner-os:
|
||||||
|
type: string
|
||||||
|
default: '["ubuntu-latest", "windows-latest", "macos-latest"]'
|
||||||
|
download-dist:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-graph-${{ inputs.cache-key-prefix }}
|
||||||
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
groovy-generate:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: ${{fromJSON(inputs.runner-os)}}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
|
- name: Setup Gradle for dependency-graph generate
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
dependency-graph: generate
|
||||||
|
- name: Run gradle build
|
||||||
|
run: ./gradlew build
|
||||||
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
|
|
||||||
|
kotlin-generate:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: ${{fromJSON(inputs.runner-os)}}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
|
- name: Setup Gradle for dependency-graph generate
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
dependency-graph: generate-and-submit
|
||||||
|
- name: Run gradle build
|
||||||
|
run: ./gradlew build
|
||||||
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
|
|
||||||
|
submit:
|
||||||
|
needs: [groovy-generate, kotlin-generate]
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
|
- name: Submit dependency graphs
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
dependency-graph: download-and-submit
|
||||||
|
|
||||||
|
multiple-builds:
|
||||||
|
runs-on: "ubuntu-latest"
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
|
- name: Setup Gradle for dependency-graph generate
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
dependency-graph: generate
|
||||||
|
- name: Run assemble
|
||||||
|
run: ./gradlew assemble
|
||||||
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
|
env:
|
||||||
|
GITHUB_JOB_CORRELATOR: job-correlator
|
||||||
|
- name: Run build
|
||||||
|
run: ./gradlew build
|
||||||
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
|
env:
|
||||||
|
GITHUB_JOB_CORRELATOR: job-correlator
|
||||||
|
- name: Check generated dependency graphs
|
||||||
|
run: |
|
||||||
|
ls -l dependency-graph-reports
|
||||||
|
if ([ ! -e dependency-graph-reports/job-correlator.json ] || [ ! -e dependency-graph-reports/job-correlator-1.json ])
|
||||||
|
then
|
||||||
|
echo "Did not find expected dependency graph files"
|
||||||
|
exit 1
|
||||||
|
fi
|
@@ -1,3 +1,3 @@
|
|||||||
# Configuration file for asdf version manager
|
# Configuration file for asdf version manager
|
||||||
nodejs 16.18.1
|
nodejs 16.18.1
|
||||||
gradle 8.1.1
|
gradle 8.2.1
|
||||||
|
2
LICENSE
2
LICENSE
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2018 GitHub, Inc. and contributors
|
Copyright (c) 2023 Gradle Inc.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
94
README.md
94
README.md
@@ -408,3 +408,97 @@ You can use the `gradle-build-action` on GitHub Enterprise Server, and benefit f
|
|||||||
- Easily run your build with different versions of Gradle
|
- Easily run your build with different versions of Gradle
|
||||||
- Save/restore of Gradle User Home (requires GHES v3.5+ : GitHub Actions cache was introduced in GHES 3.5)
|
- Save/restore of Gradle User Home (requires GHES v3.5+ : GitHub Actions cache was introduced in GHES 3.5)
|
||||||
- Support for GitHub Actions Job Summary (requires GHES 3.6+ : GitHub Actions Job Summary support was introduced in GHES 3.6). In earlier versions of GHES the build-results summary and caching report will be written to the workflow log, as part of the post-action step.
|
- Support for GitHub Actions Job Summary (requires GHES 3.6+ : GitHub Actions Job Summary support was introduced in GHES 3.6). In earlier versions of GHES the build-results summary and caching report will be written to the workflow log, as part of the post-action step.
|
||||||
|
|
||||||
|
# GitHub Dependency Graph support
|
||||||
|
**EXPERIMENTAL**
|
||||||
|
|
||||||
|
The `gradle-build-action` has experimental support for submitting a [GitHub Dependency Graph](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-the-dependency-graph) snapshot via the [GitHub Dependency Submission API](https://docs.github.com/en/rest/dependency-graph/dependency-submission?apiVersion=2022-11-28).
|
||||||
|
|
||||||
|
The dependency graph snapshot is generated via integration with the [GitHub Dependency Graph Gradle Plugin](https://plugins.gradle.org/plugin/org.gradle.github-dependency-graph-gradle-plugin), and saved as a workflow artifact. The generated snapshot files can be submitted either in the same job, or in a subsequent job (in the same or a dependent workflow).
|
||||||
|
|
||||||
|
The generated dependency graph snapshot reports all of the dependencies that were resolved during a bulid execution, and is used by GitHub to generate [Dependabot Alerts](https://docs.github.com/en/code-security/dependabot/dependabot-alerts/about-dependabot-alerts) for vulnerable dependencies, as well as to populate the [Dependency Graph insights view](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/exploring-the-dependencies-of-a-repository#viewing-the-dependency-graph).
|
||||||
|
|
||||||
|
You enable GitHub Dependency Graph support by setting the `dependency-graph` action parameter. Valid values are:
|
||||||
|
|
||||||
|
|<div style="width:290px">Option</div> | 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. |
|
||||||
|
|
||||||
|
- 'disabled': Do not generate a dependency graph for any build invocations. 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.
|
||||||
|
|
||||||
|
Dependency Graph _submission_ (but not generation) requires the `contents: write` permission, which may need to be explicitly enabled in the workflow file.
|
||||||
|
|
||||||
|
Example of a simple workflow that generates and submits a dependency graph:
|
||||||
|
```yaml
|
||||||
|
name: Submit dependency graph
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Setup Gradle to generate and submit dependency graphs
|
||||||
|
uses: gradle/gradle-build-action@dependency-graph
|
||||||
|
with:
|
||||||
|
dependency-graph: generate-and-submit
|
||||||
|
- name: Run a build, generating the dependency graph snapshot which will be submitted
|
||||||
|
run: ./gradlew build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependency snapshots generated for pull requests
|
||||||
|
|
||||||
|
This `contents: write` permission is not available for any workflow that is triggered by a pull request submitted from a forked repository, since it would permit a malicious pull request to make repository changes.
|
||||||
|
|
||||||
|
Because of this restriction, it is not possible to `generate-and-submit` a dependency graph generated for a pull-request that comes from a repository fork. In order to do so, 2 workflows will be required:
|
||||||
|
1. The first workflow runs directly against the pull request sources and will generate the dependency graph snapshot.
|
||||||
|
2. The second workflow is triggered on `workflow_run` of the first workflow, and will submit the previously saved dependency snapshots.
|
||||||
|
|
||||||
|
Note: when `download-and-submit` is used in a workflow triggered via [workflow_run](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run), the action will download snapshots saved in the triggering workflow.
|
||||||
|
|
||||||
|
***Main workflow file***
|
||||||
|
```yaml
|
||||||
|
name: run-build-and-generate-dependency-snapshot
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Setup Gradle to generate and submit dependency graphs
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
dependency-graph: generate # Only generate in this job
|
||||||
|
- name: Run a build, generating the dependency graph snapshot which will be submitted
|
||||||
|
run: ./gradlew build
|
||||||
|
```
|
||||||
|
|
||||||
|
***Dependent workflow file***
|
||||||
|
```yaml
|
||||||
|
name: submit-dependency-snapshot
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ['run-build-and-generate-dependency-snapshot']
|
||||||
|
types: [completed]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
submit-snapshots:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Retrieve dependency graph artifact and submit
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
dependency-graph: download-and-submit
|
||||||
|
```
|
||||||
|
|
||||||
|
10
action.yml
10
action.yml
@@ -58,6 +58,11 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: true
|
default: true
|
||||||
|
|
||||||
|
dependency-graph:
|
||||||
|
description: Specifies if a GitHub dependency snapshot should be generated for each Gradle build, and if so, how. Valid values are 'disabled' (default), 'generate', 'generate-and-submit' and 'download-and-submit'.
|
||||||
|
required: false
|
||||||
|
default: 'disabled'
|
||||||
|
|
||||||
# EXPERIMENTAL & INTERNAL ACTION INPUTS
|
# EXPERIMENTAL & INTERNAL ACTION INPUTS
|
||||||
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
||||||
# These properties are experimental and not (yet) designed for production use, and may change without notice in a subsequent release of `gradle-build-action`.
|
# These properties are experimental and not (yet) designed for production use, and may change without notice in a subsequent release of `gradle-build-action`.
|
||||||
@@ -75,6 +80,11 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
|
github-token:
|
||||||
|
description: The GitHub token used to authenticate when submitting via the Dependency Submission API.
|
||||||
|
default: ${{ github.token }}
|
||||||
|
required: false
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
build-scan-url:
|
build-scan-url:
|
||||||
description: Link to the build scan if any
|
description: Link to the build scan if any
|
||||||
|
24
actions/clear-dependency-graph/action.yml
Normal file
24
actions/clear-dependency-graph/action.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
name: 'Clear dependency graph for a correlator'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
job-correlator:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Set current timestamp as env variable
|
||||||
|
shell: bash
|
||||||
|
run: echo "NOW=$(date -Iseconds)" >> $GITHUB_ENV
|
||||||
|
- name: Submit empty dependency graph
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
curl -L \
|
||||||
|
-X POST \
|
||||||
|
-H "Accept: application/vnd.github+json" \
|
||||||
|
-H "Authorization: Bearer ${{ github.token }}" \
|
||||||
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||||
|
https://api.github.com/repos/${{ github.repository }}/dependency-graph/snapshots \
|
||||||
|
-d '{ "version" : 0, "job" : { "id" : "${{ github.run_id }}", "correlator" : "${{ inputs.job-correlator }} " }, "sha" : "${{ github.sha }}", "ref" : "${{ github.ref }}", "detector" : { "name" : "GitHub Dependency Graph Gradle Plugin", "version" : "0.0.3", "url" : "https://github.com/gradle/github-dependency-graph-gradle-plugin" }, "manifests" : {}, "scanned" : "${{ env.NOW }}" }'
|
||||||
|
- run: echo "::notice ::Cleared dependency graph for job correlator '${{ inputs.job-correlator }}'"
|
||||||
|
shell: bash
|
@@ -1,19 +0,0 @@
|
|||||||
name: "Dependency Graph Generate"
|
|
||||||
description: Calculates the complete dependency graph for the repository, saving it as a JSON artifact.
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
gradle-version:
|
|
||||||
description: Gradle version to use. If specified, this Gradle version will be downloaded, added to the PATH and used for invoking Gradle.
|
|
||||||
required: false
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
build-root-directory:
|
|
||||||
description: Path to the root directory of the build. Default is the root of the GitHub workspace.
|
|
||||||
required: false
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'node16'
|
|
||||||
main: '../../dist/dependency-graph-generate/index.js'
|
|
@@ -1,12 +0,0 @@
|
|||||||
name: "Dependency Graph Submit"
|
|
||||||
description: Retrieves a previously created dependency graph JSON and submits via the GitHub Dependency Submission API.
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
github-token:
|
|
||||||
description: The GitHub token used to authenticate when submitting via the Dependency Submission API.
|
|
||||||
default: ${{ github.token }}
|
|
||||||
required: false
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'node16'
|
|
||||||
main: '../../dist/dependency-graph-submit/index.js'
|
|
72834
dist/dependency-graph-generate/index.js
vendored
72834
dist/dependency-graph-generate/index.js
vendored
File diff suppressed because one or more lines are too long
1
dist/dependency-graph-generate/index.js.map
vendored
1
dist/dependency-graph-generate/index.js.map
vendored
File diff suppressed because one or more lines are too long
24783
dist/dependency-graph-submit/index.js
vendored
24783
dist/dependency-graph-submit/index.js
vendored
File diff suppressed because one or more lines are too long
1
dist/dependency-graph-submit/index.js.map
vendored
1
dist/dependency-graph-submit/index.js.map
vendored
File diff suppressed because one or more lines are too long
8609
dist/main/index.js
vendored
8609
dist/main/index.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/main/index.js.map
vendored
2
dist/main/index.js.map
vendored
File diff suppressed because one or more lines are too long
9467
dist/post/index.js
vendored
9467
dist/post/index.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/post/index.js.map
vendored
2
dist/post/index.js.map
vendored
File diff suppressed because one or more lines are too long
2317
package-lock.json
generated
2317
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@@ -11,9 +11,7 @@
|
|||||||
|
|
||||||
"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-dependency-graph-generate": "ncc build src/dependency-graph-generate.ts --out dist/dependency-graph-generate --source-map --no-source-map-register",
|
"compile": "npm run compile-main && npm run compile-post",
|
||||||
"compile-dependency-graph-submit": "ncc build src/dependency-graph-submit.ts --out dist/dependency-graph-submit --source-map --no-source-map-register",
|
|
||||||
"compile": "npm run compile-main && npm run compile-post && npm run compile-dependency-graph-generate && npm run compile-dependency-graph-submit",
|
|
||||||
|
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"check": "npm run format && npm run lint",
|
"check": "npm run format && npm run lint",
|
||||||
@@ -40,23 +38,23 @@
|
|||||||
"@actions/glob": "0.4.0",
|
"@actions/glob": "0.4.0",
|
||||||
"@actions/http-client": "2.1.0",
|
"@actions/http-client": "2.1.0",
|
||||||
"@actions/tool-cache": "2.0.1",
|
"@actions/tool-cache": "2.0.1",
|
||||||
"@octokit/rest": "19.0.11",
|
"@octokit/rest": "19.0.13",
|
||||||
"string-argv": "0.3.2"
|
"string-argv": "0.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "16.11.21",
|
"@types/node": "16.11.21",
|
||||||
"@types/jest": "29.5.2",
|
"@types/jest": "29.5.3",
|
||||||
"@types/unzipper": "0.10.6",
|
"@types/unzipper": "0.10.6",
|
||||||
"@typescript-eslint/parser": "5.60.1",
|
"@typescript-eslint/parser": "5.62.0",
|
||||||
"@vercel/ncc": "0.36.1",
|
"@vercel/ncc": "0.36.1",
|
||||||
"eslint": "8.43.0",
|
"eslint": "8.44.0",
|
||||||
"eslint-plugin-github": "4.8.0",
|
"eslint-plugin-github": "4.8.0",
|
||||||
"eslint-plugin-jest": "27.2.1",
|
"eslint-plugin-jest": "27.2.2",
|
||||||
"jest": "29.5.0",
|
"jest": "29.6.1",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"patch-package": "7.0.0",
|
"patch-package": "7.0.0",
|
||||||
"prettier": "2.8.8",
|
"prettier": "3.0.0",
|
||||||
"ts-jest": "29.1.0",
|
"ts-jest": "29.1.1",
|
||||||
"typescript": "5.1.5"
|
"typescript": "5.1.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -172,7 +172,12 @@ export class GradleStateCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initializeGradleUserHome(gradleUserHome: string, initScriptsDir: string): void {
|
private initializeGradleUserHome(gradleUserHome: string, initScriptsDir: string): void {
|
||||||
const initScriptFilenames = ['build-result-capture.init.gradle', 'build-result-capture-service.plugin.groovy']
|
const initScriptFilenames = [
|
||||||
|
'build-result-capture.init.gradle',
|
||||||
|
'build-result-capture-service.plugin.groovy',
|
||||||
|
'github-dependency-graph.init.gradle',
|
||||||
|
'github-dependency-graph-gradle-plugin-apply.groovy'
|
||||||
|
]
|
||||||
for (const initScriptFilename of initScriptFilenames) {
|
for (const initScriptFilename of initScriptFilenames) {
|
||||||
const initScriptContent = this.readInitScriptAsString(initScriptFilename)
|
const initScriptContent = this.readInitScriptAsString(initScriptFilename)
|
||||||
const initScriptPath = path.resolve(initScriptsDir, initScriptFilename)
|
const initScriptPath = path.resolve(initScriptsDir, initScriptFilename)
|
||||||
|
@@ -125,10 +125,25 @@ function getCacheKeyJobInstance(): string {
|
|||||||
|
|
||||||
// By default, we hash the full `matrix` data for the run, to uniquely identify this job invocation
|
// By default, we hash the full `matrix` data for the run, to uniquely identify this job invocation
|
||||||
// The only way we can obtain the `matrix` data is via the `workflow-job-context` parameter in action.yml.
|
// The only way we can obtain the `matrix` data is via the `workflow-job-context` parameter in action.yml.
|
||||||
const workflowJobContext = params.getJobContext()
|
const workflowJobContext = params.getJobMatrix()
|
||||||
return hashStrings([workflowJobContext])
|
return hashStrings([workflowJobContext])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getUniqueLabelForJobInstance(): string {
|
||||||
|
return getUniqueLabelForJobInstanceValues(github.context.workflow, github.context.job, params.getJobMatrix())
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUniqueLabelForJobInstanceValues(workflow: string, jobId: string, matrixJson: string): string {
|
||||||
|
const matrix = JSON.parse(matrixJson)
|
||||||
|
const matrixString = Object.values(matrix).join('-')
|
||||||
|
const label = matrixString ? `${workflow}-${jobId}-${matrixString}` : `${workflow}-${jobId}`
|
||||||
|
return sanitize(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitize(value: string): string {
|
||||||
|
return value.replace(/[^a-zA-Z0-9_-]/g, '').toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
function getCacheKeyJobExecution(): string {
|
function getCacheKeyJobExecution(): string {
|
||||||
// Used to associate a cache key with a particular execution (default is bound to the git commit sha)
|
// Used to associate a cache key with a particular execution (default is bound to the git commit sha)
|
||||||
return process.env[CACHE_KEY_JOB_EXECUTION_VAR] || github.context.sha
|
return process.env[CACHE_KEY_JOB_EXECUTION_VAR] || github.context.sha
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
import * as core from '@actions/core'
|
|
||||||
|
|
||||||
import * as provisioner from './provision'
|
|
||||||
import * as dependencyGraph from './dependency-graph'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main entry point for the action, called by Github Actions for the step.
|
|
||||||
*/
|
|
||||||
export async function run(): Promise<void> {
|
|
||||||
try {
|
|
||||||
// Download and install Gradle if required
|
|
||||||
const executable = await provisioner.provisionGradle()
|
|
||||||
|
|
||||||
// Generate and upload dependency graph artifact
|
|
||||||
await dependencyGraph.generateDependencyGraph(executable)
|
|
||||||
} catch (error) {
|
|
||||||
core.setFailed(String(error))
|
|
||||||
if (error instanceof Error && error.stack) {
|
|
||||||
core.info(error.stack)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
run()
|
|
@@ -1,16 +0,0 @@
|
|||||||
import * as core from '@actions/core'
|
|
||||||
import * as dependencyGraph from './dependency-graph'
|
|
||||||
|
|
||||||
export async function run(): Promise<void> {
|
|
||||||
try {
|
|
||||||
// Retrieve the dependency graph artifact and submit via Dependency Submission API
|
|
||||||
await dependencyGraph.submitDependencyGraph()
|
|
||||||
} catch (error) {
|
|
||||||
core.setFailed(String(error))
|
|
||||||
if (error instanceof Error && error.stack) {
|
|
||||||
core.info(error.stack)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
run()
|
|
@@ -8,59 +8,64 @@ import {Octokit} from '@octokit/rest'
|
|||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
import * as execution from './execution'
|
|
||||||
import * as layout from './repository-layout'
|
import * as layout from './repository-layout'
|
||||||
|
import {DependencyGraphOption, getJobMatrix} from './input-params'
|
||||||
|
|
||||||
const DEPENDENCY_GRAPH_ARTIFACT = 'dependency-graph'
|
const DEPENDENCY_GRAPH_ARTIFACT = 'dependency-graph'
|
||||||
const DEPENDENCY_GRAPH_FILE = 'dependency-graph.json'
|
|
||||||
|
|
||||||
export async function generateDependencyGraph(executable: string | undefined): Promise<void> {
|
export function setup(option: DependencyGraphOption): void {
|
||||||
const workspaceDirectory = layout.workspaceDirectory()
|
if (option === DependencyGraphOption.Disabled || option === DependencyGraphOption.DownloadAndSubmit) {
|
||||||
const buildRootDirectory = layout.buildRootDirectory()
|
return
|
||||||
const buildPath = getRelativePathFromWorkspace(buildRootDirectory)
|
}
|
||||||
|
|
||||||
const initScript = path.resolve(
|
core.info('Enabling dependency graph generation')
|
||||||
__dirname,
|
const jobCorrelator = getJobCorrelator()
|
||||||
'..',
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
|
||||||
'..',
|
core.exportVariable('GITHUB_JOB_CORRELATOR', jobCorrelator)
|
||||||
'src',
|
core.exportVariable('GITHUB_JOB_ID', github.context.runId)
|
||||||
'resources',
|
core.exportVariable(
|
||||||
'init-scripts',
|
'DEPENDENCY_GRAPH_REPORT_DIR',
|
||||||
'github-dependency-graph.init.gradle'
|
path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports')
|
||||||
)
|
)
|
||||||
const args = [
|
}
|
||||||
`-Dorg.gradle.github.env.GRADLE_BUILD_PATH=${buildPath}`,
|
|
||||||
'--init-script',
|
|
||||||
initScript,
|
|
||||||
':GitHubDependencyGraphPlugin_generateDependencyGraph'
|
|
||||||
]
|
|
||||||
|
|
||||||
await execution.executeGradleBuild(executable, buildRootDirectory, args)
|
export async function complete(option: DependencyGraphOption): Promise<void> {
|
||||||
const dependencyGraphJson = copyDependencyGraphToBuildRoot(buildRootDirectory)
|
switch (option) {
|
||||||
|
case DependencyGraphOption.Disabled:
|
||||||
|
return
|
||||||
|
case DependencyGraphOption.Generate:
|
||||||
|
await uploadDependencyGraphs()
|
||||||
|
return
|
||||||
|
case DependencyGraphOption.GenerateAndSubmit:
|
||||||
|
await submitDependencyGraphs(await uploadDependencyGraphs())
|
||||||
|
return
|
||||||
|
case DependencyGraphOption.DownloadAndSubmit:
|
||||||
|
await downloadAndSubmitDependencyGraphs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploadDependencyGraphs(): Promise<string[]> {
|
||||||
|
const workspaceDirectory = layout.workspaceDirectory()
|
||||||
|
const graphFiles = await findDependencyGraphFiles(workspaceDirectory)
|
||||||
|
|
||||||
|
const relativeGraphFiles = graphFiles.map(x => getRelativePathFromWorkspace(x))
|
||||||
|
core.info(`Uploading dependency graph files: ${relativeGraphFiles}`)
|
||||||
|
|
||||||
const artifactClient = artifact.create()
|
const artifactClient = artifact.create()
|
||||||
artifactClient.uploadArtifact(DEPENDENCY_GRAPH_ARTIFACT, [dependencyGraphJson], workspaceDirectory)
|
artifactClient.uploadArtifact(DEPENDENCY_GRAPH_ARTIFACT, graphFiles, workspaceDirectory)
|
||||||
|
|
||||||
|
return graphFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyDependencyGraphToBuildRoot(buildRootDirectory: string): string {
|
async function downloadAndSubmitDependencyGraphs(): Promise<void> {
|
||||||
const sourceFile = path.resolve(
|
|
||||||
buildRootDirectory,
|
|
||||||
'build',
|
|
||||||
'reports',
|
|
||||||
'github-dependency-graph-plugin',
|
|
||||||
'github-dependency-snapshot.json'
|
|
||||||
)
|
|
||||||
|
|
||||||
const destFile = path.resolve(buildRootDirectory, DEPENDENCY_GRAPH_FILE)
|
|
||||||
fs.copyFileSync(sourceFile, destFile)
|
|
||||||
return destFile
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function submitDependencyGraph(): Promise<void> {
|
|
||||||
const workspaceDirectory = layout.workspaceDirectory()
|
const workspaceDirectory = layout.workspaceDirectory()
|
||||||
|
submitDependencyGraphs(await retrieveDependencyGraphs(workspaceDirectory))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<void> {
|
||||||
const octokit: Octokit = getOctokit()
|
const octokit: Octokit = getOctokit()
|
||||||
|
|
||||||
for (const jsonFile of await retrieveDependencyGraphs(octokit, workspaceDirectory)) {
|
for (const jsonFile of dependencyGraphFiles) {
|
||||||
const jsonContent = fs.readFileSync(jsonFile, 'utf8')
|
const jsonContent = fs.readFileSync(jsonFile, 'utf8')
|
||||||
|
|
||||||
const jsonObject = JSON.parse(jsonContent)
|
const jsonObject = JSON.parse(jsonContent)
|
||||||
@@ -69,34 +74,20 @@ export async function submitDependencyGraph(): Promise<void> {
|
|||||||
const response = await octokit.request('POST /repos/{owner}/{repo}/dependency-graph/snapshots', jsonObject)
|
const response = await octokit.request('POST /repos/{owner}/{repo}/dependency-graph/snapshots', jsonObject)
|
||||||
|
|
||||||
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
|
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
|
||||||
core.info(`Submitted ${relativeJsonFile}: ${JSON.stringify(response)}`)
|
|
||||||
core.notice(`Submitted ${relativeJsonFile}: ${response.data.message}`)
|
core.notice(`Submitted ${relativeJsonFile}: ${response.data.message}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findDependencyGraphFiles(dir: string): Promise<string[]> {
|
async function retrieveDependencyGraphs(workspaceDirectory: string): Promise<string[]> {
|
||||||
const globber = await glob.create(`${dir}/**/${DEPENDENCY_GRAPH_FILE}`)
|
|
||||||
const graphFiles = globber.glob()
|
|
||||||
core.info(`Found graph files in ${dir}: ${graphFiles}`)
|
|
||||||
return graphFiles
|
|
||||||
}
|
|
||||||
|
|
||||||
async function retrieveDependencyGraphs(octokit: Octokit, workspaceDirectory: string): Promise<string[]> {
|
|
||||||
if (github.context.payload.workflow_run) {
|
if (github.context.payload.workflow_run) {
|
||||||
return await retrieveDependencyGraphsForWorkflowRun(
|
return await retrieveDependencyGraphsForWorkflowRun(github.context.payload.workflow_run.id, workspaceDirectory)
|
||||||
github.context.payload.workflow_run.id,
|
|
||||||
octokit,
|
|
||||||
workspaceDirectory
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return retrieveDependencyGraphsForCurrentWorkflow(workspaceDirectory)
|
return retrieveDependencyGraphsForCurrentWorkflow(workspaceDirectory)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function retrieveDependencyGraphsForWorkflowRun(
|
async function retrieveDependencyGraphsForWorkflowRun(runId: number, workspaceDirectory: string): Promise<string[]> {
|
||||||
runId: number,
|
const octokit: Octokit = getOctokit()
|
||||||
octokit: Octokit,
|
|
||||||
workspaceDirectory: string
|
|
||||||
): Promise<string[]> {
|
|
||||||
// Find the workflow run artifacts named "dependency-graph"
|
// Find the workflow run artifacts named "dependency-graph"
|
||||||
const artifacts = await octokit.rest.actions.listWorkflowRunArtifacts({
|
const artifacts = await octokit.rest.actions.listWorkflowRunArtifacts({
|
||||||
owner: github.context.repo.owner,
|
owner: github.context.repo.owner,
|
||||||
@@ -139,6 +130,12 @@ async function retrieveDependencyGraphsForCurrentWorkflow(workspaceDirectory: st
|
|||||||
return await findDependencyGraphFiles(downloadPath)
|
return await findDependencyGraphFiles(downloadPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function findDependencyGraphFiles(dir: string): Promise<string[]> {
|
||||||
|
const globber = await glob.create(`${dir}/dependency-graph-reports/*.json`)
|
||||||
|
const graphFiles = globber.glob()
|
||||||
|
return graphFiles
|
||||||
|
}
|
||||||
|
|
||||||
function getOctokit(): Octokit {
|
function getOctokit(): Octokit {
|
||||||
return new Octokit({
|
return new Octokit({
|
||||||
auth: getGithubToken()
|
auth: getGithubToken()
|
||||||
@@ -153,3 +150,29 @@ function getRelativePathFromWorkspace(file: string): string {
|
|||||||
const workspaceDirectory = layout.workspaceDirectory()
|
const workspaceDirectory = layout.workspaceDirectory()
|
||||||
return path.relative(workspaceDirectory, file)
|
return path.relative(workspaceDirectory, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getJobCorrelator(): string {
|
||||||
|
return constructJobCorrelator(github.context.workflow, github.context.job, getJobMatrix())
|
||||||
|
}
|
||||||
|
|
||||||
|
export function constructJobCorrelator(workflow: string, jobId: string, matrixJson: string): string {
|
||||||
|
const matrixString = describeMatrix(matrixJson)
|
||||||
|
const label = matrixString ? `${workflow}-${jobId}-${matrixString}` : `${workflow}-${jobId}`
|
||||||
|
return sanitize(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
function describeMatrix(matrixJson: string): string {
|
||||||
|
core.debug(`Got matrix json: ${matrixJson}`)
|
||||||
|
const matrix = JSON.parse(matrixJson)
|
||||||
|
if (matrix) {
|
||||||
|
return Object.values(matrix).join('-')
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitize(value: string): string {
|
||||||
|
return value
|
||||||
|
.replace(/[^a-zA-Z0-9_-\s]/g, '')
|
||||||
|
.replace(/\s+/g, '_')
|
||||||
|
.toLowerCase()
|
||||||
|
}
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as exec from '@actions/exec'
|
import * as exec from '@actions/exec'
|
||||||
import fs from 'fs'
|
|
||||||
import * as gradlew from './gradlew'
|
import * as gradlew from './gradlew'
|
||||||
|
|
||||||
export async function executeGradleBuild(executable: string | undefined, root: string, args: string[]): Promise<void> {
|
export async function executeGradleBuild(executable: string | undefined, root: string, args: string[]): Promise<void> {
|
||||||
// Use the provided executable, or look for a Gradle wrapper script to run
|
// Use the provided executable, or look for a Gradle wrapper script to run
|
||||||
const toExecute = executable ?? gradlew.locateGradleWrapperScript(root)
|
const toExecute = executable ?? gradlew.gradleWrapperScript(root)
|
||||||
verifyIsExecutableScript(toExecute)
|
|
||||||
const status: number = await exec.exec(toExecute, args, {
|
const status: number = await exec.exec(toExecute, args, {
|
||||||
cwd: root,
|
cwd: root,
|
||||||
ignoreReturnCode: true
|
ignoreReturnCode: true
|
||||||
@@ -16,11 +15,3 @@ export async function executeGradleBuild(executable: string | undefined, root: s
|
|||||||
core.setFailed(`Gradle build failed: see console output for details`)
|
core.setFailed(`Gradle build failed: see console output for details`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyIsExecutableScript(toExecute: string): void {
|
|
||||||
try {
|
|
||||||
fs.accessSync(toExecute, fs.constants.X_OK)
|
|
||||||
} catch (err) {
|
|
||||||
throw new Error(`Gradle script '${toExecute}' is not executable.`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -4,23 +4,39 @@ import fs from 'fs'
|
|||||||
const IS_WINDOWS = process.platform === 'win32'
|
const IS_WINDOWS = process.platform === 'win32'
|
||||||
|
|
||||||
export function wrapperScriptFilename(): string {
|
export function wrapperScriptFilename(): string {
|
||||||
return IS_WINDOWS ? 'gradlew.bat' : 'gradlew'
|
return IS_WINDOWS ? './gradlew.bat' : './gradlew'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function installScriptFilename(): string {
|
export function installScriptFilename(): string {
|
||||||
return IS_WINDOWS ? 'gradle.bat' : 'gradle'
|
return IS_WINDOWS ? 'gradle.bat' : 'gradle'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function locateGradleWrapperScript(buildRootDirectory: string): string {
|
export function gradleWrapperScript(buildRootDirectory: string): string {
|
||||||
validateGradleWrapper(buildRootDirectory)
|
validateGradleWrapper(buildRootDirectory)
|
||||||
return path.resolve(buildRootDirectory, wrapperScriptFilename())
|
return wrapperScriptFilename()
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateGradleWrapper(buildRootDirectory: string): void {
|
function validateGradleWrapper(buildRootDirectory: string): void {
|
||||||
|
const wrapperScript = path.resolve(buildRootDirectory, wrapperScriptFilename())
|
||||||
|
verifyExists(wrapperScript, 'Gradle Wrapper script')
|
||||||
|
verifyIsExecutableScript(wrapperScript)
|
||||||
|
|
||||||
const wrapperProperties = path.resolve(buildRootDirectory, 'gradle/wrapper/gradle-wrapper.properties')
|
const wrapperProperties = path.resolve(buildRootDirectory, 'gradle/wrapper/gradle-wrapper.properties')
|
||||||
if (!fs.existsSync(wrapperProperties)) {
|
verifyExists(wrapperProperties, 'Gradle wrapper properties file')
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyExists(file: string, description: string): void {
|
||||||
|
if (!fs.existsSync(file)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cannot locate a Gradle wrapper properties file at '${wrapperProperties}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.`
|
`Cannot locate ${description} at '${file}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function verifyIsExecutableScript(toExecute: string): void {
|
||||||
|
try {
|
||||||
|
fs.accessSync(toExecute, fs.constants.X_OK)
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`Gradle script '${toExecute}' is not executable.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -51,7 +51,7 @@ export function getArguments(): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Internal parameters
|
// Internal parameters
|
||||||
export function getJobContext(): string {
|
export function getJobMatrix(): string {
|
||||||
return core.getInput('workflow-job-context')
|
return core.getInput('workflow-job-context')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +63,27 @@ export function isJobSummaryEnabled(): boolean {
|
|||||||
return getBooleanInput('generate-job-summary', true)
|
return getBooleanInput('generate-job-summary', true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isDependencyGraphEnabled(): boolean {
|
||||||
|
return getBooleanInput('generate-dependency-graph', true)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDependencyGraphOption(): DependencyGraphOption {
|
||||||
|
const val = core.getInput('dependency-graph')
|
||||||
|
switch (val.toLowerCase().trim()) {
|
||||||
|
case 'disabled':
|
||||||
|
return DependencyGraphOption.Disabled
|
||||||
|
case 'generate':
|
||||||
|
return DependencyGraphOption.Generate
|
||||||
|
case 'generate-and-submit':
|
||||||
|
return DependencyGraphOption.GenerateAndSubmit
|
||||||
|
case 'download-and-submit':
|
||||||
|
return DependencyGraphOption.DownloadAndSubmit
|
||||||
|
}
|
||||||
|
throw TypeError(
|
||||||
|
`The value '${val} is not valid for 'dependency-graph. Valid values are: [disabled, generate-and-upload, generate-and-submit, download-and-submit]. The default value is 'disabled'.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function getBooleanInput(paramName: string, paramDefault = false): boolean {
|
function getBooleanInput(paramName: string, paramDefault = false): boolean {
|
||||||
const paramValue = core.getInput(paramName)
|
const paramValue = core.getInput(paramName)
|
||||||
switch (paramValue.toLowerCase().trim()) {
|
switch (paramValue.toLowerCase().trim()) {
|
||||||
@@ -75,3 +96,10 @@ function getBooleanInput(paramName: string, paramDefault = false): boolean {
|
|||||||
}
|
}
|
||||||
throw TypeError(`The value '${paramValue} is not valid for '${paramName}. Valid values are: [true, false]`)
|
throw TypeError(`The value '${paramValue} is not valid for '${paramName}. Valid values are: [true, false]`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DependencyGraphOption {
|
||||||
|
Disabled,
|
||||||
|
Generate,
|
||||||
|
GenerateAndSubmit,
|
||||||
|
DownloadAndSubmit
|
||||||
|
}
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven { url "https://plugins.gradle.org/m2/" }
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "org.gradle:github-dependency-graph-gradle-plugin:0.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apply plugin: org.gradle.github.GitHubDependencyGraphPlugin
|
@@ -1,12 +1,53 @@
|
|||||||
import org.gradle.github.GitHubDependencyGraphPlugin
|
import org.gradle.util.GradleVersion
|
||||||
initscript {
|
|
||||||
repositories {
|
// Only run when dependency graph is explicitly enabled
|
||||||
maven {
|
if (System.env.GITHUB_DEPENDENCY_GRAPH_ENABLED != "true") {
|
||||||
url = uri("https://plugins.gradle.org/m2/")
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
dependencies {
|
// Do not run for unsupported versions of Gradle
|
||||||
classpath("org.gradle:github-dependency-graph-gradle-plugin:+")
|
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."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to find a unique job correlator to use based on the environment variable
|
||||||
|
// This is only required for top-level builds
|
||||||
|
def isTopLevelBuild = gradle.getParent() == null
|
||||||
|
if (isTopLevelBuild) {
|
||||||
|
def jobCorrelator = ensureUniqueJobCorrelator(System.env.GITHUB_JOB_CORRELATOR)
|
||||||
|
|
||||||
|
if (jobCorrelator == null) {
|
||||||
|
println "::warning::No dependency snapshot generated for step: report file for '${jobCorrelator}' created in earlier step. Each build invocation requires a unique job correlator: specify GITHUB_JOB_CORRELATOR var for this step."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println "Generating dependency graph for '${jobCorrelator}'"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: 'github-dependency-graph-gradle-plugin-apply.groovy'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using the supplied jobCorrelator value:
|
||||||
|
* - Checks if report file already exists
|
||||||
|
* - If so, tries to find a unique value that does not yet have a corresponding report file.
|
||||||
|
* - When found, this value is set as a System property override.
|
||||||
|
*/
|
||||||
|
String ensureUniqueJobCorrelator(String jobCorrelator) {
|
||||||
|
def reportDir = System.env.DEPENDENCY_GRAPH_REPORT_DIR
|
||||||
|
def reportFile = new File(reportDir, jobCorrelator + ".json")
|
||||||
|
if (!reportFile.exists()) return jobCorrelator
|
||||||
|
|
||||||
|
// Try at most 100 suffixes
|
||||||
|
for (int i = 1; i < 100; i++) {
|
||||||
|
def candidateCorrelator = jobCorrelator + "-" + i
|
||||||
|
def candidateFile = new File(reportDir, candidateCorrelator + ".json")
|
||||||
|
if (!candidateFile.exists()) {
|
||||||
|
System.properties['GITHUB_JOB_CORRELATOR'] = candidateCorrelator
|
||||||
|
return candidateCorrelator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Could not determine unique job correlator
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
apply plugin: GitHubDependencyGraphPlugin
|
|
||||||
|
@@ -6,6 +6,7 @@ import * as os from 'os'
|
|||||||
import * as caches from './caches'
|
import * as caches from './caches'
|
||||||
import * as layout from './repository-layout'
|
import * as layout from './repository-layout'
|
||||||
import * as params from './input-params'
|
import * as params from './input-params'
|
||||||
|
import * as dependencyGraph from './dependency-graph'
|
||||||
|
|
||||||
import {logJobSummary, writeJobSummary} from './job-summary'
|
import {logJobSummary, writeJobSummary} from './job-summary'
|
||||||
import {loadBuildResults} from './build-results'
|
import {loadBuildResults} from './build-results'
|
||||||
@@ -36,6 +37,8 @@ export async function setup(): Promise<void> {
|
|||||||
await caches.restore(gradleUserHome, cacheListener)
|
await caches.restore(gradleUserHome, cacheListener)
|
||||||
|
|
||||||
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
||||||
|
|
||||||
|
dependencyGraph.setup(params.getDependencyGraphOption())
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function complete(): Promise<void> {
|
export async function complete(): Promise<void> {
|
||||||
@@ -58,6 +61,8 @@ export async function complete(): Promise<void> {
|
|||||||
} else {
|
} else {
|
||||||
logJobSummary(buildResults, cacheListener)
|
logJobSummary(buildResults, cacheListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencyGraph.complete(params.getDependencyGraphOption())
|
||||||
}
|
}
|
||||||
|
|
||||||
async function determineGradleUserHome(): Promise<string> {
|
async function determineGradleUserHome(): Promise<string> {
|
||||||
|
BIN
test/init-scripts/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
test/init-scripts/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
@@ -1,7 +1,8 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=e111cb9948407e26351227dabce49822fb88c37ee72f1d1582a69c68af2e702f
|
distributionSha256Sum=03ec176d388f2aa99defcadc3ac6adf8dd2bce5145a129659537c0874dea5ad1
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
5
test/init-scripts/gradlew
vendored
5
test/init-scripts/gradlew
vendored
@@ -130,10 +130,13 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
|
@@ -22,8 +22,9 @@ 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_X = new TestGradleVersion(GradleVersion.version('7.6.1'), 8, 19)
|
static final TestGradleVersion GRADLE_7_X = new TestGradleVersion(GradleVersion.version('7.6.2'), 8, 19)
|
||||||
static final TestGradleVersion GRADLE_8_X = 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.2.1'), 8, 19)
|
||||||
|
|
||||||
static final List<TestGradleVersion> ALL_VERSIONS = [
|
static final List<TestGradleVersion> ALL_VERSIONS = [
|
||||||
GRADLE_3_X, // First version where TestKit supports environment variables
|
GRADLE_3_X, // First version where TestKit supports environment variables
|
||||||
@@ -32,14 +33,15 @@ class BaseInitScriptTest extends Specification {
|
|||||||
GRADLE_6_NO_BUILD_SERVICE, // Last version without build service support
|
GRADLE_6_NO_BUILD_SERVICE, // Last version without build service support
|
||||||
GRADLE_6_X,
|
GRADLE_6_X,
|
||||||
GRADLE_7_X,
|
GRADLE_7_X,
|
||||||
|
GRADLE_8_0,
|
||||||
GRADLE_8_X,
|
GRADLE_8_X,
|
||||||
]
|
]
|
||||||
|
|
||||||
static final List<TestGradleVersion> CONFIGURATION_CACHE_VERSIONS =
|
static final List<TestGradleVersion> CONFIGURATION_CACHE_VERSIONS =
|
||||||
[GRADLE_7_X, GRADLE_8_X]
|
[GRADLE_7_X, GRADLE_8_0, GRADLE_8_X]
|
||||||
|
|
||||||
static final List<TestGradleVersion> SETTINGS_PLUGIN_VERSIONS =
|
static final List<TestGradleVersion> SETTINGS_PLUGIN_VERSIONS =
|
||||||
[GRADLE_6_X, GRADLE_7_X, GRADLE_8_X]
|
[GRADLE_6_X, GRADLE_7_X, GRADLE_8_0, GRADLE_8_X]
|
||||||
|
|
||||||
static final String PUBLIC_BUILD_SCAN_ID = 'i2wepy2gr7ovw'
|
static final String PUBLIC_BUILD_SCAN_ID = 'i2wepy2gr7ovw'
|
||||||
static final String DEFAULT_SCAN_UPLOAD_TOKEN = 'scan-upload-token'
|
static final String DEFAULT_SCAN_UPLOAD_TOKEN = 'scan-upload-token'
|
||||||
|
@@ -0,0 +1,128 @@
|
|||||||
|
package com.gradle.gradlebuildaction
|
||||||
|
|
||||||
|
import static org.junit.Assume.assumeTrue
|
||||||
|
|
||||||
|
class TestDependencyGraph extends BaseInitScriptTest {
|
||||||
|
def initScript = 'github-dependency-graph.init.gradle'
|
||||||
|
|
||||||
|
static final List<TestGradleVersion> NO_DEPENDENCY_GRAPH_VERSIONS = [GRADLE_3_X, GRADLE_4_X]
|
||||||
|
static final List<TestGradleVersion> DEPENDENCY_GRAPH_VERSIONS = ALL_VERSIONS - NO_DEPENDENCY_GRAPH_VERSIONS
|
||||||
|
|
||||||
|
def "does not produce dependency graph when not enabled"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help'], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assert !reportsDir.exists()
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << ALL_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "produces dependency graph when enabled"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help'], initScript, testGradleVersion.gradleVersion, [], envVars)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assert reportFile.exists()
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << DEPENDENCY_GRAPH_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dependency-graph plugin doesn't support config-cache for 8.0 of Gradle
|
||||||
|
def "produces dependency graph with configuration-cache on latest Gradle"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help'], initScript, testGradleVersion.gradleVersion, [], envVars)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assert reportFile.exists()
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << [GRADLE_8_X]
|
||||||
|
}
|
||||||
|
|
||||||
|
def "warns and produces no dependency graph when enabled for older Gradle versions"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
when:
|
||||||
|
def result = run(['help'], initScript, testGradleVersion.gradleVersion, [], envVars)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assert !reportsDir.exists()
|
||||||
|
assert result.output.contains("::warning::Dependency Graph is not supported")
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << NO_DEPENDENCY_GRAPH_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def "constructs unique job correlator for each build invocation"() {
|
||||||
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
|
def reportFile1 = new File(reportsDir, "CORRELATOR-1.json")
|
||||||
|
def reportFile2 = new File(reportsDir, "CORRELATOR-2.json")
|
||||||
|
|
||||||
|
buildFile << """
|
||||||
|
task firstTask {
|
||||||
|
doLast {
|
||||||
|
println "First"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task secondTask {
|
||||||
|
doLast {
|
||||||
|
println "Second"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['help'], initScript, testGradleVersion.gradleVersion, [], envVars)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assert reportFile.exists()
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['first'], initScript, testGradleVersion.gradleVersion, [], envVars)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assert reportFile.exists()
|
||||||
|
assert reportFile1.exists()
|
||||||
|
|
||||||
|
when:
|
||||||
|
run(['second'], initScript, testGradleVersion.gradleVersion, [], envVars)
|
||||||
|
|
||||||
|
then:
|
||||||
|
assert reportFile.exists()
|
||||||
|
assert reportFile1.exists()
|
||||||
|
assert reportFile2.exists()
|
||||||
|
|
||||||
|
where:
|
||||||
|
testGradleVersion << DEPENDENCY_GRAPH_VERSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
def getEnvVars() {
|
||||||
|
return [
|
||||||
|
GITHUB_DEPENDENCY_GRAPH_ENABLED: "true",
|
||||||
|
GITHUB_JOB_CORRELATOR: "CORRELATOR",
|
||||||
|
GITHUB_JOB_ID: "1",
|
||||||
|
GITHUB_REF: "main",
|
||||||
|
GITHUB_SHA: "123456",
|
||||||
|
GITHUB_WORKSPACE: testProjectDir.absolutePath,
|
||||||
|
DEPENDENCY_GRAPH_REPORT_DIR: reportsDir.absolutePath
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def getReportsDir() {
|
||||||
|
return new File(testProjectDir, 'build/reports/github-dependency-graph-snapshots')
|
||||||
|
}
|
||||||
|
|
||||||
|
def getReportFile() {
|
||||||
|
return new File(reportsDir, "CORRELATOR.json")
|
||||||
|
}
|
||||||
|
}
|
@@ -49,7 +49,7 @@ test('will cleanup unused gradle versions', async () => {
|
|||||||
|
|
||||||
const gradle802 = path.resolve(gradleUserHome, "caches/8.0.2")
|
const gradle802 = path.resolve(gradleUserHome, "caches/8.0.2")
|
||||||
const wrapper802 = path.resolve(gradleUserHome, "wrapper/dists/gradle-8.0.2-bin")
|
const wrapper802 = path.resolve(gradleUserHome, "wrapper/dists/gradle-8.0.2-bin")
|
||||||
const gradleCurrent = path.resolve(gradleUserHome, "caches/8.1.1")
|
const gradleCurrent = path.resolve(gradleUserHome, "caches/8.2.1")
|
||||||
|
|
||||||
expect(fs.existsSync(gradle802)).toBe(true)
|
expect(fs.existsSync(gradle802)).toBe(true)
|
||||||
expect(fs.existsSync(wrapper802)).toBe(true)
|
expect(fs.existsSync(wrapper802)).toBe(true)
|
||||||
|
34
test/jest/dependency-graph.test.ts
Normal file
34
test/jest/dependency-graph.test.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import * as dependencyGraph from '../../src/dependency-graph'
|
||||||
|
|
||||||
|
describe('dependency-graph', () => {
|
||||||
|
describe('constructs job correlator', () => {
|
||||||
|
it('removes commas from workflow name', () => {
|
||||||
|
const id = dependencyGraph.constructJobCorrelator('Workflow, with,commas', 'jobid', '{}')
|
||||||
|
expect(id).toBe('workflow_withcommas-jobid')
|
||||||
|
})
|
||||||
|
it('removes non word characters', () => {
|
||||||
|
const id = dependencyGraph.constructJobCorrelator('Workflow!_with()characters', 'job-*id', '{"foo": "bar!@#$%^&*("}')
|
||||||
|
expect(id).toBe('workflow_withcharacters-job-id-bar')
|
||||||
|
})
|
||||||
|
it('replaces spaces', () => {
|
||||||
|
const id = dependencyGraph.constructJobCorrelator('Workflow !_ with () characters, and spaces', 'job-*id', '{"foo": "bar!@#$%^&*("}')
|
||||||
|
expect(id).toBe('workflow___with_characters_and_spaces-job-id-bar')
|
||||||
|
})
|
||||||
|
it('without matrix', () => {
|
||||||
|
const id = dependencyGraph.constructJobCorrelator('workflow', 'jobid', 'null')
|
||||||
|
expect(id).toBe('workflow-jobid')
|
||||||
|
})
|
||||||
|
it('with dashes in values', () => {
|
||||||
|
const id = dependencyGraph.constructJobCorrelator('workflow-name', 'job-id', '{"os": "ubuntu-latest"}')
|
||||||
|
expect(id).toBe('workflow-name-job-id-ubuntu-latest')
|
||||||
|
})
|
||||||
|
it('with single matrix value', () => {
|
||||||
|
const id = dependencyGraph.constructJobCorrelator('workflow', 'jobid', '{"os": "windows"}')
|
||||||
|
expect(id).toBe('workflow-jobid-windows')
|
||||||
|
})
|
||||||
|
it('with composite matrix value', () => {
|
||||||
|
const id = dependencyGraph.constructJobCorrelator('workflow', 'jobid', '{"os": "windows", "java-version": "21.1", "other": "Value, with COMMA"}')
|
||||||
|
expect(id).toBe('workflow-jobid-windows-211-value_with_comma')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Reference in New Issue
Block a user