mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-10-20 15:18:56 +08:00
Compare commits
258 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2a57ddf74a | ||
|
230fd6b47f | ||
|
472ac8a356 | ||
|
3ba05ede1f | ||
|
d785346c8c | ||
|
6ca4d4ade2 | ||
|
75cec40e58 | ||
|
c317ccac62 | ||
|
a74bb0fad6 | ||
|
6ff2065a12 | ||
|
727b4612ba | ||
|
613f4ec588 | ||
|
db6202adcd | ||
|
f0f68e07c3 | ||
|
8ba5a0033b | ||
|
9edc2a11bd | ||
|
079e4844d6 | ||
|
4ebd000afd | ||
|
063fc6a872 | ||
|
e3ada7e5c2 | ||
|
d61e5be06a | ||
|
db2b34260f | ||
|
c031dc946b | ||
|
0eb881f067 | ||
|
27f2dc276c | ||
|
cba1833dde | ||
|
39db90e99b | ||
|
947a893558 | ||
|
b99e9f0bc3 | ||
|
4cf255df10 | ||
|
614d8770a4 | ||
|
69453dbfc5 | ||
|
1113cb87cb | ||
|
9c95294209 | ||
|
f901ec9c20 | ||
|
a94b9252d5 | ||
|
25672bf196 | ||
|
cb6a0acca4 | ||
|
aa2ed2e033 | ||
|
263f84178a | ||
|
0eb5996567 | ||
|
fe55bf4667 | ||
|
709ded51a5 | ||
|
8b1f1a3817 | ||
|
7abf13ee48 | ||
|
da64595ccc | ||
|
29b14c7fca | ||
|
d1ab42cddf | ||
|
422726cec5 | ||
|
4bc52c85c3 | ||
|
e7b5fd0b28 | ||
|
53ccc3e0d7 | ||
|
8ab7c9d8dd | ||
|
0cf00ed767 | ||
|
aedc5fc8f9 | ||
|
78e25cd233 | ||
|
29894757f3 | ||
|
5328161026 | ||
|
4968d2280b | ||
|
c000a0b58f | ||
|
6ff498182a | ||
|
60b1ffac6b | ||
|
9b7c81f8f6 | ||
|
b650771559 | ||
|
17f624cb5b | ||
|
21dee71590 | ||
|
83e2129213 | ||
|
b16787d530 | ||
|
204870af89 | ||
|
0918f5f2a4 | ||
|
1b1a3c48ad | ||
|
a7174b82a2 | ||
|
3de71f2c52 | ||
|
5576baa56b | ||
|
1026c62889 | ||
|
1fb8644035 | ||
|
5a5a5b4387 | ||
|
cc5cdb7fe0 | ||
|
e0d37eb073 | ||
|
bdd89aa34f | ||
|
18cdc8bf28 | ||
|
656ad4b5f2 | ||
|
bebb162342 | ||
|
6084a4eb65 | ||
|
dbb485d80d | ||
|
9bfa003014 | ||
|
fe64d05f86 | ||
|
decca791c5 | ||
|
bd08e7b7cd | ||
|
cca55d0890 | ||
|
a802a3c0ce | ||
|
d06e19f862 | ||
|
bbe1574290 | ||
|
4264cda558 | ||
|
3390540145 | ||
|
1c72a31463 | ||
|
7dfbe33bba | ||
|
e63ddf9c00 | ||
|
d5cd9d86a1 | ||
|
cae99bf6d9 | ||
|
5a90152b1f | ||
|
4b92b8d013 | ||
|
693293c29a | ||
|
ac5d8920dd | ||
|
e833360307 | ||
|
b5a08466b4 | ||
|
4032438d2b | ||
|
9b3abaad52 | ||
|
d20d631365 | ||
|
378bd0b6f8 | ||
|
6d1455a33e | ||
|
c44ebadf6f | ||
|
4d37378696 | ||
|
777a6fc967 | ||
|
d7ed6d7e8d | ||
|
0ecbac99f3 | ||
|
436390bd4e | ||
|
a587e93714 | ||
|
75e00ee3d1 | ||
|
c01af7a6f6 | ||
|
c79d4172e0 | ||
|
b85ac67c9a | ||
|
fa0c026e07 | ||
|
986024f0b7 | ||
|
6fca6b3929 | ||
|
d9cc0aeccf | ||
|
5340f6e816 | ||
|
c211be411e | ||
|
b3afdc78a7 | ||
|
e0c2736e35 | ||
|
a63892c289 | ||
|
d432f2086c | ||
|
eaad2cd2bb | ||
|
a148b21183 | ||
|
e7422f245c | ||
|
c86093d76a | ||
|
a693ccda4b | ||
|
543cacb256 | ||
|
3f3947669a | ||
|
579711fd3c | ||
|
7336529ec5 | ||
|
88af98fab4 | ||
|
01bfa29846 | ||
|
0206df026c | ||
|
41aebc770d | ||
|
bc4d6bddd4 | ||
|
1f57b4dd2d | ||
|
02d4f46354 | ||
|
b9684c0cf5 | ||
|
5423935c9b | ||
|
41ca2299a5 | ||
|
33e91b639d | ||
|
e4ec586f46 | ||
|
15a8123fbc | ||
|
f0c6ac01d3 | ||
|
63fea55da4 | ||
|
26b92e3f5c | ||
|
643092d2fc | ||
|
18c8a679dc | ||
|
13d33a88ca | ||
|
738bda9866 | ||
|
47c9af9d7d | ||
|
3fba6132b4 | ||
|
127b9b6624 | ||
|
8189d29e96 | ||
|
eb7aa853fa | ||
|
15bf8034d6 | ||
|
6bf2690b23 | ||
|
ced6c34563 | ||
|
2efcc22ff5 | ||
|
cb2742a00b | ||
|
c8c53f54bb | ||
|
863daedf86 | ||
|
55871cbb47 | ||
|
e3d60b3873 | ||
|
2dd6cc1801 | ||
|
f11e7d60d7 | ||
|
7137b09ae2 | ||
|
053f389907 | ||
|
4f9b5202aa | ||
|
466a737d16 | ||
|
eb7eb78d95 | ||
|
682d7347f7 | ||
|
3c43b6525f | ||
|
aefd8348d2 | ||
|
f2de61db4e | ||
|
4c7d97cca4 | ||
|
806543fb3a | ||
|
2afa86ca9f | ||
|
ae50675399 | ||
|
d7a54a26c7 | ||
|
02a8a21e55 | ||
|
3abad5567a | ||
|
7c8cc1a9ef | ||
|
355e9c1f86 | ||
|
26dd4cb9bb | ||
|
317ca35dca | ||
|
053762c1c1 | ||
|
95e20daa83 | ||
|
fcc1683d01 | ||
|
059f2e7791 | ||
|
692fda9de7 | ||
|
e8885a31b8 | ||
|
12e24e843d | ||
|
b35e929b1d | ||
|
c839ac993c | ||
|
83e6d042d7 | ||
|
b995a7b937 | ||
|
1c1db193aa | ||
|
9675f09de6 | ||
|
392bcac1c1 | ||
|
a2ba1beedb | ||
|
42e2fed267 | ||
|
8e2fd532f1 | ||
|
2bf5eec3b6 | ||
|
43efc20423 | ||
|
4a9a0a05a3 | ||
|
1647b85e82 | ||
|
6cee865aea | ||
|
5c61ab77ec | ||
|
a31de8476d | ||
|
b2c379621c | ||
|
04a5ee4df2 | ||
|
a188e7cd61 | ||
|
e0644c97f9 | ||
|
9cc76cdea7 | ||
|
b55d63f1f8 | ||
|
8f6be44bf5 | ||
|
469bf6123e | ||
|
9cbb22e130 | ||
|
4c65920ab9 | ||
|
bad0f7d376 | ||
|
ab09ae8fad | ||
|
2f66fb5679 | ||
|
1a6a8efda2 | ||
|
e5b01ed062 | ||
|
3d5e31b7a4 | ||
|
4336c6b886 | ||
|
f25026ba74 | ||
|
9f5ce3593a | ||
|
a5009d1aec | ||
|
ae5079ecac | ||
|
38fdc3f684 | ||
|
0821518fd9 | ||
|
c8b76ea3f7 | ||
|
bf26498bc4 | ||
|
15e064da79 | ||
|
c5e1979a6b | ||
|
dc882d2669 | ||
|
f9f0422c72 | ||
|
38eaee068d | ||
|
0a56b592f2 | ||
|
091093ee61 | ||
|
7a4f128c22 | ||
|
f943246fd9 | ||
|
8337949d80 | ||
|
76166f0035 | ||
|
a9718db8ba |
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
52
.eslintrc.json
Normal file
52
.eslintrc.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint"],
|
||||
"extends": ["plugin:github/recommended"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"eslint-comments/no-use": "off",
|
||||
"import/no-namespace": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
|
||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-extraneous-class": "error",
|
||||
"@typescript-eslint/no-for-in-array": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/prefer-for-of": "warn",
|
||||
"@typescript-eslint/prefer-function-type": "warn",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": ["error", {"ignoreStringArrays": true}],
|
||||
"@typescript-eslint/restrict-plus-operands": "error",
|
||||
"semi": "off",
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest/globals": true
|
||||
}
|
||||
}
|
@@ -1,25 +1,23 @@
|
||||
name: "PR Checks"
|
||||
on: [pull_request, push]
|
||||
name: Verify generated outputs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
check_pr:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- name: "npm ci"
|
||||
run: npm ci
|
||||
|
||||
- name: "npm run build"
|
||||
run: npm run build
|
||||
|
||||
- name: "npm run test"
|
||||
run: npm run test
|
||||
|
||||
- name: "check for uncommitted changes"
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: |
|
||||
npm install
|
||||
npm run all
|
||||
- name: Check for uncommitted changes
|
||||
# Ensure no changes, but ignore node_modules dir since dev/fresh ci deps installed.
|
||||
run: |
|
||||
git diff --exit-code --stat -- . ':!node_modules' \
|
||||
|| (echo "##[error] found changed files after build. please 'npm run build && npm run format'" \
|
||||
|| (echo "##[error] found changed files after build. please 'npm run all'" \
|
||||
"and check in all changes" \
|
||||
&& exit 1)
|
34
.github/workflows/failure-cases.yml
vendored
Normal file
34
.github/workflows/failure-cases.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Execute failure cases
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
|
||||
jobs:
|
||||
|
||||
wrapper-missing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test wrapper missing
|
||||
uses: ./
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help
|
||||
|
||||
bad-configuration:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test bad config value
|
||||
uses: ./
|
||||
continue-on-error: true
|
||||
with:
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help
|
||||
cache-disabled: yes
|
30
.github/workflows/integTest-action-inputs.yml
vendored
Normal file
30
.github/workflows/integTest-action-inputs.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Test different action inputs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
|
||||
jobs:
|
||||
action-inputs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Invoke with multi-line arguments
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: |
|
||||
--configuration-cache
|
||||
--build-cache
|
||||
-DsystemProperty=FOO
|
||||
-PgradleProperty=BAR
|
||||
test
|
||||
jar
|
75
.github/workflows/integTest-caching-config.yml
vendored
Normal file
75
.github/workflows/integTest-caching-config.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
name: Test caching configuration
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||
|
||||
jobs:
|
||||
# Run initial Gradle builds to push initial cache entries
|
||||
# These builds should start fresh without cache hits, due to the seed injected into the cache key above.
|
||||
seed-build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Build using Gradle wrapper
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test
|
||||
# Add "wrapper" to main cache entry and remove 'wrapper-zips' bundle
|
||||
# Exclude build-cache from main cache entry
|
||||
gradle-home-cache-includes: |
|
||||
caches
|
||||
notifications
|
||||
wrapper
|
||||
gradle-home-cache-excludes: |
|
||||
caches/build-cache-1
|
||||
gradle-home-cache-artifact-bundles: |
|
||||
[
|
||||
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
||||
["dependencies", "caches/modules-*/files-*/*/*/*/*/"],
|
||||
["instrumented-jars", "caches/jars-*/*/"],
|
||||
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
||||
]
|
||||
|
||||
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
|
||||
verify-build:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build with --offline
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --offline
|
||||
cache-read-only: true
|
||||
# Need the same configuration when restoring state from cache
|
||||
gradle-home-cache-includes: |
|
||||
caches
|
||||
notifications
|
||||
wrapper
|
||||
gradle-home-cache-excludes: |
|
||||
caches/build-cache-1
|
||||
gradle-home-cache-artifact-bundles: |
|
||||
[
|
||||
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
||||
["dependencies", "caches/modules-*/files-*/*/*/*/*/"],
|
||||
["instrumented-jars", "caches/jars-*/*/"],
|
||||
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
||||
]
|
||||
|
||||
|
65
.github/workflows/integTest-caching-configuration-cache.yml
vendored
Normal file
65
.github/workflows/integTest-caching-configuration-cache.yml
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
name: Test save/restore configuration-cache state
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||
|
||||
jobs:
|
||||
# Run initial Gradle builds to push initial cache entries
|
||||
# These builds should start fresh without cache hits, due to the seed injected into the cache key above.
|
||||
seed-build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Build with configuration-cache enabled
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --configuration-cache
|
||||
|
||||
# Test that the project-dot-gradle cache will cache and restore configuration-cache
|
||||
configuration-cache:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build and verify cached configuration
|
||||
uses: ./
|
||||
env:
|
||||
VERIFY_CACHED_CONFIGURATION: true
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --configuration-cache
|
||||
cache-read-only: true
|
||||
|
||||
# Check that the build can run when no bundles are restored
|
||||
no-bundles-restored:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build with no cache artifact bundles restored
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --configuration-cache
|
||||
cache-read-only: true
|
||||
gradle-home-cache-artifact-bundles: '[]'
|
||||
|
79
.github/workflows/integTest-caching-gradle-home.yml
vendored
Normal file
79
.github/workflows/integTest-caching-gradle-home.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
name: Test save/restore Gradle Home directory
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
|
||||
jobs:
|
||||
# Run initial Gradle builds to push initial cache entries
|
||||
# These builds should start fresh without cache hits, due to the seed injected into the cache key above.
|
||||
seed-build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Build using Gradle wrapper
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test
|
||||
|
||||
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
|
||||
dependencies-cache:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build with --offline
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --offline
|
||||
cache-read-only: true
|
||||
|
||||
# Test that the gradle-user-home cache will cache and restore local build-cache
|
||||
build-cache:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build and verify tasks from cache
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test -DverifyCachedBuild=true
|
||||
cache-read-only: true
|
||||
|
||||
# Check that the build can run when no bundles are restored
|
||||
no-bundles-restored:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build with no cache artifact bundles restored
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test
|
||||
cache-read-only: true
|
||||
gradle-home-cache-artifact-bundles: '[]'
|
||||
|
107
.github/workflows/integTest-execution.yml
vendored
Normal file
107
.github/workflows/integTest-execution.yml
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
name: Test Gradle execution
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
|
||||
jobs:
|
||||
# Tests for executing with different Gradle versions.
|
||||
# Each build verifies that it is executed with the expected Gradle version.
|
||||
gradle-execution:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test use defined Gradle version
|
||||
uses: ./
|
||||
with:
|
||||
gradle-version: 6.9
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=6.9
|
||||
- name: Test use Gradle version alias
|
||||
uses: ./
|
||||
with:
|
||||
gradle-version: release-candidate
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help
|
||||
- name: Test use defined Gradle executable
|
||||
uses: ./
|
||||
with:
|
||||
gradle-executable: __tests__/samples/groovy-dsl/gradlew${{ matrix.script-suffix }}
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=7.1.1
|
||||
|
||||
gradle-versions:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
include:
|
||||
- os: windows-latest
|
||||
script-suffix: '.bat'
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test Gradle 7
|
||||
uses: ./
|
||||
id: gradle7
|
||||
with:
|
||||
gradle-version: 7.2
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=7.2
|
||||
- name: Check Gradle 7 scan
|
||||
if: ${{ !steps.gradle7.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No build scan detected')
|
||||
- name: Test Gradle 6
|
||||
uses: ./
|
||||
id: gradle6
|
||||
with:
|
||||
gradle-version: 6.9
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help -DgradleVersionCheck=6.9
|
||||
- name: Check Gradle 6 scan
|
||||
if: ${{ !steps.gradle6.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No build scan detected')
|
||||
- name: Test Gradle 5
|
||||
uses: ./
|
||||
id: gradle5
|
||||
with:
|
||||
gradle-version: 5.6.4
|
||||
build-root-directory: __tests__/samples/no-wrapper-gradle-5
|
||||
arguments: help -DgradleVersionCheck=5.6.4
|
||||
- name: Check Gradle 5 scan
|
||||
if: ${{ !steps.gradle5.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No build scan detected')
|
||||
- name: Test Gradle 4
|
||||
uses: ./
|
||||
id: gradle4
|
||||
with:
|
||||
gradle-version: 4.10.3
|
||||
build-root-directory: __tests__/samples/no-wrapper-gradle-4
|
||||
arguments: help -DgradleVersionCheck=4.10.3
|
||||
- name: Check Gradle 4 scan
|
||||
if: ${{ !steps.gradle4.outputs.build-scan-url }}
|
||||
uses: actions/github-script@v3
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('No build scan detected')
|
||||
|
61
.github/workflows/integTest-gradle-user-home.yml
vendored
Normal file
61
.github/workflows/integTest-gradle-user-home.yml
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
name: Test caching with a custom GRADLE_USER_HOME
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
GRADLE_USER_HOME: custom/gradle/home
|
||||
|
||||
jobs:
|
||||
# Run initial Gradle builds to push initial cache entries
|
||||
# These builds should start fresh without cache hits, due to the seed injected into the cache key above.
|
||||
seed-build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Build using Gradle wrapper
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test
|
||||
|
||||
# Test that the gradle-user-home cache will cache dependencies, by running build with --offline
|
||||
dependencies-cache:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build with --offline
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test --offline
|
||||
cache-read-only: true
|
||||
|
||||
# Test that the gradle-user-home cache will cache and restore local build-cache
|
||||
build-cache:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Execute Gradle build and verify tasks from cache
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/groovy-dsl
|
||||
arguments: test -DverifyCachedBuild=true
|
||||
cache-read-only: true
|
42
.github/workflows/integTest-kotlin-dsl.yml
vendored
Normal file
42
.github/workflows/integTest-kotlin-dsl.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Test caching with Kotlin DSL
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX: ${{github.workflow}}#${{github.run_number}}-
|
||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||
|
||||
jobs:
|
||||
# Use kotlin-dsl project to verify caching of generated jars and compiled scripts
|
||||
seed-build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Build kotlin-dsl project
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/kotlin-dsl
|
||||
arguments: test
|
||||
|
||||
# Check that the build can run --offline
|
||||
verify-build:
|
||||
needs: seed-build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Build kotlin-dsl project
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/kotlin-dsl
|
||||
arguments: test --offline
|
20
.gitignore
vendored
20
.gitignore
vendored
@@ -1,5 +1,5 @@
|
||||
__tests__/runner/*
|
||||
lib/
|
||||
# Dependency directory
|
||||
node_modules
|
||||
|
||||
# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
@@ -42,7 +42,6 @@ bower_components
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
@@ -90,3 +89,18 @@ typings/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# OS metadata
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Ignore built ts files
|
||||
__tests__/runner/*
|
||||
# lib/**/*
|
||||
|
||||
# IntelliJ IDEA config files
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
# ASDF tool configuration
|
||||
.tool-versions
|
||||
|
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
11
.prettierrc.json
Normal file
11
.prettierrc.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
76
CODE_OF_CONDUCT.md
Normal file
76
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at paul@nosphere.org. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
205
README.md
205
README.md
@@ -1,16 +1,16 @@
|
||||
# Execute Gradle commands in Github Actions workflows
|
||||
|
||||
This Github Action can be used to run arbitrary Gradle commands on any platform supported by Github Actions.
|
||||
# Execute Gradle builds in GitHub Actions workflows
|
||||
|
||||
This GitHub Action can be used to execute a Gradle build on any platform supported by GitHub Actions.
|
||||
|
||||
## Usage
|
||||
|
||||
The following workflow will run `gradle build` using the wrapper from the repository on ubuntu, macos and windows:
|
||||
The following workflow will run `./gradlew build` on ubuntu, macos and windows.
|
||||
The only prerequisite is to have Java installed: you define the version of Java you need to run the build using the `actions/setup-java` action.
|
||||
|
||||
```yaml
|
||||
// .github/workflows/gradle-build-pr.yml
|
||||
# .github/workflows/gradle-build-pr.yml
|
||||
name: Run Gradle on PRs
|
||||
on: pull-request
|
||||
on: pull_request
|
||||
jobs:
|
||||
gradle:
|
||||
strategy:
|
||||
@@ -18,18 +18,33 @@ jobs:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: build
|
||||
```
|
||||
|
||||
## Gradle arguments
|
||||
It is possible to configure multiple Gradle executions to run sequentially in the same job.
|
||||
Each invocation will start its run with the filesystem state remaining from the previous execution.
|
||||
|
||||
```yaml
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: assemble
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: check
|
||||
```
|
||||
|
||||
## Gradle Execution
|
||||
|
||||
### Command-line arguments
|
||||
|
||||
The `arguments` input can 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
|
||||
@@ -37,50 +52,58 @@ arguments: build
|
||||
arguments: check --scan
|
||||
arguments: some arbitrary tasks
|
||||
arguments: build -PgradleProperty=foo
|
||||
arguments: build -DsystemProperty=bar
|
||||
....
|
||||
arguments: |
|
||||
build
|
||||
--scan
|
||||
-PgradleProperty=foo
|
||||
-DsystemProperty=bar
|
||||
```
|
||||
|
||||
See `gradle --help` for more information.
|
||||
|
||||
If you need to pass environment variables, simply use the Github Actions workflow syntax:
|
||||
If you need to pass environment variables, use the GitHub Actions workflow syntax:
|
||||
|
||||
```yaml
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
env:
|
||||
CI: true
|
||||
with:
|
||||
arguments: build
|
||||
```
|
||||
|
||||
## Run a build from a different directory
|
||||
### 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: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
build-root-directory: some/subdirectory
|
||||
```
|
||||
|
||||
## Use a Gradle wrapper from a different directory
|
||||
### 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: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
wrapper-directory: path/to/wrapper-directory
|
||||
```
|
||||
|
||||
## Use a specific `gradle` executable
|
||||
|
||||
```yaml
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
with:
|
||||
gradle-executable: path/to/gradle
|
||||
gradle-executable: /path/to/installed/gradle
|
||||
```
|
||||
|
||||
## Setup and use a declared Gradle version
|
||||
This mechanism can also be used to target a Gradle wrapper script that is located in a non-default location.
|
||||
|
||||
### Download, install and use a specific Gradle version
|
||||
|
||||
The `gradle-build-action` is able to download and install a specific Gradle version to execute.
|
||||
|
||||
```yaml
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
gradle-version: 5.6.2
|
||||
gradle-version: 6.5
|
||||
```
|
||||
|
||||
`gradle-version` can be set to any valid Gradle version.
|
||||
@@ -89,15 +112,16 @@ Moreover, you can use the following aliases:
|
||||
|
||||
| Alias | Selects |
|
||||
| --- |---|
|
||||
| `wrapper` | The Gradle wrapper's version (default, useful for matrix builds) |
|
||||
| `current` | The current [stable release](https://gradle.org/install/) |
|
||||
| `rc` | The current [release candidate](https://gradle.org/release-candidate/) if any, otherwise fallback to `current` |
|
||||
| `release-candidate` | The current [release candidate](https://gradle.org/release-candidate/) if any, otherwise fallback to `current` |
|
||||
| `nightly` | The latest [nightly](https://gradle.org/nightly/), fails if none. |
|
||||
| `release-nightly` | The latest [release nightly](https://gradle.org/release-nightly/), fails if none. |
|
||||
|
||||
This can be handy to automatically test your build with the next Gradle version once a release candidate is out:
|
||||
This can be handy to automatically verify your build works with the latest release candidate of Gradle:
|
||||
|
||||
```yaml
|
||||
// .github/workflows/test-gradle-rc.yml
|
||||
# .github/workflows/test-gradle-rc.yml
|
||||
name: Test latest Gradle RC
|
||||
on:
|
||||
schedule:
|
||||
@@ -106,18 +130,123 @@ jobs:
|
||||
gradle-rc:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
gradle-version: rc
|
||||
gradle-version: release-candidate
|
||||
arguments: build --dry-run # just test build configuration
|
||||
```
|
||||
|
||||
# Build scans
|
||||
## Caching
|
||||
|
||||
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-command-action` action will emit the link to the published build scan as an output named `build-scan-url`.
|
||||
By default, this action aims to cache any and all reusable state that may be speed up a subsequent build invocation.
|
||||
|
||||
You can then use that link in subsequent actions of your workflow.
|
||||
The state that is cached includes:
|
||||
- Any distributions downloaded to satisfy a `gradle-version` parameter ;
|
||||
- A subset of the Gradle User Home directory, including downloaded dependencies, wrapper distributions, and the local build cache ;
|
||||
- Any [configuration-cache](https://docs.gradle.org/nightly/userguide/configuration_cache.html) data stored in the project `.gradle` directory.
|
||||
|
||||
To reduce the space required for caching, this action makes a best effort to reduce duplication in cache entries.
|
||||
|
||||
Caching is enabled by default. You can disable caching for the action as follows:
|
||||
```yaml
|
||||
cache-disabled: true
|
||||
```
|
||||
|
||||
### Cache keys
|
||||
|
||||
For cached distributions outside of Gradle User Home, the cache key is unique to the downloaded distribution. This will not change over time.
|
||||
|
||||
The state of the Gradle User Home and configuration-cache are highly dependent on the Gradle execution, so the cache key is composed of the current commit hash and the GitHub actions job id.
|
||||
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.
|
||||
|
||||
To reduce duplication between cache entries, certain artifacts are cached independently based on their identity.
|
||||
Artifacts that are cached independently include downloaded dependencies, downloaded wrapper distributions and generated Gradle API jars.
|
||||
For example, this means that all jobs executing a particular version of the Gradle wrapper will share common entries for wrapper distributions and for generated Gradle API jars.
|
||||
|
||||
### Using the caches read-only
|
||||
|
||||
Cache storage space is limited for GitHub actions, and writing new cache entries can trigger the deletion of exising entries.
|
||||
In some circumstances, it makes sense for a Gradle invocation to read any existing cache entries but not to write changes back.
|
||||
For example, you may want to write cache entries for builds on your `main` branch, but not for any PR build invocations.
|
||||
|
||||
You can enable read-only caching for any of the caches as follows:
|
||||
|
||||
```yaml
|
||||
# Only write to the cache for builds on the 'main' branch.
|
||||
# Builds on other branches will only read existing entries from the cache.
|
||||
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
```
|
||||
|
||||
### Gradle User Home cache tuning
|
||||
|
||||
As well as any wrapper distributions, the action will attempt to save and restore the `caches` and `notifications` directories from Gradle User Home.
|
||||
|
||||
The contents to be cached can be fine tuned by including and excluding certain paths with Gradle User Home.
|
||||
|
||||
```yaml
|
||||
# Cache downloaded JDKs in addition to the default directories.
|
||||
gradle-home-cache-includes: |
|
||||
caches
|
||||
notifications
|
||||
jdks
|
||||
# Exclude the local build-cache from the directories cached.
|
||||
gradle-home-cache-excludes: |
|
||||
caches/build-cache-1
|
||||
```
|
||||
|
||||
You can specify any number of fixed paths or patterns to include or exclude.
|
||||
File pattern support is documented at https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#patterns-to-match-file-paths.
|
||||
|
||||
### Cache debugging
|
||||
|
||||
It is possible to enable additional debug logging for cache operations. You do via the `GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED` environment variable:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED: true
|
||||
```
|
||||
|
||||
Note that this setting will also prevent certain cache operations from running in parallel, further assisting with debugging.
|
||||
|
||||
## Build scans
|
||||
|
||||
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-build-action` action will:
|
||||
- Add a notice with the link to the GitHub Actions user interface
|
||||
- Emit the link to the published build scan as an output named `build-scan-url`.
|
||||
|
||||
You can then use that link in subsequent actions of your workflow. For example:
|
||||
|
||||
```yaml
|
||||
# .github/workflows/gradle-build-pr.yml
|
||||
name: Run Gradle on PRs
|
||||
on: pull_request
|
||||
jobs:
|
||||
gradle:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- uses: gradle/gradle-build-action@v2
|
||||
id: gradle
|
||||
with:
|
||||
arguments: build
|
||||
- name: "Comment build scan url"
|
||||
uses: actions/github-script@v3
|
||||
if: github.event_name == 'pull_request' && failure()
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
github.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 }}'
|
||||
})
|
||||
```
|
||||
|
95
__tests__/cache-base.test.ts
Normal file
95
__tests__/cache-base.test.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import {CacheEntryListener, CacheListener} from '../src/cache-base'
|
||||
|
||||
describe('caching report', () => {
|
||||
describe('reports not fully restored', () => {
|
||||
it('with one requested entry report', async () => {
|
||||
const report = new CacheListener()
|
||||
report.entry('foo').markRequested('1', ['2'])
|
||||
report.entry('bar').markRequested('3').markRestored('4', 500)
|
||||
expect(report.fullyRestored).toBe(false)
|
||||
})
|
||||
})
|
||||
describe('reports fully restored', () => {
|
||||
it('when empty', async () => {
|
||||
const report = new CacheListener()
|
||||
expect(report.fullyRestored).toBe(true)
|
||||
})
|
||||
it('with empty entry reports', async () => {
|
||||
const report = new CacheListener()
|
||||
report.entry('foo')
|
||||
report.entry('bar')
|
||||
expect(report.fullyRestored).toBe(true)
|
||||
})
|
||||
it('with restored entry report', async () => {
|
||||
const report = new CacheListener()
|
||||
report.entry('bar').markRequested('3').markRestored('4', 300)
|
||||
expect(report.fullyRestored).toBe(true)
|
||||
})
|
||||
it('with multiple restored entry reportss', async () => {
|
||||
const report = new CacheListener()
|
||||
report.entry('foo').markRestored('4', 3300)
|
||||
report.entry('bar').markRequested('3').markRestored('4', 333)
|
||||
expect(report.fullyRestored).toBe(true)
|
||||
})
|
||||
})
|
||||
describe('can be stringified and rehydrated', () => {
|
||||
it('when empty', async () => {
|
||||
const report = new CacheListener()
|
||||
|
||||
const stringRep = report.stringify()
|
||||
const reportClone: CacheListener = CacheListener.rehydrate(stringRep)
|
||||
|
||||
expect(reportClone.cacheEntries).toEqual([])
|
||||
|
||||
// Can call methods on rehydrated
|
||||
expect(reportClone.entry('foo')).toBeInstanceOf(CacheEntryListener)
|
||||
})
|
||||
it('with entry reports', async () => {
|
||||
const report = new CacheListener()
|
||||
report.entry('foo')
|
||||
report.entry('bar')
|
||||
report.entry('baz')
|
||||
|
||||
const stringRep = report.stringify()
|
||||
const reportClone: CacheListener = CacheListener.rehydrate(stringRep)
|
||||
|
||||
expect(reportClone.cacheEntries.length).toBe(3)
|
||||
expect(reportClone.cacheEntries[0].entryName).toBe('foo')
|
||||
expect(reportClone.cacheEntries[1].entryName).toBe('bar')
|
||||
expect(reportClone.cacheEntries[2].entryName).toBe('baz')
|
||||
|
||||
expect(reportClone.entry('foo')).toBe(reportClone.cacheEntries[0])
|
||||
})
|
||||
it('with rehydrated entry report', async () => {
|
||||
const report = new CacheListener()
|
||||
const entryReport = report.entry('foo')
|
||||
entryReport.markRequested('1', ['2', '3'])
|
||||
entryReport.markSaved('4', 100)
|
||||
|
||||
const stringRep = report.stringify()
|
||||
const reportClone: CacheListener = CacheListener.rehydrate(stringRep)
|
||||
const entryClone = reportClone.entry('foo')
|
||||
|
||||
expect(entryClone.requestedKey).toBe('1')
|
||||
expect(entryClone.requestedRestoreKeys).toEqual(['2', '3'])
|
||||
expect(entryClone.savedKey).toBe('4')
|
||||
})
|
||||
it('with live entry report', async () => {
|
||||
const report = new CacheListener()
|
||||
const entryReport = report.entry('foo')
|
||||
entryReport.markRequested('1', ['2', '3'])
|
||||
|
||||
const stringRep = report.stringify()
|
||||
const reportClone: CacheListener = CacheListener.rehydrate(stringRep)
|
||||
const entryClone = reportClone.entry('foo')
|
||||
|
||||
// Check type and call method on rehydrated entry report
|
||||
expect(entryClone).toBeInstanceOf(CacheEntryListener)
|
||||
entryClone.markSaved('4', 100)
|
||||
|
||||
expect(entryClone.requestedKey).toBe('1')
|
||||
expect(entryClone.requestedRestoreKeys).toEqual(['2', '3'])
|
||||
expect(entryClone.savedKey).toBe('4')
|
||||
})
|
||||
})
|
||||
})
|
20
__tests__/cache-utils.test.ts
Normal file
20
__tests__/cache-utils.test.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as cacheUtils from '../src/cache-utils'
|
||||
|
||||
describe('cacheUtils-utils', () => {
|
||||
describe('can hash', () => {
|
||||
it('a string', async () => {
|
||||
const hash = cacheUtils.hashStrings(['foo'])
|
||||
expect(hash).toBe('acbd18db4cc2f85cedef654fccc4a4d8')
|
||||
})
|
||||
it('multiple strings', async () => {
|
||||
const hash = cacheUtils.hashStrings(['foo', 'bar', 'baz'])
|
||||
expect(hash).toBe('6df23dc03f9b54cc38a0fc1483df6e21')
|
||||
})
|
||||
it('normalized filenames', async () => {
|
||||
const fileNames = ['/foo/bar/baz.zip', '../boo.html']
|
||||
const posixHash = cacheUtils.hashFileNames(fileNames)
|
||||
const windowsHash = cacheUtils.hashFileNames(fileNames)
|
||||
expect(posixHash).toBe(windowsHash)
|
||||
})
|
||||
})
|
||||
})
|
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
6
__tests__/data/crypto-utils-test/.gitattributes
vendored
Normal file
6
__tests__/data/crypto-utils-test/.gitattributes
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
5
__tests__/data/crypto-utils-test/.gitignore
vendored
Normal file
5
__tests__/data/crypto-utils-test/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
11
__tests__/data/crypto-utils-test/build.gradle
Normal file
11
__tests__/data/crypto-utils-test/build.gradle
Normal file
@@ -0,0 +1,11 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation('junit:junit:4.12')
|
||||
}
|
BIN
__tests__/data/crypto-utils-test/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
__tests__/data/crypto-utils-test/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
__tests__/data/crypto-utils-test/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
__tests__/data/crypto-utils-test/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
185
__tests__/data/crypto-utils-test/gradlew
vendored
Executable file
185
__tests__/data/crypto-utils-test/gradlew
vendored
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
104
__tests__/data/crypto-utils-test/gradlew.bat
vendored
Normal file
104
__tests__/data/crypto-utils-test/gradlew.bat
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
10
__tests__/data/crypto-utils-test/settings.gradle
Normal file
10
__tests__/data/crypto-utils-test/settings.gradle
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user manual at https://docs.gradle.org/6.5/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = 'basic'
|
@@ -0,0 +1,10 @@
|
||||
package basic;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BasicTest {
|
||||
@Test
|
||||
public void test() {
|
||||
assert true;
|
||||
}
|
||||
}
|
@@ -1,3 +0,0 @@
|
||||
describe('TODO - Add a test suite', () => {
|
||||
it('TODO - Add a test', async () => {});
|
||||
});
|
5
__tests__/samples/.gitignore
vendored
Normal file
5
__tests__/samples/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
23
__tests__/samples/groovy-dsl/build.gradle
Normal file
23
__tests__/samples/groovy-dsl/build.gradle
Normal file
@@ -0,0 +1,23 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation('junit:junit:4.12')
|
||||
}
|
||||
|
||||
tasks.named("test").configure {
|
||||
// Use an environment variable to bypass config-cache checks
|
||||
if (System.getenv('VERIFY_CACHED_CONFIGURATION') != null) {
|
||||
throw new RuntimeException("Configuration was not cached: unexpected configuration of test task")
|
||||
}
|
||||
doLast {
|
||||
if (System.properties.verifyCachedBuild) {
|
||||
throw new RuntimeException("Build was not cached: unexpected execution of test task")
|
||||
}
|
||||
}
|
||||
}
|
1
__tests__/samples/groovy-dsl/gradle.properties
Normal file
1
__tests__/samples/groovy-dsl/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
org.gradle.caching=true
|
BIN
__tests__/samples/groovy-dsl/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
__tests__/samples/groovy-dsl/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
__tests__/samples/groovy-dsl/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
__tests__/samples/groovy-dsl/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
185
__tests__/samples/groovy-dsl/gradlew
vendored
Executable file
185
__tests__/samples/groovy-dsl/gradlew
vendored
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
104
__tests__/samples/groovy-dsl/gradlew.bat
vendored
Normal file
104
__tests__/samples/groovy-dsl/gradlew.bat
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
1
__tests__/samples/groovy-dsl/settings.gradle
Normal file
1
__tests__/samples/groovy-dsl/settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = 'basic'
|
@@ -0,0 +1,10 @@
|
||||
package basic;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BasicTest {
|
||||
@Test
|
||||
public void test() {
|
||||
assert true;
|
||||
}
|
||||
}
|
18
__tests__/samples/kotlin-dsl/build.gradle.kts
Normal file
18
__tests__/samples/kotlin-dsl/build.gradle.kts
Normal file
@@ -0,0 +1,18 @@
|
||||
plugins {
|
||||
`java-library`
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("org.apache.commons:commons-math3:3.6.1")
|
||||
implementation("com.google.guava:guava:30.1.1-jre")
|
||||
|
||||
testImplementation("org.junit.jupiter:junit-jupiter:5.7.2")
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
1
__tests__/samples/kotlin-dsl/gradle.properties
Normal file
1
__tests__/samples/kotlin-dsl/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
org.gradle.caching=true
|
BIN
__tests__/samples/kotlin-dsl/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
__tests__/samples/kotlin-dsl/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
__tests__/samples/kotlin-dsl/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
__tests__/samples/kotlin-dsl/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
234
__tests__/samples/kotlin-dsl/gradlew
vendored
Executable file
234
__tests__/samples/kotlin-dsl/gradlew
vendored
Executable file
@@ -0,0 +1,234 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=${0##*/}
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
89
__tests__/samples/kotlin-dsl/gradlew.bat
vendored
Normal file
89
__tests__/samples/kotlin-dsl/gradlew.bat
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
15
__tests__/samples/kotlin-dsl/settings.gradle.kts
Normal file
15
__tests__/samples/kotlin-dsl/settings.gradle.kts
Normal file
@@ -0,0 +1,15 @@
|
||||
plugins {
|
||||
id("com.gradle.enterprise") version("3.7")
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
buildScan {
|
||||
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||
termsOfServiceAgree = "yes"
|
||||
publishAlways()
|
||||
isUploadInBackground = false
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "kotlin-dsl"
|
||||
|
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* This Java source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package com.example;
|
||||
|
||||
public class Library {
|
||||
public boolean someLibraryMethod() {
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This Java source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package com.example;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class LibraryTest {
|
||||
@Test void someLibraryMethodReturnsTrue() {
|
||||
Library classUnderTest = new Library();
|
||||
assertTrue(classUnderTest.someLibraryMethod(), "someLibraryMethod should return 'true'");
|
||||
}
|
||||
}
|
10
__tests__/samples/no-wrapper-gradle-4/build.gradle
Normal file
10
__tests__/samples/no-wrapper-gradle-4/build.gradle
Normal file
@@ -0,0 +1,10 @@
|
||||
plugins {
|
||||
id "com.gradle.build-scan" version "1.16"
|
||||
}
|
||||
|
||||
buildScan {
|
||||
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||
termsOfServiceAgree = "yes"
|
||||
publishAlways()
|
||||
}
|
||||
|
8
__tests__/samples/no-wrapper-gradle-4/settings.gradle
Normal file
8
__tests__/samples/no-wrapper-gradle-4/settings.gradle
Normal file
@@ -0,0 +1,8 @@
|
||||
rootProject.name = 'no-wrapper'
|
||||
|
||||
println "Using Gradle version: ${gradle.gradleVersion}"
|
||||
|
||||
def gradleVersionCheck = System.properties.gradleVersionCheck
|
||||
if (gradleVersionCheck && gradle.gradleVersion != gradleVersionCheck) {
|
||||
throw new RuntimeException("Got the wrong version: expected ${gradleVersionCheck} but was ${gradle.gradleVersion}")
|
||||
}
|
12
__tests__/samples/no-wrapper-gradle-5/build.gradle
Normal file
12
__tests__/samples/no-wrapper-gradle-5/build.gradle
Normal file
@@ -0,0 +1,12 @@
|
||||
plugins {
|
||||
id("com.gradle.build-scan") version("3.7")
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
buildScan {
|
||||
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||
termsOfServiceAgree = "yes"
|
||||
publishAlways()
|
||||
uploadInBackground = false
|
||||
}
|
||||
}
|
8
__tests__/samples/no-wrapper-gradle-5/settings.gradle
Normal file
8
__tests__/samples/no-wrapper-gradle-5/settings.gradle
Normal file
@@ -0,0 +1,8 @@
|
||||
rootProject.name = 'no-wrapper'
|
||||
|
||||
println "Using Gradle version: ${gradle.gradleVersion}"
|
||||
|
||||
def gradleVersionCheck = System.properties.gradleVersionCheck
|
||||
if (gradleVersionCheck && gradle.gradleVersion != gradleVersionCheck) {
|
||||
throw new RuntimeException("Got the wrong version: expected ${gradleVersionCheck} but was ${gradle.gradleVersion}")
|
||||
}
|
21
__tests__/samples/no-wrapper/settings.gradle
Normal file
21
__tests__/samples/no-wrapper/settings.gradle
Normal file
@@ -0,0 +1,21 @@
|
||||
plugins {
|
||||
id("com.gradle.enterprise") version("3.7")
|
||||
}
|
||||
|
||||
gradleEnterprise {
|
||||
buildScan {
|
||||
termsOfServiceUrl = "https://gradle.com/terms-of-service"
|
||||
termsOfServiceAgree = "yes"
|
||||
publishAlways()
|
||||
uploadInBackground = false
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = 'no-wrapper'
|
||||
|
||||
println "Using Gradle version: ${gradle.gradleVersion}"
|
||||
|
||||
def gradleVersionCheck = System.properties.gradleVersionCheck
|
||||
if (gradleVersionCheck && gradle.gradleVersion != gradleVersionCheck) {
|
||||
throw new RuntimeException("Got the wrong version: expected ${gradleVersionCheck} but was ${gradle.gradleVersion}")
|
||||
}
|
64
action.yml
64
action.yml
@@ -1,33 +1,81 @@
|
||||
name: "Gradle Command"
|
||||
description: 'Execute Gradle Command Line'
|
||||
author: 'Paul Merlin <paul@nospere.org>'
|
||||
name: "Gradle Build Action"
|
||||
description: 'Executes a Gradle build, caching useful state in the GitHub actions cache'
|
||||
|
||||
# https://help.github.com/en/articles/metadata-syntax-for-github-actions
|
||||
|
||||
inputs:
|
||||
wrapper-directory:
|
||||
description: Path to the Gradle Wrapper directory
|
||||
required: false
|
||||
gradle-executable:
|
||||
description: Path to the Gradle executable
|
||||
required: false
|
||||
|
||||
gradle-version:
|
||||
description: Gradle version to use
|
||||
required: false
|
||||
|
||||
build-root-directory:
|
||||
description: Path to the root directory of the build
|
||||
required: false
|
||||
|
||||
arguments:
|
||||
description: Gradle command line arguments, see gradle --help
|
||||
description: Gradle command line arguments (supports multi-line input)
|
||||
required: false
|
||||
|
||||
cache-disabled:
|
||||
description: When 'true', all caching is disabled. No entries will be written to or read from the cache.
|
||||
required: false
|
||||
default: false
|
||||
|
||||
cache-read-only:
|
||||
description: When 'true', existing entries will be read from the cache but no entries will be written.
|
||||
required: false
|
||||
default: false
|
||||
# e.g. Use the following setting to only write cache entries from your 'main' branch
|
||||
# cache-read-only: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
gradle-home-cache-includes:
|
||||
description: Paths within Gradle User Home to cache.
|
||||
required: false
|
||||
default: |
|
||||
caches
|
||||
notifications
|
||||
|
||||
gradle-home-cache-excludes:
|
||||
description: Paths within Gradle User Home to exclude from cache.
|
||||
required: false
|
||||
|
||||
# e.g. Use the following setting to prevent the local build cache from being saved/restored
|
||||
# gradle-home-cache-excludes: |
|
||||
# ["caches/build-cache-1"]
|
||||
|
||||
# EXPERIMENTAL & INTERNAL CONFIGURATION PROPERTIES
|
||||
# The following action properties allow fine-grained tweaking of the action caching behaviour.
|
||||
# These properties are not designed for production use, and may change without notice in a subsequent release of `gradle-build-action`.
|
||||
# Use at your own risk!
|
||||
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).
|
||||
required: false
|
||||
default: ${{ toJSON(matrix) }}
|
||||
gradle-home-cache-artifact-bundles:
|
||||
description: Names and patterns of artifact bundles to cache separately. (EXPERIMENTAL - may be changed/removed without notice)
|
||||
required: false
|
||||
default: |
|
||||
[
|
||||
["generated-gradle-jars", "caches/*/generated-gradle-jars/*.jar"],
|
||||
["wrapper-zips", "wrapper/dists/*/*/*.zip"],
|
||||
["dependencies", "caches/modules-*/files-*/*/*/*/*/"],
|
||||
["instrumented-jars", "caches/jars-*/*/"],
|
||||
["kotlin-dsl", "caches/*/kotlin-dsl/*/*/"]
|
||||
]
|
||||
|
||||
outputs:
|
||||
build-scan-url:
|
||||
description: Link to the build scan if any
|
||||
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'lib/main.js'
|
||||
main: 'dist/main/index.js'
|
||||
post: 'dist/post/index.js'
|
||||
post-if: success()
|
||||
|
||||
branding:
|
||||
icon: 'box'
|
||||
|
2
dist/main/index.js
vendored
Normal file
2
dist/main/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/main/index.js.map
vendored
Normal file
1
dist/main/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3912
dist/main/sourcemap-register.js
vendored
Normal file
3912
dist/main/sourcemap-register.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
dist/post/index.js
vendored
Normal file
2
dist/post/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/post/index.js.map
vendored
Normal file
1
dist/post/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3912
dist/post/sourcemap-register.js
vendored
Normal file
3912
dist/post/sourcemap-register.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
moduleFileExtensions: ['js', 'ts', 'json'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
testRunner: 'jest-circus/runner',
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true
|
||||
verbose: true,
|
||||
setupFilesAfterEnv: ['./jest.setup.js']
|
||||
}
|
1
jest.setup.js
Normal file
1
jest.setup.js
Normal file
@@ -0,0 +1 @@
|
||||
jest.setTimeout(10000) // in milliseconds
|
11969
package-lock.json
generated
11969
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
55
package.json
55
package.json
@@ -1,15 +1,20 @@
|
||||
{
|
||||
"name": "gradle-command-action",
|
||||
"name": "gradle-build-action",
|
||||
"version": "1.0.0",
|
||||
"description": "Execute Gradle Command Line",
|
||||
"main": "lib/main.js",
|
||||
"private": true,
|
||||
"description": "Execute Gradle Build",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "jest"
|
||||
"postinstall": "patch-package",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"build": "ncc build src/main.ts --out dist/main --source-map --minify && ncc build src/post.ts --out dist/post --source-map --minify",
|
||||
"test": "jest",
|
||||
"all": "npm run format && npm run lint && npm run build && npm test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/eskatos/gradle-command-action.git"
|
||||
"url": "git+https://github.com/gradle/gradle-build-action.git"
|
||||
},
|
||||
"keywords": [
|
||||
"github",
|
||||
@@ -17,24 +22,32 @@
|
||||
"github-actions",
|
||||
"gradle"
|
||||
],
|
||||
"author": "Paul Merlin <paul@nosphere.org>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "1.1.1",
|
||||
"@actions/exec": "1.0.1",
|
||||
"@actions/io": "1.0.1",
|
||||
"@actions/tool-cache": "1.1.1",
|
||||
"string-argv": "0.3.1",
|
||||
"typed-rest-client": "1.5.0",
|
||||
"unzipper": "0.10.5"
|
||||
"@actions/cache": "1.0.7",
|
||||
"@actions/core": "1.5.0",
|
||||
"@actions/exec": "1.1.0",
|
||||
"@actions/github": "5.0.0",
|
||||
"@actions/glob": "0.2.0",
|
||||
"@actions/http-client": "1.0.11",
|
||||
"@actions/tool-cache": "1.7.1",
|
||||
"patch-package": "6.4.7",
|
||||
"string-argv": "0.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "24.0.18",
|
||||
"@types/node": "12.7.5",
|
||||
"@types/unzipper": "0.10.0",
|
||||
"jest": "24.9.0",
|
||||
"jest-circus": "24.9.0",
|
||||
"ts-jest": "24.1.0",
|
||||
"typescript": "3.6.3"
|
||||
"@types/jest": "27.0.2",
|
||||
"@types/node": "14.17.3",
|
||||
"@types/unzipper": "0.10.4",
|
||||
"@typescript-eslint/parser": "4.28.2",
|
||||
"@zeit/ncc": "0.22.3",
|
||||
"eslint": "7.30.0",
|
||||
"eslint-plugin-github": "4.1.3",
|
||||
"eslint-plugin-jest": "24.3.6",
|
||||
"jest": "27.3.1",
|
||||
"jest-circus": "27.3.1",
|
||||
"js-yaml": "3.14.1",
|
||||
"prettier": "2.3.2",
|
||||
"ts-jest": "27.0.7",
|
||||
"typescript": "4.3.5"
|
||||
}
|
||||
}
|
||||
|
92
patches/@actions+cache+1.0.7.patch
Normal file
92
patches/@actions+cache+1.0.7.patch
Normal file
@@ -0,0 +1,92 @@
|
||||
diff --git a/node_modules/@actions/cache/lib/cache.d.ts b/node_modules/@actions/cache/lib/cache.d.ts
|
||||
index 805a8e5..d3ab419 100644
|
||||
--- a/node_modules/@actions/cache/lib/cache.d.ts
|
||||
+++ b/node_modules/@actions/cache/lib/cache.d.ts
|
||||
@@ -5,6 +5,11 @@ export declare class ValidationError extends Error {
|
||||
export declare class ReserveCacheError extends Error {
|
||||
constructor(message: string);
|
||||
}
|
||||
+export declare class CacheEntry {
|
||||
+ key: string;
|
||||
+ size?: number;
|
||||
+ constructor(key: string, size?: number);
|
||||
+}
|
||||
/**
|
||||
* Restores cache from keys
|
||||
*
|
||||
@@ -14,7 +19,7 @@ export declare class ReserveCacheError extends Error {
|
||||
* @param downloadOptions cache download options
|
||||
* @returns string returns the key for the cache hit, otherwise returns undefined
|
||||
*/
|
||||
-export declare function restoreCache(paths: string[], primaryKey: string, restoreKeys?: string[], options?: DownloadOptions): Promise<string | undefined>;
|
||||
+export declare function restoreCache(paths: string[], primaryKey: string, restoreKeys?: string[], options?: DownloadOptions): Promise<CacheEntry | undefined>;
|
||||
/**
|
||||
* Saves a list of files with the specified key
|
||||
*
|
||||
@@ -23,4 +28,4 @@ export declare function restoreCache(paths: string[], primaryKey: string, restor
|
||||
* @param options cache upload options
|
||||
* @returns number returns cacheId if the cache was saved successfully and throws an error if save fails
|
||||
*/
|
||||
-export declare function saveCache(paths: string[], key: string, options?: UploadOptions): Promise<number>;
|
||||
+export declare function saveCache(paths: string[], key: string, options?: UploadOptions): Promise<CacheEntry>;
|
||||
diff --git a/node_modules/@actions/cache/lib/cache.js b/node_modules/@actions/cache/lib/cache.js
|
||||
index df78fe0..540114f 100644
|
||||
--- a/node_modules/@actions/cache/lib/cache.js
|
||||
+++ b/node_modules/@actions/cache/lib/cache.js
|
||||
@@ -37,6 +37,13 @@ class ReserveCacheError extends Error {
|
||||
}
|
||||
}
|
||||
exports.ReserveCacheError = ReserveCacheError;
|
||||
+class CacheEntry {
|
||||
+ constructor(key, size) {
|
||||
+ this.key = key;
|
||||
+ this.size = size;
|
||||
+ }
|
||||
+}
|
||||
+exports.CacheEntry = CacheEntry;
|
||||
function checkPaths(paths) {
|
||||
if (!paths || paths.length === 0) {
|
||||
throw new ValidationError(`Path Validation Error: At least one directory or file path is required`);
|
||||
@@ -84,6 +91,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
}
|
||||
const archivePath = path.join(yield utils.createTempDirectory(), utils.getCacheFileName(compressionMethod));
|
||||
core.debug(`Archive Path: ${archivePath}`);
|
||||
+ const restoredEntry = new CacheEntry(cacheEntry.cacheKey);
|
||||
try {
|
||||
// Download the cache from the cache entry
|
||||
yield cacheHttpClient.downloadCache(cacheEntry.archiveLocation, archivePath, options);
|
||||
@@ -91,6 +99,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
yield tar_1.listTar(archivePath, compressionMethod);
|
||||
}
|
||||
const archiveFileSize = utils.getArchiveFileSizeIsBytes(archivePath);
|
||||
+ restoredEntry.size = archiveFileSize;
|
||||
core.info(`Cache Size: ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B)`);
|
||||
yield tar_1.extractTar(archivePath, compressionMethod);
|
||||
core.info('Cache restored successfully');
|
||||
@@ -104,7 +113,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
|
||||
core.debug(`Failed to delete archive: ${error}`);
|
||||
}
|
||||
}
|
||||
- return cacheEntry.cacheKey;
|
||||
+ return restoredEntry;
|
||||
});
|
||||
}
|
||||
exports.restoreCache = restoreCache;
|
||||
@@ -147,7 +156,7 @@ function saveCache(paths, key, options) {
|
||||
}
|
||||
core.debug(`Saving Cache (ID: ${cacheId})`);
|
||||
yield cacheHttpClient.saveCache(cacheId, archivePath, options);
|
||||
- return cacheId;
|
||||
+ return new CacheEntry(key, archiveFileSize);
|
||||
});
|
||||
}
|
||||
exports.saveCache = saveCache;
|
||||
diff --git a/node_modules/@actions/cache/lib/cache.js.map b/node_modules/@actions/cache/lib/cache.js.map
|
||||
index 05fc369..41b9189 100644
|
||||
--- a/node_modules/@actions/cache/lib/cache.js.map
|
||||
+++ b/node_modules/@actions/cache/lib/cache.js.map
|
||||
@@ -1 +1 @@
|
||||
-{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
|
||||
\ No newline at end of file
|
||||
+{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
|
||||
\ No newline at end of file
|
50
src/build-scan-capture.ts
Normal file
50
src/build-scan-capture.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import * as core from '@actions/core'
|
||||
|
||||
export function writeInitScript(): string {
|
||||
const tmpDir = process.env['RUNNER_TEMP'] || ''
|
||||
const initScript = path.resolve(tmpDir, 'build-scan-capture.init.gradle')
|
||||
core.info(`Writing init script: ${initScript}`)
|
||||
if (fs.existsSync(initScript)) {
|
||||
return initScript
|
||||
}
|
||||
fs.writeFileSync(
|
||||
initScript,
|
||||
`
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
// Don't run against the included builds (if the main build has any).
|
||||
def isTopLevelBuild = gradle.getParent() == null
|
||||
if (isTopLevelBuild) {
|
||||
def version = GradleVersion.current().baseVersion
|
||||
def atLeastGradle4 = version >= GradleVersion.version("4.0")
|
||||
def atLeastGradle6 = version >= GradleVersion.version("6.0")
|
||||
|
||||
if (atLeastGradle6) {
|
||||
settingsEvaluated { settings ->
|
||||
if (settings.pluginManager.hasPlugin("com.gradle.enterprise")) {
|
||||
registerCallbacks(settings.extensions["gradleEnterprise"].buildScan, settings.rootProject.name)
|
||||
}
|
||||
}
|
||||
} else if (atLeastGradle4) {
|
||||
projectsEvaluated { gradle ->
|
||||
if (gradle.rootProject.pluginManager.hasPlugin("com.gradle.build-scan")) {
|
||||
registerCallbacks(gradle.rootProject.extensions["buildScan"], gradle.rootProject.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def registerCallbacks(buildScanExtension, rootProjectName) {
|
||||
buildScanExtension.with {
|
||||
def scanFile = new File("gradle-build-scan.txt")
|
||||
buildScanPublished { buildScan ->
|
||||
scanFile.text = buildScan.buildScanUri
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
return initScript
|
||||
}
|
258
src/cache-base.ts
Normal file
258
src/cache-base.ts
Normal file
@@ -0,0 +1,258 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
import * as github from '@actions/github'
|
||||
import {isCacheDebuggingEnabled, getCacheKeyPrefix, hashStrings} from './cache-utils'
|
||||
|
||||
const JOB_CONTEXT_PARAMETER = 'workflow-job-context'
|
||||
|
||||
function generateCacheKey(cacheName: string): CacheKey {
|
||||
const cacheKeyPrefix = getCacheKeyPrefix()
|
||||
|
||||
// At the most general level, share caches for all executions on the same OS
|
||||
const runnerOs = process.env['RUNNER_OS'] || ''
|
||||
const cacheKeyForOs = `${cacheKeyPrefix}${cacheName}|${runnerOs}`
|
||||
|
||||
// Prefer caches that run this job
|
||||
const cacheKeyForJob = `${cacheKeyForOs}|${github.context.job}`
|
||||
|
||||
// Prefer (even more) jobs that run this job with the same context (matrix)
|
||||
const cacheKeyForJobContext = `${cacheKeyForJob}[${determineJobContext()}]`
|
||||
|
||||
// Exact match on Git SHA
|
||||
const cacheKey = `${cacheKeyForJobContext}-${github.context.sha}`
|
||||
|
||||
return new CacheKey(cacheKey, [cacheKeyForJobContext, cacheKeyForJob, cacheKeyForOs])
|
||||
}
|
||||
|
||||
function determineJobContext(): string {
|
||||
// By default, we hash the full `matrix` data for the run, to uniquely identify this job invocation
|
||||
const workflowJobContext = core.getInput(JOB_CONTEXT_PARAMETER)
|
||||
return hashStrings([workflowJobContext])
|
||||
}
|
||||
|
||||
class CacheKey {
|
||||
key: string
|
||||
restoreKeys: string[]
|
||||
|
||||
constructor(key: string, restoreKeys: string[]) {
|
||||
this.key = key
|
||||
this.restoreKeys = restoreKeys
|
||||
}
|
||||
}
|
||||
|
||||
export class CacheListener {
|
||||
cacheEntries: CacheEntryListener[] = []
|
||||
|
||||
get fullyRestored(): boolean {
|
||||
return this.cacheEntries.every(x => !x.wasRequestedButNotRestored())
|
||||
}
|
||||
|
||||
entry(name: string): CacheEntryListener {
|
||||
for (const entry of this.cacheEntries) {
|
||||
if (entry.entryName === name) {
|
||||
return entry
|
||||
}
|
||||
}
|
||||
|
||||
const newEntry = new CacheEntryListener(name)
|
||||
this.cacheEntries.push(newEntry)
|
||||
return newEntry
|
||||
}
|
||||
|
||||
stringify(): string {
|
||||
return JSON.stringify(this)
|
||||
}
|
||||
|
||||
static rehydrate(stringRep: string): CacheListener {
|
||||
const rehydrated: CacheListener = Object.assign(new CacheListener(), JSON.parse(stringRep))
|
||||
const entries = rehydrated.cacheEntries
|
||||
for (let index = 0; index < entries.length; index++) {
|
||||
const rawEntry = entries[index]
|
||||
entries[index] = Object.assign(new CacheEntryListener(rawEntry.entryName), rawEntry)
|
||||
}
|
||||
return rehydrated
|
||||
}
|
||||
}
|
||||
|
||||
export class CacheEntryListener {
|
||||
entryName: string
|
||||
requestedKey: string | undefined
|
||||
requestedRestoreKeys: string[] | undefined
|
||||
restoredKey: string | undefined
|
||||
restoredSize: number | undefined
|
||||
|
||||
savedKey: string | undefined
|
||||
savedSize: number | undefined
|
||||
|
||||
constructor(entryName: string) {
|
||||
this.entryName = entryName
|
||||
}
|
||||
|
||||
wasRequestedButNotRestored(): boolean {
|
||||
return this.requestedKey !== undefined && this.restoredKey === undefined
|
||||
}
|
||||
|
||||
markRequested(key: string, restoreKeys: string[] = []): CacheEntryListener {
|
||||
this.requestedKey = key
|
||||
this.requestedRestoreKeys = restoreKeys
|
||||
return this
|
||||
}
|
||||
|
||||
markRestored(key: string, size: number | undefined): CacheEntryListener {
|
||||
this.restoredKey = key
|
||||
this.restoredSize = size
|
||||
return this
|
||||
}
|
||||
|
||||
markSaved(key: string, size: number | undefined): CacheEntryListener {
|
||||
this.savedKey = key
|
||||
this.savedSize = size
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractCache {
|
||||
private cacheName: string
|
||||
private cacheDescription: string
|
||||
private cacheKeyStateKey: string
|
||||
private cacheResultStateKey: string
|
||||
|
||||
protected readonly cacheDebuggingEnabled: boolean
|
||||
|
||||
constructor(cacheName: string, cacheDescription: string) {
|
||||
this.cacheName = cacheName
|
||||
this.cacheDescription = cacheDescription
|
||||
this.cacheKeyStateKey = `CACHE_KEY_${cacheName}`
|
||||
this.cacheResultStateKey = `CACHE_RESULT_${cacheName}`
|
||||
this.cacheDebuggingEnabled = isCacheDebuggingEnabled()
|
||||
}
|
||||
|
||||
async restore(listener: CacheListener): Promise<void> {
|
||||
if (this.cacheOutputExists()) {
|
||||
core.info(`${this.cacheDescription} already exists. Not restoring from cache.`)
|
||||
return
|
||||
}
|
||||
|
||||
const cacheKey = this.prepareCacheKey()
|
||||
const entryReport = listener.entry(this.cacheDescription)
|
||||
entryReport.markRequested(cacheKey.key, cacheKey.restoreKeys)
|
||||
|
||||
this.debug(
|
||||
`Requesting ${this.cacheDescription} with
|
||||
key:${cacheKey.key}
|
||||
restoreKeys:[${cacheKey.restoreKeys}]`
|
||||
)
|
||||
|
||||
const cacheResult = await this.restoreCache(this.getCachePath(), cacheKey.key, cacheKey.restoreKeys)
|
||||
|
||||
if (!cacheResult) {
|
||||
core.info(`${this.cacheDescription} cache not found. Will start with empty.`)
|
||||
return
|
||||
}
|
||||
|
||||
core.saveState(this.cacheResultStateKey, cacheResult)
|
||||
entryReport.markRestored(cacheResult.key, cacheResult.size)
|
||||
core.info(`Restored ${this.cacheDescription} from cache key: ${cacheResult}`)
|
||||
|
||||
try {
|
||||
await this.afterRestore(listener)
|
||||
} catch (error) {
|
||||
core.warning(`Restore ${this.cacheDescription} failed in 'afterRestore': ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
prepareCacheKey(): CacheKey {
|
||||
const cacheKey = generateCacheKey(this.cacheName)
|
||||
|
||||
core.saveState(this.cacheKeyStateKey, cacheKey.key)
|
||||
return cacheKey
|
||||
}
|
||||
|
||||
protected async restoreCache(
|
||||
cachePath: string[],
|
||||
cacheKey: string,
|
||||
cacheRestoreKeys: string[] = []
|
||||
): Promise<cache.CacheEntry | undefined> {
|
||||
try {
|
||||
return await cache.restoreCache(cachePath, cacheKey, cacheRestoreKeys)
|
||||
} catch (error) {
|
||||
if (error instanceof cache.ValidationError) {
|
||||
// Validation errors should fail the build action
|
||||
throw error
|
||||
}
|
||||
// Warn about any other error and continue
|
||||
core.warning(`Failed to restore ${cacheKey}: ${error}`)
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
protected async afterRestore(_listener: CacheListener): Promise<void> {}
|
||||
|
||||
async save(listener: CacheListener): Promise<void> {
|
||||
if (!this.cacheOutputExists()) {
|
||||
this.debug(`No ${this.cacheDescription} to cache.`)
|
||||
return
|
||||
}
|
||||
|
||||
const cacheKey = core.getState(this.cacheKeyStateKey)
|
||||
const cacheResult = core.getState(this.cacheResultStateKey)
|
||||
|
||||
if (!cacheKey) {
|
||||
this.debug(`${this.cacheDescription} existed prior to cache restore. Not saving.`)
|
||||
return
|
||||
}
|
||||
|
||||
if (cacheResult && cacheKey === cacheResult) {
|
||||
core.info(`Cache hit occurred on the cache key ${cacheKey}, not saving cache.`)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await this.beforeSave(listener)
|
||||
} catch (error) {
|
||||
core.warning(`Save ${this.cacheDescription} failed in 'beforeSave': ${error}`)
|
||||
return
|
||||
}
|
||||
|
||||
core.info(`Caching ${this.cacheDescription} with cache key: ${cacheKey}`)
|
||||
const cachePath = this.getCachePath()
|
||||
const savedEntry = await this.saveCache(cachePath, cacheKey)
|
||||
|
||||
if (savedEntry) {
|
||||
listener.entry(this.cacheDescription).markSaved(savedEntry.key, savedEntry.size)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
protected async beforeSave(_listener: CacheListener): Promise<void> {}
|
||||
|
||||
protected async saveCache(cachePath: string[], cacheKey: string): Promise<cache.CacheEntry | undefined> {
|
||||
try {
|
||||
return await cache.saveCache(cachePath, cacheKey)
|
||||
} catch (error) {
|
||||
if (error instanceof cache.ValidationError) {
|
||||
// Validation errors should fail the build action
|
||||
throw error
|
||||
} else if (error instanceof cache.ReserveCacheError) {
|
||||
// Reserve cache errors are expected if the artifact has been previously cached
|
||||
this.debug(error.message)
|
||||
} else {
|
||||
// Warn about any other error and continue
|
||||
core.warning(String(error))
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
protected debug(message: string): void {
|
||||
if (this.cacheDebuggingEnabled) {
|
||||
core.info(message)
|
||||
} else {
|
||||
core.debug(message)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract cacheOutputExists(): boolean
|
||||
protected abstract getCachePath(): string[]
|
||||
}
|
256
src/cache-gradle-user-home.ts
Normal file
256
src/cache-gradle-user-home.ts
Normal file
@@ -0,0 +1,256 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import os from 'os'
|
||||
import * as core from '@actions/core'
|
||||
import * as glob from '@actions/glob'
|
||||
import * as exec from '@actions/exec'
|
||||
|
||||
import {AbstractCache, CacheEntryListener, CacheListener} from './cache-base'
|
||||
import {getCacheKeyPrefix, hashFileNames, tryDelete} from './cache-utils'
|
||||
|
||||
const META_FILE_DIR = '.gradle-build-action'
|
||||
|
||||
const INCLUDE_PATHS_PARAMETER = 'gradle-home-cache-includes'
|
||||
const EXCLUDE_PATHS_PARAMETER = 'gradle-home-cache-excludes'
|
||||
const ARTIFACT_BUNDLES_PARAMETER = 'gradle-home-cache-artifact-bundles'
|
||||
|
||||
export class GradleUserHomeCache extends AbstractCache {
|
||||
private gradleUserHome: string
|
||||
|
||||
constructor(rootDir: string) {
|
||||
super('gradle', 'Gradle User Home')
|
||||
this.gradleUserHome = this.determineGradleUserHome(rootDir)
|
||||
}
|
||||
|
||||
async afterRestore(listener: CacheListener): Promise<void> {
|
||||
await this.reportGradleUserHomeSize('as restored from cache')
|
||||
await this.restoreArtifactBundles(listener)
|
||||
await this.reportGradleUserHomeSize('after restoring common artifacts')
|
||||
}
|
||||
|
||||
private async restoreArtifactBundles(listener: CacheListener): Promise<void> {
|
||||
const processes: Promise<void>[] = []
|
||||
|
||||
const bundleMetaFiles = await this.getBundleMetaFiles()
|
||||
const bundlePatterns = this.getArtifactBundles()
|
||||
|
||||
// Iterate over all bundle meta files and try to restore
|
||||
for (const bundleMetaFile of bundleMetaFiles) {
|
||||
const bundle = path.basename(bundleMetaFile, '.cache')
|
||||
const entryListener = listener.entry(bundle)
|
||||
const bundlePattern = bundlePatterns.get(bundle)
|
||||
|
||||
// Handle case where the 'artifactBundlePatterns' have been changed
|
||||
if (bundlePattern === undefined) {
|
||||
core.info(`Found bundle metafile for ${bundle} but no such bundle defined`)
|
||||
entryListener.markRequested('BUNDLE_NOT_CONFIGURED')
|
||||
tryDelete(bundleMetaFile)
|
||||
} else {
|
||||
const p = this.restoreArtifactBundle(bundle, bundlePattern, bundleMetaFile, entryListener)
|
||||
// Run sequentially when debugging enabled
|
||||
if (this.cacheDebuggingEnabled) {
|
||||
await p
|
||||
}
|
||||
processes.push(p)
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(processes)
|
||||
}
|
||||
|
||||
private async restoreArtifactBundle(
|
||||
bundle: string,
|
||||
bundlePattern: string,
|
||||
bundleMetaFile: string,
|
||||
listener: CacheEntryListener
|
||||
): Promise<void> {
|
||||
const cacheKey = fs.readFileSync(bundleMetaFile, 'utf-8').trim()
|
||||
listener.markRequested(cacheKey)
|
||||
|
||||
const restoredEntry = await this.restoreCache([bundlePattern], cacheKey)
|
||||
if (restoredEntry) {
|
||||
core.info(`Restored ${bundle} with key ${cacheKey} to ${bundlePattern}`)
|
||||
listener.markRestored(restoredEntry.key, restoredEntry.size)
|
||||
} else {
|
||||
core.info(`Did not restore ${bundle} with key ${cacheKey} to ${bundlePattern}`)
|
||||
tryDelete(bundleMetaFile)
|
||||
}
|
||||
}
|
||||
|
||||
private getBundleMetaFile(name: string): string {
|
||||
return path.resolve(this.gradleUserHome, META_FILE_DIR, `${name}.cache`)
|
||||
}
|
||||
|
||||
private async getBundleMetaFiles(): Promise<string[]> {
|
||||
const metaFiles = path.resolve(this.gradleUserHome, META_FILE_DIR, '*.cache')
|
||||
const globber = await glob.create(metaFiles)
|
||||
const bundleFiles = await globber.glob()
|
||||
return bundleFiles
|
||||
}
|
||||
|
||||
async beforeSave(listener: CacheListener): Promise<void> {
|
||||
await this.reportGradleUserHomeSize('before saving common artifacts')
|
||||
this.removeExcludedPaths()
|
||||
await this.saveArtifactBundles(listener)
|
||||
await this.reportGradleUserHomeSize(
|
||||
"after saving common artifacts (only 'caches' and 'notifications' will be stored)"
|
||||
)
|
||||
}
|
||||
|
||||
private removeExcludedPaths(): void {
|
||||
const rawPaths: string[] = core.getMultilineInput(EXCLUDE_PATHS_PARAMETER)
|
||||
const resolvedPaths = rawPaths.map(x => path.resolve(this.gradleUserHome, x))
|
||||
|
||||
for (const p of resolvedPaths) {
|
||||
this.debug(`Deleting excluded path: ${p}`)
|
||||
tryDelete(p)
|
||||
}
|
||||
}
|
||||
|
||||
private async saveArtifactBundles(listener: CacheListener): Promise<void> {
|
||||
const processes: Promise<void>[] = []
|
||||
for (const [bundle, pattern] of this.getArtifactBundles()) {
|
||||
const entryListener = listener.entry(bundle)
|
||||
|
||||
const p = this.saveArtifactBundle(bundle, pattern, entryListener)
|
||||
// Run sequentially when debugging enabled
|
||||
if (this.cacheDebuggingEnabled) {
|
||||
await p
|
||||
}
|
||||
processes.push(p)
|
||||
}
|
||||
|
||||
await Promise.all(processes)
|
||||
}
|
||||
|
||||
private async saveArtifactBundle(
|
||||
bundle: string,
|
||||
artifactPath: string,
|
||||
listener: CacheEntryListener
|
||||
): Promise<void> {
|
||||
const bundleMetaFile = this.getBundleMetaFile(bundle)
|
||||
|
||||
const globber = await glob.create(artifactPath, {
|
||||
implicitDescendants: false,
|
||||
followSymbolicLinks: false
|
||||
})
|
||||
const bundleFiles = await globber.glob()
|
||||
|
||||
// Handle no matching files
|
||||
if (bundleFiles.length === 0) {
|
||||
this.debug(`No files found to cache for ${bundle}`)
|
||||
if (fs.existsSync(bundleMetaFile)) {
|
||||
tryDelete(bundleMetaFile)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const previouslyRestoredKey = fs.existsSync(bundleMetaFile)
|
||||
? fs.readFileSync(bundleMetaFile, 'utf-8').trim()
|
||||
: ''
|
||||
const cacheKey = this.createCacheKey(bundle, bundleFiles)
|
||||
|
||||
if (previouslyRestoredKey === cacheKey) {
|
||||
this.debug(`No change to previously restored ${bundle}. Not caching.`)
|
||||
} else {
|
||||
core.info(`Caching ${bundle} with cache key: ${cacheKey}`)
|
||||
const savedEntry = await this.saveCache([artifactPath], cacheKey)
|
||||
if (savedEntry !== undefined) {
|
||||
this.writeBundleMetaFile(bundleMetaFile, cacheKey)
|
||||
listener.markSaved(savedEntry.key, savedEntry.size)
|
||||
}
|
||||
}
|
||||
|
||||
for (const file of bundleFiles) {
|
||||
tryDelete(file)
|
||||
}
|
||||
}
|
||||
|
||||
protected createCacheKey(bundle: string, files: string[]): string {
|
||||
const cacheKeyPrefix = getCacheKeyPrefix()
|
||||
const relativeFiles = files.map(x => path.relative(this.gradleUserHome, x))
|
||||
const key = hashFileNames(relativeFiles)
|
||||
|
||||
this.debug(`Generating cache key for ${bundle} from files: ${relativeFiles}`)
|
||||
|
||||
return `${cacheKeyPrefix}${bundle}-${key}`
|
||||
}
|
||||
|
||||
private writeBundleMetaFile(metaFile: string, cacheKey: string): void {
|
||||
this.debug(`Writing bundle metafile: ${metaFile}`)
|
||||
|
||||
const dirName = path.dirname(metaFile)
|
||||
if (!fs.existsSync(dirName)) {
|
||||
fs.mkdirSync(dirName)
|
||||
}
|
||||
|
||||
fs.writeFileSync(metaFile, cacheKey)
|
||||
}
|
||||
|
||||
protected determineGradleUserHome(rootDir: string): string {
|
||||
const customGradleUserHome = process.env['GRADLE_USER_HOME']
|
||||
if (customGradleUserHome) {
|
||||
return path.resolve(rootDir, customGradleUserHome)
|
||||
}
|
||||
|
||||
return path.resolve(os.homedir(), '.gradle')
|
||||
}
|
||||
|
||||
protected cacheOutputExists(): boolean {
|
||||
// Need to check for 'caches' directory to avoid incorrect detection on MacOS agents
|
||||
const dir = path.resolve(this.gradleUserHome, 'caches')
|
||||
return fs.existsSync(dir)
|
||||
}
|
||||
|
||||
protected getCachePath(): string[] {
|
||||
const rawPaths: string[] = core.getMultilineInput(INCLUDE_PATHS_PARAMETER)
|
||||
rawPaths.push(META_FILE_DIR)
|
||||
const resolvedPaths = rawPaths.map(x => this.resolveCachePath(x))
|
||||
this.debug(`Using cache paths: ${resolvedPaths}`)
|
||||
return resolvedPaths
|
||||
}
|
||||
|
||||
private resolveCachePath(rawPath: string): string {
|
||||
if (rawPath.startsWith('!')) {
|
||||
const resolved = this.resolveCachePath(rawPath.substring(1))
|
||||
return `!${resolved}`
|
||||
}
|
||||
return path.resolve(this.gradleUserHome, rawPath)
|
||||
}
|
||||
|
||||
private getArtifactBundles(): Map<string, string> {
|
||||
const artifactBundleDefinition = core.getInput(ARTIFACT_BUNDLES_PARAMETER)
|
||||
this.debug(`Using artifact bundle definition: ${artifactBundleDefinition}`)
|
||||
const artifactBundles = JSON.parse(artifactBundleDefinition)
|
||||
return new Map(Array.from(artifactBundles, ([key, value]) => [key, path.resolve(this.gradleUserHome, value)]))
|
||||
}
|
||||
|
||||
private async reportGradleUserHomeSize(label: string): Promise<void> {
|
||||
if (!this.cacheDebuggingEnabled) {
|
||||
return
|
||||
}
|
||||
if (!fs.existsSync(this.gradleUserHome)) {
|
||||
return
|
||||
}
|
||||
const result = await exec.getExecOutput('du', ['-h', '-c', '-t', '5M'], {
|
||||
cwd: this.gradleUserHome,
|
||||
silent: true,
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
|
||||
core.info(`Gradle User Home (directories >5M): ${label}`)
|
||||
|
||||
core.info(
|
||||
result.stdout
|
||||
.trimEnd()
|
||||
.replace(/\t/g, ' ')
|
||||
.split('\n')
|
||||
.map(it => {
|
||||
return ` ${it}`
|
||||
})
|
||||
.join('\n')
|
||||
)
|
||||
|
||||
core.info('-----------------------')
|
||||
}
|
||||
}
|
30
src/cache-project-dot-gradle.ts
Normal file
30
src/cache-project-dot-gradle.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import {AbstractCache} from './cache-base'
|
||||
|
||||
// TODO: Maybe allow the user to override / tweak this set
|
||||
const PATHS_TO_CACHE = [
|
||||
'configuration-cache' // Only configuration-cache is stored at present
|
||||
]
|
||||
|
||||
export class ProjectDotGradleCache extends AbstractCache {
|
||||
private rootDir: string
|
||||
constructor(rootDir: string) {
|
||||
super('project', 'Project configuration cache')
|
||||
this.rootDir = rootDir
|
||||
}
|
||||
|
||||
protected cacheOutputExists(): boolean {
|
||||
const dir = this.getProjectDotGradleDir()
|
||||
return fs.existsSync(dir)
|
||||
}
|
||||
|
||||
protected getCachePath(): string[] {
|
||||
const dir = this.getProjectDotGradleDir()
|
||||
return PATHS_TO_CACHE.map(x => path.resolve(dir, x))
|
||||
}
|
||||
|
||||
private getProjectDotGradleDir(): string {
|
||||
return path.resolve(this.rootDir, '.gradle')
|
||||
}
|
||||
}
|
68
src/cache-utils.ts
Normal file
68
src/cache-utils.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as crypto from 'crypto'
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
|
||||
const CACHE_PROTOCOL_VERSION = 'v4-'
|
||||
|
||||
const CACHE_DISABLED_PARAMETER = 'cache-disabled'
|
||||
const CACHE_READONLY_PARAMETER = 'cache-read-only'
|
||||
const CACHE_DEBUG_VAR = 'GRADLE_BUILD_ACTION_CACHE_DEBUG_ENABLED'
|
||||
const CACHE_PREFIX_VAR = 'GRADLE_BUILD_ACTION_CACHE_KEY_PREFIX'
|
||||
|
||||
export function isCacheDisabled(): boolean {
|
||||
return core.getBooleanInput(CACHE_DISABLED_PARAMETER)
|
||||
}
|
||||
|
||||
export function isCacheReadOnly(): boolean {
|
||||
return core.getBooleanInput(CACHE_READONLY_PARAMETER)
|
||||
}
|
||||
|
||||
export function isCacheDebuggingEnabled(): boolean {
|
||||
return process.env[CACHE_DEBUG_VAR] ? true : false
|
||||
}
|
||||
|
||||
export function getCacheKeyPrefix(): string {
|
||||
// Prefix can be used to force change all cache keys (defaults to cache protocol version)
|
||||
return process.env[CACHE_PREFIX_VAR] || CACHE_PROTOCOL_VERSION
|
||||
}
|
||||
|
||||
export function hashStrings(values: string[]): string {
|
||||
const hash = crypto.createHash('md5')
|
||||
for (const value of values) {
|
||||
hash.update(value)
|
||||
}
|
||||
return hash.digest('hex')
|
||||
}
|
||||
|
||||
export function hashFileNames(fileNames: string[]): string {
|
||||
return hashStrings(fileNames.map(x => x.replace(new RegExp(`\\${path.sep}`, 'g'), '/')))
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to delete a file or directory, waiting to allow locks to be released
|
||||
*/
|
||||
export async function tryDelete(file: string): Promise<void> {
|
||||
const stat = fs.lstatSync(file)
|
||||
for (let count = 0; count < 3; count++) {
|
||||
try {
|
||||
if (stat.isDirectory()) {
|
||||
fs.rmdirSync(file, {recursive: true})
|
||||
} else {
|
||||
fs.unlinkSync(file)
|
||||
}
|
||||
return
|
||||
} catch (error) {
|
||||
if (count === 2) {
|
||||
throw error
|
||||
} else {
|
||||
core.warning(String(error))
|
||||
await delay(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function delay(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
94
src/caches.ts
Normal file
94
src/caches.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import {GradleUserHomeCache} from './cache-gradle-user-home'
|
||||
import {ProjectDotGradleCache} from './cache-project-dot-gradle'
|
||||
import * as core from '@actions/core'
|
||||
import {isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||
import {CacheEntryListener, CacheListener} from './cache-base'
|
||||
|
||||
const BUILD_ROOT_DIR = 'BUILD_ROOT_DIR'
|
||||
const CACHE_LISTENER = 'CACHE_LISTENER'
|
||||
|
||||
export async function restore(buildRootDirectory: string): Promise<void> {
|
||||
if (isCacheDisabled()) {
|
||||
core.info('Cache is disabled: will not restore state from previous builds.')
|
||||
return
|
||||
}
|
||||
|
||||
await core.group('Restore Gradle state from cache', async () => {
|
||||
core.saveState(BUILD_ROOT_DIR, buildRootDirectory)
|
||||
|
||||
const cacheListener = new CacheListener()
|
||||
await new GradleUserHomeCache(buildRootDirectory).restore(cacheListener)
|
||||
|
||||
const projectDotGradleCache = new ProjectDotGradleCache(buildRootDirectory)
|
||||
if (cacheListener.fullyRestored) {
|
||||
// Only restore the configuration-cache if the Gradle Home is fully restored
|
||||
await projectDotGradleCache.restore(cacheListener)
|
||||
} else {
|
||||
// Otherwise, prepare the cache key for later save()
|
||||
core.info('Gradle Home cache not fully restored: not restoring configuration-cache state')
|
||||
projectDotGradleCache.prepareCacheKey()
|
||||
}
|
||||
|
||||
core.saveState(CACHE_LISTENER, cacheListener.stringify())
|
||||
})
|
||||
}
|
||||
|
||||
export async function save(): Promise<void> {
|
||||
const cacheListener: CacheListener = CacheListener.rehydrate(core.getState(CACHE_LISTENER))
|
||||
|
||||
if (isCacheReadOnly()) {
|
||||
core.info('Cache is read-only: will not save state for use in subsequent builds.')
|
||||
logCachingReport(cacheListener)
|
||||
return
|
||||
}
|
||||
|
||||
await core.group('Caching Gradle state', async () => {
|
||||
const buildRootDirectory = core.getState(BUILD_ROOT_DIR)
|
||||
return Promise.all([
|
||||
new GradleUserHomeCache(buildRootDirectory).save(cacheListener),
|
||||
new ProjectDotGradleCache(buildRootDirectory).save(cacheListener)
|
||||
])
|
||||
})
|
||||
|
||||
logCachingReport(cacheListener)
|
||||
}
|
||||
|
||||
function logCachingReport(listener: CacheListener): void {
|
||||
core.info(`---------- Caching Summary -------------
|
||||
Restored Entries Count: ${getCount(listener.cacheEntries, e => e.restoredSize)}
|
||||
Size: ${getSum(listener.cacheEntries, e => e.restoredSize)}
|
||||
Saved Entries Count: ${getCount(listener.cacheEntries, e => e.savedSize)}
|
||||
Size: ${getSum(listener.cacheEntries, e => e.savedSize)}`)
|
||||
|
||||
core.startGroup('Cache Entry details')
|
||||
for (const entry of listener.cacheEntries) {
|
||||
core.info(`Entry: ${entry.entryName}
|
||||
Requested Key : ${entry.requestedKey ?? ''}
|
||||
Restored Key : ${entry.restoredKey ?? ''}
|
||||
Size: ${formatSize(entry.restoredSize)}
|
||||
Saved Key : ${entry.savedKey ?? ''}
|
||||
Size: ${formatSize(entry.savedSize)}`)
|
||||
}
|
||||
core.endGroup()
|
||||
}
|
||||
|
||||
function getCount(
|
||||
cacheEntries: CacheEntryListener[],
|
||||
predicate: (value: CacheEntryListener) => number | undefined
|
||||
): number {
|
||||
return cacheEntries.filter(e => predicate(e) !== undefined).length
|
||||
}
|
||||
|
||||
function getSum(
|
||||
cacheEntries: CacheEntryListener[],
|
||||
predicate: (value: CacheEntryListener) => number | undefined
|
||||
): string {
|
||||
return formatSize(cacheEntries.map(e => predicate(e) ?? 0).reduce((p, v) => p + v, 0))
|
||||
}
|
||||
|
||||
function formatSize(bytes: number | undefined): string {
|
||||
if (bytes === undefined || bytes === 0) {
|
||||
return ''
|
||||
}
|
||||
return `${Math.round(bytes / (1024 * 1024))} MB (${bytes} B)`
|
||||
}
|
@@ -1,40 +1,40 @@
|
||||
import * as exec from "@actions/exec";
|
||||
import * as exec from '@actions/exec'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import {writeInitScript} from './build-scan-capture'
|
||||
|
||||
export async function execute(executable: string, root: string, args: string[]): Promise<BuildResult> {
|
||||
let buildScanUrl: string | undefined
|
||||
|
||||
export async function execute(executable: string, root: string, argv: string[]): Promise<BuildResult> {
|
||||
// TODO: instead of running with no-daemon, run `--stop` in post action.
|
||||
args.push('--no-daemon')
|
||||
|
||||
let publishing = false;
|
||||
let buildScanLink: any = null;
|
||||
const initScript = writeInitScript()
|
||||
args.push('--init-script')
|
||||
args.push(initScript)
|
||||
|
||||
await exec.exec(executable, argv, {
|
||||
const buildScanFile = path.resolve(root, 'gradle-build-scan.txt')
|
||||
if (fs.existsSync(buildScanFile)) {
|
||||
fs.unlinkSync(buildScanFile)
|
||||
}
|
||||
|
||||
const status: number = await exec.exec(executable, args, {
|
||||
cwd: root,
|
||||
listeners: {
|
||||
stdline: (line: string) => {
|
||||
if (line.startsWith("Publishing build scan...")) {
|
||||
publishing = true;
|
||||
}
|
||||
if (publishing && line.length == 0) {
|
||||
publishing = false
|
||||
}
|
||||
if (publishing && line.startsWith("http")) {
|
||||
buildScanLink = line.trim();
|
||||
publishing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
|
||||
if (buildScanLink != null) {
|
||||
return new BuildResultImpl(buildScanLink.toString());
|
||||
if (fs.existsSync(buildScanFile)) {
|
||||
buildScanUrl = fs.readFileSync(buildScanFile, 'utf-8')
|
||||
}
|
||||
return new BuildResultImpl(null as unknown as string);
|
||||
|
||||
return new BuildResultImpl(status, buildScanUrl)
|
||||
}
|
||||
|
||||
export interface BuildResult {
|
||||
buildScanUrl: string
|
||||
readonly status: number
|
||||
readonly buildScanUrl?: string
|
||||
}
|
||||
|
||||
class BuildResultImpl implements BuildResult {
|
||||
constructor(readonly buildScanUrl: string) {
|
||||
}
|
||||
constructor(readonly status: number, readonly buildScanUrl?: string) {}
|
||||
}
|
||||
|
@@ -1,9 +1,26 @@
|
||||
export function wrapperFilename() {
|
||||
const isWindows = process.platform === "win32";
|
||||
return isWindows ? "gradlew.bat" : "gradlew";
|
||||
import * as path from 'path'
|
||||
import fs from 'fs'
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32'
|
||||
|
||||
export function wrapperScriptFilename(): string {
|
||||
return IS_WINDOWS ? 'gradlew.bat' : 'gradlew'
|
||||
}
|
||||
|
||||
export function installScriptFilename() {
|
||||
const isWindows = process.platform === "win32";
|
||||
return isWindows ? "gradle.bat" : "gradle";
|
||||
export function installScriptFilename(): string {
|
||||
return IS_WINDOWS ? 'gradle.bat' : 'gradle'
|
||||
}
|
||||
|
||||
export function locateGradleWrapperScript(buildRootDirectory: string): string {
|
||||
validateGradleWrapper(buildRootDirectory)
|
||||
return path.resolve(buildRootDirectory, wrapperScriptFilename())
|
||||
}
|
||||
|
||||
function validateGradleWrapper(buildRootDirectory: string): void {
|
||||
const wrapperProperties = path.resolve(buildRootDirectory, 'gradle/wrapper/gradle-wrapper.properties')
|
||||
if (!fs.existsSync(wrapperProperties)) {
|
||||
throw new Error(
|
||||
`Cannot locate a Gradle wrapper properties file at '${wrapperProperties}'. Specify 'gradle-version' or 'gradle-executable' for projects without Gradle wrapper configured.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
101
src/main.ts
101
src/main.ts
@@ -1,74 +1,75 @@
|
||||
import * as core from "@actions/core";
|
||||
import * as path from "path";
|
||||
import {parseArgsStringToArgv} from "string-argv";
|
||||
import * as core from '@actions/core'
|
||||
import * as path from 'path'
|
||||
import {parseArgsStringToArgv} from 'string-argv'
|
||||
|
||||
import * as execution from "./execution";
|
||||
import * as gradlew from "./gradlew";
|
||||
import * as provision from "./provision";
|
||||
import * as caches from './caches'
|
||||
import * as execution from './execution'
|
||||
import * as gradlew from './gradlew'
|
||||
import * as provision from './provision'
|
||||
|
||||
|
||||
// Invoked by Github Actions
|
||||
async function run() {
|
||||
// Invoked by GitHub Actions
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
const workspaceDirectory = process.env[`GITHUB_WORKSPACE`] || ''
|
||||
const buildRootDirectory = resolveBuildRootDirectory(workspaceDirectory)
|
||||
|
||||
const baseDirectory = process.env[`GITHUB_WORKSPACE`] || "";
|
||||
await caches.restore(buildRootDirectory)
|
||||
|
||||
let result = await execution.execute(
|
||||
await resolveGradleExecutable(baseDirectory),
|
||||
resolveBuildRootDirectory(baseDirectory),
|
||||
parseCommandLineArguments()
|
||||
);
|
||||
const args: string[] = parseCommandLineArguments()
|
||||
|
||||
if (result.buildScanUrl != null) {
|
||||
core.setOutput("build-scan-url", result.buildScanUrl);
|
||||
const result = await execution.execute(
|
||||
await resolveGradleExecutable(workspaceDirectory, buildRootDirectory),
|
||||
buildRootDirectory,
|
||||
args
|
||||
)
|
||||
|
||||
if (result.buildScanUrl) {
|
||||
core.setOutput('build-scan-url', result.buildScanUrl)
|
||||
}
|
||||
|
||||
if (result.status !== 0) {
|
||||
if (result.buildScanUrl) {
|
||||
core.setFailed(`Gradle build failed: ${result.buildScanUrl}`)
|
||||
} else {
|
||||
core.setFailed(`Gradle build failed: process exited with status ${result.status}`)
|
||||
}
|
||||
} else {
|
||||
if (result.buildScanUrl) {
|
||||
core.notice(`Gradle build succeeded: ${result.buildScanUrl}`)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
core.setFailed(String(error))
|
||||
if (error instanceof Error && error.stack) {
|
||||
core.info(error.stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
||||
|
||||
run();
|
||||
|
||||
|
||||
async function resolveGradleExecutable(baseDirectory: string): Promise<string> {
|
||||
|
||||
const gradleVersion = inputOrNull("gradle-version");
|
||||
if (gradleVersion != null) {
|
||||
return provision.gradleVersion(gradleVersion)
|
||||
async function resolveGradleExecutable(workspaceDirectory: string, buildRootDirectory: string): Promise<string> {
|
||||
const gradleVersion = core.getInput('gradle-version')
|
||||
if (gradleVersion !== '' && gradleVersion !== 'wrapper') {
|
||||
return path.resolve(await provision.gradleVersion(gradleVersion))
|
||||
}
|
||||
|
||||
const gradleExecutable = inputOrNull("gradle-executable");
|
||||
if (gradleExecutable != null) {
|
||||
return path.join(baseDirectory, gradleExecutable)
|
||||
const gradleExecutable = core.getInput('gradle-executable')
|
||||
if (gradleExecutable !== '') {
|
||||
return path.resolve(workspaceDirectory, gradleExecutable)
|
||||
}
|
||||
|
||||
const wrapperDirectory = inputOrNull("wrapper-directory");
|
||||
const executableDirectory = wrapperDirectory != null
|
||||
? path.join(baseDirectory, wrapperDirectory)
|
||||
: baseDirectory;
|
||||
|
||||
return path.join(executableDirectory, gradlew.wrapperFilename());
|
||||
return gradlew.locateGradleWrapperScript(buildRootDirectory)
|
||||
}
|
||||
|
||||
|
||||
function resolveBuildRootDirectory(baseDirectory: string): string {
|
||||
let buildRootDirectory = inputOrNull("build-root-directory");
|
||||
return buildRootDirectory == null ? baseDirectory : path.join(baseDirectory, buildRootDirectory);
|
||||
const buildRootDirectory = core.getInput('build-root-directory')
|
||||
const resolvedBuildRootDirectory =
|
||||
buildRootDirectory === '' ? path.resolve(baseDirectory) : path.resolve(baseDirectory, buildRootDirectory)
|
||||
return resolvedBuildRootDirectory
|
||||
}
|
||||
|
||||
|
||||
function parseCommandLineArguments(): string[] {
|
||||
const input = inputOrNull("arguments");
|
||||
return input == null ? [] : parseArgsStringToArgv(input)
|
||||
}
|
||||
|
||||
|
||||
function inputOrNull(name: string): string | null {
|
||||
const inputString = core.getInput(name);
|
||||
if (inputString.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return inputString
|
||||
const input = core.getInput('arguments')
|
||||
return parseArgsStringToArgv(input)
|
||||
}
|
||||
|
16
src/post.ts
Normal file
16
src/post.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as caches from './caches'
|
||||
|
||||
// Invoked by GitHub Actions
|
||||
export async function run(): Promise<void> {
|
||||
try {
|
||||
await caches.save()
|
||||
} catch (error) {
|
||||
core.setFailed(String(error))
|
||||
if (error instanceof Error && error.stack) {
|
||||
core.info(error.stack)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
235
src/provision.ts
235
src/provision.ts
@@ -1,163 +1,160 @@
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as httpm from 'typed-rest-client/HttpClient';
|
||||
import * as unzip from "unzipper"
|
||||
import * as core from "@actions/core";
|
||||
import * as io from '@actions/io';
|
||||
import * as toolCache from "@actions/tool-cache";
|
||||
import * as fs from 'fs'
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
import * as httpm from '@actions/http-client'
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
|
||||
import * as gradlew from "./gradlew";
|
||||
import * as gradlew from './gradlew'
|
||||
import {isCacheDisabled, isCacheReadOnly} from './cache-utils'
|
||||
|
||||
const gradleVersionsBaseUrl = 'https://services.gradle.org/versions'
|
||||
|
||||
/**
|
||||
* @return Gradle executable
|
||||
* @return Gradle executable path
|
||||
*/
|
||||
export async function gradleVersion(gradleVersion: string): Promise<string> {
|
||||
switch (gradleVersion) {
|
||||
case "current":
|
||||
return gradleCurrent();
|
||||
case "rc":
|
||||
return gradleReleaseCandidate();
|
||||
case "nightly":
|
||||
return gradleNightly();
|
||||
case "release-nightly":
|
||||
return gradleReleaseNightly();
|
||||
export async function gradleVersion(version: string): Promise<string> {
|
||||
switch (version) {
|
||||
case 'current':
|
||||
return gradleCurrent()
|
||||
case 'rc':
|
||||
core.warning(`Specifying gradle-version 'rc' has been deprecated. Use 'release-candidate' instead.`)
|
||||
return gradleReleaseCandidate()
|
||||
case 'release-candidate':
|
||||
return gradleReleaseCandidate()
|
||||
case 'nightly':
|
||||
return gradleNightly()
|
||||
case 'release-nightly':
|
||||
return gradleReleaseNightly()
|
||||
default:
|
||||
return gradle(gradleVersion);
|
||||
return gradle(version)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const gradleVersionsBaseUrl = "https://services.gradle.org/versions";
|
||||
|
||||
|
||||
async function gradleCurrent(): Promise<string> {
|
||||
const json = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/current`);
|
||||
return provisionGradle(json.version, json.downloadUrl);
|
||||
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/current`)
|
||||
return provisionGradle(versionInfo)
|
||||
}
|
||||
|
||||
|
||||
async function gradleReleaseCandidate(): Promise<string> {
|
||||
const json = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-candidate`);
|
||||
if (json != null) {
|
||||
return provisionGradle(json.version, json.downloadUrl);
|
||||
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-candidate`)
|
||||
if (versionInfo && versionInfo.version && versionInfo.downloadUrl) {
|
||||
return provisionGradle(versionInfo)
|
||||
}
|
||||
return gradleCurrent();
|
||||
core.info('No current release-candidate found, will fallback to current')
|
||||
return gradleCurrent()
|
||||
}
|
||||
|
||||
|
||||
async function gradleNightly(): Promise<string> {
|
||||
const json = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/nightly`);
|
||||
return provisionGradle(json.version, json.downloadUrl);
|
||||
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/nightly`)
|
||||
return provisionGradle(versionInfo)
|
||||
}
|
||||
|
||||
|
||||
async function gradleReleaseNightly(): Promise<string> {
|
||||
const json = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-nightly`);
|
||||
return provisionGradle(json.version, json.downloadUrl);
|
||||
const versionInfo = await gradleVersionDeclaration(`${gradleVersionsBaseUrl}/release-nightly`)
|
||||
return provisionGradle(versionInfo)
|
||||
}
|
||||
|
||||
|
||||
async function gradle(version: string): Promise<string> {
|
||||
const declaration = await findGradleVersionDeclaration(version);
|
||||
if (declaration == null) {
|
||||
throw new Error(`Gradle version ${version} does not exists`);
|
||||
const versionInfo = await findGradleVersionDeclaration(version)
|
||||
if (!versionInfo) {
|
||||
throw new Error(`Gradle version ${version} does not exists`)
|
||||
}
|
||||
return provisionGradle(declaration.version, declaration.downloadUrl);
|
||||
return provisionGradle(versionInfo)
|
||||
}
|
||||
|
||||
|
||||
async function gradleVersionDeclaration(url: string): Promise<any | null> {
|
||||
const httpc = new httpm.HttpClient("gradle-github-action");
|
||||
const response = await httpc.get(url);
|
||||
const body = await response.readBody();
|
||||
const json = JSON.parse(body);
|
||||
return (json == null || json.version == null || json.version.length <= 0)
|
||||
? null
|
||||
: json
|
||||
async function gradleVersionDeclaration(url: string): Promise<GradleVersionInfo> {
|
||||
return await httpGetGradleVersion(url)
|
||||
}
|
||||
|
||||
|
||||
async function findGradleVersionDeclaration(version: string): Promise<any | null> {
|
||||
const httpc = new httpm.HttpClient("gradle-github-action");
|
||||
const response = await httpc.get(`${gradleVersionsBaseUrl}/all`);
|
||||
const body = await response.readBody();
|
||||
const json = JSON.parse(body);
|
||||
const found = json.find(entry => {
|
||||
return entry.version == version;
|
||||
});
|
||||
return found != undefined ? found : null
|
||||
async function findGradleVersionDeclaration(version: string): Promise<GradleVersionInfo | undefined> {
|
||||
const gradleVersions = await httpGetGradleVersions(`${gradleVersionsBaseUrl}/all`)
|
||||
return gradleVersions.find((entry: GradleVersionInfo) => {
|
||||
return entry.version === version
|
||||
})
|
||||
}
|
||||
|
||||
async function provisionGradle(version: string, url: string): Promise<string> {
|
||||
async function provisionGradle(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
return core.group(`Provision Gradle ${versionInfo.version}`, async () => {
|
||||
return locateGradleAndDownloadIfRequired(versionInfo)
|
||||
})
|
||||
}
|
||||
|
||||
const cachedInstall: string = toolCache.find("gradle", version);
|
||||
if (cachedInstall != null && cachedInstall.length > 0) {
|
||||
const cachedExecutable = executableFrom(cachedInstall);
|
||||
core.info(`Provisioned Gradle executable ${cachedExecutable}`);
|
||||
return cachedExecutable;
|
||||
async function locateGradleAndDownloadIfRequired(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
const installsDir = path.join(os.homedir(), 'gradle-installations/installs')
|
||||
const installDir = path.join(installsDir, `gradle-${versionInfo.version}`)
|
||||
if (fs.existsSync(installDir)) {
|
||||
core.info(`Gradle installation already exists at ${installDir}`)
|
||||
return executableFrom(installDir)
|
||||
}
|
||||
|
||||
const home = process.env["HOME"] || "";
|
||||
const tmpdir = path.join(home, "gradle-provision-tmpdir");
|
||||
const downloadsDir = path.join(tmpdir, "downloads");
|
||||
const installsDir = path.join(tmpdir, "installs");
|
||||
await io.mkdirP(downloadsDir);
|
||||
await io.mkdirP(installsDir);
|
||||
const downloadPath = await downloadAndCacheGradleDistribution(versionInfo)
|
||||
await toolCache.extractZip(downloadPath, installsDir)
|
||||
core.info(`Extracted Gradle ${versionInfo.version} to ${installDir}`)
|
||||
|
||||
core.info(`Downloading ${url}`);
|
||||
const executable = executableFrom(installDir)
|
||||
fs.chmodSync(executable, '755')
|
||||
core.info(`Provisioned Gradle executable ${executable}`)
|
||||
|
||||
const downloadPath = path.join(downloadsDir, `gradle-${version}-bin.zip`);
|
||||
await httpDownload(url, downloadPath);
|
||||
core.info(`Downloaded at ${downloadPath}, size ${fs.statSync(downloadPath).size}`);
|
||||
|
||||
await extractZip(downloadPath, installsDir);
|
||||
const installDir = path.join(installsDir, `gradle-${version}`);
|
||||
core.info(`Extracted in ${installDir}`);
|
||||
|
||||
const executable = executableFrom(installDir);
|
||||
fs.chmodSync(executable, "755");
|
||||
core.info(`Provisioned Gradle executable ${executable}`);
|
||||
|
||||
toolCache.cacheDir(installDir, "gradle", version);
|
||||
|
||||
return executable;
|
||||
return executable
|
||||
}
|
||||
|
||||
async function downloadAndCacheGradleDistribution(versionInfo: GradleVersionInfo): Promise<string> {
|
||||
const downloadPath = path.join(os.homedir(), `gradle-installations/downloads/gradle-${versionInfo.version}-bin.zip`)
|
||||
|
||||
if (isCacheDisabled()) {
|
||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||
return downloadPath
|
||||
}
|
||||
|
||||
const cacheKey = `gradle-${versionInfo.version}`
|
||||
const restoreKey = await cache.restoreCache([downloadPath], cacheKey)
|
||||
if (restoreKey) {
|
||||
core.info(`Restored Gradle distribution ${cacheKey} from cache to ${downloadPath}`)
|
||||
return downloadPath
|
||||
}
|
||||
core.info(`Gradle distribution ${versionInfo.version} not found in cache. Will download.`)
|
||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||
|
||||
if (!isCacheReadOnly()) {
|
||||
try {
|
||||
await cache.saveCache([downloadPath], cacheKey)
|
||||
} catch (error) {
|
||||
// Fail on validation errors or non-errors (the latter to keep Typescript happy)
|
||||
if (error instanceof cache.ValidationError || !(error instanceof Error)) {
|
||||
throw error
|
||||
}
|
||||
core.warning(error.message)
|
||||
}
|
||||
}
|
||||
return downloadPath
|
||||
}
|
||||
|
||||
async function downloadGradleDistribution(versionInfo: GradleVersionInfo, downloadPath: string): Promise<void> {
|
||||
await toolCache.downloadTool(versionInfo.downloadUrl, downloadPath)
|
||||
core.info(`Downloaded ${versionInfo.downloadUrl} to ${downloadPath} (size ${fs.statSync(downloadPath).size})`)
|
||||
}
|
||||
|
||||
function executableFrom(installDir: string): string {
|
||||
return path.join(installDir, "bin", `${gradlew.installScriptFilename()}`);
|
||||
return path.join(installDir, 'bin', `${gradlew.installScriptFilename()}`)
|
||||
}
|
||||
|
||||
|
||||
async function httpDownload(url: string, path: string): Promise<void> {
|
||||
return new Promise<void>(function (resolve, reject) {
|
||||
const httpc = new httpm.HttpClient("gradle-github-action");
|
||||
const writeStream = fs.createWriteStream(path);
|
||||
httpc.get(url).then(response => {
|
||||
response.message.pipe(writeStream)
|
||||
.on("close", () => {
|
||||
resolve();
|
||||
})
|
||||
.on("error", err => {
|
||||
reject(err)
|
||||
});
|
||||
}).catch(reason => {
|
||||
reject(reason);
|
||||
});
|
||||
});
|
||||
async function httpGetGradleVersion(url: string): Promise<GradleVersionInfo> {
|
||||
return JSON.parse(await httpGetString(url))
|
||||
}
|
||||
|
||||
|
||||
async function extractZip(zip: string, destination: string): Promise<void> {
|
||||
return new Promise<void>(function (resolve, reject) {
|
||||
fs.createReadStream(zip)
|
||||
.pipe(unzip.Extract({"path": destination}))
|
||||
.on("close", () => {
|
||||
resolve();
|
||||
})
|
||||
.on("error", err => {
|
||||
reject(err)
|
||||
});
|
||||
});
|
||||
async function httpGetGradleVersions(url: string): Promise<GradleVersionInfo[]> {
|
||||
return JSON.parse(await httpGetString(url))
|
||||
}
|
||||
|
||||
async function httpGetString(url: string): Promise<string> {
|
||||
const httpClient = new httpm.HttpClient('gradle/gradle-build-action')
|
||||
const response = await httpClient.get(url)
|
||||
return response.readBody()
|
||||
}
|
||||
|
||||
interface GradleVersionInfo {
|
||||
version: string
|
||||
downloadUrl: string
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"incremental": false, /* Enable incremental compilation */
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
@@ -15,7 +15,7 @@
|
||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
"removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
@@ -23,13 +23,13 @@
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
"strictNullChecks": true, /* Enable strict null checks. */
|
||||
"strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
"strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
"strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
|
Reference in New Issue
Block a user