mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-10-20 07:08:56 +08:00
Compare commits
4 Commits
v3.0.0-bet
...
release/v2
Author | SHA1 | Date | |
---|---|---|---|
|
a8f75513ea | ||
|
9283312acb | ||
|
7c8a278ea0 | ||
|
d8ca9b7d2e |
@@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "com.gradle.enterprise" version "3.16.1"
|
id "com.gradle.enterprise" version "3.15.1"
|
||||||
id "com.gradle.common-custom-user-data-gradle-plugin" version "1.12.1"
|
id "com.gradle.common-custom-user-data-gradle-plugin" version "1.12"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
@@ -8,7 +8,7 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("org.apache.commons:commons-math3:3.6.1")
|
api("org.apache.commons:commons-math3:3.6.1")
|
||||||
implementation("com.google.guava:guava:33.0.0-jre")
|
implementation("com.google.guava:guava:32.1.3-jre")
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.10.1")
|
testImplementation("org.junit.jupiter:junit-jupiter:5.10.1")
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.gradle.enterprise") version "3.16.1"
|
id("com.gradle.enterprise") version "3.15.1"
|
||||||
id("com.gradle.common-custom-user-data-gradle-plugin") version "1.12.1"
|
id("com.gradle.common-custom-user-data-gradle-plugin") version "1.12"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "com.gradle.build-scan" version "3.16.1"
|
id "com.gradle.build-scan" version "3.15.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "com.gradle.enterprise" version "3.16.1"
|
id "com.gradle.enterprise" version "3.15.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
47
.github/workflows/ci-codeql.yml
vendored
47
.github/workflows/ci-codeql.yml
vendored
@@ -1,10 +1,22 @@
|
|||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
#
|
||||||
name: CI-codeql
|
name: CI-codeql
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "main" ]
|
branches: [ main ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "main" ]
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ main ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '25 23 * * 2'
|
- cron: '25 23 * * 2'
|
||||||
|
|
||||||
@@ -20,7 +32,9 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: [ 'javascript-typescript' ]
|
language: [ 'javascript' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
|
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
@@ -28,12 +42,29 @@ jobs:
|
|||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v2
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
config: |
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
paths:
|
# By default, queries listed here will override any specified in a config file.
|
||||||
- src
|
# 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@v2
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
|
# and modify them (or add more) to build your code if your project
|
||||||
|
# uses a compiled language
|
||||||
|
|
||||||
|
#- run: |
|
||||||
|
# make bootstrap
|
||||||
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v2
|
||||||
|
26
.github/workflows/ci-full-check.yml
vendored
26
.github/workflows/ci-full-check.yml
vendored
@@ -9,6 +9,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
- release/**
|
||||||
paths:
|
paths:
|
||||||
- '.github/**'
|
- '.github/**'
|
||||||
- 'dist/**'
|
- 'dist/**'
|
||||||
@@ -25,19 +26,12 @@ jobs:
|
|||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
caching-config:
|
caching-config:
|
||||||
uses: ./.github/workflows/integ-test-caching-config.yml
|
uses: ./.github/workflows/integ-test-action-inputs-caching.yml
|
||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
dependency-graph:
|
dependency-graph:
|
||||||
uses: ./.github/workflows/integ-test-dependency-graph.yml
|
uses: ./.github/workflows/integ-test-dependency-graph.yml
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
with:
|
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
|
||||||
|
|
||||||
dependency-graph-failures:
|
|
||||||
uses: ./.github/workflows/integ-test-dependency-graph-failures.yml
|
|
||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
@@ -51,24 +45,22 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
develocity-injection:
|
gradle-enterprise-injection:
|
||||||
uses: ./.github/workflows/integ-test-inject-develocity.yml
|
uses: ./.github/workflows/integ-test-inject-gradle-enterprise.yml
|
||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
secrets:
|
secrets:
|
||||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
|
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
|
||||||
|
|
||||||
provision-gradle-versions:
|
provision-gradle-versions:
|
||||||
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml
|
uses: ./.github/workflows/integ-test-provision-gradle-versions.yml
|
||||||
with:
|
with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
cache-key-prefix: ${{github.run_number}}-
|
||||||
|
|
||||||
restore-configuration-cache:
|
# restore-configuration-cache:
|
||||||
uses: ./.github/workflows/integ-test-restore-configuration-cache.yml
|
# uses: ./.github/workflows/integ-test-restore-configuration-cache.yml
|
||||||
with:
|
# with:
|
||||||
cache-key-prefix: ${{github.run_number}}-
|
# cache-key-prefix: ${{github.run_number}}-
|
||||||
secrets:
|
|
||||||
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
|
|
||||||
restore-custom-gradle-home:
|
restore-custom-gradle-home:
|
||||||
uses: ./.github/workflows/integ-test-restore-custom-gradle-home.yml
|
uses: ./.github/workflows/integ-test-restore-custom-gradle-home.yml
|
||||||
|
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.11.0 # Use a released version to avoid breakages
|
uses: gradle/gradle-build-action@v2.10.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
|
||||||
|
35
.github/workflows/ci-quick-check.yml
vendored
35
.github/workflows/ci-quick-check.yml
vendored
@@ -3,7 +3,9 @@ name: CI-quick-check
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches-ignore: main
|
branches-ignore:
|
||||||
|
- main
|
||||||
|
- release/**
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-distribution:
|
build-distribution:
|
||||||
@@ -45,7 +47,7 @@ jobs:
|
|||||||
|
|
||||||
caching-config:
|
caching-config:
|
||||||
needs: build-distribution
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-caching-config.yml
|
uses: ./.github/workflows/integ-test-action-inputs-caching.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
download-dist: true
|
download-dist: true
|
||||||
@@ -53,15 +55,6 @@ jobs:
|
|||||||
dependency-graph:
|
dependency-graph:
|
||||||
needs: build-distribution
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-dependency-graph.yml
|
uses: ./.github/workflows/integ-test-dependency-graph.yml
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
with:
|
|
||||||
runner-os: '["ubuntu-latest"]'
|
|
||||||
download-dist: true
|
|
||||||
|
|
||||||
dependency-graph-failures:
|
|
||||||
needs: build-distribution
|
|
||||||
uses: ./.github/workflows/integ-test-dependency-graph-failures.yml
|
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
download-dist: true
|
download-dist: true
|
||||||
@@ -80,14 +73,14 @@ jobs:
|
|||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
download-dist: true
|
download-dist: true
|
||||||
|
|
||||||
develocity-injection:
|
gradle-enterprise-injection:
|
||||||
needs: build-distribution
|
needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-inject-develocity.yml
|
uses: ./.github/workflows/integ-test-inject-gradle-enterprise.yml
|
||||||
with:
|
with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
download-dist: true
|
download-dist: true
|
||||||
secrets:
|
secrets:
|
||||||
DEVELOCITY_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
|
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_SOLUTIONS_ACCESS_TOKEN }}
|
||||||
|
|
||||||
provision-gradle-versions:
|
provision-gradle-versions:
|
||||||
needs: build-distribution
|
needs: build-distribution
|
||||||
@@ -96,14 +89,12 @@ jobs:
|
|||||||
runner-os: '["ubuntu-latest"]'
|
runner-os: '["ubuntu-latest"]'
|
||||||
download-dist: true
|
download-dist: true
|
||||||
|
|
||||||
restore-configuration-cache:
|
# restore-configuration-cache:
|
||||||
needs: build-distribution
|
# needs: build-distribution
|
||||||
uses: ./.github/workflows/integ-test-restore-configuration-cache.yml
|
# uses: ./.github/workflows/integ-test-restore-configuration-cache.yml
|
||||||
with:
|
# with:
|
||||||
runner-os: '["ubuntu-latest"]'
|
# runner-os: '["ubuntu-latest"]'
|
||||||
download-dist: true
|
# download-dist: true
|
||||||
secrets:
|
|
||||||
GRADLE_ENCRYPTION_KEY: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
|
|
||||||
restore-containerized-gradle-home:
|
restore-containerized-gradle-home:
|
||||||
needs: build-distribution
|
needs: build-distribution
|
||||||
|
3
.github/workflows/ci-verify-outputs.yml
vendored
3
.github/workflows/ci-verify-outputs.yml
vendored
@@ -8,6 +8,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
- release/**
|
||||||
- dependabot/**
|
- dependabot/**
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -33,7 +34,7 @@ jobs:
|
|||||||
id: diff
|
id: diff
|
||||||
|
|
||||||
# If index.js was different than expected, upload the expected version as an artifact
|
# If index.js was different than expected, upload the expected version as an artifact
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v3
|
||||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||||
with:
|
with:
|
||||||
name: dist
|
name: dist
|
||||||
|
23
.github/workflows/demo-job-summary.yml
vendored
23
.github/workflows/demo-job-summary.yml
vendored
@@ -8,7 +8,7 @@ env:
|
|||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
many-gradle-builds:
|
run-gradle-builds:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
@@ -42,27 +42,6 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: ./gradlew not-a-real-task
|
run: ./gradlew not-a-real-task
|
||||||
|
|
||||||
successful-builds-with-no-summary:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Build distribution
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
add-job-summary: on-failure
|
|
||||||
- name: Build kotlin-dsl project
|
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
|
||||||
run: ./gradlew assemble
|
|
||||||
- name: Build kotlin-dsl project without Build Scan®
|
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
|
||||||
run: ./gradlew assemble check --no-scan
|
|
||||||
|
|
||||||
pre-existing-gradle-home:
|
pre-existing-gradle-home:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
46
.github/workflows/demo-pr-build-scan-comment.yml
vendored
46
.github/workflows/demo-pr-build-scan-comment.yml
vendored
@@ -2,50 +2,26 @@ name: Demo adding Build Scan® comment to PR
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [assigned, review_requested]
|
types: [assigned, review_requested]
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
successful-build-with-always-comment:
|
gradle:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout project sources
|
- name: Checkout project sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
|
||||||
add-job-summary-as-pr-comment: always
|
|
||||||
- name: Run build with Gradle wrapper
|
- name: Run build with Gradle wrapper
|
||||||
id: gradle
|
id: gradle
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: ./gradlew build --scan
|
run: ./gradlew build --scan
|
||||||
|
- name: "Add Build Scan URL as PR comment"
|
||||||
successful-build-with-comment-on-failure:
|
uses: actions/github-script@v7
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout project sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
with:
|
||||||
add-job-summary-as-pr-comment: on-failure
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
- name: Run build with Gradle wrapper
|
script: |
|
||||||
id: gradle
|
github.rest.issues.createComment({
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
issue_number: context.issue.number,
|
||||||
run: ./gradlew build --scan
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
failing-build-with-comment-on-failure:
|
body: 'PR ready for review: ${{ steps.gradle.outputs.build-scan-url }}'
|
||||||
runs-on: ubuntu-latest
|
})
|
||||||
steps:
|
|
||||||
- name: Checkout project sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
add-job-summary-as-pr-comment: on-failure
|
|
||||||
- name: Run build with Gradle wrapper
|
|
||||||
id: gradle
|
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
|
||||||
run: ./gradlew no-a-real-task --scan
|
|
||||||
continue-on-error: true
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
name: Test caching configuration
|
name: Test action inputs for caching
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
@@ -38,8 +38,7 @@ jobs:
|
|||||||
enterprise
|
enterprise
|
||||||
# Exclude build-cache from main cache entry
|
# Exclude build-cache from main cache entry
|
||||||
gradle-home-cache-excludes: |
|
gradle-home-cache-excludes: |
|
||||||
caches/build-cache-*
|
caches/build-cache-1
|
||||||
caches/*/executionHistory
|
|
||||||
- name: Build using Gradle wrapper
|
- name: Build using Gradle wrapper
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: ./gradlew test
|
run: ./gradlew test
|
||||||
@@ -64,8 +63,7 @@ jobs:
|
|||||||
caches
|
caches
|
||||||
enterprise
|
enterprise
|
||||||
gradle-home-cache-excludes: |
|
gradle-home-cache-excludes: |
|
||||||
caches/build-cache-*
|
caches/build-cache-1
|
||||||
caches/*/executionHistory
|
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
- name: Execute Gradle build with --offline
|
- name: Execute Gradle build with --offline
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
@@ -1,103 +0,0 @@
|
|||||||
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
|
|
@@ -12,9 +12,6 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-graph-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: dependency-graph-${{ inputs.cache-key-prefix }}
|
||||||
@@ -34,7 +31,7 @@ jobs:
|
|||||||
- name: Setup Gradle for dependency-graph generate
|
- name: Setup Gradle for dependency-graph generate
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
dependency-graph: generate-and-upload
|
dependency-graph: generate
|
||||||
- name: Run gradle build
|
- name: Run gradle build
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
@@ -58,7 +55,7 @@ jobs:
|
|||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
|
|
||||||
submit:
|
submit:
|
||||||
needs: [groovy-generate]
|
needs: [groovy-generate, kotlin-generate]
|
||||||
runs-on: "ubuntu-latest"
|
runs-on: "ubuntu-latest"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
@@ -83,22 +80,18 @@ jobs:
|
|||||||
- name: Setup Gradle for dependency-graph generate
|
- name: Setup Gradle for dependency-graph generate
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
dependency-graph: generate-and-submit
|
dependency-graph: generate
|
||||||
- id: gradle-assemble
|
- id: gradle-assemble
|
||||||
run: ./gradlew assemble
|
run: ./gradlew assemble
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
- id: gradle-build
|
- id: gradle-build
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
- id: gradle-build-again
|
|
||||||
run: ./gradlew build
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
- name: Check generated dependency graphs
|
- name: Check generated dependency graphs
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "gradle-assemble report file: ${{ steps.gradle-assemble.outputs.dependency-graph-file }}"
|
echo "gradle-assemble report file: ${{ steps.gradle-assemble.outputs.dependency-graph-file }}"
|
||||||
echo "gradle-build report file: ${{ steps.gradle-build.outputs.dependency-graph-file }}"
|
echo "gradle-build report file: ${{ steps.gradle-build.outputs.dependency-graph-file }}"
|
||||||
echo "gradle-build-again report file: ${{ steps.gradle-build-again.outputs.dependency-graph-file }}"
|
|
||||||
ls -l dependency-graph-reports
|
ls -l dependency-graph-reports
|
||||||
if [ ! -e "${{ steps.gradle-assemble.outputs.dependency-graph-file }}" ]; then
|
if [ ! -e "${{ steps.gradle-assemble.outputs.dependency-graph-file }}" ]; then
|
||||||
echo "Did not find gradle-assemble dependency graph file"
|
echo "Did not find gradle-assemble dependency graph file"
|
||||||
@@ -108,41 +101,3 @@ jobs:
|
|||||||
echo "Did not find gradle-build dependency graph files"
|
echo "Did not find gradle-build dependency graph files"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if [ ! -e "${{ steps.gradle-build-again.outputs.dependency-graph-file }}" ]; then
|
|
||||||
echo "Did not find gradle-build-again dependency graph files"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
config-cache:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout sources
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Download distribution if required
|
|
||||||
uses: ./.github/actions/download-dist
|
|
||||||
- name: Setup Gradle for dependency-graph generate
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
dependency-graph: generate-and-submit
|
|
||||||
- id: config-cache-store
|
|
||||||
run: ./gradlew assemble --configuration-cache
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
- name: Check and delete generated dependency graph
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -e "${{ steps.config-cache-store.outputs.dependency-graph-file }}" ]; then
|
|
||||||
echo "Did not find config-cache-store dependency graph files"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
rm ${{ steps.config-cache-store.outputs.dependency-graph-file }}
|
|
||||||
- id: config-cache-reuse
|
|
||||||
run: ./gradlew assemble --configuration-cache
|
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
- name: Check no dependency graph is generated
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -z "$(ls -A dependency-graph-reports)" ]; then
|
|
||||||
echo "Expected no dependency graph files to be generated"
|
|
||||||
ls -l dependency-graph-reports
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
@@ -21,7 +21,6 @@ jobs:
|
|||||||
# Test that pre-installed runner JDKs are detected
|
# Test that pre-installed runner JDKs are detected
|
||||||
pre-installed-toolchains:
|
pre-installed-toolchains:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
matrix:
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
os: ${{fromJSON(inputs.runner-os)}}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
@@ -36,7 +35,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: |
|
run: |
|
||||||
gradle --info javaToolchains > output.txt
|
gradle -q javaToolchains > output.txt
|
||||||
cat output.txt
|
cat output.txt
|
||||||
- name: Verify detected toolchains
|
- name: Verify detected toolchains
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -45,12 +44,10 @@ jobs:
|
|||||||
grep -q 'Eclipse Temurin JDK 1.8' output.txt || (echo "::error::Did not detect preinstalled JDK 1.8" && exit 1)
|
grep -q 'Eclipse Temurin JDK 1.8' output.txt || (echo "::error::Did not detect preinstalled JDK 1.8" && exit 1)
|
||||||
grep -q 'Eclipse Temurin JDK 11' output.txt || (echo "::error::Did not detect preinstalled JDK 11" && exit 1)
|
grep -q 'Eclipse Temurin JDK 11' output.txt || (echo "::error::Did not detect preinstalled JDK 11" && exit 1)
|
||||||
grep -q 'Eclipse Temurin JDK 17' output.txt || (echo "::error::Did not detect preinstalled JDK 17" && exit 1)
|
grep -q 'Eclipse Temurin JDK 17' output.txt || (echo "::error::Did not detect preinstalled JDK 17" && exit 1)
|
||||||
grep -q 'Eclipse Temurin JDK 21' output.txt || (echo "::error::Did not detect preinstalled JDK 21" && exit 1)
|
|
||||||
|
|
||||||
# Test that JDKs provisioned by setup-java are detected
|
# Test that JDKs provisioned by setup-java are detected
|
||||||
setup-java-installed-toolchain:
|
setup-java-installed-toolchain:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
matrix:
|
||||||
os: ${{fromJSON(inputs.runner-os)}}
|
os: ${{fromJSON(inputs.runner-os)}}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
@@ -75,19 +72,42 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: |
|
run: |
|
||||||
gradle --info javaToolchains > output.txt
|
gradle -q javaToolchains > output.txt
|
||||||
cat output.txt
|
cat output.txt
|
||||||
- name: Verify setup JDKs are detected
|
- name: Verify detected toolchains
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: |
|
run: |
|
||||||
grep -q 'Eclipse Temurin JDK 16' output.txt || (echo "::error::Did not detect setup-java installed JDK 16" && exit 1)
|
grep -q 'Eclipse Temurin JDK 16' output.txt || (echo "::error::Did not detect setup-java installed JDK 16" && exit 1)
|
||||||
grep -q 'Eclipse Temurin JDK 20' output.txt || (echo "::error::Did not detect setup-java installed JDK 20" && exit 1)
|
grep -q 'Eclipse Temurin JDK 20' output.txt || (echo "::error::Did not detect setup-java installed JDK 20" && exit 1)
|
||||||
- name: Verify pre-installed toolchains are detected
|
|
||||||
|
# Test that predefined JDK detection property is not overwritten by action
|
||||||
|
check-no-overwrite:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: ${{fromJSON(inputs.runner-os)}}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout sources
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Download distribution if required
|
||||||
|
uses: ./.github/actions/download-dist
|
||||||
|
- name: Configure java installations env var in Gradle User Home
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
|
||||||
run: |
|
run: |
|
||||||
grep -q 'Eclipse Temurin JDK 1.8' output.txt || (echo "::error::Did not detect preinstalled JDK 1.8" && exit 1)
|
mkdir -p ~/.gradle
|
||||||
grep -q 'Eclipse Temurin JDK 11' output.txt || (echo "::error::Did not detect preinstalled JDK 11" && exit 1)
|
echo "org.gradle.java.installations.fromEnv=XXXXX" > ~/.gradle/gradle.properties
|
||||||
grep -q 'Eclipse Temurin JDK 17' output.txt || (echo "::error::Did not detect preinstalled JDK 17" && exit 1)
|
- name: Setup Gradle
|
||||||
grep -q 'Eclipse Temurin JDK 21' output.txt || (echo "::error::Did not detect preinstalled JDK 21" && exit 1)
|
uses: ./
|
||||||
|
- name: Check gradle.properties
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cat ~/.gradle/gradle.properties
|
||||||
|
if grep -q 'org.gradle.java.installations.fromEnv=JAVA_HOME' ~/.gradle/gradle.properties ; then
|
||||||
|
echo 'Found overwritten fromEnv'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! grep -q 'org.gradle.java.installations.fromEnv=XXXXX' ~/.gradle/gradle.properties ; then
|
||||||
|
echo 'Did NOT find original fromEnv'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
6
.github/workflows/integ-test-execution.yml
vendored
6
.github/workflows/integ-test-execution.yml
vendored
@@ -46,6 +46,12 @@ jobs:
|
|||||||
gradle-version: release-candidate
|
gradle-version: release-candidate
|
||||||
build-root-directory: .github/workflow-samples/no-wrapper
|
build-root-directory: .github/workflow-samples/no-wrapper
|
||||||
arguments: help
|
arguments: help
|
||||||
|
- name: Test use defined Gradle executable
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
gradle-executable: .github/workflow-samples/groovy-dsl/gradlew${{ matrix.script-suffix }}
|
||||||
|
build-root-directory: .github/workflow-samples/no-wrapper
|
||||||
|
arguments: help
|
||||||
|
|
||||||
gradle-versions:
|
gradle-versions:
|
||||||
strategy:
|
strategy:
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
name: Test develocity injection
|
name: Test gradle enterprise injection
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
@@ -12,21 +12,21 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
secrets:
|
secrets:
|
||||||
DEVELOCITY_ACCESS_KEY:
|
GRADLE_ENTERPRISE_ACCESS_KEY:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }}
|
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: provision-gradle-versions-${{ inputs.cache-key-prefix }}
|
||||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||||
DEVELOCITY_INJECTION_ENABLED: true
|
GRADLE_ENTERPRISE_INJECTION_ENABLED: true
|
||||||
DEVELOCITY_URL: https://ge.solutions-team.gradle.com
|
GRADLE_ENTERPRISE_URL: https://ge.solutions-team.gradle.com
|
||||||
DEVELOCITY_PLUGIN_VERSION: 3.16.1
|
GRADLE_ENTERPRISE_PLUGIN_VERSION: 3.15.1
|
||||||
DEVELOCITY_CCUD_PLUGIN_VERSION: 1.12.1
|
GRADLE_ENTERPRISE_CCUD_PLUGIN_VERSION: 1.12
|
||||||
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} # This env var has not (yet) been renamed/aliased in GE plugin 3.16.1
|
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
inject-develocity:
|
inject-gradle-enterprise:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
|
gradle: [current, 7.6.2, 6.9.4, 5.6.4]
|
@@ -11,9 +11,6 @@ on:
|
|||||||
download-dist:
|
download-dist:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
secrets:
|
|
||||||
GRADLE_ENCRYPTION_KEY:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
DOWNLOAD_DIST: ${{ inputs.download-dist }}
|
||||||
@@ -37,11 +34,9 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Groovy build with configuration-cache enabled
|
- name: Groovy build with configuration-cache enabled
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
|
|
||||||
verify-build-groovy:
|
verify-build-groovy:
|
||||||
env:
|
env:
|
||||||
@@ -60,12 +55,10 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Groovy build with configuration-cache enabled
|
- name: Groovy build with configuration-cache enabled
|
||||||
id: execute
|
id: execute
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
- name: Check that configuration-cache was used
|
- name: Check that configuration-cache was used
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
@@ -95,11 +88,9 @@ jobs:
|
|||||||
GRADLE_BUILD_ACTION_SKIP_RESTORE: "generated-gradle-jars|wrapper-zips|java-toolchains|instrumented-jars|dependencies|kotlin-dsl"
|
GRADLE_BUILD_ACTION_SKIP_RESTORE: "generated-gradle-jars|wrapper-zips|java-toolchains|instrumented-jars|dependencies|kotlin-dsl"
|
||||||
with:
|
with:
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Check execute Gradle build with configuration cache enabled (but not restored)
|
- name: Check execute Gradle build with configuration cache enabled (but not restored)
|
||||||
working-directory: .github/workflow-samples/groovy-dsl
|
working-directory: .github/workflow-samples/groovy-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
|
|
||||||
seed-build-kotlin:
|
seed-build-kotlin:
|
||||||
env:
|
env:
|
||||||
@@ -117,11 +108,9 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Execute 'help' with configuration-cache enabled
|
- name: Execute 'help' with configuration-cache enabled
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: gradle help --configuration-cache
|
run: ./gradlew help --configuration-cache
|
||||||
|
|
||||||
modify-build-kotlin:
|
modify-build-kotlin:
|
||||||
env:
|
env:
|
||||||
@@ -140,11 +129,9 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
cache-read-only: false # For testing, allow writing cache entries on non-default branches
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Execute 'test' with configuration-cache enabled
|
- name: Execute 'test' with configuration-cache enabled
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
|
|
||||||
# Test restore configuration-cache from the third build invocation
|
# Test restore configuration-cache from the third build invocation
|
||||||
verify-build-kotlin:
|
verify-build-kotlin:
|
||||||
@@ -164,12 +151,10 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
cache-read-only: true
|
cache-read-only: true
|
||||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
- name: Execute 'test' again with configuration-cache enabled
|
- name: Execute 'test' again with configuration-cache enabled
|
||||||
id: execute
|
id: execute
|
||||||
working-directory: .github/workflow-samples/kotlin-dsl
|
working-directory: .github/workflow-samples/kotlin-dsl
|
||||||
run: gradle test --configuration-cache
|
run: ./gradlew test --configuration-cache
|
||||||
- name: Check that configuration-cache was used
|
- name: Check that configuration-cache was used
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
# Configuration file for asdf version manager
|
# Configuration file for asdf version manager
|
||||||
nodejs 20.10.0
|
nodejs 16.18.1
|
||||||
gradle 8.5
|
gradle 8.5
|
||||||
|
314
README.md
314
README.md
@@ -4,7 +4,7 @@ This GitHub Action can be used to configure Gradle and optionally execute a Grad
|
|||||||
|
|
||||||
## Why use the `gradle-build-action`?
|
## Why use the `gradle-build-action`?
|
||||||
|
|
||||||
It is possible to directly invoke Gradle in your workflow, and the `actions/setup-java@v4` action provides a simple way to cache Gradle dependencies.
|
It is possible to directly invoke Gradle in your workflow, and the `actions/setup-java@v3` action provides a simple way to cache Gradle dependencies.
|
||||||
|
|
||||||
However, the `gradle-build-action` offers a number of advantages over this approach:
|
However, the `gradle-build-action` offers a number of advantages over this approach:
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-java@v4
|
- uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 11
|
java-version: 11
|
||||||
@@ -85,7 +85,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-java@v4
|
- uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 11
|
java-version: 11
|
||||||
@@ -97,6 +97,7 @@ jobs:
|
|||||||
- run: echo "The release-candidate version was ${{ steps.setup-gradle.outputs.gradle-version }}"
|
- run: echo "The release-candidate version was ${{ steps.setup-gradle.outputs.gradle-version }}"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Caching build state between Jobs
|
## Caching build state between Jobs
|
||||||
|
|
||||||
The `gradle-build-action` will use the GitHub Actions cache to save and restore reusable state that may be speed up a subsequent build invocation. This includes most content that is downloaded from the internet as part of a build, as well as expensive to create content like compiled build scripts, transformed Jar files, etc.
|
The `gradle-build-action` will use the GitHub Actions cache to save and restore reusable state that may be speed up a subsequent build invocation. This includes most content that is downloaded from the internet as part of a build, as well as expensive to create content like compiled build scripts, transformed Jar files, etc.
|
||||||
@@ -120,7 +121,7 @@ cache-disabled: true
|
|||||||
|
|
||||||
By default, the `gradle-build-action` will only write to the cache from Jobs on the default (`main`/`master`) branch.
|
By default, the `gradle-build-action` will only write to the cache from Jobs on the default (`main`/`master`) branch.
|
||||||
Jobs on other branches will read entries from the cache but will not write updated entries.
|
Jobs on other branches will read entries from the cache but will not write updated entries.
|
||||||
See [Optimizing cache effectiveness](#select-which-branches-should-write-to-the-cache) for a more detailed explanation.
|
See [Optimizing cache effectiveness](#optimizing-cache-effectiveness) for a more detailed explanation.
|
||||||
|
|
||||||
In some circumstances it makes sense to change this default, and to configure a workflow Job to read existing cache entries but not to write changes back.
|
In some circumstances it makes sense to change this default, and to configure a workflow Job to read existing cache entries but not to write changes back.
|
||||||
|
|
||||||
@@ -160,31 +161,6 @@ If you want override the default and have the `gradle-build-action` caches overw
|
|||||||
cache-overwrite-existing: true
|
cache-overwrite-existing: true
|
||||||
```
|
```
|
||||||
|
|
||||||
### Saving configuration-cache data
|
|
||||||
|
|
||||||
When Gradle is executed with the [configuration-cache](https://docs.gradle.org/current/userguide/configuration_cache.html) enabled, the configuration-cache data is stored
|
|
||||||
in the project directory, at `<project-dir>/.gradle/configuration-cache`. Due to the way the configuration-cache works, [this file may contain stored credentials and other
|
|
||||||
secrets](https://docs.gradle.org/release-nightly/userguide/configuration_cache.html#config_cache:secrets), and this data needs to be encrypted in order to be safely stored in the GitHub Actions cache.
|
|
||||||
|
|
||||||
In order to benefit from configuration caching in your GitHub Actions workflow, you must:
|
|
||||||
- Execute your build with Gradle 8.6 or newer. This can be achieved directly, or via the Gradle Wrapper.
|
|
||||||
- Enable the configuration cache for your build.
|
|
||||||
- Generate a [valid Gradle encryption key](https://docs.gradle.org/8.6-rc-1/userguide/configuration_cache.html#config_cache:secrets:configuring_encryption_key) and save it as a [GitHub Actions secret](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions).
|
|
||||||
- Provide the secret key via the `cache-encryption-key` action parameter.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
jobs:
|
|
||||||
gradle-with-configuration-cache:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: gradle/gradle-build-action@v3
|
|
||||||
with:
|
|
||||||
gradle-version: 8.6-rc-1
|
|
||||||
cache-encryption-key: ${{ secrets.GradleEncryptionKey }}
|
|
||||||
- run: gradle build --configuration-cache
|
|
||||||
```
|
|
||||||
|
|
||||||
### Incompatibility with other caching mechanisms
|
### Incompatibility with other caching mechanisms
|
||||||
|
|
||||||
When using `gradle-build-action` we recommend that you avoid using other mechanisms to save and restore the Gradle User Home.
|
When using `gradle-build-action` we recommend that you avoid using other mechanisms to save and restore the Gradle User Home.
|
||||||
@@ -247,11 +223,11 @@ For this reason, it's very difficult to create a cache key that will determinist
|
|||||||
|
|
||||||
The Gradle User Home cache key is composed of:
|
The Gradle User Home cache key is composed of:
|
||||||
- The current operating system (`RUNNER_OS`)
|
- The current operating system (`RUNNER_OS`)
|
||||||
- The Job id
|
- The workflow name and Job ID
|
||||||
- A hash of the Job matrix parameters and the workflow name
|
- A hash of the Job matrix parameters
|
||||||
- The git SHA for the latest commit
|
- The git SHA for the latest commit
|
||||||
|
|
||||||
Specifically, the cache key is: `${cache-protocol}-gradle|${runner-os}|${job-id}[${hash-of-job-matrix-and-workflow-name}]-${git-sha}`
|
Specifically, the cache key is: `${cache-protocol}-gradle|${runner-os}|${workflow-name}-${job-id}[${hash-of-job-matrix}]-${git-sha}`
|
||||||
|
|
||||||
As such, the cache key is likely to change on each subsequent run of GitHub actions.
|
As such, the cache key is likely to change on each subsequent run of GitHub actions.
|
||||||
This allows the most recent state to always be available in the GitHub actions cache.
|
This allows the most recent state to always be available in the GitHub actions cache.
|
||||||
@@ -259,9 +235,9 @@ This allows the most recent state to always be available in the GitHub actions c
|
|||||||
### Finding a matching cache entry
|
### Finding a matching cache entry
|
||||||
|
|
||||||
In most cases, no exact match will exist for the cache key. Instead, the Gradle User Home will be restored for the closest matching cache entry, using a set of "restore keys". The entries will be matched with the following precedence:
|
In most cases, no exact match will exist for the cache key. Instead, the Gradle User Home will be restored for the closest matching cache entry, using a set of "restore keys". The entries will be matched with the following precedence:
|
||||||
- An exact match on OS, job id, workflow name, matrix and Git SHA
|
- An exact match on OS, workflow, job, 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, workflow, job and matrix values
|
||||||
- The most recent entry saved for the same OS and job id
|
- The most recent entry saved for the same OS, workflow and job
|
||||||
- The most recent entry saved for the same OS
|
- The most recent entry saved for the same OS
|
||||||
|
|
||||||
Due to branch scoping of cache entries, the above match will be first performed for entries from the same branch, and then for the default ('main') branch.
|
Due to branch scoping of cache entries, the above match will be first performed for entries from the same branch, and then for the default ('main') branch.
|
||||||
@@ -314,22 +290,19 @@ There are some techniques that can be used to avoid/mitigate this issue:
|
|||||||
### Select which branches should write to the cache
|
### Select which branches should write to the cache
|
||||||
|
|
||||||
GitHub cache entries are not shared between builds on different branches.
|
GitHub cache entries are not shared between builds on different branches.
|
||||||
Workflow runs can restore caches created in either the current branch or the default branch (usually main).
|
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.
|
||||||
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.
|
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.
|
||||||
|
|
||||||
By default, the `gradle-build-action` will only _write_ to the cache for builds run on the default (`master`/`main`) branch.
|
By default, the `gradle-build-action` will only _write_ to the cache for builds run on the default (`master`/`main`) branch.
|
||||||
Jobs run on other branches will only read from the cache. In most cases, this is the desired behavior.
|
Jobs run on other branches will only read from the cache. In most cases, this is the desired behaviour,
|
||||||
This is because Jobs run on other branches will benefit from the cache Gradle User Home from `main`,
|
because Jobs run against 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.
|
without writing private cache entries that could lead to evicting shared entries.
|
||||||
|
|
||||||
If you have other long-lived development branches that would benefit from writing to the cache,
|
If you have other long-lived development branches that would benefit from writing to the cache,
|
||||||
you can configure this by disabling the `cache-read-only` action parameter for these branches.
|
you can configure these by overriding the `cache-read-only` action parameter.
|
||||||
See [Using the cache read-only](#using-the-cache-read-only) for more details.
|
See [Using the cache read-only](#using-the-cache-read-only) for more details.
|
||||||
|
|
||||||
Note there are some cases where writing cache entries is typically unhelpful (these are disabled by default):
|
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.
|
||||||
- For `pull_request` triggered runs, the cache scope is limited to the merge ref (`refs/pull/.../merge`) and can only be restored by re-runs of the same pull request.
|
|
||||||
- For `merge_group` triggered runs, the cache scope is limited to a temporary branch with a special prefix created to validate pull request changes, and won't be available on subsequent Merge Queue executions.
|
|
||||||
|
|
||||||
|
|
||||||
### Exclude content from Gradle User Home cache
|
### Exclude content from Gradle User Home cache
|
||||||
|
|
||||||
@@ -371,57 +344,62 @@ gradle-home-cache-cleanup: true
|
|||||||
|
|
||||||
## Build reporting
|
## Build reporting
|
||||||
|
|
||||||
The `gradle-build-action` collects information about any Gradle executions that occur in a workflow, including the root project,
|
The `gradle-build-action` collects information about any Gradle executions that occur in a workflow, and reports these via
|
||||||
requested tasks, build outcome and any Build Scan link generated. Details of cache entries read and written are also collected.
|
a Job Summary, visible in the GitHub Actions UI. For each Gradle execution, details about the invocation are listed, together with
|
||||||
These details are compiled into a Job Summary, which is visible in the GitHub Actions UI.
|
a link to any Build Scan® published.
|
||||||
|
|
||||||
Generation of a Job Summary is enabled by default for all Jobs using the `gradle-build-action`. This feature can be configured
|
Generation of a Job Summary is enabled by default. If this is not desired, it can be disable as follows:
|
||||||
so that a Job Summary is never generated, or so that a Job Summary is only generated on build failure:
|
|
||||||
```yaml
|
```yaml
|
||||||
add-job-summary: 'on-failure' # Valid values are 'always' (default), 'never', and 'on-failure'
|
generate-job-summary: false
|
||||||
```
|
```
|
||||||
|
|
||||||
### Adding Job Summary as a Pull Request comment
|
Note that the action collects information about Gradle invocations via an [Initialization Script](https://docs.gradle.org/current/userguide/init_scripts.html#sec:using_an_init_script)
|
||||||
|
located at `USER_HOME/.gradle/init.d/build-result-capture.init.gradle`.
|
||||||
|
If you are using init scripts for the [Gradle Enterprise Gradle Plugin](https://plugins.gradle.org/plugin/com.gradle.enterprise) like
|
||||||
|
[`scans-init.gradle` or `gradle-enterprise-init.gradle`](https://docs.gradle.com/enterprise/gradle-plugin/#scans_gradle_com),
|
||||||
|
you'll need to ensure these files are applied prior to `build-result-capture.init.gradle`.
|
||||||
|
Since Gradle applies init scripts in alphabetical order, one way to ensure this is via file naming.
|
||||||
|
|
||||||
It is sometimes more convenient to view the results of a GitHub Actions Job directly from the Pull Request that triggered
|
### Build Scan® link as Step output
|
||||||
the Job. For this purpose you can configure the action so that Job Summary data is added as a Pull Request comment.
|
|
||||||
|
|
||||||
|
As well as reporting the [Build Scan](https://gradle.com/build-scans/) link in the Job Summary,
|
||||||
|
the `gradle-build-action` action makes this link available as a Step output named `build-scan-url`.
|
||||||
|
|
||||||
|
You can then use that link in subsequent actions of your workflow. For example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: CI
|
# .github/workflows/gradle-build-pr.yml
|
||||||
on:
|
name: Run Gradle on PRs
|
||||||
pull_request:
|
on: pull_request
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-gradle-build:
|
gradle:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout project sources
|
- name: Checkout project sources
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v3
|
uses: gradle/gradle-build-action@v2
|
||||||
|
- name: Run build with Gradle wrapper
|
||||||
|
id: gradle
|
||||||
|
run: ./gradlew build --scan
|
||||||
|
- name: "Add Build Scan URL as PR comment"
|
||||||
|
uses: actions/github-script@v5
|
||||||
|
if: github.event_name == 'pull_request' && failure()
|
||||||
with:
|
with:
|
||||||
add-job-summary-as-pr-comment: on-failure # Valid values are 'never' (default), 'always', and 'on-failure'
|
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||||
- run: ./gradlew build --scan
|
script: |
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: '❌ ${{ github.workflow }} failed: ${{ steps.gradle.outputs.build-scan-url }}'
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that in order to add a Pull Request comment, the workflow must be configured with the `pull-requests: write` permission.
|
### Saving build outputs
|
||||||
|
|
||||||
|
By default, a GitHub Actions workflow using `gradle-build-action` will record the log output and any Build Scan links for your build,
|
||||||
### Build Scan® link as Step output
|
but any output files generated by the build will not be saved.
|
||||||
|
|
||||||
As well as reporting all [Build Scan](https://gradle.com/build-scans/) links in the Job Summary,
|
|
||||||
the `gradle-build-action` action makes this link available an an output of any Step that executes Gradle.
|
|
||||||
|
|
||||||
The output name is `build-scan-url`. You can then use the build scan link in subsequent actions of your workflow.
|
|
||||||
|
|
||||||
### Saving arbitrary build outputs
|
|
||||||
|
|
||||||
By default, a GitHub Actions workflow using `gradle-build-action` will record the log output and any Build Scan
|
|
||||||
links for your build, but any output files generated by the build will not be saved.
|
|
||||||
|
|
||||||
To save selected files from your build execution, you can use the core [Upload-Artifact](https://github.com/actions/upload-artifact) action.
|
To save selected files from your build execution, you can use the core [Upload-Artifact](https://github.com/actions/upload-artifact) action.
|
||||||
For example:
|
For example:
|
||||||
@@ -445,13 +423,102 @@ jobs:
|
|||||||
path: build/reports/
|
path: build/reports/
|
||||||
```
|
```
|
||||||
|
|
||||||
### Use of custom init-scripts in Gradle User Home
|
## Use the action to invoke Gradle
|
||||||
|
|
||||||
Note that the action collects information about Gradle invocations via an [Initialization Script](https://docs.gradle.org/current/userguide/init_scripts.html#sec:using_an_init_script)
|
If the `gradle-build-action` is configured with an `arguments` input, then Gradle will execute a Gradle build with the arguments provided. NOTE: We recommend using the `gradle-build-action` as a "Setup Gradle" step as described above, with Gradle being invoked via a regular `run` command.
|
||||||
located at `USER_HOME/.gradle/init.d/gradle-build-action.build-result-capture.init.gradle`.
|
|
||||||
|
|
||||||
If you are adding any custom init scripts to the `USER_HOME/.gradle/init.d` directory, it may be necessary to ensure these files are applied prior to `gradle-build-action.build-result-capture.init.gradle`.
|
If no `arguments` are provided, the action will not execute Gradle, but will still cache Gradle state and configure build-scan capture for all subsequent Gradle executions.
|
||||||
Since Gradle applies init scripts in alphabetical order, one way to ensure this is via file naming.
|
|
||||||
|
```yaml
|
||||||
|
name: Run Gradle on PRs
|
||||||
|
on: pull_request
|
||||||
|
jobs:
|
||||||
|
gradle:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 11
|
||||||
|
|
||||||
|
- name: Setup and execute Gradle 'test' task
|
||||||
|
uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Gradle executions in the same Job
|
||||||
|
|
||||||
|
It is possible to configure multiple Gradle executions to run sequentially in the same job.
|
||||||
|
The initial Action step will perform the Gradle setup.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: assemble
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: check
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gradle command-line arguments
|
||||||
|
|
||||||
|
The `arguments` input can be used to pass arbitrary arguments to the `gradle` command line.
|
||||||
|
Arguments can be supplied in a single line, or as a multi-line input.
|
||||||
|
|
||||||
|
Here are some valid examples:
|
||||||
|
```yaml
|
||||||
|
arguments: build
|
||||||
|
arguments: check --scan
|
||||||
|
arguments: some arbitrary tasks
|
||||||
|
arguments: build -PgradleProperty=foo
|
||||||
|
arguments: |
|
||||||
|
build
|
||||||
|
--scan
|
||||||
|
-PgradleProperty=foo
|
||||||
|
-DsystemProperty=bar
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to pass environment variables, use the GitHub Actions workflow syntax:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
with:
|
||||||
|
arguments: build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Gradle build located in a subdirectory
|
||||||
|
|
||||||
|
By default, the action will execute Gradle in the root directory of your project.
|
||||||
|
Use the `build-root-directory` input to target a Gradle build in a subdirectory.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: build
|
||||||
|
build-root-directory: some/subdirectory
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using a specific Gradle executable
|
||||||
|
|
||||||
|
The action will first look for a Gradle wrapper script in the root directory of your project.
|
||||||
|
If not found, `gradle` will be executed from the PATH.
|
||||||
|
Use the `gradle-executable` input to execute using a specific Gradle installation.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: gradle/gradle-build-action@v2
|
||||||
|
with:
|
||||||
|
arguments: build
|
||||||
|
gradle-executable: /path/to/installed/gradle
|
||||||
|
```
|
||||||
|
|
||||||
|
This mechanism can also be used to target a Gradle wrapper script that is located in a non-default location.
|
||||||
|
|
||||||
## Support for GitHub Enterprise Server (GHES)
|
## Support for GitHub Enterprise Server (GHES)
|
||||||
|
|
||||||
@@ -476,10 +543,9 @@ You enable GitHub Dependency Graph support by setting the `dependency-graph` act
|
|||||||
| Option | Behaviour |
|
| Option | Behaviour |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `disabled` | Do not generate a dependency graph for any build invocations.<p>This is the default. |
|
| `disabled` | Do not generate a dependency graph for any build invocations.<p>This is the default. |
|
||||||
| `generate` | Generate a dependency graph snapshot for each build invocation. |
|
| `generate` | Generate a dependency graph snapshot for each build invocation, saving as a workflow artifact. |
|
||||||
| `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-submit` | As per `generate`, but any generated dependency graph snapshots will be submitted at the end 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, 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. |
|
||||||
| `download-and-submit` | Download any previously saved dependency graph snapshots, and submit them via the Dependency Submission API. This can be useful to submit [dependency graphs for pull requests submitted from a repository forks](#dependency-graphs-for-pull-request-workflows). |
|
|
||||||
|
|
||||||
Example of a CI workflow that generates and submits a dependency graph:
|
Example of a CI workflow that generates and submits a dependency graph:
|
||||||
```yaml
|
```yaml
|
||||||
@@ -513,22 +579,6 @@ Depending on [repository settings](https://docs.github.com/en/actions/security-g
|
|||||||
> for a PR submitted from a forked repository.
|
> for a PR submitted from a forked repository.
|
||||||
> For a configuration that supports this setup, see [Dependency Graphs for pull request workflows](#dependency-graphs-for-pull-request-workflows).
|
> For a configuration that supports this setup, see [Dependency Graphs for pull request workflows](#dependency-graphs-for-pull-request-workflows).
|
||||||
|
|
||||||
### Making dependency graph failures cause Job failures
|
|
||||||
|
|
||||||
By default, if a failure is encountered when generating or submitting the dependency graph, the action will log the failure as a warning and continue.
|
|
||||||
This allows your workflow to be resilient to dependency graph failures, in case dependency graph production is a side-effect rather than the primary purpose of a workflow.
|
|
||||||
|
|
||||||
If instead you have a workflow that has a primary purpose to generate and submit a dependency graph, then it makes sense for this workflow to fail if the dependency
|
|
||||||
graph cannot be generated or submitted. You can enable this behaviour with the `dependency-graph-continue-on-failure` parameter, which defaults to `true`.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# Ensure that the workflow Job will fail if the dependency graph cannot be submitted
|
|
||||||
- uses: gradle/gradle-build-action@v3
|
|
||||||
with:
|
|
||||||
dependency-graph: generate-and-submit
|
|
||||||
dependency-graph-continue-on-failure: false
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using a custom plugin repository
|
### Using a custom plugin repository
|
||||||
|
|
||||||
By default, the action downloads the `github-dependency-graph-gradle-plugin` from the Gradle Plugin Portal (https://plugins.gradle.org). If your GitHub Actions environment does not have access to this URL, you can specify a custom plugin repository to use.
|
By default, the action downloads the `github-dependency-graph-gradle-plugin` from the Gradle Plugin Portal (https://plugins.gradle.org). If your GitHub Actions environment does not have access to this URL, you can specify a custom plugin repository to use.
|
||||||
@@ -705,9 +755,6 @@ name: run-build-and-generate-dependency-snapshot
|
|||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -716,7 +763,7 @@ jobs:
|
|||||||
- name: Setup Gradle to generate and submit dependency graphs
|
- name: Setup Gradle to generate and submit dependency graphs
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/gradle-build-action@v2
|
||||||
with:
|
with:
|
||||||
dependency-graph: generate-and-upload # Generate graphs and save as workflow artifacts
|
dependency-graph: generate # Only generate in this job
|
||||||
- name: Run a build, generating the dependency graph snapshot which will be submitted
|
- name: Run a build, generating the dependency graph snapshot which will be submitted
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
```
|
```
|
||||||
@@ -730,9 +777,6 @@ on:
|
|||||||
workflows: ['run-build-and-generate-dependency-snapshot']
|
workflows: ['run-build-and-generate-dependency-snapshot']
|
||||||
types: [completed]
|
types: [completed]
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
submit-dependency-graph:
|
submit-dependency-graph:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -740,7 +784,7 @@ jobs:
|
|||||||
- name: Retrieve dependency graph artifact and submit
|
- name: Retrieve dependency graph artifact and submit
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/gradle-build-action@v2
|
||||||
with:
|
with:
|
||||||
dependency-graph: download-and-submit # Download saved workflow artifacts and submit
|
dependency-graph: download-and-submit
|
||||||
```
|
```
|
||||||
|
|
||||||
### Integrating `dependency-review-action` for pull request workflows
|
### Integrating `dependency-review-action` for pull request workflows
|
||||||
@@ -806,26 +850,27 @@ To reduce storage costs for these artifacts, you can set the `artifact-retention
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Develocity plugin injection
|
# Gradle Enterprise plugin injection
|
||||||
|
|
||||||
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.
|
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.
|
||||||
This is achieved via an init-script installed into Gradle User Home, which is enabled and parameterized via environment variables.
|
This is achieved via an init-script installed into Gradle User Home, which is enabled and parameterized via environment variables.
|
||||||
|
|
||||||
The same auto-injection behavior is available for the Common Custom User Data Gradle plugin, which enriches any build scans published with additional useful information.
|
The same auto-injection behavior is available for the Common Custom User Data Gradle plugin, which enriches any build scans published with additional useful information.
|
||||||
|
|
||||||
## Enabling Develocity injection
|
## Enabling Gradle Enterprise injection
|
||||||
|
|
||||||
In order to enable Develocity injection for your build, you must provide the required configuration via environment variables.
|
In order to enable Gradle Enterprise for your build, you must provide the required configuration via environment variables.
|
||||||
|
|
||||||
Here's a minimal example:
|
Here's a minimal example:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: Run build with Develocity injection
|
name: Run build with Gradle Enterprise injection
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEVELOCITY_INJECTION_ENABLED: true
|
GRADLE_ENTERPRISE_INJECTION_ENABLED: true
|
||||||
DEVELOCITY_URL: https://develocity.your-server.com
|
GRADLE_ENTERPRISE_URL: https://ge.gradle.org
|
||||||
DEVELOCITY_PLUGIN_VERSION: 3.16.1
|
GRADLE_ENTERPRISE_PLUGIN_VERSION: 3.15.1
|
||||||
|
GRADLE_ENTERPRISE_ACCESS_KEY: ${{ secrets.GE_ACCESS_KEY }} # Required to publish scans to ge.gradle.org
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -834,37 +879,36 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/gradle-build-action@v2
|
||||||
- name: Run a Gradle build with Develocity injection enabled
|
- name: Run a Gradle build with Gradle Enterprise injection enabled
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
This configuration will automatically apply `v3.15.1` of the [Gradle Enterprise Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/), and publish build scans to https://ge.gradle.org.
|
||||||
|
|
||||||
This example assumes that the `develocity.your-server.com` server allows anonymous publishing of build scans.
|
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,
|
||||||
In the likely scenario that your Develocity server requires authentication, you will also need to configure an addition environment variable
|
but will be used by the GE plugin in order to authenticate with the server.
|
||||||
with a valid [Develocity access key](https://docs.gradle.com/enterprise/gradle-plugin/#via_environment_variable).
|
|
||||||
|
|
||||||
## Configuring Develocity injection
|
## Configuring Gradle Enterprise injection
|
||||||
|
|
||||||
The `init-script` supports a number of additional configuration parameters that you may fine useful. All configuration options (required and optional) are detailed below:
|
The `init-script` supports a number of additional configuration parameters that you may fine useful. All configuration options (required and optional) are detailed below:
|
||||||
|
|
||||||
| Variable | Required | Description |
|
| Variable | Required | Description |
|
||||||
|-----------------------------------| --- | --- |
|
| --- | --- | --- |
|
||||||
| DEVELOCITY_INJECTION_ENABLED | :white_check_mark: | enables Develocity injection |
|
| GRADLE_ENTERPRISE_INJECTION_ENABLED | :white_check_mark: | enables Gradle Enterprise injection |
|
||||||
| DEVELOCITY_URL | :white_check_mark: | the URL of the Develocity server |
|
| GRADLE_ENTERPRISE_URL | :white_check_mark: | the URL of the Gradle Enterprise server |
|
||||||
| DEVELOCITY_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Develocity instance is using a self-signed certificate |
|
| GRADLE_ENTERPRISE_ALLOW_UNTRUSTED_SERVER | | allow communication with an untrusted server; set to _true_ if your Gradle Enterprise 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 |
|
| GRADLE_ENTERPRISE_ENFORCE_URL | | enforce the configured Gradle Enterprise URL over a URL configured in the project's build; set to _true_ to enforce publication of build scans to the configured Gradle Enterprise URL |
|
||||||
| DEVELOCITY_PLUGIN_VERSION | :white_check_mark: | the version of the [Develocity Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/) to apply |
|
| GRADLE_ENTERPRISE_PLUGIN_VERSION | :white_check_mark: | the version of the [Gradle Enterprise Gradle plugin](https://docs.gradle.com/enterprise/gradle-plugin/) to apply |
|
||||||
| DEVELOCITY_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_CCUD_PLUGIN_VERSION | | the version of the [Common Custom User Data Gradle plugin](https://github.com/gradle/common-custom-user-data-gradle-plugin) to apply, if any |
|
||||||
| GRADLE_PLUGIN_REPOSITORY_URL | | the URL of the repository to use when resolving the Develocity and CCUD plugins; the Gradle Plugin Portal is used by default |
|
| GRADLE_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 |
|
||||||
|
|
||||||
## Publishing to scans.gradle.com
|
## Publishing to scans.gradle.com
|
||||||
|
|
||||||
Develocity injection is designed to enable publishing of build scans to a Develocity instance,
|
Gradle Enterprise injection is designed to enable publishing of build scans to a Gradle Enterprise instance,
|
||||||
and is not suitable for publishing to the public Build Scans instance (https://scans.gradle.com).
|
and is not suitable for publishing to the public Build Scans instance (https://scans.gradle.com).
|
||||||
|
|
||||||
In order to publish Build Scans to scans.gradle.com, you need to:
|
In order to publish Build Scans to scans.gradle.com, you need to:
|
||||||
- Apply the Develocity plugin to your build configuration ([see docs](https://docs.gradle.com/enterprise/get-started/#applying_the_plugin))
|
- Apply the Gradle Enterprise plugin to your build configuration ([see docs](https://docs.gradle.com/enterprise/get-started/#applying_the_plugin))
|
||||||
- Programmatically accept the Terms of Service for scans.gradle.com ([see docs](https://docs.gradle.com/enterprise/gradle-plugin/#connecting_to_scans_gradle_com))
|
- Programmatically accept the Terms of Service for scans.gradle.com ([see docs](https://docs.gradle.com/enterprise/gradle-plugin/#connecting_to_scans_gradle_com))
|
||||||
- Execute the build with `--scan` or configure your build with `publishAlways()` ([see docs](https://docs.gradle.com/enterprise/get-started/#always_publishing_a_build_scan))
|
- Execute the build with `--scan` or configure your build with `publishAlways()` ([see docs](https://docs.gradle.com/enterprise/get-started/#always_publishing_a_build_scan))
|
||||||
|
|
||||||
|
59
action.yml
59
action.yml
@@ -8,6 +8,14 @@ inputs:
|
|||||||
description: Gradle version to use. If specified, this Gradle version will be downloaded, added to the PATH and used for invoking Gradle.
|
description: Gradle version to use. If specified, this Gradle version will be downloaded, added to the PATH and used for invoking Gradle.
|
||||||
required: false
|
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
|
||||||
|
|
||||||
cache-disabled:
|
cache-disabled:
|
||||||
description: When 'true', all caching is disabled. No entries will be written to or read from the cache.
|
description: When 'true', all caching is disabled. No entries will be written to or read from the cache.
|
||||||
required: false
|
required: false
|
||||||
@@ -32,13 +40,6 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
cache-encryption-key:
|
|
||||||
description: |
|
|
||||||
A base64 encoded AES key used to encrypt the configuration-cache data. The key is exported as 'GRADLE_ENCRYPTION_KEY' for later steps.
|
|
||||||
A suitable key can be generated with `openssl rand -base64 16`.
|
|
||||||
Configuration-cache data will not be saved/restored without an encryption key being provided.
|
|
||||||
required: false
|
|
||||||
|
|
||||||
gradle-home-cache-includes:
|
gradle-home-cache-includes:
|
||||||
description: Paths within Gradle User Home to cache.
|
description: Paths within Gradle User Home to cache.
|
||||||
required: false
|
required: false
|
||||||
@@ -58,46 +59,23 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
add-job-summary:
|
|
||||||
description: Specifies when a Job Summary should be inluded in the action results. Valid values are 'never', 'always' (default), and 'on-failure'.
|
|
||||||
required: false
|
|
||||||
default: 'always'
|
|
||||||
|
|
||||||
add-job-summary-as-pr-comment:
|
|
||||||
description: Specifies when each Job Summary should be added as a PR comment. Valid values are 'never' (default), 'always', and 'on-failure'. No action will be taken if the workflow was not triggered from a pull request.
|
|
||||||
required: false
|
|
||||||
default: 'never'
|
|
||||||
|
|
||||||
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', 'generate-and-upload' and 'download-and-submit'.
|
|
||||||
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
|
|
||||||
|
|
||||||
# DEPRECATED ACTION INPUTS
|
|
||||||
arguments:
|
arguments:
|
||||||
description: Gradle command line arguments (supports multi-line input)
|
description: Gradle command line arguments (supports multi-line input)
|
||||||
required: false
|
required: false
|
||||||
deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step. See https://github.com/gradle/gradle-build-action?tab=readme-ov-file#use-the-action-to-setup-gradle.
|
|
||||||
|
|
||||||
build-root-directory:
|
|
||||||
description: Path to the root directory of the build. Default is the root of the GitHub workspace.
|
|
||||||
required: false
|
|
||||||
deprecation-message: Using the action to execute Gradle directly is deprecated in favor of using the action to setup Gradle, and executing Gradle in a subsequent Step. See https://github.com/gradle/gradle-build-action?tab=readme-ov-file#use-the-action-to-setup-gradle.
|
|
||||||
|
|
||||||
generate-job-summary:
|
generate-job-summary:
|
||||||
description: When 'false', no Job Summary will be generated for the Job.
|
description: When 'false', no Job Summary will be generated for the Job.
|
||||||
required: false
|
required: false
|
||||||
default: true
|
default: true
|
||||||
deprecation-message: Superceded by the new 'add-job-summary' and 'add-job-summary-as-pr-comment' parameters.
|
|
||||||
|
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', 'download-and-submit' and 'clear'.
|
||||||
|
required: false
|
||||||
|
default: 'disabled'
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
# 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.
|
||||||
@@ -107,7 +85,6 @@ inputs:
|
|||||||
description: When 'true', the action will not attempt to restore the Gradle User Home entries from other Jobs.
|
description: When 'true', the action will not attempt to restore the Gradle User Home entries from other Jobs.
|
||||||
required: false
|
required: false
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
workflow-job-context:
|
workflow-job-context:
|
||||||
description: Used to uniquely identify the current job invocation. Defaults to the matrix values for this job; this should not be overridden by users (INTERNAL).
|
description: Used to uniquely identify the current job invocation. Defaults to the matrix values for this job; this should not be overridden by users (INTERNAL).
|
||||||
required: false
|
required: false
|
||||||
@@ -127,7 +104,7 @@ outputs:
|
|||||||
description: Version of Gradle that was setup by the action
|
description: Version of Gradle that was setup by the action
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: 'node16'
|
||||||
main: 'dist/main/index.js'
|
main: 'dist/main/index.js'
|
||||||
post: 'dist/post/index.js'
|
post: 'dist/post/index.js'
|
||||||
|
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
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
|
|
60311
dist/main/index.js
vendored
60311
dist/main/index.js
vendored
File diff suppressed because one or more lines are too long
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
59464
dist/post/index.js
vendored
59464
dist/post/index.js
vendored
File diff suppressed because one or more lines are too long
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
4510
package-lock.json
generated
4510
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@@ -8,11 +8,13 @@
|
|||||||
"format": "prettier --write **/*.ts",
|
"format": "prettier --write **/*.ts",
|
||||||
"format-check": "prettier --check **/*.ts",
|
"format-check": "prettier --check **/*.ts",
|
||||||
"lint": "eslint src/**/*.ts",
|
"lint": "eslint src/**/*.ts",
|
||||||
|
|
||||||
"compile-main": "ncc build src/main.ts --out dist/main --source-map --no-source-map-register",
|
"compile-main": "ncc build src/main.ts --out dist/main --source-map --no-source-map-register",
|
||||||
"compile-post": "ncc build src/post.ts --out dist/post --source-map --no-source-map-register",
|
"compile-post": "ncc build src/post.ts --out dist/post --source-map --no-source-map-register",
|
||||||
"compile": "npm-run-all --parallel compile-*",
|
"compile": "npm run compile-main && npm run compile-post",
|
||||||
"check": "npm-run-all --parallel format lint",
|
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
|
"check": "npm run format && npm run lint",
|
||||||
"build": "npm run check && npm run compile",
|
"build": "npm run check && npm run compile",
|
||||||
"all": "npm run build && npm test"
|
"all": "npm run build && npm test"
|
||||||
},
|
},
|
||||||
@@ -28,32 +30,30 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/artifact": "2.0.0",
|
"@actions/artifact": "1.1.2",
|
||||||
"@actions/cache": "3.2.2",
|
"@actions/cache": "3.2.2",
|
||||||
"@actions/core": "1.10.1",
|
"@actions/core": "1.10.1",
|
||||||
"@actions/exec": "1.1.1",
|
"@actions/exec": "1.1.1",
|
||||||
"@actions/github": "6.0.0",
|
"@actions/github": "5.1.1",
|
||||||
"@actions/glob": "0.4.0",
|
"@actions/glob": "0.4.0",
|
||||||
"@actions/http-client": "2.2.0",
|
"@actions/http-client": "2.2.0",
|
||||||
"@actions/tool-cache": "2.0.1",
|
"@actions/tool-cache": "2.0.1",
|
||||||
"@octokit/rest": "19.0.13",
|
"@octokit/rest": "19.0.13",
|
||||||
"@octokit/webhooks-types": "7.3.1",
|
"@octokit/webhooks-types": "7.3.1",
|
||||||
"semver": "7.5.4",
|
|
||||||
"string-argv": "0.3.2"
|
"string-argv": "0.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/node": "16.18.38",
|
||||||
"@types/jest": "29.5.11",
|
"@types/jest": "29.5.11",
|
||||||
"@types/node": "20.10.0",
|
|
||||||
"@types/unzipper": "0.10.9",
|
"@types/unzipper": "0.10.9",
|
||||||
"@typescript-eslint/parser": "6.17.0",
|
"@typescript-eslint/parser": "6.14.0",
|
||||||
"@vercel/ncc": "0.38.1",
|
"@vercel/ncc": "0.38.1",
|
||||||
"eslint": "8.56.0",
|
"eslint": "8.55.0",
|
||||||
"eslint-plugin-github": "4.10.1",
|
"eslint-plugin-github": "4.10.1",
|
||||||
"eslint-plugin-jest": "27.6.1",
|
"eslint-plugin-jest": "27.6.0",
|
||||||
"eslint-plugin-prettier": "5.1.2",
|
"eslint-plugin-prettier": "5.0.1",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"npm-run-all": "4.1.5",
|
|
||||||
"patch-package": "8.0.0",
|
"patch-package": "8.0.0",
|
||||||
"prettier": "3.1.1",
|
"prettier": "3.1.1",
|
||||||
"ts-jest": "29.1.1",
|
"ts-jest": "29.1.1",
|
||||||
|
@@ -1,13 +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 * as glob from '@actions/glob'
|
|
||||||
|
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import * as params from './input-params'
|
import * as params from './input-params'
|
||||||
import {CacheListener} from './cache-reporting'
|
import {CacheListener} from './cache-reporting'
|
||||||
import {saveCache, restoreCache, cacheDebug, isCacheDebuggingEnabled, tryDelete, generateCacheKey} from './cache-utils'
|
import {saveCache, restoreCache, cacheDebug, isCacheDebuggingEnabled, tryDelete, generateCacheKey} from './cache-utils'
|
||||||
import {GradleHomeEntryExtractor, ConfigurationCacheEntryExtractor} from './cache-extract-entries'
|
import {GradleHomeEntryExtractor} from './cache-extract-entries'
|
||||||
|
|
||||||
const RESTORED_CACHE_KEY_KEY = 'restored-cache-key'
|
const RESTORED_CACHE_KEY_KEY = 'restored-cache-key'
|
||||||
|
|
||||||
@@ -17,24 +15,22 @@ export class GradleStateCache {
|
|||||||
private cacheName: string
|
private cacheName: string
|
||||||
private cacheDescription: string
|
private cacheDescription: string
|
||||||
|
|
||||||
protected readonly userHome: string
|
|
||||||
protected readonly gradleUserHome: string
|
protected readonly gradleUserHome: string
|
||||||
|
|
||||||
constructor(userHome: string, gradleUserHome: string) {
|
constructor(gradleUserHome: string) {
|
||||||
this.userHome = userHome
|
|
||||||
this.gradleUserHome = gradleUserHome
|
this.gradleUserHome = gradleUserHome
|
||||||
this.cacheName = 'gradle'
|
this.cacheName = 'gradle'
|
||||||
this.cacheDescription = 'Gradle User Home'
|
this.cacheDescription = 'Gradle User Home'
|
||||||
}
|
}
|
||||||
|
|
||||||
init(): void {
|
init(): void {
|
||||||
this.initializeGradleUserHome()
|
const actionCacheDir = path.resolve(this.gradleUserHome, '.gradle-build-action')
|
||||||
|
fs.mkdirSync(actionCacheDir, {recursive: true})
|
||||||
|
|
||||||
// Export the GRADLE_ENCRYPTION_KEY variable if provided
|
const initScriptsDir = path.resolve(this.gradleUserHome, 'init.d')
|
||||||
const encryptionKey = params.getCacheEncryptionKey()
|
fs.mkdirSync(initScriptsDir, {recursive: true})
|
||||||
if (encryptionKey) {
|
|
||||||
core.exportVariable('GRADLE_ENCRYPTION_KEY', encryptionKey)
|
this.initializeGradleUserHome(this.gradleUserHome, initScriptsDir)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheOutputExists(): boolean {
|
cacheOutputExists(): boolean {
|
||||||
@@ -83,7 +79,7 @@ export class GradleStateCache {
|
|||||||
async afterRestore(listener: CacheListener): Promise<void> {
|
async afterRestore(listener: CacheListener): Promise<void> {
|
||||||
await this.debugReportGradleUserHomeSize('as restored from cache')
|
await this.debugReportGradleUserHomeSize('as restored from cache')
|
||||||
await new GradleHomeEntryExtractor(this.gradleUserHome).restore(listener)
|
await new GradleHomeEntryExtractor(this.gradleUserHome).restore(listener)
|
||||||
await new ConfigurationCacheEntryExtractor(this.gradleUserHome).restore(listener)
|
// await new ConfigurationCacheEntryExtractor(this.gradleUserHome).restore(listener)
|
||||||
await this.debugReportGradleUserHomeSize('after restoring common artifacts')
|
await this.debugReportGradleUserHomeSize('after restoring common artifacts')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,10 +127,10 @@ export class GradleStateCache {
|
|||||||
*/
|
*/
|
||||||
async beforeSave(listener: CacheListener): Promise<void> {
|
async beforeSave(listener: CacheListener): Promise<void> {
|
||||||
await this.debugReportGradleUserHomeSize('before saving common artifacts')
|
await this.debugReportGradleUserHomeSize('before saving common artifacts')
|
||||||
await this.deleteExcludedPaths()
|
this.deleteExcludedPaths()
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
new GradleHomeEntryExtractor(this.gradleUserHome).extract(listener),
|
new GradleHomeEntryExtractor(this.gradleUserHome).extract(listener)
|
||||||
new ConfigurationCacheEntryExtractor(this.gradleUserHome).extract(listener)
|
// new ConfigurationCacheEntryExtractor(this.gradleUserHome).extract(listener)
|
||||||
])
|
])
|
||||||
await this.debugReportGradleUserHomeSize(
|
await this.debugReportGradleUserHomeSize(
|
||||||
"after extracting common artifacts (only 'caches' and 'notifications' will be stored)"
|
"after extracting common artifacts (only 'caches' and 'notifications' will be stored)"
|
||||||
@@ -144,21 +140,13 @@ export class GradleStateCache {
|
|||||||
/**
|
/**
|
||||||
* Delete any file paths that are excluded by the `gradle-home-cache-excludes` parameter.
|
* Delete any file paths that are excluded by the `gradle-home-cache-excludes` parameter.
|
||||||
*/
|
*/
|
||||||
private async deleteExcludedPaths(): Promise<void> {
|
private deleteExcludedPaths(): void {
|
||||||
const rawPaths: string[] = params.getCacheExcludes()
|
const rawPaths: string[] = params.getCacheExcludes()
|
||||||
rawPaths.push('caches/*/cc-keystore')
|
|
||||||
const resolvedPaths = rawPaths.map(x => path.resolve(this.gradleUserHome, x))
|
const resolvedPaths = rawPaths.map(x => path.resolve(this.gradleUserHome, x))
|
||||||
|
|
||||||
for (const p of resolvedPaths) {
|
for (const p of resolvedPaths) {
|
||||||
cacheDebug(`Removing excluded path: ${p}`)
|
cacheDebug(`Deleting excluded path: ${p}`)
|
||||||
const globber = await glob.create(p, {
|
tryDelete(p)
|
||||||
implicitDescendants: false
|
|
||||||
})
|
|
||||||
|
|
||||||
for (const toDelete of await globber.glob()) {
|
|
||||||
cacheDebug(`Removing excluded file: ${toDelete}`)
|
|
||||||
await tryDelete(toDelete)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,59 +171,40 @@ export class GradleStateCache {
|
|||||||
return path.resolve(this.gradleUserHome, rawPath)
|
return path.resolve(this.gradleUserHome, rawPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeGradleUserHome(): void {
|
private initializeGradleUserHome(gradleUserHome: string, initScriptsDir: string): void {
|
||||||
// Create a directory for storing action metadata
|
// Ensure that pre-installed java versions are detected. Only add property if it isn't already defined.
|
||||||
const actionCacheDir = path.resolve(this.gradleUserHome, '.gradle-build-action')
|
const gradleProperties = path.resolve(gradleUserHome, 'gradle.properties')
|
||||||
fs.mkdirSync(actionCacheDir, {recursive: true})
|
const existingGradleProperties = fs.existsSync(gradleProperties)
|
||||||
|
? fs.readFileSync(gradleProperties, 'utf8')
|
||||||
this.copyInitScripts()
|
: ''
|
||||||
|
if (!existingGradleProperties.includes('org.gradle.java.installations.fromEnv=')) {
|
||||||
// Copy the default toolchain definitions to `~/.m2/toolchains.xml`
|
fs.appendFileSync(
|
||||||
this.registerToolchains()
|
gradleProperties,
|
||||||
|
`
|
||||||
|
# Auto-detect pre-installed JDKs
|
||||||
|
org.gradle.java.installations.fromEnv=JAVA_HOME_8_X64,JAVA_HOME_11_X64,JAVA_HOME_17_X64
|
||||||
|
`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private copyInitScripts(): void {
|
// Copy init scripts from src/resources
|
||||||
// Copy init scripts from src/resources to Gradle UserHome
|
|
||||||
const initScriptsDir = path.resolve(this.gradleUserHome, 'init.d')
|
|
||||||
fs.mkdirSync(initScriptsDir, {recursive: true})
|
|
||||||
const initScriptFilenames = [
|
const initScriptFilenames = [
|
||||||
'gradle-build-action.build-result-capture.init.gradle',
|
'gradle-build-action.build-result-capture.init.gradle',
|
||||||
'gradle-build-action.build-result-capture-service.plugin.groovy',
|
'gradle-build-action.build-result-capture-service.plugin.groovy',
|
||||||
'gradle-build-action.github-dependency-graph.init.gradle',
|
'gradle-build-action.github-dependency-graph.init.gradle',
|
||||||
'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy',
|
'gradle-build-action.github-dependency-graph-gradle-plugin-apply.groovy',
|
||||||
'gradle-build-action.inject-develocity.init.gradle'
|
'gradle-build-action.inject-gradle-enterprise.init.gradle'
|
||||||
]
|
]
|
||||||
for (const initScriptFilename of initScriptFilenames) {
|
for (const initScriptFilename of initScriptFilenames) {
|
||||||
const initScriptContent = this.readResourceFileAsString('init-scripts', initScriptFilename)
|
const initScriptContent = this.readInitScriptAsString(initScriptFilename)
|
||||||
const initScriptPath = path.resolve(initScriptsDir, initScriptFilename)
|
const initScriptPath = path.resolve(initScriptsDir, initScriptFilename)
|
||||||
fs.writeFileSync(initScriptPath, initScriptContent)
|
fs.writeFileSync(initScriptPath, initScriptContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerToolchains(): void {
|
private readInitScriptAsString(resource: string): string {
|
||||||
const preInstalledToolchains = this.readResourceFileAsString('toolchains.xml')
|
|
||||||
const m2dir = path.resolve(this.userHome, '.m2')
|
|
||||||
const toolchainXmlTarget = path.resolve(m2dir, 'toolchains.xml')
|
|
||||||
if (!fs.existsSync(toolchainXmlTarget)) {
|
|
||||||
// Write a new toolchains.xml file if it doesn't exist
|
|
||||||
fs.mkdirSync(m2dir, {recursive: true})
|
|
||||||
fs.writeFileSync(toolchainXmlTarget, preInstalledToolchains)
|
|
||||||
|
|
||||||
core.info(`Wrote default JDK locations to ${toolchainXmlTarget}`)
|
|
||||||
} else {
|
|
||||||
// Merge into an existing toolchains.xml file
|
|
||||||
const existingToolchainContent = fs.readFileSync(toolchainXmlTarget, 'utf8')
|
|
||||||
const appendedContent = preInstalledToolchains.split('<toolchains>').pop()!
|
|
||||||
const mergedContent = existingToolchainContent.replace('</toolchains>', appendedContent)
|
|
||||||
|
|
||||||
fs.writeFileSync(toolchainXmlTarget, mergedContent)
|
|
||||||
core.info(`Merged default JDK locations into ${toolchainXmlTarget}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readResourceFileAsString(...paths: string[]): string {
|
|
||||||
// Resolving relative to __dirname will allow node to find the resource at runtime
|
// Resolving relative to __dirname will allow node to find the resource at runtime
|
||||||
const absolutePath = path.resolve(__dirname, '..', '..', 'src', 'resources', ...paths)
|
const absolutePath = path.resolve(__dirname, '..', '..', 'src', 'resources', 'init-scripts', resource)
|
||||||
return fs.readFileSync(absolutePath, 'utf8')
|
return fs.readFileSync(absolutePath, 'utf8')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,14 +2,13 @@ import path from 'path'
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as glob from '@actions/glob'
|
import * as glob from '@actions/glob'
|
||||||
import * as semver from 'semver'
|
|
||||||
|
|
||||||
import * as params from './input-params'
|
import * as params from './input-params'
|
||||||
|
|
||||||
import {META_FILE_DIR} from './cache-base'
|
import {META_FILE_DIR} from './cache-base'
|
||||||
import {CacheEntryListener, CacheListener} from './cache-reporting'
|
import {CacheEntryListener, CacheListener} from './cache-reporting'
|
||||||
import {cacheDebug, getCacheKeyPrefix, hashFileNames, restoreCache, saveCache, tryDelete} from './cache-utils'
|
import {cacheDebug, getCacheKeyPrefix, hashFileNames, restoreCache, saveCache, tryDelete} from './cache-utils'
|
||||||
import {BuildResult, loadBuildResults} from './build-results'
|
import {loadBuildResults} from './build-results'
|
||||||
|
|
||||||
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE'
|
const SKIP_RESTORE_VAR = 'GRADLE_BUILD_ACTION_SKIP_RESTORE'
|
||||||
|
|
||||||
@@ -47,7 +46,6 @@ class ExtractedCacheEntryDefinition {
|
|||||||
pattern: string
|
pattern: string
|
||||||
bundle: boolean
|
bundle: boolean
|
||||||
uniqueFileNames = true
|
uniqueFileNames = true
|
||||||
notCacheableReason: string | undefined
|
|
||||||
|
|
||||||
constructor(artifactType: string, pattern: string, bundle: boolean) {
|
constructor(artifactType: string, pattern: string, bundle: boolean) {
|
||||||
this.artifactType = artifactType
|
this.artifactType = artifactType
|
||||||
@@ -55,24 +53,10 @@ class ExtractedCacheEntryDefinition {
|
|||||||
this.bundle = bundle
|
this.bundle = bundle
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicate that the file names matching the cache entry pattern are NOT sufficient to uniquely identify the contents.
|
|
||||||
* If the file names are sufficient, then we use a hash of the file names to identify the entry.
|
|
||||||
* With non-unique-file-names, we hash the file contents to identify the cache entry.
|
|
||||||
*/
|
|
||||||
withNonUniqueFileNames(): ExtractedCacheEntryDefinition {
|
withNonUniqueFileNames(): ExtractedCacheEntryDefinition {
|
||||||
this.uniqueFileNames = false
|
this.uniqueFileNames = false
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify that the cache entry, should not be saved for some reason, even though the contents exist.
|
|
||||||
* This is used to prevent configuration-cache entries being cached when they were generated by Gradle < 8.6,
|
|
||||||
*/
|
|
||||||
notCacheableBecause(reason: string): ExtractedCacheEntryDefinition {
|
|
||||||
this.notCacheableReason = reason
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -158,11 +142,6 @@ abstract class AbstractEntryExtractor {
|
|||||||
const artifactType = cacheEntryDefinition.artifactType
|
const artifactType = cacheEntryDefinition.artifactType
|
||||||
const pattern = cacheEntryDefinition.pattern
|
const pattern = cacheEntryDefinition.pattern
|
||||||
|
|
||||||
if (cacheEntryDefinition.notCacheableReason) {
|
|
||||||
listener.entry(pattern).markNotSaved(cacheEntryDefinition.notCacheableReason)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all matching files for this cache entry definition
|
// Find all matching files for this cache entry definition
|
||||||
const globber = await glob.create(pattern, {
|
const globber = await glob.create(pattern, {
|
||||||
implicitDescendants: false
|
implicitDescendants: false
|
||||||
@@ -277,7 +256,7 @@ abstract class AbstractEntryExtractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const filedata = fs.readFileSync(cacheMetadataFile, 'utf-8')
|
const filedata = fs.readFileSync(cacheMetadataFile, 'utf-8')
|
||||||
cacheDebug(`Loaded cache metadata for ${this.extractorName}: ${filedata}`)
|
cacheDebug(`Loaded cache metadata: ${filedata}`)
|
||||||
const extractedCacheEntryMetadata = JSON.parse(filedata) as ExtractedCacheEntryMetadata
|
const extractedCacheEntryMetadata = JSON.parse(filedata) as ExtractedCacheEntryMetadata
|
||||||
return extractedCacheEntryMetadata.entries
|
return extractedCacheEntryMetadata.entries
|
||||||
}
|
}
|
||||||
@@ -285,12 +264,12 @@ abstract class AbstractEntryExtractor {
|
|||||||
/**
|
/**
|
||||||
* Saves information about the extracted cache entries into the 'cache-metadata.json' file.
|
* Saves information about the extracted cache entries into the 'cache-metadata.json' file.
|
||||||
*/
|
*/
|
||||||
protected saveMetadataForCacheResults(results: ExtractedCacheEntry[]): void {
|
private saveMetadataForCacheResults(results: ExtractedCacheEntry[]): void {
|
||||||
const extractedCacheEntryMetadata = new ExtractedCacheEntryMetadata()
|
const extractedCacheEntryMetadata = new ExtractedCacheEntryMetadata()
|
||||||
extractedCacheEntryMetadata.entries = results.filter(x => x.cacheKey !== undefined)
|
extractedCacheEntryMetadata.entries = results.filter(x => x.cacheKey !== undefined)
|
||||||
|
|
||||||
const filedata = JSON.stringify(extractedCacheEntryMetadata)
|
const filedata = JSON.stringify(extractedCacheEntryMetadata)
|
||||||
cacheDebug(`Saving cache metadata for ${this.extractorName}: ${filedata}`)
|
cacheDebug(`Saving cache metadata: ${filedata}`)
|
||||||
|
|
||||||
fs.writeFileSync(this.getCacheMetadataFile(), filedata, 'utf-8')
|
fs.writeFileSync(this.getCacheMetadataFile(), filedata, 'utf-8')
|
||||||
}
|
}
|
||||||
@@ -372,96 +351,37 @@ export class ConfigurationCacheEntryExtractor extends AbstractEntryExtractor {
|
|||||||
* entry is not reusable.
|
* entry is not reusable.
|
||||||
*/
|
*/
|
||||||
async restore(listener: CacheListener): Promise<void> {
|
async restore(listener: CacheListener): Promise<void> {
|
||||||
if (!listener.fullyRestored) {
|
if (listener.fullyRestored) {
|
||||||
this.markNotRestored(listener, 'Gradle User Home was not fully restored')
|
return super.restore(listener)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.getCacheEncryptionKey()) {
|
core.info('Not restoring configuration-cache state, as Gradle User Home was not fully restored')
|
||||||
this.markNotRestored(listener, 'Encryption Key was not provided')
|
for (const cacheEntry of this.loadExtractedCacheEntries()) {
|
||||||
return
|
listener.entry(cacheEntry.pattern).markRequested('NOT_RESTORED')
|
||||||
}
|
}
|
||||||
|
|
||||||
return await super.restore(listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
private markNotRestored(listener: CacheListener, reason: string): void {
|
|
||||||
const cacheEntries = this.loadExtractedCacheEntries()
|
|
||||||
if (cacheEntries.length > 0) {
|
|
||||||
core.info(`Not restoring configuration-cache state, as ${reason}`)
|
|
||||||
for (const cacheEntry of cacheEntries) {
|
|
||||||
listener.entry(cacheEntry.pattern).markNotRestored(reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the results file based on no entries restored
|
|
||||||
this.saveMetadataForCacheResults([])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async extract(listener: CacheListener): Promise<void> {
|
|
||||||
if (!params.getCacheEncryptionKey()) {
|
|
||||||
const cacheEntryDefinitions = this.getExtractedCacheEntryDefinitions()
|
|
||||||
if (cacheEntryDefinitions.length > 0) {
|
|
||||||
core.info('Not saving configuration-cache state, as no encryption key was provided')
|
|
||||||
for (const cacheEntry of cacheEntryDefinitions) {
|
|
||||||
listener.entry(cacheEntry.pattern).markNotSaved('No encryption key provided')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
await super.extract(listener)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract cache entries for the configuration cache in each project.
|
* Extract cache entries for the configuration cache in each project.
|
||||||
*/
|
*/
|
||||||
protected getExtractedCacheEntryDefinitions(): ExtractedCacheEntryDefinition[] {
|
protected getExtractedCacheEntryDefinitions(): ExtractedCacheEntryDefinition[] {
|
||||||
// Group BuildResult by existing configCacheDir
|
return this.getProjectRoots().map(projectRoot => {
|
||||||
const groupedResults = this.getConfigCacheDirectoriesWithAssociatedBuildResults()
|
const configCachePath = path.resolve(projectRoot, '.gradle/configuration-cache')
|
||||||
|
return new ExtractedCacheEntryDefinition(
|
||||||
return Object.entries(groupedResults).map(([configCachePath, pathResults]) => {
|
|
||||||
// Create a entry definition for each unique configuration cache directory
|
|
||||||
const definition = new ExtractedCacheEntryDefinition(
|
|
||||||
'configuration-cache',
|
'configuration-cache',
|
||||||
configCachePath,
|
configCachePath,
|
||||||
true
|
true
|
||||||
).withNonUniqueFileNames()
|
).withNonUniqueFileNames()
|
||||||
|
|
||||||
// If any associated build result used Gradle < 8.6, then mark it as not cacheable
|
|
||||||
if (
|
|
||||||
pathResults.find(result => {
|
|
||||||
const gradleVersion = semver.coerce(result.gradleVersion)
|
|
||||||
return gradleVersion && semver.lt(gradleVersion, '8.6.0')
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
core.info(
|
|
||||||
`Not saving config-cache data for ${configCachePath}. Configuration cache data is only saved for Gradle 8.6+`
|
|
||||||
)
|
|
||||||
definition.notCacheableBecause('Configuration cache data only saved for Gradle 8.6+')
|
|
||||||
}
|
|
||||||
return definition
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private getConfigCacheDirectoriesWithAssociatedBuildResults(): Record<string, BuildResult[]> {
|
/**
|
||||||
return loadBuildResults().reduce(
|
* For every Gradle invocation, we record the project root directory. This method returns the entire
|
||||||
(acc, buildResult) => {
|
* set of project roots, to allow saving of configuration-cache entries for each.
|
||||||
// For each build result, find the config-cache dir
|
*/
|
||||||
const configCachePath = path.resolve(buildResult.rootProjectDir, '.gradle/configuration-cache')
|
private getProjectRoots(): string[] {
|
||||||
// Ignore case where config-cache dir doesn't exist
|
const buildResults = loadBuildResults()
|
||||||
if (!fs.existsSync(configCachePath)) {
|
const projectRootDirs = buildResults.map(x => x.rootProjectDir)
|
||||||
return acc
|
return [...new Set(projectRootDirs)] // Remove duplicates
|
||||||
}
|
|
||||||
|
|
||||||
// Group by unique config cache directories and collect associated build results
|
|
||||||
if (!acc[configCachePath]) {
|
|
||||||
acc[configCachePath] = []
|
|
||||||
}
|
|
||||||
acc[configCachePath].push(buildResult)
|
|
||||||
return acc
|
|
||||||
},
|
|
||||||
{} as Record<string, BuildResult[]>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import * as core from '@actions/core'
|
||||||
import * as cache from '@actions/cache'
|
import * as cache from '@actions/cache'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,36 +112,47 @@ export class CacheEntryListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateCachingReport(listener: CacheListener): string {
|
export function writeCachingReport(listener: CacheListener): void {
|
||||||
const entries = listener.cacheEntries
|
const entries = listener.cacheEntries
|
||||||
|
|
||||||
return `
|
core.summary.addRaw(
|
||||||
<details>
|
`\n<details><summary><h4>Caching for gradle-build-action was ${listener.cacheStatus} - expand for details</h4></summary>\n`
|
||||||
<summary><h4>Caching for gradle-build-action was ${listener.cacheStatus} - expand for details</h4></summary>
|
)
|
||||||
${renderEntryTable(entries)}
|
|
||||||
|
|
||||||
<h5>Cache Entry Details</h5>
|
core.summary.addTable([
|
||||||
<pre>
|
[
|
||||||
${renderEntryDetails(listener)}
|
{data: '', header: true},
|
||||||
|
{data: 'Count', header: true},
|
||||||
|
{data: 'Total Size (Mb)', header: true}
|
||||||
|
],
|
||||||
|
['Entries Restored', `${getCount(entries, e => e.restoredSize)}`, `${getSize(entries, e => e.restoredSize)}`],
|
||||||
|
['Entries Saved', `${getCount(entries, e => e.savedSize)}`, `${getSize(entries, e => e.savedSize)}`]
|
||||||
|
])
|
||||||
|
|
||||||
|
core.summary.addHeading('Cache Entry Details', 5)
|
||||||
|
|
||||||
|
const entryDetails = renderEntryDetails(listener)
|
||||||
|
core.summary.addRaw(`<pre>
|
||||||
|
${entryDetails}
|
||||||
</pre>
|
</pre>
|
||||||
</details>
|
</details>
|
||||||
`
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEntryTable(entries: CacheEntryListener[]): string {
|
export function logCachingReport(listener: CacheListener): void {
|
||||||
return `
|
const entries = listener.cacheEntries
|
||||||
<table>
|
|
||||||
<tr><td></td><th>Count</th><th>Total Size (Mb)</th></tr>
|
core.startGroup(`Caching for gradle-build-action was ${listener.cacheStatus} - expand for details`)
|
||||||
<tr><td>Entries Restored</td>
|
|
||||||
<td>${getCount(entries, e => e.restoredSize)}</td>
|
core.info(
|
||||||
<td>${getSize(entries, e => e.restoredSize)}</td>
|
`Entries Restored: ${getCount(entries, e => e.restoredSize)} (${getSize(entries, e => e.restoredSize)} Mb)`
|
||||||
</tr>
|
)
|
||||||
<tr><td>Entries Saved</td>
|
core.info(`Entries Saved : ${getCount(entries, e => e.savedSize)} (${getSize(entries, e => e.savedSize)} Mb)`)
|
||||||
<td>${getCount(entries, e => e.savedSize)}</td>
|
|
||||||
<td>${getSize(entries, e => e.savedSize)}</td>
|
core.info(`Cache Entry Details`)
|
||||||
</tr>
|
core.info(renderEntryDetails(listener))
|
||||||
</table>
|
|
||||||
`
|
core.endGroup()
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderEntryDetails(listener: CacheListener): string {
|
function renderEntryDetails(listener: CacheListener): string {
|
||||||
@@ -186,9 +198,6 @@ function getSavedMessage(entry: CacheEntryListener, cacheReadOnly: boolean): str
|
|||||||
if (cacheReadOnly) {
|
if (cacheReadOnly) {
|
||||||
return '(Entry not saved: cache is read-only)'
|
return '(Entry not saved: cache is read-only)'
|
||||||
}
|
}
|
||||||
if (entry.notRestored) {
|
|
||||||
return '(Entry not saved: not restored)'
|
|
||||||
}
|
|
||||||
return '(Entry not saved: reason unknown)'
|
return '(Entry not saved: reason unknown)'
|
||||||
}
|
}
|
||||||
if (entry.savedSize === 0) {
|
if (entry.savedSize === 0) {
|
||||||
|
@@ -11,7 +11,7 @@ import * as params from './input-params'
|
|||||||
|
|
||||||
import {CacheEntryListener} from './cache-reporting'
|
import {CacheEntryListener} from './cache-reporting'
|
||||||
|
|
||||||
const CACHE_PROTOCOL_VERSION = 'v9-'
|
const CACHE_PROTOCOL_VERSION = 'v8-'
|
||||||
|
|
||||||
const CACHE_KEY_PREFIX_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX'
|
const CACHE_KEY_PREFIX_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX'
|
||||||
const CACHE_KEY_OS_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_ENVIRONMENT'
|
const CACHE_KEY_OS_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_ENVIRONMENT'
|
||||||
@@ -86,10 +86,10 @@ export function generateCacheKey(cacheName: string): CacheKey {
|
|||||||
// At the most general level, share caches for all executions on the same OS
|
// At the most general level, share caches for all executions on the same OS
|
||||||
const cacheKeyForEnvironment = `${cacheKeyBase}|${getCacheKeyEnvironment()}`
|
const cacheKeyForEnvironment = `${cacheKeyBase}|${getCacheKeyEnvironment()}`
|
||||||
|
|
||||||
// Then prefer caches that run job with the same ID
|
// Prefer caches that run this job
|
||||||
const cacheKeyForJob = `${cacheKeyForEnvironment}|${getCacheKeyJob()}`
|
const cacheKeyForJob = `${cacheKeyForEnvironment}|${getCacheKeyJob()}`
|
||||||
|
|
||||||
// Prefer (even more) jobs that run this job in the same workflow with the same context (matrix)
|
// Prefer (even more) jobs that run this job with the same context (matrix)
|
||||||
const cacheKeyForJobContext = `${cacheKeyForJob}[${getCacheKeyJobInstance()}]`
|
const cacheKeyForJobContext = `${cacheKeyForJob}[${getCacheKeyJobInstance()}]`
|
||||||
|
|
||||||
// Exact match on Git SHA
|
// Exact match on Git SHA
|
||||||
@@ -113,7 +113,12 @@ function getCacheKeyEnvironment(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getCacheKeyJob(): string {
|
function getCacheKeyJob(): string {
|
||||||
return process.env[CACHE_KEY_JOB_VAR] || github.context.job
|
return process.env[CACHE_KEY_JOB_VAR] || getCacheKeyForJob(github.context.workflow, github.context.job)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCacheKeyForJob(workflowName: string, jobId: string): string {
|
||||||
|
const sanitizedWorkflow = workflowName.replace(/,/g, '').toLowerCase()
|
||||||
|
return `${sanitizedWorkflow}-${jobId}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCacheKeyJobInstance(): string {
|
function getCacheKeyJobInstance(): string {
|
||||||
@@ -122,11 +127,25 @@ function getCacheKeyJobInstance(): string {
|
|||||||
return override
|
return override
|
||||||
}
|
}
|
||||||
|
|
||||||
// By default, we hash the workflow name and 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 workflowName = github.context.workflow
|
|
||||||
const workflowJobContext = params.getJobMatrix()
|
const workflowJobContext = params.getJobMatrix()
|
||||||
return hashStrings([workflowName, 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 {
|
||||||
|
@@ -13,7 +13,7 @@ import {CacheCleaner} from './cache-cleaner'
|
|||||||
|
|
||||||
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
const CACHE_RESTORED_VAR = 'GRADLE_BUILD_ACTION_CACHE_RESTORED'
|
||||||
|
|
||||||
export async function restore(userHome: string, gradleUserHome: string, cacheListener: CacheListener): Promise<void> {
|
export async function restore(gradleUserHome: string, cacheListener: CacheListener): Promise<void> {
|
||||||
// Bypass restore cache on all but first action step in workflow.
|
// Bypass restore cache on all but first action step in workflow.
|
||||||
if (process.env[CACHE_RESTORED_VAR]) {
|
if (process.env[CACHE_RESTORED_VAR]) {
|
||||||
core.info('Cache only restored on first action step.')
|
core.info('Cache only restored on first action step.')
|
||||||
@@ -21,7 +21,7 @@ export async function restore(userHome: string, gradleUserHome: string, cacheLis
|
|||||||
}
|
}
|
||||||
core.exportVariable(CACHE_RESTORED_VAR, true)
|
core.exportVariable(CACHE_RESTORED_VAR, true)
|
||||||
|
|
||||||
const gradleStateCache = new GradleStateCache(userHome, gradleUserHome)
|
const gradleStateCache = new GradleStateCache(gradleUserHome)
|
||||||
|
|
||||||
if (isCacheDisabled()) {
|
if (isCacheDisabled()) {
|
||||||
core.info('Cache is disabled: will not restore state from previous builds.')
|
core.info('Cache is disabled: will not restore state from previous builds.')
|
||||||
@@ -65,7 +65,6 @@ export async function restore(userHome: string, gradleUserHome: string, cacheLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function save(
|
export async function save(
|
||||||
userHome: string,
|
|
||||||
gradleUserHome: string,
|
gradleUserHome: string,
|
||||||
cacheListener: CacheListener,
|
cacheListener: CacheListener,
|
||||||
daemonController: DaemonController
|
daemonController: DaemonController
|
||||||
@@ -99,6 +98,6 @@ export async function save(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await core.group('Caching Gradle state', async () => {
|
await core.group('Caching Gradle state', async () => {
|
||||||
return new GradleStateCache(userHome, gradleUserHome).save(cacheListener)
|
return new GradleStateCache(gradleUserHome).save(cacheListener)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
|
import * as artifact from '@actions/artifact'
|
||||||
import * as github from '@actions/github'
|
import * as github from '@actions/github'
|
||||||
import * as glob from '@actions/glob'
|
import * as glob from '@actions/glob'
|
||||||
import {DefaultArtifactClient} from '@actions/artifact'
|
import * as toolCache from '@actions/tool-cache'
|
||||||
import {GitHub} from '@actions/github/lib/utils'
|
import {GitHub} from '@actions/github/lib/utils'
|
||||||
import {RequestError} from '@octokit/request-error'
|
import {RequestError} from '@octokit/request-error'
|
||||||
import type {PullRequestEvent} from '@octokit/webhooks-types'
|
import type {PullRequestEvent} from '@octokit/webhooks-types'
|
||||||
@@ -10,15 +11,9 @@ import * as path from 'path'
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
|
||||||
import * as layout from './repository-layout'
|
import * as layout from './repository-layout'
|
||||||
import {PostActionJobFailure} from './errors'
|
import {DependencyGraphOption, getJobMatrix, getArtifactRetentionDays} from './input-params'
|
||||||
import {
|
|
||||||
DependencyGraphOption,
|
|
||||||
getDependencyGraphContinueOnFailure,
|
|
||||||
getJobMatrix,
|
|
||||||
getArtifactRetentionDays
|
|
||||||
} from './input-params'
|
|
||||||
|
|
||||||
const DEPENDENCY_GRAPH_PREFIX = 'dependency-graph_'
|
const DEPENDENCY_GRAPH_ARTIFACT = 'dependency-graph'
|
||||||
|
|
||||||
export async function setup(option: DependencyGraphOption): Promise<void> {
|
export async function setup(option: DependencyGraphOption): Promise<void> {
|
||||||
if (option === DependencyGraphOption.Disabled) {
|
if (option === DependencyGraphOption.Disabled) {
|
||||||
@@ -31,68 +26,57 @@ export async function setup(option: DependencyGraphOption): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
core.info('Enabling dependency graph generation')
|
core.info('Enabling dependency graph generation')
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED', 'true')
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', getDependencyGraphContinueOnFailure())
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator())
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR', getJobCorrelator())
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_JOB_ID', github.context.runId)
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_REF', github.context.ref)
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_SHA', getShaFromContext())
|
core.exportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory())
|
||||||
maybeExportVariable('GITHUB_DEPENDENCY_GRAPH_WORKSPACE', layout.workspaceDirectory())
|
core.exportVariable(
|
||||||
maybeExportVariable(
|
|
||||||
'DEPENDENCY_GRAPH_REPORT_DIR',
|
'DEPENDENCY_GRAPH_REPORT_DIR',
|
||||||
path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports')
|
path.resolve(layout.workspaceDirectory(), 'dependency-graph-reports')
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
function maybeExportVariable(variableName: string, value: unknown): void {
|
// To clear the dependency graph, we generate an empty graph by excluding all projects and configurations
|
||||||
if (!process.env[variableName]) {
|
if (option === DependencyGraphOption.Clear) {
|
||||||
core.exportVariable(variableName, value)
|
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_PROJECTS', '')
|
||||||
|
core.exportVariable('DEPENDENCY_GRAPH_INCLUDE_CONFIGURATIONS', '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function complete(option: DependencyGraphOption): Promise<void> {
|
export async function complete(option: DependencyGraphOption): Promise<void> {
|
||||||
try {
|
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case DependencyGraphOption.Disabled:
|
case DependencyGraphOption.Disabled:
|
||||||
case DependencyGraphOption.Generate: // Performed via init-script: nothing to do here
|
|
||||||
case DependencyGraphOption.DownloadAndSubmit: // Performed in setup
|
case DependencyGraphOption.DownloadAndSubmit: // Performed in setup
|
||||||
return
|
return
|
||||||
case DependencyGraphOption.GenerateAndSubmit:
|
case DependencyGraphOption.Generate:
|
||||||
await submitDependencyGraphs(await findGeneratedDependencyGraphFiles())
|
await uploadDependencyGraphs()
|
||||||
|
return
|
||||||
|
case DependencyGraphOption.GenerateAndSubmit:
|
||||||
|
case DependencyGraphOption.Clear: // Submit the empty dependency graph
|
||||||
|
await submitDependencyGraphs(await uploadDependencyGraphs())
|
||||||
return
|
return
|
||||||
case DependencyGraphOption.GenerateAndUpload:
|
|
||||||
await uploadDependencyGraphs(await findGeneratedDependencyGraphFiles())
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
warnOrFail(option, e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findGeneratedDependencyGraphFiles(): Promise<string[]> {
|
async function uploadDependencyGraphs(): Promise<string[]> {
|
||||||
const workspaceDirectory = layout.workspaceDirectory()
|
const workspaceDirectory = layout.workspaceDirectory()
|
||||||
return await findDependencyGraphFiles(workspaceDirectory)
|
const graphFiles = await findDependencyGraphFiles(workspaceDirectory)
|
||||||
}
|
|
||||||
|
|
||||||
async function uploadDependencyGraphs(dependencyGraphFiles: string[]): Promise<void> {
|
const relativeGraphFiles = graphFiles.map(x => getRelativePathFromWorkspace(x))
|
||||||
const workspaceDirectory = layout.workspaceDirectory()
|
core.info(`Uploading dependency graph files: ${relativeGraphFiles}`)
|
||||||
|
|
||||||
const artifactClient = new DefaultArtifactClient()
|
const artifactClient = artifact.create()
|
||||||
for (const dependencyGraphFile of dependencyGraphFiles) {
|
artifactClient.uploadArtifact(DEPENDENCY_GRAPH_ARTIFACT, graphFiles, workspaceDirectory, {
|
||||||
const relativePath = getRelativePathFromWorkspace(dependencyGraphFile)
|
|
||||||
core.info(`Uploading dependency graph file: ${relativePath}`)
|
|
||||||
const artifactName = `${DEPENDENCY_GRAPH_PREFIX}${path.basename(dependencyGraphFile)}`
|
|
||||||
await artifactClient.uploadArtifact(artifactName, [dependencyGraphFile], workspaceDirectory, {
|
|
||||||
retentionDays: getArtifactRetentionDays()
|
retentionDays: getArtifactRetentionDays()
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
return graphFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadAndSubmitDependencyGraphs(): Promise<void> {
|
async function downloadAndSubmitDependencyGraphs(): Promise<void> {
|
||||||
try {
|
const workspaceDirectory = layout.workspaceDirectory()
|
||||||
await submitDependencyGraphs(await downloadDependencyGraphs())
|
submitDependencyGraphs(await retrieveDependencyGraphs(workspaceDirectory))
|
||||||
} catch (e) {
|
|
||||||
warnOrFail(DependencyGraphOption.DownloadAndSubmit, e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<void> {
|
async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<void> {
|
||||||
@@ -101,7 +85,7 @@ async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<v
|
|||||||
await submitDependencyGraphFile(jsonFile)
|
await submitDependencyGraphFile(jsonFile)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof RequestError) {
|
if (error instanceof RequestError) {
|
||||||
throw new Error(translateErrorMessage(jsonFile, error))
|
core.warning(buildWarningMessage(jsonFile, error))
|
||||||
} else {
|
} else {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
@@ -109,9 +93,9 @@ async function submitDependencyGraphs(dependencyGraphFiles: string[]): Promise<v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function translateErrorMessage(jsonFile: string, error: RequestError): string {
|
function buildWarningMessage(jsonFile: string, error: RequestError): string {
|
||||||
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
|
const relativeJsonFile = getRelativePathFromWorkspace(jsonFile)
|
||||||
const mainWarning = `Dependency submission failed for ${relativeJsonFile}.\n${String(error)}`
|
const mainWarning = `Failed to submit dependency graph ${relativeJsonFile}.\n${String(error)}`
|
||||||
if (error.message === 'Resource not accessible by integration') {
|
if (error.message === 'Resource not accessible by integration') {
|
||||||
return `${mainWarning}
|
return `${mainWarning}
|
||||||
Please ensure that the 'contents: write' permission is available for the workflow job.
|
Please ensure that the 'contents: write' permission is available for the workflow job.
|
||||||
@@ -134,37 +118,56 @@ async function submitDependencyGraphFile(jsonFile: string): Promise<void> {
|
|||||||
core.notice(`Submitted ${relativeJsonFile}: ${response.data.message}`)
|
core.notice(`Submitted ${relativeJsonFile}: ${response.data.message}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function downloadDependencyGraphs(): Promise<string[]> {
|
async function retrieveDependencyGraphs(workspaceDirectory: string): Promise<string[]> {
|
||||||
const workspaceDirectory = layout.workspaceDirectory()
|
if (github.context.payload.workflow_run) {
|
||||||
|
return await retrieveDependencyGraphsForWorkflowRun(github.context.payload.workflow_run.id, workspaceDirectory)
|
||||||
const findBy = github.context.payload.workflow_run
|
}
|
||||||
? {
|
return retrieveDependencyGraphsForCurrentWorkflow(workspaceDirectory)
|
||||||
token: getGithubToken(),
|
|
||||||
workflowRunId: github.context.payload.workflow_run.id,
|
|
||||||
repositoryName: github.context.repo.repo,
|
|
||||||
repositoryOwner: github.context.repo.owner
|
|
||||||
}
|
}
|
||||||
: undefined
|
|
||||||
|
|
||||||
const artifactClient = new DefaultArtifactClient()
|
async function retrieveDependencyGraphsForWorkflowRun(runId: number, workspaceDirectory: string): Promise<string[]> {
|
||||||
|
const octokit = getOctokit()
|
||||||
|
|
||||||
|
// Find the workflow run artifacts named "dependency-graph"
|
||||||
|
const artifacts = await octokit.rest.actions.listWorkflowRunArtifacts({
|
||||||
|
owner: github.context.repo.owner,
|
||||||
|
repo: github.context.repo.repo,
|
||||||
|
run_id: runId
|
||||||
|
})
|
||||||
|
|
||||||
|
const matchArtifact = artifacts.data.artifacts.find(candidate => {
|
||||||
|
return candidate.name === DEPENDENCY_GRAPH_ARTIFACT
|
||||||
|
})
|
||||||
|
|
||||||
|
if (matchArtifact === undefined) {
|
||||||
|
throw new Error(`Dependency graph artifact not found. Has it been generated by workflow run '${runId}'?`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download the dependency-graph artifact
|
||||||
|
const download = await octokit.rest.actions.downloadArtifact({
|
||||||
|
owner: github.context.repo.owner,
|
||||||
|
repo: github.context.repo.repo,
|
||||||
|
artifact_id: matchArtifact.id,
|
||||||
|
archive_format: 'zip'
|
||||||
|
})
|
||||||
|
|
||||||
|
const downloadBuffer = download.data as ArrayBuffer
|
||||||
|
const downloadZip = path.resolve(workspaceDirectory, 'dependency-graph.zip')
|
||||||
|
fs.writeFileSync(downloadZip, Buffer.from(downloadBuffer))
|
||||||
|
|
||||||
|
// Expance the dependency-graph zip and locate each dependency-graph JSON file
|
||||||
|
const extractDir = path.resolve(workspaceDirectory, 'dependency-graph')
|
||||||
|
const extracted = await toolCache.extractZip(downloadZip, extractDir)
|
||||||
|
core.info(`Extracted dependency graph artifacts to ${extracted}: ${fs.readdirSync(extracted)}`)
|
||||||
|
|
||||||
|
return findDependencyGraphFiles(extracted)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function retrieveDependencyGraphsForCurrentWorkflow(workspaceDirectory: string): Promise<string[]> {
|
||||||
|
const artifactClient = artifact.create()
|
||||||
const downloadPath = path.resolve(workspaceDirectory, 'dependency-graph')
|
const downloadPath = path.resolve(workspaceDirectory, 'dependency-graph')
|
||||||
|
await artifactClient.downloadArtifact(DEPENDENCY_GRAPH_ARTIFACT, downloadPath)
|
||||||
const dependencyGraphArtifacts = (
|
return await findDependencyGraphFiles(downloadPath)
|
||||||
await artifactClient.listArtifacts({
|
|
||||||
latest: true,
|
|
||||||
findBy
|
|
||||||
})
|
|
||||||
).artifacts.filter(candidate => candidate.name.startsWith(DEPENDENCY_GRAPH_PREFIX))
|
|
||||||
|
|
||||||
for (const artifact of dependencyGraphArtifacts) {
|
|
||||||
const downloadedArtifact = await artifactClient.downloadArtifact(artifact.id, {
|
|
||||||
path: downloadPath,
|
|
||||||
findBy
|
|
||||||
})
|
|
||||||
core.info(`Downloading dependency-graph artifact ${artifact.name} to ${downloadedArtifact.downloadPath}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return findDependencyGraphFiles(downloadPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findDependencyGraphFiles(dir: string): Promise<string[]> {
|
async function findDependencyGraphFiles(dir: string): Promise<string[]> {
|
||||||
@@ -173,14 +176,6 @@ async function findDependencyGraphFiles(dir: string): Promise<string[]> {
|
|||||||
return graphFiles
|
return graphFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
function warnOrFail(option: String, error: unknown): void {
|
|
||||||
if (!getDependencyGraphContinueOnFailure()) {
|
|
||||||
throw new PostActionJobFailure(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
core.warning(`Failed to ${option} dependency graph. Will continue.\n${String(error)}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOctokit(): InstanceType<typeof GitHub> {
|
function getOctokit(): InstanceType<typeof GitHub> {
|
||||||
return github.getOctokit(getGithubToken())
|
return github.getOctokit(getGithubToken())
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +0,0 @@
|
|||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -28,7 +28,7 @@ function validateGradleWrapper(buildRootDirectory: string): void {
|
|||||||
function verifyExists(file: string, description: string): void {
|
function verifyExists(file: string, description: string): void {
|
||||||
if (!fs.existsSync(file)) {
|
if (!fs.existsSync(file)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Cannot locate ${description} at '${file}'. Specify 'gradle-version' for projects without Gradle wrapper configured.`
|
`Cannot locate ${description} at '${file}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,10 +29,6 @@ export function isCacheCleanupEnabled(): boolean {
|
|||||||
return getBooleanInput('gradle-home-cache-cleanup')
|
return getBooleanInput('gradle-home-cache-cleanup')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCacheEncryptionKey(): string {
|
|
||||||
return core.getInput('cache-encryption-key')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCacheIncludes(): string[] {
|
export function getCacheIncludes(): string[] {
|
||||||
return core.getMultilineInput('gradle-home-cache-includes')
|
return core.getMultilineInput('gradle-home-cache-includes')
|
||||||
}
|
}
|
||||||
@@ -49,6 +45,10 @@ export function getGradleVersion(): string {
|
|||||||
return core.getInput('gradle-version')
|
return core.getInput('gradle-version')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getGradleExecutable(): string {
|
||||||
|
return core.getInput('gradle-executable')
|
||||||
|
}
|
||||||
|
|
||||||
export function getArguments(): string[] {
|
export function getArguments(): string[] {
|
||||||
const input = core.getInput('arguments')
|
const input = core.getInput('arguments')
|
||||||
return parseArgsStringToArgv(input)
|
return parseArgsStringToArgv(input)
|
||||||
@@ -67,25 +67,8 @@ export function isJobSummaryEnabled(): boolean {
|
|||||||
return getBooleanInput('generate-job-summary', true)
|
return getBooleanInput('generate-job-summary', true)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getJobSummaryOption(): JobSummaryOption {
|
export function isDependencyGraphEnabled(): boolean {
|
||||||
return parseJobSummaryOption('add-job-summary')
|
return getBooleanInput('generate-dependency-graph', true)
|
||||||
}
|
|
||||||
|
|
||||||
export function getPRCommentOption(): JobSummaryOption {
|
|
||||||
return parseJobSummaryOption('add-job-summary-as-pr-comment')
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseJobSummaryOption(paramName: string): JobSummaryOption {
|
|
||||||
const val = core.getInput(paramName)
|
|
||||||
switch (val.toLowerCase().trim()) {
|
|
||||||
case 'never':
|
|
||||||
return JobSummaryOption.Never
|
|
||||||
case 'always':
|
|
||||||
return JobSummaryOption.Always
|
|
||||||
case 'on-failure':
|
|
||||||
return JobSummaryOption.OnFailure
|
|
||||||
}
|
|
||||||
throw TypeError(`The value '${val}' is not valid for ${paramName}. Valid values are: [never, always, on-failure].`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDependencyGraphOption(): DependencyGraphOption {
|
export function getDependencyGraphOption(): DependencyGraphOption {
|
||||||
@@ -97,20 +80,16 @@ export function getDependencyGraphOption(): DependencyGraphOption {
|
|||||||
return DependencyGraphOption.Generate
|
return DependencyGraphOption.Generate
|
||||||
case 'generate-and-submit':
|
case 'generate-and-submit':
|
||||||
return DependencyGraphOption.GenerateAndSubmit
|
return DependencyGraphOption.GenerateAndSubmit
|
||||||
case 'generate-and-upload':
|
|
||||||
return DependencyGraphOption.GenerateAndUpload
|
|
||||||
case 'download-and-submit':
|
case 'download-and-submit':
|
||||||
return DependencyGraphOption.DownloadAndSubmit
|
return DependencyGraphOption.DownloadAndSubmit
|
||||||
|
case 'clear':
|
||||||
|
return DependencyGraphOption.Clear
|
||||||
}
|
}
|
||||||
throw TypeError(
|
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'.`
|
`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'.`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDependencyGraphContinueOnFailure(): boolean {
|
|
||||||
return getBooleanInput('dependency-graph-continue-on-failure', true)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getArtifactRetentionDays(): number {
|
export function getArtifactRetentionDays(): number {
|
||||||
const val = core.getInput('artifact-retention-days')
|
const val = core.getInput('artifact-retention-days')
|
||||||
return parseNumericInput('artifact-retention-days', val, 0)
|
return parseNumericInput('artifact-retention-days', val, 0)
|
||||||
@@ -142,15 +121,9 @@ function getBooleanInput(paramName: string, paramDefault = false): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum DependencyGraphOption {
|
export enum DependencyGraphOption {
|
||||||
Disabled = 'disabled',
|
Disabled,
|
||||||
Generate = 'generate',
|
Generate,
|
||||||
GenerateAndSubmit = 'generate-and-submit',
|
GenerateAndSubmit,
|
||||||
GenerateAndUpload = 'generate-and-upload',
|
DownloadAndSubmit,
|
||||||
DownloadAndSubmit = 'download-and-submit'
|
Clear
|
||||||
}
|
|
||||||
|
|
||||||
export enum JobSummaryOption {
|
|
||||||
Never = 'never',
|
|
||||||
Always = 'always',
|
|
||||||
OnFailure = 'on-failure'
|
|
||||||
}
|
}
|
||||||
|
@@ -1,94 +1,45 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as github from '@actions/github'
|
|
||||||
import {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
|
||||||
import {RequestError} from '@octokit/request-error'
|
|
||||||
|
|
||||||
import * as params from './input-params'
|
|
||||||
import {BuildResult} from './build-results'
|
import {BuildResult} from './build-results'
|
||||||
import {CacheListener, generateCachingReport} from './cache-reporting'
|
import {writeCachingReport, CacheListener, logCachingReport} from './cache-reporting'
|
||||||
|
|
||||||
export async function generateJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): Promise<void> {
|
export async function writeJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): Promise<void> {
|
||||||
const summaryTable = renderSummaryTable(buildResults)
|
core.info('Writing job summary')
|
||||||
const cachingReport = generateCachingReport(cacheListener)
|
|
||||||
|
|
||||||
if (shouldGenerateJobSummary(buildResults)) {
|
if (buildResults.length === 0) {
|
||||||
core.info('Generating Job Summary')
|
core.debug('No Gradle build results found. Summary table will not be generated.')
|
||||||
|
} else {
|
||||||
|
writeSummaryTable(buildResults)
|
||||||
|
}
|
||||||
|
|
||||||
|
writeCachingReport(cacheListener)
|
||||||
|
|
||||||
core.summary.addRaw(summaryTable)
|
|
||||||
core.summary.addRaw(cachingReport)
|
|
||||||
await core.summary.write()
|
await core.summary.write()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function logJobSummary(buildResults: BuildResult[], cacheListener: CacheListener): Promise<void> {
|
||||||
|
if (buildResults.length === 0) {
|
||||||
|
core.debug('No Gradle build results found. Summary table will not be logged.')
|
||||||
} else {
|
} else {
|
||||||
core.info('============================')
|
logSummaryTable(buildResults)
|
||||||
core.info(summaryTable)
|
|
||||||
core.info('============================')
|
|
||||||
core.info(cachingReport)
|
|
||||||
core.info('============================')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldAddPRComment(buildResults)) {
|
logCachingReport(cacheListener)
|
||||||
await addPRComment(summaryTable)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addPRComment(jobSummary: string): Promise<void> {
|
function writeSummaryTable(results: BuildResult[]): void {
|
||||||
const context = github.context
|
core.summary.addHeading('Gradle Builds', 3)
|
||||||
if (context.payload.pull_request == null) {
|
|
||||||
core.info('No pull_request trigger: not adding PR comment')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const pull_request_number = context.payload.pull_request.number
|
core.summary.addRaw(`
|
||||||
core.info(`Adding Job Summary as comment to PR #${pull_request_number}.`)
|
|
||||||
|
|
||||||
const prComment = `<h3>Job Summary for gradle-build-action</h3>
|
|
||||||
<h5>${github.context.workflow} :: <em>${github.context.job}</em></h5>
|
|
||||||
|
|
||||||
${jobSummary}`
|
|
||||||
|
|
||||||
const github_token = params.getGithubToken()
|
|
||||||
const octokit = github.getOctokit(github_token)
|
|
||||||
try {
|
|
||||||
await octokit.rest.issues.createComment({
|
|
||||||
...context.repo,
|
|
||||||
issue_number: pull_request_number,
|
|
||||||
body: prComment
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof RequestError) {
|
|
||||||
core.warning(buildWarningMessage(error))
|
|
||||||
} else {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildWarningMessage(error: RequestError): string {
|
|
||||||
const mainWarning = `Failed to generate PR comment.\n${String(error)}`
|
|
||||||
if (error.message === 'Resource not accessible by integration') {
|
|
||||||
return `${mainWarning}
|
|
||||||
Please ensure that the 'pull-requests: write' permission is available for the workflow job.
|
|
||||||
Note that this permission is never available for a workflow triggered from a repository fork.
|
|
||||||
`
|
|
||||||
}
|
|
||||||
return mainWarning
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderSummaryTable(results: BuildResult[]): string {
|
|
||||||
if (results.length === 0) {
|
|
||||||
return 'No Gradle build results detected.'
|
|
||||||
}
|
|
||||||
|
|
||||||
return `
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Gradle Root Project</th>
|
<th>Root Project</th>
|
||||||
<th>Requested Tasks</th>
|
<th>Requested Tasks</th>
|
||||||
<th>Gradle Version</th>
|
<th>Gradle Version</th>
|
||||||
<th>Build Outcome</th>
|
<th>Build Outcome</th>
|
||||||
<th>Build Scan®</th>
|
<th>Build Scan®</th>
|
||||||
</tr>${results.map(result => renderBuildResultRow(result)).join('')}
|
</tr>${results.map(result => renderBuildResultRow(result)).join('')}
|
||||||
</table>
|
</table>
|
||||||
`
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderBuildResultRow(result: BuildResult): string {
|
function renderBuildResultRow(result: BuildResult): string {
|
||||||
@@ -126,32 +77,18 @@ function renderBuildScanBadge(outcomeText: string, outcomeColor: string, targetU
|
|||||||
return `<a href="${targetUrl}" rel="nofollow">${badgeHtml}</a>`
|
return `<a href="${targetUrl}" rel="nofollow">${badgeHtml}</a>`
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldGenerateJobSummary(buildResults: BuildResult[]): boolean {
|
function logSummaryTable(results: BuildResult[]): void {
|
||||||
// Check if Job Summary is supported on this platform
|
core.info('============================')
|
||||||
if (!process.env[SUMMARY_ENV_VAR]) {
|
core.info('Gradle Builds')
|
||||||
return false
|
core.info('----------------------------')
|
||||||
}
|
core.info('Root Project | Requested Tasks | Gradle Version | Build Outcome | Build Scan®')
|
||||||
|
core.info('----------------------------')
|
||||||
// Check if Job Summary is disabled using the deprecated input
|
for (const result of results) {
|
||||||
if (!params.isJobSummaryEnabled()) {
|
core.info(
|
||||||
return false
|
`${result.rootProjectName} | ${result.requestedTasks} | ${result.gradleVersion} | ${
|
||||||
}
|
result.buildFailed ? 'FAILED' : 'SUCCESS'
|
||||||
|
} | ${result.buildScanFailed ? 'Publish failed' : result.buildScanUri}`
|
||||||
return shouldAddJobSummary(params.getJobSummaryOption(), buildResults)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
function shouldAddPRComment(buildResults: BuildResult[]): boolean {
|
|
||||||
return shouldAddJobSummary(params.getPRCommentOption(), buildResults)
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldAddJobSummary(option: params.JobSummaryOption, buildResults: BuildResult[]): boolean {
|
|
||||||
switch (option) {
|
|
||||||
case params.JobSummaryOption.Always:
|
|
||||||
return true
|
|
||||||
case params.JobSummaryOption.Never:
|
|
||||||
return false
|
|
||||||
case params.JobSummaryOption.OnFailure:
|
|
||||||
core.info(`Got these build results: ${JSON.stringify(buildResults)}`)
|
|
||||||
return buildResults.some(result => result.buildFailed)
|
|
||||||
}
|
}
|
||||||
|
core.info('============================')
|
||||||
}
|
}
|
||||||
|
@@ -29,9 +29,6 @@ export async function run(): Promise<void> {
|
|||||||
core.info(error.stack)
|
core.info(error.stack)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit process.exit() to prevent waiting for hanging promises.
|
|
||||||
process.exit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
run()
|
run()
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as setupGradle from './setup-gradle'
|
import * as setupGradle from './setup-gradle'
|
||||||
import {PostActionJobFailure} from './errors'
|
|
||||||
|
|
||||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||||
@@ -14,17 +13,10 @@ export async function run(): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
await setupGradle.complete()
|
await setupGradle.complete()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof PostActionJobFailure) {
|
|
||||||
core.setFailed(String(error))
|
|
||||||
} else {
|
|
||||||
handleFailure(error)
|
handleFailure(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit process.exit() to prevent waiting for promises left hanging by `@actions/cache` on save.
|
|
||||||
process.exit()
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleFailure(error: unknown): void {
|
function handleFailure(error: unknown): void {
|
||||||
core.warning(`Unhandled error in Gradle post-action - job will continue: ${error}`)
|
core.warning(`Unhandled error in Gradle post-action - job will continue: ${error}`)
|
||||||
if (error instanceof Error && error.stack) {
|
if (error instanceof Error && error.stack) {
|
||||||
|
@@ -8,6 +8,7 @@ import * as toolCache from '@actions/tool-cache'
|
|||||||
|
|
||||||
import * as gradlew from './gradlew'
|
import * as gradlew from './gradlew'
|
||||||
import * as params from './input-params'
|
import * as params from './input-params'
|
||||||
|
import * as layout from './repository-layout'
|
||||||
import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
import {handleCacheFailure, isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||||
|
|
||||||
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
|
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
|
||||||
@@ -19,7 +20,13 @@ const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
|
|||||||
export async function provisionGradle(): Promise<string | undefined> {
|
export async function provisionGradle(): Promise<string | undefined> {
|
||||||
const gradleVersion = params.getGradleVersion()
|
const gradleVersion = params.getGradleVersion()
|
||||||
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
|
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
|
||||||
return addToPath(await installGradle(gradleVersion))
|
return addToPath(path.resolve(await installGradle(gradleVersion)))
|
||||||
|
}
|
||||||
|
|
||||||
|
const gradleExecutable = params.getGradleExecutable()
|
||||||
|
if (gradleExecutable !== '') {
|
||||||
|
const workspaceDirectory = layout.workspaceDirectory()
|
||||||
|
return addToPath(path.resolve(workspaceDirectory, gradleExecutable))
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined
|
return undefined
|
||||||
|
@@ -9,7 +9,7 @@ buildscript {
|
|||||||
maven { url pluginRepositoryUrl }
|
maven { url pluginRepositoryUrl }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.gradle:github-dependency-graph-gradle-plugin:1.1.1"
|
classpath "org.gradle:github-dependency-graph-gradle-plugin:1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apply plugin: org.gradle.github.GitHubDependencyGraphPlugin
|
apply plugin: org.gradle.github.GitHubDependencyGraphPlugin
|
||||||
|
@@ -6,13 +6,8 @@ if (getVariable('GITHUB_DEPENDENCY_GRAPH_ENABLED') != "true") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do not run for unsupported versions of Gradle
|
// Do not run for unsupported versions of Gradle
|
||||||
def gradleVersion = GradleVersion.current().baseVersion
|
if (GradleVersion.current().baseVersion < GradleVersion.version("5.0")) {
|
||||||
if (gradleVersion < GradleVersion.version("5.2") ||
|
println "::warning::Dependency Graph is not supported for Gradle versions < 5.0. No dependency snapshot will be generated."
|
||||||
(gradleVersion >= GradleVersion.version("7.0") && gradleVersion < GradleVersion.version("7.1"))) {
|
|
||||||
if (getVariable('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE') != "true") {
|
|
||||||
throw new GradleException("Dependency Graph is not supported for ${gradleVersion}. No dependency snapshot will be generated.")
|
|
||||||
}
|
|
||||||
println "::warning::Dependency Graph is not supported for ${gradleVersion}. No dependency snapshot will be generated."
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +22,12 @@ if (isTopLevelBuild) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def githubOutput = System.getenv("GITHUB_OUTPUT")
|
||||||
|
if (githubOutput) {
|
||||||
|
new File(githubOutput) << "dependency-graph-file=${reportFile.absolutePath}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
println "Generating dependency graph into '${reportFile}'"
|
println "Generating dependency graph into '${reportFile}'"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,21 +15,21 @@ initscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// finish early if injection is disabled
|
// finish early if injection is disabled
|
||||||
def gradleInjectionEnabled = getInputParam("develocity.injection-enabled")
|
def gradleInjectionEnabled = getInputParam("gradle-enterprise.injection-enabled")
|
||||||
if (gradleInjectionEnabled != "true") {
|
if (gradleInjectionEnabled != "true") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
def pluginRepositoryUrl = getInputParam('gradle.plugin-repository.url')
|
def pluginRepositoryUrl = getInputParam('gradle-enterprise.plugin-repository.url')
|
||||||
def gePluginVersion = getInputParam('develocity.plugin.version')
|
def gePluginVersion = getInputParam('gradle-enterprise.plugin.version')
|
||||||
def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version')
|
def ccudPluginVersion = getInputParam('gradle-enterprise.ccud-plugin.version')
|
||||||
|
|
||||||
def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0')
|
def atLeastGradle5 = GradleVersion.current() >= GradleVersion.version('5.0')
|
||||||
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
|
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
|
||||||
|
|
||||||
if (gePluginVersion || ccudPluginVersion && atLeastGradle4) {
|
if (gePluginVersion || ccudPluginVersion && atLeastGradle4) {
|
||||||
pluginRepositoryUrl = pluginRepositoryUrl ?: 'https://plugins.gradle.org/m2'
|
pluginRepositoryUrl = pluginRepositoryUrl ?: 'https://plugins.gradle.org/m2'
|
||||||
logger.quiet("Develocity plugins resolution: $pluginRepositoryUrl")
|
logger.quiet("Gradle Enterprise plugins resolution: $pluginRepositoryUrl")
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven { url pluginRepositoryUrl }
|
maven { url pluginRepositoryUrl }
|
||||||
@@ -52,9 +52,9 @@ initscript {
|
|||||||
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
|
def BUILD_SCAN_PLUGIN_ID = 'com.gradle.build-scan'
|
||||||
def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin'
|
def BUILD_SCAN_PLUGIN_CLASS = 'com.gradle.scan.plugin.BuildScanPlugin'
|
||||||
|
|
||||||
def DEVELOCITY_PLUGIN_ID = 'com.gradle.enterprise'
|
def GRADLE_ENTERPRISE_PLUGIN_ID = 'com.gradle.enterprise'
|
||||||
def DEVELOCITY_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin'
|
def GRADLE_ENTERPRISE_PLUGIN_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin'
|
||||||
def DEVELOCITY_EXTENSION_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterpriseExtension'
|
def GRADLE_ENTERPRISE_EXTENSION_CLASS = 'com.gradle.enterprise.gradleplugin.GradleEnterpriseExtension'
|
||||||
def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection'
|
def CI_AUTO_INJECTION_CUSTOM_VALUE_NAME = 'CI auto injection'
|
||||||
def CI_AUTO_INJECTION_CUSTOM_VALUE_VALUE = 'gradle-build-action'
|
def CI_AUTO_INJECTION_CUSTOM_VALUE_VALUE = 'gradle-build-action'
|
||||||
def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin'
|
def CCUD_PLUGIN_ID = 'com.gradle.common-custom-user-data-gradle-plugin'
|
||||||
@@ -71,17 +71,17 @@ def getInputParam = { String name ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
// finish early if injection is disabled
|
// finish early if injection is disabled
|
||||||
def gradleInjectionEnabled = getInputParam("develocity.injection-enabled")
|
def gradleInjectionEnabled = getInputParam("gradle-enterprise.injection-enabled")
|
||||||
if (gradleInjectionEnabled != "true") {
|
if (gradleInjectionEnabled != "true") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
def geUrl = getInputParam('develocity.url')
|
def geUrl = getInputParam('gradle-enterprise.url')
|
||||||
def geAllowUntrustedServer = Boolean.parseBoolean(getInputParam('develocity.allow-untrusted-server'))
|
def geAllowUntrustedServer = Boolean.parseBoolean(getInputParam('gradle-enterprise.allow-untrusted-server'))
|
||||||
def geEnforceUrl = Boolean.parseBoolean(getInputParam('develocity.enforce-url'))
|
def geEnforceUrl = Boolean.parseBoolean(getInputParam('gradle-enterprise.enforce-url'))
|
||||||
def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('develocity.build-scan.upload-in-background'))
|
def buildScanUploadInBackground = Boolean.parseBoolean(getInputParam('gradle-enterprise.build-scan.upload-in-background'))
|
||||||
def gePluginVersion = getInputParam('develocity.plugin.version')
|
def gePluginVersion = getInputParam('gradle-enterprise.plugin.version')
|
||||||
def ccudPluginVersion = getInputParam('develocity.ccud-plugin.version')
|
def ccudPluginVersion = getInputParam('gradle-enterprise.ccud-plugin.version')
|
||||||
|
|
||||||
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
|
def atLeastGradle4 = GradleVersion.current() >= GradleVersion.version('4.0')
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
|||||||
}
|
}
|
||||||
if (!scanPluginComponent) {
|
if (!scanPluginComponent) {
|
||||||
logger.quiet("Applying $BUILD_SCAN_PLUGIN_CLASS via init script")
|
logger.quiet("Applying $BUILD_SCAN_PLUGIN_CLASS via init script")
|
||||||
logger.quiet("Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
|
logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
|
||||||
applyPluginExternally(pluginManager, BUILD_SCAN_PLUGIN_CLASS)
|
applyPluginExternally(pluginManager, BUILD_SCAN_PLUGIN_CLASS)
|
||||||
buildScan.server = geUrl
|
buildScan.server = geUrl
|
||||||
buildScan.allowUntrustedServer = geAllowUntrustedServer
|
buildScan.allowUntrustedServer = geAllowUntrustedServer
|
||||||
@@ -115,7 +115,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
|||||||
if (geUrl && geEnforceUrl) {
|
if (geUrl && geEnforceUrl) {
|
||||||
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
|
pluginManager.withPlugin(BUILD_SCAN_PLUGIN_ID) {
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
logger.quiet("Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
|
logger.quiet("Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
|
||||||
buildScan.server = geUrl
|
buildScan.server = geUrl
|
||||||
buildScan.allowUntrustedServer = geAllowUntrustedServer
|
buildScan.allowUntrustedServer = geAllowUntrustedServer
|
||||||
}
|
}
|
||||||
@@ -137,11 +137,11 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
|||||||
} else {
|
} else {
|
||||||
gradle.settingsEvaluated { settings ->
|
gradle.settingsEvaluated { settings ->
|
||||||
if (gePluginVersion) {
|
if (gePluginVersion) {
|
||||||
if (!settings.pluginManager.hasPlugin(DEVELOCITY_PLUGIN_ID)) {
|
if (!settings.pluginManager.hasPlugin(GRADLE_ENTERPRISE_PLUGIN_ID)) {
|
||||||
logger.quiet("Applying $DEVELOCITY_PLUGIN_CLASS via init script")
|
logger.quiet("Applying $GRADLE_ENTERPRISE_PLUGIN_CLASS via init script")
|
||||||
logger.quiet("Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
|
logger.quiet("Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
|
||||||
applyPluginExternally(settings.pluginManager, DEVELOCITY_PLUGIN_CLASS)
|
applyPluginExternally(settings.pluginManager, GRADLE_ENTERPRISE_PLUGIN_CLASS)
|
||||||
extensionsWithPublicType(settings, DEVELOCITY_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
|
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
|
||||||
ext.server = geUrl
|
ext.server = geUrl
|
||||||
ext.allowUntrustedServer = geAllowUntrustedServer
|
ext.allowUntrustedServer = geAllowUntrustedServer
|
||||||
ext.buildScan.publishAlways()
|
ext.buildScan.publishAlways()
|
||||||
@@ -151,8 +151,8 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (geUrl && geEnforceUrl) {
|
if (geUrl && geEnforceUrl) {
|
||||||
extensionsWithPublicType(settings, DEVELOCITY_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
|
extensionsWithPublicType(settings, GRADLE_ENTERPRISE_EXTENSION_CLASS).collect { settings[it.name] }.each { ext ->
|
||||||
logger.quiet("Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
|
logger.quiet("Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer")
|
||||||
ext.server = geUrl
|
ext.server = geUrl
|
||||||
ext.allowUntrustedServer = geAllowUntrustedServer
|
ext.allowUntrustedServer = geAllowUntrustedServer
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ if (GradleVersion.current() < GradleVersion.version('6.0')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void applyPluginExternally(def pluginManager, String pluginClassName) {
|
void applyPluginExternally(def pluginManager, String pluginClassName) {
|
||||||
def externallyApplied = 'develocity.externally-applied'
|
def externallyApplied = 'gradle.enterprise.externally-applied'
|
||||||
def oldValue = System.getProperty(externallyApplied)
|
def oldValue = System.getProperty(externallyApplied)
|
||||||
System.setProperty(externallyApplied, 'true')
|
System.setProperty(externallyApplied, 'true')
|
||||||
try {
|
try {
|
@@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<toolchains>
|
|
||||||
<!-- JDK Toolchains installed by default on GitHub-hosted runners -->
|
|
||||||
<toolchain>
|
|
||||||
<type>jdk</type>
|
|
||||||
<provides>
|
|
||||||
<version>8</version>
|
|
||||||
<vendor>Eclipse Temurin</vendor>
|
|
||||||
</provides>
|
|
||||||
<configuration>
|
|
||||||
<jdkHome>${env.JAVA_HOME_8_X64}</jdkHome>
|
|
||||||
</configuration>
|
|
||||||
</toolchain>
|
|
||||||
<toolchain>
|
|
||||||
<type>jdk</type>
|
|
||||||
<provides>
|
|
||||||
<version>11</version>
|
|
||||||
<vendor>Eclipse Temurin</vendor>
|
|
||||||
</provides>
|
|
||||||
<configuration>
|
|
||||||
<jdkHome>${env.JAVA_HOME_11_X64}</jdkHome>
|
|
||||||
</configuration>
|
|
||||||
</toolchain>
|
|
||||||
<toolchain>
|
|
||||||
<type>jdk</type>
|
|
||||||
<provides>
|
|
||||||
<version>17</version>
|
|
||||||
<vendor>Eclipse Temurin</vendor>
|
|
||||||
</provides>
|
|
||||||
<configuration>
|
|
||||||
<jdkHome>${env.JAVA_HOME_17_X64}</jdkHome>
|
|
||||||
</configuration>
|
|
||||||
</toolchain>
|
|
||||||
<toolchain>
|
|
||||||
<type>jdk</type>
|
|
||||||
<provides>
|
|
||||||
<version>21</version>
|
|
||||||
<vendor>Eclipse Temurin</vendor>
|
|
||||||
</provides>
|
|
||||||
<configuration>
|
|
||||||
<jdkHome>${env.JAVA_HOME_21_X64}</jdkHome>
|
|
||||||
</configuration>
|
|
||||||
</toolchain>
|
|
||||||
</toolchains>
|
|
@@ -1,24 +1,23 @@
|
|||||||
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 {SUMMARY_ENV_VAR} from '@actions/core/lib/summary'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as os from 'os'
|
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 * as dependencyGraph from './dependency-graph'
|
||||||
import * as jobSummary from './job-summary'
|
|
||||||
|
|
||||||
|
import {logJobSummary, writeJobSummary} from './job-summary'
|
||||||
import {loadBuildResults} from './build-results'
|
import {loadBuildResults} from './build-results'
|
||||||
import {CacheListener} from './cache-reporting'
|
import {CacheListener} from './cache-reporting'
|
||||||
import {DaemonController} from './daemon-controller'
|
import {DaemonController} from './daemon-controller'
|
||||||
|
|
||||||
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
const GRADLE_SETUP_VAR = 'GRADLE_BUILD_ACTION_SETUP_COMPLETED'
|
||||||
const USER_HOME = 'USER_HOME'
|
|
||||||
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
const GRADLE_USER_HOME = 'GRADLE_USER_HOME'
|
||||||
const CACHE_LISTENER = 'CACHE_LISTENER'
|
const CACHE_LISTENER = 'CACHE_LISTENER'
|
||||||
|
|
||||||
export async function setup(): Promise<void> {
|
export async function setup(): Promise<void> {
|
||||||
const userHome = await determineUserHome()
|
|
||||||
const gradleUserHome = await determineGradleUserHome()
|
const gradleUserHome = await determineGradleUserHome()
|
||||||
|
|
||||||
// Bypass setup on all but first action step in workflow.
|
// Bypass setup on all but first action step in workflow.
|
||||||
@@ -31,12 +30,11 @@ export async function setup(): Promise<void> {
|
|||||||
// Record setup complete: visible in post-action, to control action completion
|
// Record setup complete: visible in post-action, to control action completion
|
||||||
core.saveState(GRADLE_SETUP_VAR, true)
|
core.saveState(GRADLE_SETUP_VAR, true)
|
||||||
|
|
||||||
// Save the User Home and Gradle User Home for use in the post-action step.
|
// Save the Gradle User Home for use in the post-action step.
|
||||||
core.saveState(USER_HOME, userHome)
|
|
||||||
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
core.saveState(GRADLE_USER_HOME, gradleUserHome)
|
||||||
|
|
||||||
const cacheListener = new CacheListener()
|
const cacheListener = new CacheListener()
|
||||||
await caches.restore(userHome, gradleUserHome, cacheListener)
|
await caches.restore(gradleUserHome, cacheListener)
|
||||||
|
|
||||||
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
||||||
|
|
||||||
@@ -48,22 +46,23 @@ export async function complete(): Promise<void> {
|
|||||||
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.')
|
core.info('Gradle setup post-action only performed for first gradle-build-action step in workflow.')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
core.info('In post-action step')
|
core.info('In final post-action step, saving state and writing summary')
|
||||||
|
|
||||||
const buildResults = loadBuildResults()
|
const buildResults = loadBuildResults()
|
||||||
|
|
||||||
const userHome = core.getState(USER_HOME)
|
|
||||||
const gradleUserHome = core.getState(GRADLE_USER_HOME)
|
const gradleUserHome = core.getState(GRADLE_USER_HOME)
|
||||||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||||
const daemonController = new DaemonController(buildResults)
|
const daemonController = new DaemonController(buildResults)
|
||||||
|
|
||||||
await caches.save(userHome, gradleUserHome, cacheListener, daemonController)
|
await caches.save(gradleUserHome, cacheListener, daemonController)
|
||||||
|
|
||||||
await jobSummary.generateJobSummary(buildResults, cacheListener)
|
if (shouldGenerateJobSummary()) {
|
||||||
|
await writeJobSummary(buildResults, cacheListener)
|
||||||
|
} else {
|
||||||
|
logJobSummary(buildResults, cacheListener)
|
||||||
|
}
|
||||||
|
|
||||||
await dependencyGraph.complete(params.getDependencyGraphOption())
|
await dependencyGraph.complete(params.getDependencyGraphOption())
|
||||||
|
|
||||||
core.info('Completed post-action step')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function determineGradleUserHome(): Promise<string> {
|
async function determineGradleUserHome(): Promise<string> {
|
||||||
@@ -92,3 +91,12 @@ async function determineUserHome(): Promise<string> {
|
|||||||
core.debug(`Determined user.home from java -version output: '${userHome}'`)
|
core.debug(`Determined user.home from java -version output: '${userHome}'`)
|
||||||
return userHome
|
return userHome
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shouldGenerateJobSummary(): boolean {
|
||||||
|
// Check if Job Summary is supported on this platform
|
||||||
|
if (!process.env[SUMMARY_ENV_VAR]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return params.isJobSummaryEnabled()
|
||||||
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id "com.gradle.enterprise" version "3.16.1"
|
id "com.gradle.enterprise" version "3.15.1"
|
||||||
id "com.gradle.common-custom-user-data-gradle-plugin" version "1.12.1"
|
id "com.gradle.common-custom-user-data-gradle-plugin" version "1.12"
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
@@ -16,15 +16,14 @@ import java.nio.file.Files
|
|||||||
import java.util.zip.GZIPOutputStream
|
import java.util.zip.GZIPOutputStream
|
||||||
|
|
||||||
class BaseInitScriptTest extends Specification {
|
class BaseInitScriptTest extends Specification {
|
||||||
static final String DEVELOCITY_PLUGIN_VERSION = '3.16.1'
|
static final String GE_PLUGIN_VERSION = '3.15.1'
|
||||||
static final String CCUD_PLUGIN_VERSION = '1.12.1'
|
static final String CCUD_PLUGIN_VERSION = '1.12'
|
||||||
|
|
||||||
static final TestGradleVersion GRADLE_3_X = new TestGradleVersion(GradleVersion.version('3.5.1'), 7, 9)
|
static final TestGradleVersion GRADLE_3_X = new TestGradleVersion(GradleVersion.version('3.5.1'), 7, 9)
|
||||||
static final TestGradleVersion GRADLE_4_X = new TestGradleVersion(GradleVersion.version('4.10.3'), 7, 10)
|
static final TestGradleVersion GRADLE_4_X = new TestGradleVersion(GradleVersion.version('4.10.3'), 7, 10)
|
||||||
static final TestGradleVersion GRADLE_5_X = new TestGradleVersion(GradleVersion.version('5.6.4'), 8, 12)
|
static final TestGradleVersion GRADLE_5_X = new TestGradleVersion(GradleVersion.version('5.6.4'), 8, 12)
|
||||||
static final TestGradleVersion GRADLE_6_NO_BUILD_SERVICE = new TestGradleVersion(GradleVersion.version('6.5.1'), 8, 14)
|
static final TestGradleVersion GRADLE_6_NO_BUILD_SERVICE = new TestGradleVersion(GradleVersion.version('6.5.1'), 8, 14)
|
||||||
static final TestGradleVersion GRADLE_6_X = new TestGradleVersion(GradleVersion.version('6.9.4'), 8, 15)
|
static final TestGradleVersion GRADLE_6_X = new TestGradleVersion(GradleVersion.version('6.9.4'), 8, 15)
|
||||||
static final TestGradleVersion GRADLE_7_1 = new TestGradleVersion(GradleVersion.version('7.6.2'), 8, 19)
|
|
||||||
static final TestGradleVersion GRADLE_7_X = new TestGradleVersion(GradleVersion.version('7.6.2'), 8, 19)
|
static final TestGradleVersion GRADLE_7_X = new TestGradleVersion(GradleVersion.version('7.6.2'), 8, 19)
|
||||||
static final TestGradleVersion GRADLE_8_0 = new TestGradleVersion(GradleVersion.version('8.0.2'), 8, 19)
|
static final TestGradleVersion GRADLE_8_0 = new TestGradleVersion(GradleVersion.version('8.0.2'), 8, 19)
|
||||||
static final TestGradleVersion GRADLE_8_X = new TestGradleVersion(GradleVersion.version('8.5'), 8, 19)
|
static final TestGradleVersion GRADLE_8_X = new TestGradleVersion(GradleVersion.version('8.5'), 8, 19)
|
||||||
@@ -147,7 +146,7 @@ class BaseInitScriptTest extends Specification {
|
|||||||
} else {
|
} else {
|
||||||
"""
|
"""
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.gradle.enterprise' version '${DEVELOCITY_PLUGIN_VERSION}'
|
id 'com.gradle.enterprise' version '${GE_PLUGIN_VERSION}'
|
||||||
${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""}
|
${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""}
|
||||||
}
|
}
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
@@ -175,7 +174,7 @@ class BaseInitScriptTest extends Specification {
|
|||||||
} else if (gradleVersion < GradleVersion.version('6.0')) {
|
} else if (gradleVersion < GradleVersion.version('6.0')) {
|
||||||
"""
|
"""
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.gradle.build-scan' version '${DEVELOCITY_PLUGIN_VERSION}'
|
id 'com.gradle.build-scan' version '${GE_PLUGIN_VERSION}'
|
||||||
${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""}
|
${ccudPluginVersion ? "id 'com.gradle.common-custom-user-data-gradle-plugin' version '$ccudPluginVersion'" : ""}
|
||||||
}
|
}
|
||||||
gradleEnterprise {
|
gradleEnterprise {
|
||||||
|
@@ -171,7 +171,7 @@ class TestBuildResultRecorder extends BaseInitScriptTest {
|
|||||||
when:
|
when:
|
||||||
settingsFile.text = """
|
settingsFile.text = """
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.gradle.enterprise' version '3.16.1' apply(false)
|
id 'com.gradle.enterprise' version '3.15.1' apply(false)
|
||||||
}
|
}
|
||||||
gradle.settingsEvaluated {
|
gradle.settingsEvaluated {
|
||||||
apply plugin: 'com.gradle.enterprise'
|
apply plugin: 'com.gradle.enterprise'
|
||||||
|
@@ -1,16 +1,11 @@
|
|||||||
package com.gradle.gradlebuildaction
|
package com.gradle.gradlebuildaction
|
||||||
|
|
||||||
import org.gradle.util.GradleVersion
|
|
||||||
|
|
||||||
import static org.junit.Assume.assumeTrue
|
import static org.junit.Assume.assumeTrue
|
||||||
|
|
||||||
class TestDependencyGraph extends BaseInitScriptTest {
|
class TestDependencyGraph extends BaseInitScriptTest {
|
||||||
def initScript = 'gradle-build-action.github-dependency-graph.init.gradle'
|
def initScript = 'gradle-build-action.github-dependency-graph.init.gradle'
|
||||||
|
|
||||||
static final TestGradleVersion GRADLE_5_1 = new TestGradleVersion(GradleVersion.version('5.1.1'), 8, 12)
|
static final List<TestGradleVersion> NO_DEPENDENCY_GRAPH_VERSIONS = [GRADLE_3_X, GRADLE_4_X]
|
||||||
static final TestGradleVersion GRADLE_7_0 = new TestGradleVersion(GradleVersion.version('7.0.1'), 8, 12)
|
|
||||||
|
|
||||||
static final List<TestGradleVersion> NO_DEPENDENCY_GRAPH_VERSIONS = [GRADLE_3_X, GRADLE_4_X, GRADLE_5_1, GRADLE_7_0]
|
|
||||||
static final List<TestGradleVersion> DEPENDENCY_GRAPH_VERSIONS = ALL_VERSIONS - NO_DEPENDENCY_GRAPH_VERSIONS
|
static final List<TestGradleVersion> DEPENDENCY_GRAPH_VERSIONS = ALL_VERSIONS - NO_DEPENDENCY_GRAPH_VERSIONS
|
||||||
|
|
||||||
def "does not produce dependency graph when not enabled"() {
|
def "does not produce dependency graph when not enabled"() {
|
||||||
@@ -34,6 +29,7 @@ class TestDependencyGraph extends BaseInitScriptTest {
|
|||||||
|
|
||||||
then:
|
then:
|
||||||
assert reportFile.exists()
|
assert reportFile.exists()
|
||||||
|
assert gitHubOutputFile.text == "dependency-graph-file=${reportFile.absolutePath}\n"
|
||||||
|
|
||||||
where:
|
where:
|
||||||
testGradleVersion << [GRADLE_8_X]
|
testGradleVersion << [GRADLE_8_X]
|
||||||
@@ -61,23 +57,7 @@ class TestDependencyGraph extends BaseInitScriptTest {
|
|||||||
|
|
||||||
then:
|
then:
|
||||||
assert !reportsDir.exists()
|
assert !reportsDir.exists()
|
||||||
assert result.output.contains("::warning::Dependency Graph is not supported for ${testGradleVersion}")
|
assert result.output.contains("::warning::Dependency Graph is not supported")
|
||||||
|
|
||||||
where:
|
|
||||||
testGradleVersion << NO_DEPENDENCY_GRAPH_VERSIONS
|
|
||||||
}
|
|
||||||
|
|
||||||
def "fails build when enabled for older Gradle versions if continue-on-failure is false"() {
|
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
|
||||||
|
|
||||||
when:
|
|
||||||
def vars = envVars
|
|
||||||
vars.put('GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE', 'false')
|
|
||||||
def result = runAndFail(['help'], initScript, testGradleVersion.gradleVersion, [], vars)
|
|
||||||
|
|
||||||
then:
|
|
||||||
assert !reportsDir.exists()
|
|
||||||
assert result.output.contains("Dependency Graph is not supported for ${testGradleVersion}")
|
|
||||||
|
|
||||||
where:
|
where:
|
||||||
testGradleVersion << NO_DEPENDENCY_GRAPH_VERSIONS
|
testGradleVersion << NO_DEPENDENCY_GRAPH_VERSIONS
|
||||||
@@ -130,13 +110,13 @@ class TestDependencyGraph extends BaseInitScriptTest {
|
|||||||
def getEnvVars() {
|
def getEnvVars() {
|
||||||
return [
|
return [
|
||||||
GITHUB_DEPENDENCY_GRAPH_ENABLED: "true",
|
GITHUB_DEPENDENCY_GRAPH_ENABLED: "true",
|
||||||
GITHUB_DEPENDENCY_GRAPH_CONTINUE_ON_FAILURE: "true",
|
|
||||||
GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR: "CORRELATOR",
|
GITHUB_DEPENDENCY_GRAPH_JOB_CORRELATOR: "CORRELATOR",
|
||||||
GITHUB_DEPENDENCY_GRAPH_JOB_ID: "1",
|
GITHUB_DEPENDENCY_GRAPH_JOB_ID: "1",
|
||||||
GITHUB_DEPENDENCY_GRAPH_REF: "main",
|
GITHUB_DEPENDENCY_GRAPH_REF: "main",
|
||||||
GITHUB_DEPENDENCY_GRAPH_SHA: "123456",
|
GITHUB_DEPENDENCY_GRAPH_SHA: "123456",
|
||||||
GITHUB_DEPENDENCY_GRAPH_WORKSPACE: testProjectDir.absolutePath,
|
GITHUB_DEPENDENCY_GRAPH_WORKSPACE: testProjectDir.absolutePath,
|
||||||
DEPENDENCY_GRAPH_REPORT_DIR: reportsDir.absolutePath,
|
DEPENDENCY_GRAPH_REPORT_DIR: reportsDir.absolutePath,
|
||||||
|
GITHUB_OUTPUT: gitHubOutputFile.absolutePath
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,4 +127,8 @@ class TestDependencyGraph extends BaseInitScriptTest {
|
|||||||
def getReportFile() {
|
def getReportFile() {
|
||||||
return new File(reportsDir, "CORRELATOR.json")
|
return new File(reportsDir, "CORRELATOR.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def getGitHubOutputFile() {
|
||||||
|
return new File(testProjectDir, "GITHUB_OUTPUT")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,28 +5,28 @@ import org.gradle.util.GradleVersion
|
|||||||
|
|
||||||
import static org.junit.Assume.assumeTrue
|
import static org.junit.Assume.assumeTrue
|
||||||
|
|
||||||
class TestDevelocityInjection extends BaseInitScriptTest {
|
class TestGradleEnterpriseInjection extends BaseInitScriptTest {
|
||||||
static final List<TestGradleVersion> CCUD_COMPATIBLE_VERSIONS = ALL_VERSIONS - [GRADLE_3_X]
|
static final List<TestGradleVersion> CCUD_COMPATIBLE_VERSIONS = ALL_VERSIONS - [GRADLE_3_X]
|
||||||
|
|
||||||
def initScript = 'gradle-build-action.inject-develocity.init.gradle'
|
def initScript = 'gradle-build-action.inject-gradle-enterprise.init.gradle'
|
||||||
|
|
||||||
private static final GradleVersion GRADLE_6 = GradleVersion.version('6.0')
|
private static final GradleVersion GRADLE_6 = GradleVersion.version('6.0')
|
||||||
|
|
||||||
def "does not apply Develocity plugins when not requested"() {
|
def "does not apply GE plugins when not requested"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def result = run([], initScript, testGradleVersion.gradleVersion)
|
def result = run([], initScript, testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputMissesDevelocityPluginApplicationViaInitScript(result)
|
outputMissesGePluginApplicationViaInitScript(result)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
where:
|
where:
|
||||||
testGradleVersion << ALL_VERSIONS
|
testGradleVersion << ALL_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "does not override Develocity plugin when already defined in project"() {
|
def "does not override GE plugin when already defined in project"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
given:
|
given:
|
||||||
@@ -36,7 +36,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
def result = run(testGradleVersion, testConfig())
|
def result = run(testGradleVersion, testConfig())
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputMissesDevelocityPluginApplicationViaInitScript(result)
|
outputMissesGePluginApplicationViaInitScript(result)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -46,14 +46,14 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
testGradleVersion << ALL_VERSIONS
|
testGradleVersion << ALL_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "applies Develocity plugin via init script when not defined in project"() {
|
def "applies GE plugin via init script when not defined in project"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def result = run(testGradleVersion, testConfig())
|
def result = run(testGradleVersion, testConfig())
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -63,14 +63,14 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
testGradleVersion << ALL_VERSIONS
|
testGradleVersion << ALL_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "applies Develocity and CCUD plugins via init script when not defined in project"() {
|
def "applies GE and CCUD plugins via init script when not defined in project"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
|
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
||||||
outputContainsCcudPluginApplicationViaInitScript(result)
|
outputContainsCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -80,7 +80,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
testGradleVersion << CCUD_COMPATIBLE_VERSIONS
|
testGradleVersion << CCUD_COMPATIBLE_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "applies CCUD plugin via init script where Develocity plugin already applied"() {
|
def "applies CCUD plugin via init script where GE plugin already applied"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
given:
|
given:
|
||||||
@@ -90,7 +90,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
|
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputMissesDevelocityPluginApplicationViaInitScript(result)
|
outputMissesGePluginApplicationViaInitScript(result)
|
||||||
outputContainsCcudPluginApplicationViaInitScript(result)
|
outputContainsCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -110,7 +110,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
|
def result = run(testGradleVersion, testConfig().withCCUDPlugin())
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputMissesDevelocityPluginApplicationViaInitScript(result)
|
outputMissesGePluginApplicationViaInitScript(result)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -120,18 +120,18 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
testGradleVersion << CCUD_COMPATIBLE_VERSIONS
|
testGradleVersion << CCUD_COMPATIBLE_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "ignores Develocity URL and allowUntrustedServer when Develocity plugin is not applied by the init script"() {
|
def "ignores GE URL and allowUntrustedServer when GE plugin is not applied by the init script"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
given:
|
given:
|
||||||
declareGePluginApplication(testGradleVersion.gradleVersion)
|
declareGePluginApplication(testGradleVersion.gradleVersion)
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def config = testConfig().withServer(URI.create('https://develocity-server.invalid'))
|
def config = testConfig().withServer(URI.create('https://ge-server.invalid'))
|
||||||
def result = run(testGradleVersion, config)
|
def result = run(testGradleVersion, config)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputMissesDevelocityPluginApplicationViaInitScript(result)
|
outputMissesGePluginApplicationViaInitScript(result)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -141,7 +141,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
testGradleVersion << ALL_VERSIONS
|
testGradleVersion << ALL_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "configures Develocity URL and allowUntrustedServer when Develocity plugin is applied by the init script"() {
|
def "configures GE URL and allowUntrustedServer when GE plugin is applied by the init script"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
when:
|
when:
|
||||||
@@ -149,8 +149,8 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
def result = run(testGradleVersion, config)
|
def result = run(testGradleVersion, config)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
||||||
outputContainsDevelocityConnectionInfo(result, mockScansServer.address.toString(), true)
|
outputContainsGeConnectionInfo(result, mockScansServer.address.toString(), true)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
outputContainsPluginRepositoryInfo(result, 'https://plugins.gradle.org/m2')
|
outputContainsPluginRepositoryInfo(result, 'https://plugins.gradle.org/m2')
|
||||||
|
|
||||||
@@ -161,22 +161,22 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
testGradleVersion << ALL_VERSIONS
|
testGradleVersion << ALL_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "enforces Develocity URL and allowUntrustedServer in project if enforce url parameter is enabled"() {
|
def "enforces GE URL and allowUntrustedServer in project if enforce url parameter is enabled"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
given:
|
given:
|
||||||
declareGePluginApplication(testGradleVersion.gradleVersion, URI.create('https://develocity-server.invalid'))
|
declareGePluginApplication(testGradleVersion.gradleVersion, URI.create('https://ge-server.invalid'))
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def config = testConfig().withServer(mockScansServer.address, true)
|
def config = testConfig().withServer(mockScansServer.address, true)
|
||||||
def result = run(testGradleVersion, config)
|
def result = run(testGradleVersion, config)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputMissesDevelocityPluginApplicationViaInitScript(result)
|
outputMissesGePluginApplicationViaInitScript(result)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
outputEnforcesDevelocityUrl(result, mockScansServer.address.toString(), true)
|
outputEnforcesGeUrl(result, mockScansServer.address.toString(), true)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
outputContainsBuildScanUrl(result)
|
outputContainsBuildScanUrl(result)
|
||||||
@@ -185,7 +185,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
testGradleVersion << ALL_VERSIONS
|
testGradleVersion << ALL_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "can configure alternative repository for plugins when Develocity plugin is applied by the init script"() {
|
def "can configure alternative repository for plugins when GE plugin is applied by the init script"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
when:
|
when:
|
||||||
@@ -193,8 +193,8 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
def result = run(testGradleVersion, config)
|
def result = run(testGradleVersion, config)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
||||||
outputContainsDevelocityConnectionInfo(result, mockScansServer.address.toString(), true)
|
outputContainsGeConnectionInfo(result, mockScansServer.address.toString(), true)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
outputContainsPluginRepositoryInfo(result, 'https://plugins.grdev.net/m2')
|
outputContainsPluginRepositoryInfo(result, 'https://plugins.grdev.net/m2')
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
def result = run(testGradleVersion, config)
|
def result = run(testGradleVersion, config)
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputMissesDevelocityPluginApplicationViaInitScript(result)
|
outputMissesGePluginApplicationViaInitScript(result)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
result.output.contains('Common Custom User Data Gradle plugin must be at least 1.7. Configured version is 1.6.6.')
|
result.output.contains('Common Custom User Data Gradle plugin must be at least 1.7. Configured version is 1.6.6.')
|
||||||
|
|
||||||
@@ -221,15 +221,15 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
testGradleVersion << ALL_VERSIONS
|
testGradleVersion << ALL_VERSIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
def "can configure Develocity via CCUD system property overrides when CCUD plugin is inject via init script"() {
|
def "can configure GE via CCUD system property overrides when CCUD plugin is inject via init script"() {
|
||||||
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
assumeTrue testGradleVersion.compatibleWithCurrentJvm
|
||||||
|
|
||||||
when:
|
when:
|
||||||
def config = testConfig().withCCUDPlugin().withServer(URI.create('https://develocity-server.invalid'))
|
def config = testConfig().withCCUDPlugin().withServer(URI.create('https://ge-server.invalid'))
|
||||||
def result = run(testGradleVersion, config, ["help", "-Dgradle.enterprise.url=${mockScansServer.address}".toString()])
|
def result = run(testGradleVersion, config, ["help", "-Dgradle.enterprise.url=${mockScansServer.address}".toString()])
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
||||||
outputContainsCcudPluginApplicationViaInitScript(result)
|
outputContainsCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -247,7 +247,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
def result = run(testGradleVersion, config, ["help", "--configuration-cache"])
|
def result = run(testGradleVersion, config, ["help", "--configuration-cache"])
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputContainsDevelocityPluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
outputContainsGePluginApplicationViaInitScript(result, testGradleVersion.gradleVersion)
|
||||||
outputContainsCcudPluginApplicationViaInitScript(result)
|
outputContainsCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -257,7 +257,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
result = run(testGradleVersion, config, ["help", "--configuration-cache"])
|
result = run(testGradleVersion, config, ["help", "--configuration-cache"])
|
||||||
|
|
||||||
then:
|
then:
|
||||||
outputMissesDevelocityPluginApplicationViaInitScript(result)
|
outputMissesGePluginApplicationViaInitScript(result)
|
||||||
outputMissesCcudPluginApplicationViaInitScript(result)
|
outputMissesCcudPluginApplicationViaInitScript(result)
|
||||||
|
|
||||||
and:
|
and:
|
||||||
@@ -273,7 +273,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
assert 1 == result.output.count(message)
|
assert 1 == result.output.count(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
void outputContainsDevelocityPluginApplicationViaInitScript(BuildResult result, GradleVersion gradleVersion) {
|
void outputContainsGePluginApplicationViaInitScript(BuildResult result, GradleVersion gradleVersion) {
|
||||||
def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script"
|
def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script"
|
||||||
def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script"
|
def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script"
|
||||||
if (gradleVersion < GRADLE_6) {
|
if (gradleVersion < GRADLE_6) {
|
||||||
@@ -287,7 +287,7 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void outputMissesDevelocityPluginApplicationViaInitScript(BuildResult result) {
|
void outputMissesGePluginApplicationViaInitScript(BuildResult result) {
|
||||||
def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script"
|
def pluginApplicationLogMsgGradle4And5 = "Applying com.gradle.scan.plugin.BuildScanPlugin via init script"
|
||||||
def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script"
|
def pluginApplicationLogMsgGradle6AndHigher = "Applying com.gradle.enterprise.gradleplugin.GradleEnterprisePlugin via init script"
|
||||||
assert !result.output.contains(pluginApplicationLogMsgGradle4And5)
|
assert !result.output.contains(pluginApplicationLogMsgGradle4And5)
|
||||||
@@ -305,20 +305,20 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
assert !result.output.contains(pluginApplicationLogMsg)
|
assert !result.output.contains(pluginApplicationLogMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
void outputContainsDevelocityConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
|
void outputContainsGeConnectionInfo(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
|
||||||
def geConnectionInfo = "Connection to Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
|
def geConnectionInfo = "Connection to Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
|
||||||
assert result.output.contains(geConnectionInfo)
|
assert result.output.contains(geConnectionInfo)
|
||||||
assert 1 == result.output.count(geConnectionInfo)
|
assert 1 == result.output.count(geConnectionInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
void outputContainsPluginRepositoryInfo(BuildResult result, String gradlePluginRepositoryUrl) {
|
void outputContainsPluginRepositoryInfo(BuildResult result, String gradlePluginRepositoryUrl) {
|
||||||
def repositoryInfo = "Develocity plugins resolution: ${gradlePluginRepositoryUrl}"
|
def repositoryInfo = "Gradle Enterprise plugins resolution: ${gradlePluginRepositoryUrl}"
|
||||||
assert result.output.contains(repositoryInfo)
|
assert result.output.contains(repositoryInfo)
|
||||||
assert 1 == result.output.count(repositoryInfo)
|
assert 1 == result.output.count(repositoryInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
void outputEnforcesDevelocityUrl(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
|
void outputEnforcesGeUrl(BuildResult result, String geUrl, boolean geAllowUntrustedServer) {
|
||||||
def enforceUrl = "Enforcing Develocity: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
|
def enforceUrl = "Enforcing Gradle Enterprise: $geUrl, allowUntrustedServer: $geAllowUntrustedServer"
|
||||||
assert result.output.contains(enforceUrl)
|
assert result.output.contains(enforceUrl)
|
||||||
assert 1 == result.output.count(enforceUrl)
|
assert 1 == result.output.count(enforceUrl)
|
||||||
}
|
}
|
||||||
@@ -369,31 +369,31 @@ class TestDevelocityInjection extends BaseInitScriptTest {
|
|||||||
|
|
||||||
def getEnvVars() {
|
def getEnvVars() {
|
||||||
Map<String, String> envVars = [
|
Map<String, String> envVars = [
|
||||||
DEVELOCITY_INJECTION_ENABLED: "true",
|
GRADLE_ENTERPRISE_INJECTION_ENABLED: "true",
|
||||||
DEVELOCITY_URL: serverUrl,
|
GRADLE_ENTERPRISE_URL: serverUrl,
|
||||||
DEVELOCITY_ALLOW_UNTRUSTED_SERVER: "true",
|
GRADLE_ENTERPRISE_ALLOW_UNTRUSTED_SERVER: "true",
|
||||||
DEVELOCITY_PLUGIN_VERSION: DEVELOCITY_PLUGIN_VERSION,
|
GRADLE_ENTERPRISE_PLUGIN_VERSION: GE_PLUGIN_VERSION,
|
||||||
DEVELOCITY_BUILD_SCAN_UPLOAD_IN_BACKGROUND: "true" // Need to upload in background since our Mock server doesn't cope with foreground upload
|
GRADLE_ENTERPRISE_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("DEVELOCITY_ENFORCE_URL", "true")
|
if (enforceUrl) envVars.put("GRADLE_ENTERPRISE_ENFORCE_URL", "true")
|
||||||
if (ccudPluginVersion != null) envVars.put("DEVELOCITY_CCUD_PLUGIN_VERSION", ccudPluginVersion)
|
if (ccudPluginVersion != null) envVars.put("GRADLE_ENTERPRISE_CCUD_PLUGIN_VERSION", ccudPluginVersion)
|
||||||
if (pluginRepositoryUrl != null) envVars.put("GRADLE_PLUGIN_REPOSITORY_URL", pluginRepositoryUrl)
|
if (pluginRepositoryUrl != null) envVars.put("GRADLE_ENTERPRISE_PLUGIN_REPOSITORY_URL", pluginRepositoryUrl)
|
||||||
|
|
||||||
return envVars
|
return envVars
|
||||||
}
|
}
|
||||||
|
|
||||||
def getJvmArgs() {
|
def getJvmArgs() {
|
||||||
List<String> jvmArgs = [
|
List<String> jvmArgs = [
|
||||||
"-Ddevelocity.injection-enabled=true",
|
"-Dgradle-enterprise.injection-enabled=true",
|
||||||
"-Ddevelocity.url=$serverUrl",
|
"-Dgradle-enterprise.url=$serverUrl",
|
||||||
"-Ddevelocity.allow-untrusted-server=true",
|
"-Dgradle-enterprise.allow-untrusted-server=true",
|
||||||
"-Ddevelocity.plugin.version=$DEVELOCITY_PLUGIN_VERSION",
|
"-Dgradle-enterprise.plugin.version=$GE_PLUGIN_VERSION",
|
||||||
"-Ddevelocity.build-scan.upload-in-background=true"
|
"-Dgradle-enterprise.build-scan.upload-in-background=true"
|
||||||
]
|
]
|
||||||
|
|
||||||
if (enforceUrl) jvmArgs.add("-Ddevelocity.enforce-url=true")
|
if (enforceUrl) jvmArgs.add("-Dgradle-enterprise.enforce-url=true")
|
||||||
if (ccudPluginVersion != null) jvmArgs.add("-Ddevelocity.ccud-plugin.version=$ccudPluginVersion")
|
if (ccudPluginVersion != null) jvmArgs.add("-Dgradle-enterprise.ccud-plugin.version=$ccudPluginVersion")
|
||||||
if (pluginRepositoryUrl != null) jvmArgs.add("-Dgradle.plugin-repository.url=$pluginRepositoryUrl")
|
if (pluginRepositoryUrl != null) jvmArgs.add("-Dgradle-enterprise.plugin-repository.url=$pluginRepositoryUrl")
|
||||||
|
|
||||||
return jvmArgs.collect { it.toString() } // Convert from GStrings
|
return jvmArgs.collect { it.toString() } // Convert from GStrings
|
||||||
}
|
}
|
@@ -17,4 +17,10 @@ describe('cacheUtils-utils', () => {
|
|||||||
expect(posixHash).toBe(windowsHash)
|
expect(posixHash).toBe(windowsHash)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe('sanitizes workflow name in cache key', () => {
|
||||||
|
it('with comma', () => {
|
||||||
|
const cacheKey = cacheUtils.getCacheKeyForJob("Workflow, with,commas", "JOB_ID")
|
||||||
|
expect(cacheKey).toBe('workflow withcommas-JOB_ID')
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user