mirror of
https://github.com/gradle/gradle-build-action.git
synced 2025-10-20 07:08:56 +08:00
Compare commits
120 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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",
|
||||
"@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,24 @@
|
||||
name: "PR Checks"
|
||||
on: [pull_request, push]
|
||||
# make sure the build works and doesn't produce spurious changes
|
||||
name: dev
|
||||
|
||||
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)
|
93
.github/workflows/prod.yml
vendored
Normal file
93
.github/workflows/prod.yml
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
# make sure the action works on a clean machine without building
|
||||
name: prod
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
gradle-execution:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-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 Gradle wrapper
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/basic
|
||||
arguments: test
|
||||
- name: Test use defined Gradle version
|
||||
uses: ./
|
||||
with:
|
||||
gradle-version: 6.9
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help
|
||||
- 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/basic/gradlew${{ matrix.script-suffix }}
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
arguments: help
|
||||
- name: Test custom wrapper location (deprecated)
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/no-wrapper
|
||||
wrapper-directory: __tests__/samples/basic
|
||||
arguments: help
|
||||
|
||||
dependencies-cache:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test dependencies-cache-enabled
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/basic
|
||||
arguments: test --no-daemon
|
||||
dependencies-cache-enabled: true
|
||||
|
||||
configuration-cache:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Test configuration-cache-enabled
|
||||
uses: ./
|
||||
with:
|
||||
build-root-directory: __tests__/samples/basic
|
||||
arguments: test --configuration-cache --no-daemon
|
||||
configuration-cache-enabled: true
|
||||
dependencies-cache-enabled: true
|
||||
# Configuration cache requires dependencies cache, since it assumes dependencies are already downloaded.
|
||||
|
||||
|
||||
failures: # These build invocations are informational only, and are expected to fail
|
||||
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
|
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": 80,
|
||||
"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
|
172
README.md
172
README.md
@@ -1,16 +1,15 @@
|
||||
# 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` using the wrapper from the repository 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,11 +17,11 @@ 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@v1
|
||||
with:
|
||||
arguments: build
|
||||
```
|
||||
@@ -43,10 +42,10 @@ arguments: build -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, simply use the GitHub Actions workflow syntax:
|
||||
|
||||
```yaml
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
env:
|
||||
CI: true
|
||||
```
|
||||
@@ -54,33 +53,35 @@ If you need to pass environment variables, simply use the Github Actions workflo
|
||||
## Run a build from a different directory
|
||||
|
||||
```yaml
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
with:
|
||||
build-root-directory: some/subdirectory
|
||||
```
|
||||
|
||||
## Use a specific `gradle` executable
|
||||
|
||||
```yaml
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
with:
|
||||
gradle-executable: path/to/gradle
|
||||
```
|
||||
|
||||
## Use a Gradle wrapper from a different directory
|
||||
|
||||
```yaml
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
with:
|
||||
wrapper-directory: path/to/wrapper-directory
|
||||
gradle-executable: path/to/gradlew
|
||||
```
|
||||
|
||||
## Use a specific `gradle` executable
|
||||
|
||||
```yaml
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
with:
|
||||
gradle-executable: path/to/gradle
|
||||
```
|
||||
NOTE: The `wrapper-directory` input has been deprecated. Use `gradle-executable` instead.
|
||||
|
||||
## Setup and use a declared Gradle version
|
||||
|
||||
```yaml
|
||||
- uses: eskatos/gradle-command-action@v1
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
with:
|
||||
gradle-version: 5.6.2
|
||||
gradle-version: 6.5
|
||||
```
|
||||
|
||||
`gradle-version` can be set to any valid Gradle version.
|
||||
@@ -89,15 +90,16 @@ Moreover, you can use the following aliases:
|
||||
|
||||
| Alias | Selects |
|
||||
| --- |---|
|
||||
| `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` |
|
||||
| `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. |
|
||||
| `wrapper` | The Gradle wrapper's version (default, useful for matrix builds) |
|
||||
| `current` | The current [stable release](https://gradle.org/install/) |
|
||||
| `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, for example, automatically test your build with the next Gradle version once a release candidate is out:
|
||||
|
||||
```yaml
|
||||
// .github/workflows/test-gradle-rc.yml
|
||||
# .github/workflows/test-gradle-rc.yml
|
||||
name: Test latest Gradle RC
|
||||
on:
|
||||
schedule:
|
||||
@@ -106,18 +108,122 @@ 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@v1
|
||||
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`.
|
||||
This action provides 3 levels of caching to help speed up your GitHub Actions:
|
||||
|
||||
- `distributions` caches any downloaded Gradle zips, including any downloaded [wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html) versions, saving time downloading Gradle distributions ;
|
||||
- `dependencies` caches the [dependencies](https://docs.gradle.org/current/userguide/dependency_resolution.html#sub:cache_copy), saving time downloading dependencies ;
|
||||
- `configuration` caches the [build configuration](https://docs.gradle.org/nightly/userguide/configuration_cache.html), saving time configuring the build.
|
||||
|
||||
Only the first one, caching downloaded distributions, is enabled by default.
|
||||
Future versions of this action will enable all caching by default.
|
||||
|
||||
You can control which level is enabled as follows:
|
||||
|
||||
```yaml
|
||||
distributions-cache-enabled: true
|
||||
dependencies-cache-enabled: true
|
||||
configuration-cache-enabled: true
|
||||
```
|
||||
|
||||
NOTE: The `wrapper-cache-enabled` flag has been deprecated, replaced by `distributions-cache-enabled` which enables caching for all downloaded distributions, including Gradle wrapper downloads.
|
||||
|
||||
The distributions cache is simple and can't be configured further.
|
||||
|
||||
The dependencies and configuration cache will compute a cache key in a best effort manner.
|
||||
Keep reading to learn how to better control how they work.
|
||||
|
||||
Note that enabling configuration cache without thee dependencies cache is not permitted, since a hit in the configuration cache assumes that dependencies are already present in the local dependencies cache.
|
||||
|
||||
### Configuring the dependencies and configuration caches
|
||||
|
||||
Both the dependencies and configuration caches use the same default configuration:
|
||||
|
||||
They use the following inputs to calculate the cache key:
|
||||
|
||||
```text
|
||||
**/*.gradle
|
||||
**/*.gradle.kts
|
||||
**/gradle.properties
|
||||
gradle/**
|
||||
```
|
||||
|
||||
This is a good enough approximation.
|
||||
They restore cached state even if there isn't an exact match.
|
||||
|
||||
If the defaults don't suit your needs you can override them with the following inputs:
|
||||
|
||||
```yaml
|
||||
dependencies-cache-key: |
|
||||
**/gradle.properties
|
||||
gradle/dependency-locks/**
|
||||
dependencies-cache-exact: true
|
||||
configuration-cache-key: |
|
||||
**/gradle.properties
|
||||
gradle/dependency-locks/**
|
||||
configuration-cache-exact: true
|
||||
```
|
||||
|
||||
Coming up with a good cache key isn't trivial and depends on your build.
|
||||
The above example isn't realistic.
|
||||
Stick to the defaults unless you know what you are doing.
|
||||
|
||||
If you happen to use Gradle [dependency locking](https://docs.gradle.org/current/userguide/dependency_locking.html) you can make the dependencies cache more precise with the following configuration:
|
||||
|
||||
```yaml
|
||||
dependencies-cache-enabled: true
|
||||
dependencies-cache-key: gradle/dependency-locks/**
|
||||
dependencies-cache-exact: true
|
||||
```
|
||||
|
||||
## Build scans
|
||||
|
||||
If your build publishes a [build scan](https://gradle.com/build-scans/) the `gradle-build-action` action will 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:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- uses: gradle/gradle-build-action@v1
|
||||
with:
|
||||
arguments: build
|
||||
id: gradle
|
||||
- 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 }}'
|
||||
})
|
||||
```
|
||||
|
33
__tests__/cache-wrapper.test.ts
Normal file
33
__tests__/cache-wrapper.test.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as cacheWrapper from '../src/cache-wrapper'
|
||||
import * as path from 'path'
|
||||
|
||||
describe('cache', () => {
|
||||
describe('can extract gradle wrapper slug', () => {
|
||||
it('from wrapper properties file', async () => {
|
||||
const version = cacheWrapper.extractGradleWrapperSlugFrom(
|
||||
path.resolve(
|
||||
'__tests__/data/cache-wrapper-test/gradle-wrapper.properties'
|
||||
)
|
||||
)
|
||||
expect(version).toBe('6.6.1-bin')
|
||||
})
|
||||
it('for -bin dist', async () => {
|
||||
const version = cacheWrapper.extractGradleWrapperSlugFromDistUri(
|
||||
'distributionUrl=https\\://services.gradle.org/distributions/gradle-6.6.1-bin.zip'
|
||||
)
|
||||
expect(version).toBe('6.6.1-bin')
|
||||
})
|
||||
it('for -all dist', async () => {
|
||||
const version = cacheWrapper.extractGradleWrapperSlugFromDistUri(
|
||||
'distributionUrl=https\\://services.gradle.org/distributions/gradle-6.6.1-all.zip'
|
||||
)
|
||||
expect(version).toBe('6.6.1-all')
|
||||
})
|
||||
it('for milestone', async () => {
|
||||
const version = cacheWrapper.extractGradleWrapperSlugFromDistUri(
|
||||
'distributionUrl=https\\://services.gradle.org/distributions/gradle-6.6-milestone-1-all.zip'
|
||||
)
|
||||
expect(version).toBe('6.6-milestone-1-all')
|
||||
})
|
||||
})
|
||||
})
|
39
__tests__/crypto-utils.test.ts
Normal file
39
__tests__/crypto-utils.test.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as cryptoUtils from '../src/crypto-utils'
|
||||
import * as path from 'path'
|
||||
|
||||
describe('crypto-utils', () => {
|
||||
describe('can hash', () => {
|
||||
it('a directory', async () => {
|
||||
const hash = await cryptoUtils.hashFiles(
|
||||
path.resolve('__tests__/data/crypto-utils-test/gradle')
|
||||
)
|
||||
expect(hash).toBe(
|
||||
process.platform === 'win32'
|
||||
? '3364336e94e746ce65a31748a6371b7efd7d499e18ad605c74c91cde0edc0a44'
|
||||
: '63b9f14f65d014e585099c9c274b9dcbddf5cfd1a8978e5a24efb89ff9304348'
|
||||
)
|
||||
})
|
||||
it('a directory with a glob', async () => {
|
||||
const hash = await cryptoUtils.hashFiles(
|
||||
path.resolve('__tests__/data/crypto-utils-test/'),
|
||||
['gradle/**']
|
||||
)
|
||||
expect(hash).toBe(
|
||||
process.platform === 'win32'
|
||||
? '3364336e94e746ce65a31748a6371b7efd7d499e18ad605c74c91cde0edc0a44'
|
||||
: '63b9f14f65d014e585099c9c274b9dcbddf5cfd1a8978e5a24efb89ff9304348'
|
||||
)
|
||||
})
|
||||
it('a directory with globs', async () => {
|
||||
const hash = await cryptoUtils.hashFiles(
|
||||
path.resolve('__tests__/data/crypto-utils-test/'),
|
||||
['**/*.gradle', 'gradle/**']
|
||||
)
|
||||
expect(hash).toBe(
|
||||
process.platform === 'win32'
|
||||
? 'd9b66fded38f79f601ce745d64ed726a8df8c0b242b02bcd2c1d331f54742ad6'
|
||||
: 'f42cd10636f09799f4e01cc84e7ae906cc1d9140f1446f8dcd054d19cbc44c2b'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
@@ -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 () => {});
|
||||
});
|
6
__tests__/samples/basic/.gitattributes
vendored
Normal file
6
__tests__/samples/basic/.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__/samples/basic/.gitignore
vendored
Normal file
5
__tests__/samples/basic/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
11
__tests__/samples/basic/build.gradle
Normal file
11
__tests__/samples/basic/build.gradle
Normal file
@@ -0,0 +1,11 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation('junit:junit:4.12')
|
||||
}
|
BIN
__tests__/samples/basic/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
__tests__/samples/basic/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
__tests__/samples/basic/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
__tests__/samples/basic/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/basic/gradlew
vendored
Executable file
185
__tests__/samples/basic/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/basic/gradlew.bat
vendored
Normal file
104
__tests__/samples/basic/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/basic/settings.gradle
Normal file
1
__tests__/samples/basic/settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = 'basic'
|
10
__tests__/samples/basic/src/test/java/basic/BasicTest.java
Normal file
10
__tests__/samples/basic/src/test/java/basic/BasicTest.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package basic;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BasicTest {
|
||||
@Test
|
||||
public void test() {
|
||||
assert true;
|
||||
}
|
||||
}
|
6
__tests__/samples/no-wrapper/.gitattributes
vendored
Normal file
6
__tests__/samples/no-wrapper/.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__/samples/no-wrapper/.gitignore
vendored
Normal file
5
__tests__/samples/no-wrapper/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
3
__tests__/samples/no-wrapper/settings.gradle
Normal file
3
__tests__/samples/no-wrapper/settings.gradle
Normal file
@@ -0,0 +1,3 @@
|
||||
rootProject.name = 'no-wrapper'
|
||||
|
||||
println "Using Gradle version: ${gradle.gradleVersion}"
|
41
action.yml
41
action.yml
@@ -1,6 +1,5 @@
|
||||
name: "Gradle Command"
|
||||
description: 'Execute Gradle Command Line'
|
||||
author: 'Paul Merlin <paul@nospere.org>'
|
||||
name: "Gradle Build Action"
|
||||
description: 'Execute Gradle Build'
|
||||
|
||||
# https://help.github.com/en/articles/metadata-syntax-for-github-actions
|
||||
|
||||
@@ -8,6 +7,7 @@ inputs:
|
||||
wrapper-directory:
|
||||
description: Path to the Gradle Wrapper directory
|
||||
required: false
|
||||
deprecationMessage: Use 'gradle-executable' to point to a gradlew[.bat] file in a non-default location
|
||||
gradle-executable:
|
||||
description: Path to the Gradle executable
|
||||
required: false
|
||||
@@ -20,6 +20,37 @@ inputs:
|
||||
arguments:
|
||||
description: Gradle command line arguments, see gradle --help
|
||||
required: false
|
||||
distributions-cache-enabled:
|
||||
description: Whether caching downloaded Gradle distributions is enabled or not, default to 'true'
|
||||
required: false
|
||||
default: true
|
||||
wrapper-cache-enabled:
|
||||
description: Whether caching wrapper installation is enabled or not, default to 'true'
|
||||
required: false
|
||||
default: true
|
||||
deprecationMessage: Replaced by 'distributions-cache-enabled' which enables caching for all downloaded Gradle distributions
|
||||
dependencies-cache-enabled:
|
||||
description: Whether caching dependencies is enabled or not, default to 'false'
|
||||
required: false
|
||||
default: false
|
||||
dependencies-cache-key:
|
||||
description: Globs of files to hash in the build root directory, separated by new lines, use best-effort if unset
|
||||
required: false
|
||||
dependencies-cache-exact:
|
||||
description: Whether to restore only if exact match, default to 'false'
|
||||
required: false
|
||||
default: false
|
||||
configuration-cache-enabled:
|
||||
description: Whether caching build configuration is enabled or not, default to 'false'
|
||||
required: false
|
||||
default: false
|
||||
configuration-cache-key:
|
||||
description: Globs of files to hash in the build root directory, separated by new lines, use best-effort if unset
|
||||
required: false
|
||||
configuration-cache-exact:
|
||||
description: Whether to restore only if exact match, default to 'false'
|
||||
required: false
|
||||
default: false
|
||||
|
||||
outputs:
|
||||
build-scan-url:
|
||||
@@ -27,7 +58,9 @@ outputs:
|
||||
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'lib/main.js'
|
||||
main: 'dist/main/index.js'
|
||||
post: 'dist/post/index.js'
|
||||
post-if: success()
|
||||
|
||||
branding:
|
||||
icon: 'box'
|
||||
|
1
dist/main/index.js
vendored
Normal file
1
dist/main/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/post/index.js
vendored
Normal file
1
dist/post/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -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
|
7414
package-lock.json
generated
7414
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
51
package.json
51
package.json
@@ -1,15 +1,19 @@
|
||||
{
|
||||
"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"
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"build": "ncc build src/main.ts --out dist/main --minify && ncc build src/post.ts --out dist/post --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",
|
||||
@@ -20,21 +24,28 @@
|
||||
"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.4.0",
|
||||
"@actions/exec": "1.1.0",
|
||||
"@actions/glob": "0.2.0",
|
||||
"@actions/http-client": "1.0.11",
|
||||
"@actions/tool-cache": "1.7.1",
|
||||
"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": "26.0.23",
|
||||
"@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": "26.6.3",
|
||||
"jest-circus": "26.6.3",
|
||||
"js-yaml": "3.14.1",
|
||||
"prettier": "2.3.2",
|
||||
"ts-jest": "26.5.6",
|
||||
"typescript": "4.3.5"
|
||||
}
|
||||
}
|
||||
|
106
src/cache-configuration.ts
Normal file
106
src/cache-configuration.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
|
||||
import * as crypto from './crypto-utils'
|
||||
|
||||
import {
|
||||
inputCacheKeyGlobs,
|
||||
tryDeleteFiles,
|
||||
isDependenciesCacheDisabled
|
||||
} from './cache-dependencies'
|
||||
|
||||
const CONFIGURATION_CACHE_PATH = 'CONFIGURATION_CACHE_PATH'
|
||||
const CONFIGURATION_CACHE_KEY = 'CONFIGURATION_CACHE_KEY'
|
||||
const CONFIGURATION_CACHE_RESULT = 'CONFIGURATION_CACHE_RESULT'
|
||||
|
||||
export async function restoreCachedConfiguration(
|
||||
rootDir: string
|
||||
): Promise<void> {
|
||||
if (isConfigurationCacheDisabled()) return
|
||||
|
||||
if (isDependenciesCacheDisabled()) {
|
||||
throw new Error(
|
||||
`Must enable dependencies-cache when configuration-cache is enabled`
|
||||
)
|
||||
}
|
||||
|
||||
const cachePath = path.resolve(rootDir, '.gradle/configuration-cache')
|
||||
if (fs.existsSync(cachePath)) return
|
||||
core.saveState(CONFIGURATION_CACHE_PATH, cachePath)
|
||||
|
||||
const inputCacheExact = core.getBooleanInput('configuration-cache-exact')
|
||||
const cacheKeyGlobs = inputCacheKeyGlobs('configuration-cache-key')
|
||||
|
||||
const hash = await crypto.hashFiles(rootDir, cacheKeyGlobs)
|
||||
const cacheKeyPrefix = 'configuration-'
|
||||
const cacheKey = `${cacheKeyPrefix}${hash}`
|
||||
core.saveState(CONFIGURATION_CACHE_KEY, cacheKey)
|
||||
|
||||
const cacheResult = await cache.restoreCache(
|
||||
[cachePath],
|
||||
cacheKey,
|
||||
inputCacheExact ? [] : [cacheKeyPrefix]
|
||||
)
|
||||
|
||||
if (!cacheResult) {
|
||||
core.info(
|
||||
'Configuration cache not found, expect task graph calculation.'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
core.saveState(CONFIGURATION_CACHE_RESULT, cacheResult)
|
||||
core.info(`Configuration restored from cache key: ${cacheResult}`)
|
||||
return
|
||||
}
|
||||
|
||||
export async function cacheConfiguration(): Promise<void> {
|
||||
if (isConfigurationCacheDisabled()) return
|
||||
|
||||
const cachePath = core.getState(CONFIGURATION_CACHE_PATH)
|
||||
const cacheKey = core.getState(CONFIGURATION_CACHE_KEY)
|
||||
const cacheResult = core.getState(CONFIGURATION_CACHE_RESULT)
|
||||
|
||||
if (!cachePath || !fs.existsSync(cachePath)) {
|
||||
core.debug('No configuration to cache.')
|
||||
return
|
||||
}
|
||||
|
||||
if (cacheResult && cacheKey === cacheResult) {
|
||||
core.info(
|
||||
`Configuration cache hit occurred on the cache key ${cacheKey}, not saving cache.`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const locksDeleted = tryDeleteFiles([
|
||||
path.resolve(cachePath, 'configuration-cache.lock')
|
||||
])
|
||||
if (!locksDeleted) {
|
||||
core.warning(
|
||||
'Unable to delete configuration lock files, try using --no-daemon or stopping the daemon last if you have several Gradle steps, not saving cache.'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await cache.saveCache([cachePath], cacheKey)
|
||||
} catch (error) {
|
||||
if (error.name === cache.ValidationError.name) {
|
||||
throw error
|
||||
} else if (error.name === cache.ReserveCacheError.name) {
|
||||
core.info(error.message)
|
||||
} else {
|
||||
core.info(`[warning] ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
function isConfigurationCacheDisabled(): boolean {
|
||||
return !core.getBooleanInput('configuration-cache-enabled')
|
||||
}
|
119
src/cache-dependencies.ts
Normal file
119
src/cache-dependencies.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import * as os from 'os'
|
||||
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
|
||||
import * as crypto from './crypto-utils'
|
||||
|
||||
const DEPENDENCIES_CACHE_PATH = 'DEPENDENCIES_CACHE_PATH'
|
||||
const DEPENDENCIES_CACHE_KEY = 'DEPENDENCIES_CACHE_KEY'
|
||||
const DEPENDENCIES_CACHE_RESULT = 'DEPENDENCIES_CACHE_RESULT'
|
||||
|
||||
export async function restoreCachedDependencies(
|
||||
rootDir: string
|
||||
): Promise<void> {
|
||||
if (isDependenciesCacheDisabled()) return
|
||||
|
||||
const cachePath = path.resolve(os.homedir(), '.gradle/caches/modules-2')
|
||||
if (fs.existsSync(cachePath)) return
|
||||
core.saveState(DEPENDENCIES_CACHE_PATH, cachePath)
|
||||
|
||||
const inputCacheExact = core.getBooleanInput('dependencies-cache-exact')
|
||||
const cacheKeyGlobs = inputCacheKeyGlobs('dependencies-cache-key')
|
||||
|
||||
const hash = await crypto.hashFiles(rootDir, cacheKeyGlobs)
|
||||
const cacheKeyPrefix = 'dependencies-'
|
||||
const cacheKey = `${cacheKeyPrefix}${hash}`
|
||||
core.saveState(DEPENDENCIES_CACHE_KEY, cacheKey)
|
||||
|
||||
const cacheResult = await cache.restoreCache(
|
||||
[cachePath],
|
||||
cacheKey,
|
||||
inputCacheExact ? [] : [cacheKeyPrefix]
|
||||
)
|
||||
|
||||
if (!cacheResult) {
|
||||
core.info('Dependencies cache not found, expect dependencies download.')
|
||||
return
|
||||
}
|
||||
|
||||
core.saveState(DEPENDENCIES_CACHE_RESULT, cacheResult)
|
||||
core.info(`Dependencies restored from cache key: ${cacheResult}`)
|
||||
return
|
||||
}
|
||||
|
||||
export async function cacheDependencies(): Promise<void> {
|
||||
if (isDependenciesCacheDisabled()) return
|
||||
|
||||
const cachePath = core.getState(DEPENDENCIES_CACHE_PATH)
|
||||
const cacheKey = core.getState(DEPENDENCIES_CACHE_KEY)
|
||||
const cacheResult = core.getState(DEPENDENCIES_CACHE_RESULT)
|
||||
|
||||
if (!cachePath || !fs.existsSync(cachePath)) {
|
||||
core.debug('No dependencies to cache.')
|
||||
return
|
||||
}
|
||||
|
||||
if (cacheResult && cacheKey === cacheResult) {
|
||||
core.info(
|
||||
`Dependencies cache hit occurred on the cache key ${cacheKey}, not saving cache.`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const locksDeleted = tryDeleteFiles([
|
||||
path.resolve(cachePath, 'modules-2.lock')
|
||||
])
|
||||
if (!locksDeleted) {
|
||||
core.warning(
|
||||
'Unable to delete dependencies lock files, try using --no-daemon or stopping the daemon last if you have several Gradle steps, not saving cache.'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await cache.saveCache([cachePath], cacheKey)
|
||||
} catch (error) {
|
||||
if (error.name === cache.ValidationError.name) {
|
||||
throw error
|
||||
} else if (error.name === cache.ReserveCacheError.name) {
|
||||
core.info(error.message)
|
||||
} else {
|
||||
core.info(`[warning] ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
export function tryDeleteFiles(filePaths: string[]): boolean {
|
||||
let failure = false
|
||||
for (const filePath of filePaths) {
|
||||
if (fs.existsSync(filePath)) {
|
||||
try {
|
||||
fs.unlinkSync(filePath)
|
||||
} catch (error) {
|
||||
failure = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return !failure
|
||||
}
|
||||
|
||||
export function isDependenciesCacheDisabled(): boolean {
|
||||
return !core.getBooleanInput('dependencies-cache-enabled')
|
||||
}
|
||||
|
||||
export function inputCacheKeyGlobs(input: string): string[] {
|
||||
const inputValue = core.getMultilineInput(input)
|
||||
return inputValue.length > 0
|
||||
? inputValue
|
||||
: [
|
||||
'**/*.gradle',
|
||||
'**/*.gradle.kts',
|
||||
'**/gradle.properties',
|
||||
'gradle/**'
|
||||
]
|
||||
}
|
132
src/cache-wrapper.ts
Normal file
132
src/cache-wrapper.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import * as os from 'os'
|
||||
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
|
||||
const WRAPPER_SLUG = 'WRAPPER_SLUG'
|
||||
|
||||
export async function restoreCachedWrapperDist(
|
||||
gradlewDirectory: string | null
|
||||
): Promise<void> {
|
||||
if (isWrapperCacheDisabled()) return
|
||||
if (gradlewDirectory == null) return
|
||||
|
||||
const wrapperProperties = path.join(
|
||||
path.resolve(gradlewDirectory),
|
||||
'gradle/wrapper/gradle-wrapper.properties'
|
||||
)
|
||||
const wrapperSlug = extractGradleWrapperSlugFrom(wrapperProperties)
|
||||
if (!wrapperSlug) {
|
||||
core.warning(
|
||||
`Could not calculate wrapper version from ${wrapperProperties}`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const wrapperDir = getWrapperDir(wrapperSlug)
|
||||
const cacheKey = getCacheKey(wrapperSlug)
|
||||
const cachePath = getCachePath(wrapperSlug)
|
||||
|
||||
// Check if the wrapper has already been downloaded to Gradle User Home
|
||||
if (fs.existsSync(wrapperDir)) return
|
||||
|
||||
try {
|
||||
const restoredKey = await cache.restoreCache([cachePath], cacheKey)
|
||||
|
||||
if (restoredKey) {
|
||||
core.info(
|
||||
`Wrapper installation restored from cache key: ${restoredKey}`
|
||||
)
|
||||
} else {
|
||||
core.info(
|
||||
`Wrapper installation cache not found. Will download and cache with key: ${cacheKey}.`
|
||||
)
|
||||
// Save the slug to trigger caching of the downloaded wrapper
|
||||
core.saveState(WRAPPER_SLUG, wrapperSlug)
|
||||
}
|
||||
} catch (error) {
|
||||
core.info(
|
||||
`Wrapper installation cache restore failed for key: ${cacheKey}.\n ${error}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function cacheWrapperDist(): Promise<void> {
|
||||
if (isWrapperCacheDisabled()) return
|
||||
|
||||
const wrapperSlug = core.getState(WRAPPER_SLUG)
|
||||
if (!wrapperSlug) return
|
||||
|
||||
const wrapperDir = getWrapperDir(wrapperSlug)
|
||||
const cacheKey = getCacheKey(wrapperSlug)
|
||||
const cachePath = getCachePath(wrapperSlug)
|
||||
|
||||
if (!fs.existsSync(wrapperDir)) {
|
||||
core.warning(`No wrapper installation to cache at ${wrapperDir}`)
|
||||
return
|
||||
}
|
||||
|
||||
core.info(`Will cache wrapper zip ${cachePath} with key ${cacheKey}`)
|
||||
|
||||
try {
|
||||
await cache.saveCache([cachePath], cacheKey)
|
||||
} catch (error) {
|
||||
if (error.name === cache.ValidationError.name) {
|
||||
throw error
|
||||
} else if (error.name === cache.ReserveCacheError.name) {
|
||||
core.info(error.message)
|
||||
} else {
|
||||
core.info(`[warning] ${error.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
export function extractGradleWrapperSlugFrom(
|
||||
wrapperProperties: string
|
||||
): string | null {
|
||||
const props = fs.readFileSync(wrapperProperties, {encoding: 'utf8'})
|
||||
const distUrlLine = props
|
||||
.split('\n')
|
||||
.find(line => line.startsWith('distributionUrl'))
|
||||
if (!distUrlLine) return null
|
||||
return extractGradleWrapperSlugFromDistUri(distUrlLine.substr(16).trim())
|
||||
}
|
||||
|
||||
export function extractGradleWrapperSlugFromDistUri(
|
||||
distUri: string
|
||||
): string | null {
|
||||
const regex = /.*gradle-(.*-(bin|all))\.zip/
|
||||
const match = distUri.match(regex)
|
||||
return match ? match[1] : null
|
||||
}
|
||||
|
||||
function isWrapperCacheDisabled(): boolean {
|
||||
// Check if either 'distributions' or 'wrapper' cache has been disabled
|
||||
const wrapperCacheEnabled = core.getBooleanInput('wrapper-cache-enabled')
|
||||
const distributionsCacheEnabled = core.getBooleanInput(
|
||||
'distributions-cache-enabled'
|
||||
)
|
||||
return !wrapperCacheEnabled || !distributionsCacheEnabled
|
||||
}
|
||||
|
||||
function getCacheKey(wrapperSlug: string): string {
|
||||
return `wrapper-v1-${wrapperSlug}`
|
||||
}
|
||||
|
||||
function getWrapperDir(wrapperSlug: string): string {
|
||||
return path.resolve(
|
||||
os.homedir(),
|
||||
`.gradle/wrapper/dists/gradle-${wrapperSlug}`
|
||||
)
|
||||
}
|
||||
|
||||
function getCachePath(wrapperSlug: string): string {
|
||||
return path.resolve(
|
||||
os.homedir(),
|
||||
`.gradle/wrapper/dists/gradle-${wrapperSlug}/*/gradle-${wrapperSlug}.zip`
|
||||
)
|
||||
}
|
13
src/crypto-utils.ts
Normal file
13
src/crypto-utils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as path from 'path'
|
||||
import * as glob from '@actions/glob'
|
||||
|
||||
export async function hashFiles(
|
||||
baseDir: string,
|
||||
patterns: string[] = ['**'],
|
||||
followSymbolicLinks = false
|
||||
): Promise<string | null> {
|
||||
const combinedPatterns = patterns
|
||||
.map(pattern => `${baseDir}${path.sep}${pattern}`)
|
||||
.join('\n')
|
||||
return glob.hashFiles(combinedPatterns, {followSymbolicLinks})
|
||||
}
|
@@ -1,40 +1,42 @@
|
||||
import * as exec from "@actions/exec";
|
||||
import * as exec from '@actions/exec'
|
||||
import * as cacheDependencies from './cache-dependencies'
|
||||
import * as cacheConfiguration from './cache-configuration'
|
||||
|
||||
export async function execute(
|
||||
executable: string,
|
||||
root: string,
|
||||
argv: string[]
|
||||
): Promise<BuildResult> {
|
||||
await cacheDependencies.restoreCachedDependencies(root)
|
||||
await cacheConfiguration.restoreCachedConfiguration(root)
|
||||
|
||||
export async function execute(executable: string, root: string, argv: string[]): Promise<BuildResult> {
|
||||
let publishing = false
|
||||
let buildScanUrl: string | undefined
|
||||
|
||||
let publishing = false;
|
||||
let buildScanLink: any = null;
|
||||
|
||||
await exec.exec(executable, argv, {
|
||||
const status: number = await exec.exec(executable, argv, {
|
||||
cwd: root,
|
||||
ignoreReturnCode: true,
|
||||
listeners: {
|
||||
stdline: (line: string) => {
|
||||
if (line.startsWith("Publishing build scan...")) {
|
||||
publishing = true;
|
||||
if (line.includes('Publishing build scan...')) {
|
||||
publishing = true
|
||||
}
|
||||
if (publishing && line.length == 0) {
|
||||
publishing = false
|
||||
}
|
||||
if (publishing && line.startsWith("http")) {
|
||||
buildScanLink = line.trim();
|
||||
if (publishing && line.startsWith('http')) {
|
||||
buildScanUrl = line.trim()
|
||||
publishing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (buildScanLink != null) {
|
||||
return new BuildResultImpl(buildScanLink.toString());
|
||||
}
|
||||
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,24 @@
|
||||
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 wrapperFilename(): 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 validateGradleWrapper(gradlewDirectory: string): void {
|
||||
const wrapperProperties = path.resolve(
|
||||
gradlewDirectory,
|
||||
'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.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
106
src/main.ts
106
src/main.ts
@@ -1,74 +1,82 @@
|
||||
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 cacheWrapper from './cache-wrapper'
|
||||
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`] || "";
|
||||
|
||||
let result = await execution.execute(
|
||||
await resolveGradleExecutable(baseDirectory),
|
||||
resolveBuildRootDirectory(baseDirectory),
|
||||
const result = await execution.execute(
|
||||
await resolveGradleExecutable(
|
||||
workspaceDirectory,
|
||||
buildRootDirectory
|
||||
),
|
||||
buildRootDirectory,
|
||||
parseCommandLineArguments()
|
||||
);
|
||||
)
|
||||
|
||||
if (result.buildScanUrl != null) {
|
||||
core.setOutput("build-scan-url", result.buildScanUrl);
|
||||
if (result.buildScanUrl) {
|
||||
core.setOutput('build-scan-url', result.buildScanUrl)
|
||||
}
|
||||
|
||||
if (result.status !== 0) {
|
||||
core.setFailed(`Gradle process exited with status ${result.status}`)
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
core.setFailed(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
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 !== '') {
|
||||
if (gradleExecutable.endsWith(gradlew.wrapperFilename())) {
|
||||
await cacheWrapper.restoreCachedWrapperDist(
|
||||
path.resolve(gradleExecutable, '..')
|
||||
)
|
||||
}
|
||||
return path.resolve(workspaceDirectory, gradleExecutable)
|
||||
}
|
||||
|
||||
const wrapperDirectory = inputOrNull("wrapper-directory");
|
||||
const executableDirectory = wrapperDirectory != null
|
||||
? path.join(baseDirectory, wrapperDirectory)
|
||||
: baseDirectory;
|
||||
const wrapperDirectory = core.getInput('wrapper-directory')
|
||||
const gradlewDirectory =
|
||||
wrapperDirectory !== ''
|
||||
? path.resolve(workspaceDirectory, wrapperDirectory)
|
||||
: buildRootDirectory
|
||||
|
||||
return path.join(executableDirectory, gradlew.wrapperFilename());
|
||||
gradlew.validateGradleWrapper(gradlewDirectory)
|
||||
await cacheWrapper.restoreCachedWrapperDist(gradlewDirectory)
|
||||
|
||||
return path.resolve(gradlewDirectory, gradlew.wrapperFilename())
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
|
12
src/post.ts
Normal file
12
src/post.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import * as cacheWrapper from './cache-wrapper'
|
||||
import * as cacheDependencies from './cache-dependencies'
|
||||
import * as cacheConfiguration from './cache-configuration'
|
||||
|
||||
// Invoked by GitHub Actions
|
||||
export async function run(): Promise<void> {
|
||||
await cacheWrapper.cacheWrapperDist()
|
||||
await cacheDependencies.cacheDependencies()
|
||||
await cacheConfiguration.cacheConfiguration()
|
||||
}
|
||||
|
||||
run()
|
270
src/provision.ts
270
src/provision.ts
@@ -1,163 +1,193 @@
|
||||
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'
|
||||
|
||||
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> {
|
||||
|
||||
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 provisionGradle(
|
||||
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 (isDistributionsCacheDisabled()) {
|
||||
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}`
|
||||
)
|
||||
} else {
|
||||
core.info(
|
||||
`Gradle distribution ${versionInfo.version} not found in cache. Will download.`
|
||||
)
|
||||
await downloadGradleDistribution(versionInfo, downloadPath)
|
||||
|
||||
try {
|
||||
await cache.saveCache([downloadPath], cacheKey)
|
||||
} catch (error) {
|
||||
if (error.name === cache.ValidationError.name) {
|
||||
throw error
|
||||
} else if (error.name === cache.ReserveCacheError.name) {
|
||||
core.info(error.message)
|
||||
} else {
|
||||
core.info(`[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()
|
||||
}
|
||||
|
||||
function isDistributionsCacheDisabled(): boolean {
|
||||
return !core.getBooleanInput('distributions-cache-enabled')
|
||||
}
|
||||
|
||||
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