Compare commits
9 Commits
testEnable
...
fix-345
Author | SHA1 | Date | |
---|---|---|---|
01b0229624 | |||
c4678ef19f | |||
fe28a720e4 | |||
84dee78cdb | |||
bd9fe45728 | |||
e9d6e93306 | |||
a89dcfa06d | |||
114965806a | |||
2bdaf00273 |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1 +1 @@
|
|||||||
* @actions/actions-cache
|
* @artifacts-actions
|
||||||
|
52
.github/workflows/check-dist.yml
vendored
52
.github/workflows/check-dist.yml
vendored
@ -1,52 +0,0 @@
|
|||||||
# `dist/index.js` is a special file in Actions.
|
|
||||||
# When you reference an action with `uses:` in a workflow,
|
|
||||||
# `index.js` is the code that will run.
|
|
||||||
# For our project, we generate this file through a build process
|
|
||||||
# from other source files.
|
|
||||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
|
||||||
name: Check dist/
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
pull_request:
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
check-dist:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set Node.js 12.x
|
|
||||||
uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: 12.x
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Rebuild the dist/ directory
|
|
||||||
run: npm run build
|
|
||||||
|
|
||||||
- name: Compare the expected and actual dist/ directories
|
|
||||||
run: |
|
|
||||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
|
||||||
echo "Detected uncommitted changes after build. See status below:"
|
|
||||||
git diff
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
id: diff
|
|
||||||
|
|
||||||
# If index.js was different than expected, upload the expected version as an artifact
|
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
|
||||||
with:
|
|
||||||
name: dist
|
|
||||||
path: dist/
|
|
22
.github/workflows/close-inactive-issues.yml
vendored
22
.github/workflows/close-inactive-issues.yml
vendored
@ -1,22 +0,0 @@
|
|||||||
name: Close inactive issues
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "30 8 * * *"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
close-issues:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v3
|
|
||||||
with:
|
|
||||||
days-before-issue-stale: 365
|
|
||||||
days-before-issue-close: 5
|
|
||||||
stale-issue-label: "stale"
|
|
||||||
stale-issue-message: "This issue is stale because it has been open for 365 days with no activity. Leave a comment to avoid closing this issue in 5 days."
|
|
||||||
close-issue-message: "This issue was closed because it has been inactive for 5 days since being marked as stale."
|
|
||||||
days-before-pr-stale: -1
|
|
||||||
days-before-pr-close: -1
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
10
.github/workflows/licensed.yml
vendored
10
.github/workflows/licensed.yml
vendored
@ -1,12 +1,8 @@
|
|||||||
name: Licensed
|
name: Licensed
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push: {branches: main}
|
||||||
branches:
|
pull_request: {branches: main}
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@ -21,4 +17,4 @@ jobs:
|
|||||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
|
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
|
||||||
sudo tar -xzf licensed.tar.gz
|
sudo tar -xzf licensed.tar.gz
|
||||||
sudo mv licensed /usr/local/bin/licensed
|
sudo mv licensed /usr/local/bin/licensed
|
||||||
- run: licensed status
|
- run: licensed status
|
17
.github/workflows/workflow.yml
vendored
17
.github/workflows/workflow.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
os: [ubuntu-latest, ubuntu-16.04, windows-latest, macOS-latest]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
@ -47,12 +47,23 @@ jobs:
|
|||||||
run: npm run lint
|
run: npm run lint
|
||||||
- name: Build & Test
|
- name: Build & Test
|
||||||
run: npm run test
|
run: npm run test
|
||||||
|
- name: Ensure dist/ folder is up-to-date
|
||||||
|
if: ${{ runner.os == 'Linux' }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
npm run build
|
||||||
|
if [ "$(git diff --ignore-space-at-eol | wc -l)" -gt "0" ]; then
|
||||||
|
echo "Detected uncommitted changes after build. See status below:"
|
||||||
|
git diff
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# End to end save and restore
|
# End to end save and restore
|
||||||
test-save:
|
test-save:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
os: [ubuntu-latest, ubuntu-16.04, windows-latest, macOS-latest]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
@ -75,7 +86,7 @@ jobs:
|
|||||||
needs: test-save
|
needs: test-save
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
os: [ubuntu-latest, ubuntu-16.04, windows-latest, macOS-latest]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
|
BIN
.licenses/npm/@actions/cache.dep.yml
generated
BIN
.licenses/npm/@actions/cache.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/core.dep.yml
generated
BIN
.licenses/npm/@actions/core.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/exec.dep.yml
generated
BIN
.licenses/npm/@actions/exec.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/glob.dep.yml
generated
BIN
.licenses/npm/@actions/glob.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/http-client.dep.yml
generated
BIN
.licenses/npm/@actions/http-client.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/io.dep.yml
generated
BIN
.licenses/npm/@actions/io.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/abort-controller.dep.yml
generated
BIN
.licenses/npm/@azure/abort-controller.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/core-auth.dep.yml
generated
BIN
.licenses/npm/@azure/core-auth.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/core-http.dep.yml
generated
BIN
.licenses/npm/@azure/core-http.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/core-lro.dep.yml
generated
BIN
.licenses/npm/@azure/core-lro.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/core-paging.dep.yml
generated
BIN
.licenses/npm/@azure/core-paging.dep.yml
generated
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@azure/logger.dep.yml
generated
BIN
.licenses/npm/@azure/logger.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/ms-rest-js.dep.yml
generated
BIN
.licenses/npm/@azure/ms-rest-js.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@azure/storage-blob.dep.yml
generated
BIN
.licenses/npm/@azure/storage-blob.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@opencensus/web-types.dep.yml
generated
Normal file
BIN
.licenses/npm/@opencensus/web-types.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@opentelemetry/api-0.10.2.dep.yml
generated
Normal file
BIN
.licenses/npm/@opentelemetry/api-0.10.2.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@opentelemetry/api-0.6.1.dep.yml
generated
Normal file
BIN
.licenses/npm/@opentelemetry/api-0.6.1.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/@opentelemetry/context-base-0.10.2.dep.yml
generated
Normal file
BIN
.licenses/npm/@opentelemetry/context-base-0.10.2.dep.yml
generated
Normal file
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@types/node-fetch.dep.yml
generated
BIN
.licenses/npm/@types/node-fetch.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/node.dep.yml
generated
BIN
.licenses/npm/@types/node.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/tunnel.dep.yml
generated
BIN
.licenses/npm/@types/tunnel.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/balanced-match.dep.yml
generated
BIN
.licenses/npm/balanced-match.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/events.dep.yml
generated
BIN
.licenses/npm/events.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/form-data-4.0.0.dep.yml
generated
BIN
.licenses/npm/form-data-4.0.0.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/mime-db.dep.yml
generated
BIN
.licenses/npm/mime-db.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/mime-types.dep.yml
generated
BIN
.licenses/npm/mime-types.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/node-fetch.dep.yml
generated
BIN
.licenses/npm/node-fetch.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/tslib-1.13.0.dep.yml
generated
Normal file
BIN
.licenses/npm/tslib-1.13.0.dep.yml
generated
Normal file
Binary file not shown.
BIN
.licenses/npm/tslib-1.14.1.dep.yml
generated
BIN
.licenses/npm/tslib-1.14.1.dep.yml
generated
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/webidl-conversions.dep.yml
generated
BIN
.licenses/npm/webidl-conversions.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/whatwg-url.dep.yml
generated
BIN
.licenses/npm/whatwg-url.dep.yml
generated
Binary file not shown.
10
README.md
10
README.md
@ -19,6 +19,7 @@ See ["Caching dependencies to speed up workflows"](https://help.github.com/githu
|
|||||||
path: |
|
path: |
|
||||||
~/cache
|
~/cache
|
||||||
!~/cache/exclude
|
!~/cache/exclude
|
||||||
|
**/node_modules
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -99,7 +100,6 @@ See [Examples](examples.md) for a list of `actions/cache` implementations for us
|
|||||||
- [OCaml/Reason - esy](./examples.md#ocamlreason---esy)
|
- [OCaml/Reason - esy](./examples.md#ocamlreason---esy)
|
||||||
- [PHP - Composer](./examples.md#php---composer)
|
- [PHP - Composer](./examples.md#php---composer)
|
||||||
- [Python - pip](./examples.md#python---pip)
|
- [Python - pip](./examples.md#python---pip)
|
||||||
- [Python - pipenv](./examples.md#python---pipenv)
|
|
||||||
- [R - renv](./examples.md#r---renv)
|
- [R - renv](./examples.md#r---renv)
|
||||||
- [Ruby - Bundler](./examples.md#ruby---bundler)
|
- [Ruby - Bundler](./examples.md#ruby---bundler)
|
||||||
- [Rust - Cargo](./examples.md#rust---cargo)
|
- [Rust - Cargo](./examples.md#rust---cargo)
|
||||||
@ -143,7 +143,7 @@ See [Using contexts to create cache keys](https://help.github.com/en/actions/con
|
|||||||
|
|
||||||
## Cache Limits
|
## Cache Limits
|
||||||
|
|
||||||
A repository can have up to 10GB of caches. Once the 10GB limit is reached, older caches will be evicted based on when the cache was last accessed. Caches that are not accessed within the last week will also be evicted.
|
A repository can have up to 5GB of caches. Once the 5GB limit is reached, older caches will be evicted based on when the cache was last accessed. Caches that are not accessed within the last week will also be evicted.
|
||||||
|
|
||||||
## Skipping steps based on cache-hit
|
## Skipping steps based on cache-hit
|
||||||
|
|
||||||
@ -167,12 +167,6 @@ steps:
|
|||||||
|
|
||||||
> Note: The `id` defined in `actions/cache` must match the `id` in the `if` statement (i.e. `steps.[ID].outputs.cache-hit`)
|
> Note: The `id` defined in `actions/cache` must match the `id` in the `if` statement (i.e. `steps.[ID].outputs.cache-hit`)
|
||||||
|
|
||||||
## Known limitation
|
|
||||||
|
|
||||||
- `action/cache` is currently not supported on GitHub Enterprise Server. <https://github.com/github/roadmap/issues/273> is tracking this.
|
|
||||||
|
|
||||||
Since GitHub Enterprise Server uses self-hosted runners, dependencies are typically cached on the runner by whatever dependency management tool is being used (npm, maven, etc.). This eliminates the need for explicit caching in some scenarios.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
We would love for you to contribute to `actions/cache`, pull requests are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
We would love for you to contribute to `actions/cache`, pull requests are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
||||||
|
|
||||||
|
@ -17,6 +17,24 @@ afterEach(() => {
|
|||||||
delete process.env[RefKey];
|
delete process.env[RefKey];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("isGhes returns true if server url is not github.com", () => {
|
||||||
|
try {
|
||||||
|
process.env["GITHUB_SERVER_URL"] = "http://example.com";
|
||||||
|
expect(actionUtils.isGhes()).toBe(true);
|
||||||
|
} finally {
|
||||||
|
process.env["GITHUB_SERVER_URL"] = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("isGhes returns true when server url is github.com", () => {
|
||||||
|
try {
|
||||||
|
process.env["GITHUB_SERVER_URL"] = "http://github.com";
|
||||||
|
expect(actionUtils.isGhes()).toBe(false);
|
||||||
|
} finally {
|
||||||
|
process.env["GITHUB_SERVER_URL"] = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test("isExactKeyMatch with undefined cache key returns false", () => {
|
test("isExactKeyMatch with undefined cache key returns false", () => {
|
||||||
const key = "linux-rust";
|
const key = "linux-rust";
|
||||||
const cacheKey = undefined;
|
const cacheKey = undefined;
|
||||||
@ -195,6 +213,39 @@ test("getInputAsArray handles empty lines correctly", () => {
|
|||||||
expect(actionUtils.getInputAsArray("foo")).toEqual(["bar", "baz"]);
|
expect(actionUtils.getInputAsArray("foo")).toEqual(["bar", "baz"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("getInputAsArray sorts files correctly", () => {
|
||||||
|
testUtils.setInput(
|
||||||
|
"foo",
|
||||||
|
"bar\n!baz\nwaldo\nqux\nquux\ncorge\ngrault\ngarply"
|
||||||
|
);
|
||||||
|
expect(actionUtils.getInputAsArray("foo")).toEqual([
|
||||||
|
"!baz",
|
||||||
|
"bar",
|
||||||
|
"corge",
|
||||||
|
"garply",
|
||||||
|
"grault",
|
||||||
|
"quux",
|
||||||
|
"qux",
|
||||||
|
"waldo"
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getInputAsArray removes spaces after ! at the beginning", () => {
|
||||||
|
testUtils.setInput(
|
||||||
|
"foo",
|
||||||
|
"! bar\n! baz\n! qux\n!quux\ncorge\ngrault! garply\n!\r\t waldo"
|
||||||
|
);
|
||||||
|
expect(actionUtils.getInputAsArray("foo")).toEqual([
|
||||||
|
"!bar",
|
||||||
|
"!baz",
|
||||||
|
"!quux",
|
||||||
|
"!qux",
|
||||||
|
"!waldo",
|
||||||
|
"corge",
|
||||||
|
"grault! garply"
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test("getInputAsInt returns undefined if input not set", () => {
|
test("getInputAsInt returns undefined if input not set", () => {
|
||||||
expect(actionUtils.getInputAsInt("undefined")).toBeUndefined();
|
expect(actionUtils.getInputAsInt("undefined")).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
@ -32,6 +32,8 @@ beforeAll(() => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
process.env[Events.Key] = Events.Push;
|
process.env[Events.Key] = Events.Push;
|
||||||
process.env[RefKey] = "refs/heads/feature-branch";
|
process.env[RefKey] = "refs/heads/feature-branch";
|
||||||
|
|
||||||
|
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -53,6 +55,23 @@ test("restore with invalid event outputs warning", async () => {
|
|||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("restore on GHES should no-op", async () => {
|
||||||
|
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||||
|
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||||
|
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||||
|
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
"Cache action is not supported on GHES"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("restore with no path should fail", async () => {
|
test("restore with no path should fail", async () => {
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||||
@ -78,7 +97,7 @@ test("restore with no key", async () => {
|
|||||||
test("restore with too many keys should fail", async () => {
|
test("restore with too many keys should fail", async () => {
|
||||||
const path = "node_modules";
|
const path = "node_modules";
|
||||||
const key = "node-test";
|
const key = "node-test";
|
||||||
const restoreKeys = [...Array(20).keys()].map(x => x.toString());
|
const restoreKeys = [...Array(20).keys()].map(x => x.toString()).sort();
|
||||||
testUtils.setInputs({
|
testUtils.setInputs({
|
||||||
path: path,
|
path: path,
|
||||||
key,
|
key,
|
||||||
|
@ -52,6 +52,8 @@ beforeAll(() => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
process.env[Events.Key] = Events.Push;
|
process.env[Events.Key] = Events.Push;
|
||||||
process.env[RefKey] = "refs/heads/feature-branch";
|
process.env[RefKey] = "refs/heads/feature-branch";
|
||||||
|
|
||||||
|
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -99,6 +101,20 @@ test("save with no primary key in state outputs warning", async () => {
|
|||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("save on GHES should no-op", async () => {
|
||||||
|
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||||
|
|
||||||
|
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||||
|
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||||
|
|
||||||
|
await run();
|
||||||
|
|
||||||
|
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
"Cache action is not supported on GHES"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("save with exact match returns early", async () => {
|
test("save with exact match returns early", async () => {
|
||||||
const infoMock = jest.spyOn(core, "info");
|
const infoMock = jest.spyOn(core, "info");
|
||||||
const failedMock = jest.spyOn(core, "setFailed");
|
const failedMock = jest.spyOn(core, "setFailed");
|
||||||
|
17
dist/restore/index.js
vendored
17
dist/restore/index.js
vendored
@ -36328,9 +36328,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.getInputAsInt = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = void 0;
|
exports.getInputAsInt = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = exports.isGhes = void 0;
|
||||||
const core = __importStar(__webpack_require__(470));
|
const core = __importStar(__webpack_require__(470));
|
||||||
const constants_1 = __webpack_require__(196);
|
const constants_1 = __webpack_require__(196);
|
||||||
|
function isGhes() {
|
||||||
|
const ghUrl = new URL(process.env["GITHUB_SERVER_URL"] || "https://github.com");
|
||||||
|
return ghUrl.hostname.toUpperCase() !== "GITHUB.COM";
|
||||||
|
}
|
||||||
|
exports.isGhes = isGhes;
|
||||||
function isExactKeyMatch(key, cacheKey) {
|
function isExactKeyMatch(key, cacheKey) {
|
||||||
return !!(cacheKey &&
|
return !!(cacheKey &&
|
||||||
cacheKey.localeCompare(key, undefined, {
|
cacheKey.localeCompare(key, undefined, {
|
||||||
@ -36376,8 +36381,9 @@ function getInputAsArray(name, options) {
|
|||||||
return core
|
return core
|
||||||
.getInput(name, options)
|
.getInput(name, options)
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.map(s => s.trim())
|
.map(s => s.replace(/^!\s+/, "!").trim())
|
||||||
.filter(x => x !== "");
|
.filter(x => x !== "")
|
||||||
|
.sort();
|
||||||
}
|
}
|
||||||
exports.getInputAsArray = getInputAsArray;
|
exports.getInputAsArray = getInputAsArray;
|
||||||
function getInputAsInt(name, options) {
|
function getInputAsInt(name, options) {
|
||||||
@ -46714,6 +46720,11 @@ const utils = __importStar(__webpack_require__(443));
|
|||||||
function run() {
|
function run() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
|
if (utils.isGhes()) {
|
||||||
|
utils.logWarning("Cache action is not supported on GHES");
|
||||||
|
utils.setCacheHitOutput(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Validate inputs, this can cause task failure
|
// Validate inputs, this can cause task failure
|
||||||
if (!utils.isValidEvent()) {
|
if (!utils.isValidEvent()) {
|
||||||
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
|
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
|
||||||
|
21
dist/save/index.js
vendored
21
dist/save/index.js
vendored
@ -36328,9 +36328,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.getInputAsInt = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = void 0;
|
exports.getInputAsInt = exports.getInputAsArray = exports.isValidEvent = exports.logWarning = exports.getCacheState = exports.setOutputAndState = exports.setCacheHitOutput = exports.setCacheState = exports.isExactKeyMatch = exports.isGhes = void 0;
|
||||||
const core = __importStar(__webpack_require__(470));
|
const core = __importStar(__webpack_require__(470));
|
||||||
const constants_1 = __webpack_require__(196);
|
const constants_1 = __webpack_require__(196);
|
||||||
|
function isGhes() {
|
||||||
|
const ghUrl = new URL(process.env["GITHUB_SERVER_URL"] || "https://github.com");
|
||||||
|
return ghUrl.hostname.toUpperCase() !== "GITHUB.COM";
|
||||||
|
}
|
||||||
|
exports.isGhes = isGhes;
|
||||||
function isExactKeyMatch(key, cacheKey) {
|
function isExactKeyMatch(key, cacheKey) {
|
||||||
return !!(cacheKey &&
|
return !!(cacheKey &&
|
||||||
cacheKey.localeCompare(key, undefined, {
|
cacheKey.localeCompare(key, undefined, {
|
||||||
@ -36376,8 +36381,9 @@ function getInputAsArray(name, options) {
|
|||||||
return core
|
return core
|
||||||
.getInput(name, options)
|
.getInput(name, options)
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.map(s => s.trim())
|
.map(s => s.replace(/^!\s+/, "!").trim())
|
||||||
.filter(x => x !== "");
|
.filter(x => x !== "")
|
||||||
|
.sort();
|
||||||
}
|
}
|
||||||
exports.getInputAsArray = getInputAsArray;
|
exports.getInputAsArray = getInputAsArray;
|
||||||
function getInputAsInt(name, options) {
|
function getInputAsInt(name, options) {
|
||||||
@ -44893,13 +44899,13 @@ const cache = __importStar(__webpack_require__(692));
|
|||||||
const core = __importStar(__webpack_require__(470));
|
const core = __importStar(__webpack_require__(470));
|
||||||
const constants_1 = __webpack_require__(196);
|
const constants_1 = __webpack_require__(196);
|
||||||
const utils = __importStar(__webpack_require__(443));
|
const utils = __importStar(__webpack_require__(443));
|
||||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
|
||||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
|
||||||
// throw an uncaught exception. Instead of failing this action, just warn.
|
|
||||||
process.on("uncaughtException", e => utils.logWarning(e.message));
|
|
||||||
function run() {
|
function run() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
|
if (utils.isGhes()) {
|
||||||
|
utils.logWarning("Cache action is not supported on GHES");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!utils.isValidEvent()) {
|
if (!utils.isValidEvent()) {
|
||||||
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
|
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
|
||||||
return;
|
return;
|
||||||
@ -44922,7 +44928,6 @@ function run() {
|
|||||||
yield cache.saveCache(cachePaths, primaryKey, {
|
yield cache.saveCache(cachePaths, primaryKey, {
|
||||||
uploadChunkSize: utils.getInputAsInt(constants_1.Inputs.UploadChunkSize)
|
uploadChunkSize: utils.getInputAsInt(constants_1.Inputs.UploadChunkSize)
|
||||||
});
|
});
|
||||||
core.info(`Cache saved with key: ${primaryKey}`);
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
if (error.name === cache.ValidationError.name) {
|
if (error.name === cache.ValidationError.name) {
|
||||||
|
276
examples.md
276
examples.md
@ -1,44 +1,38 @@
|
|||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
- [C# - NuGet](#c---nuget)
|
- [Examples](#examples)
|
||||||
- [D - DUB](#d---dub)
|
- [C# - NuGet](#c---nuget)
|
||||||
- [POSIX](#posix)
|
- [D - DUB](#d---dub)
|
||||||
- [Windows](#windows)
|
- [Elixir - Mix](#elixir---mix)
|
||||||
- [Elixir - Mix](#elixir---mix)
|
- [Go - Modules](#go---modules)
|
||||||
- [Go - Modules](#go---modules)
|
- [Haskell - Cabal](#haskell---cabal)
|
||||||
- [Linux](#linux)
|
- [Java - Gradle](#java---gradle)
|
||||||
- [macOS](#macos)
|
- [Java - Maven](#java---maven)
|
||||||
- [Windows](#windows-1)
|
- [Node - npm](#node---npm)
|
||||||
- [Haskell - Cabal](#haskell---cabal)
|
- [macOS and Ubuntu](#macos-and-ubuntu)
|
||||||
- [Java - Gradle](#java---gradle)
|
- [Windows](#windows)
|
||||||
- [Java - Maven](#java---maven)
|
- [Using multiple systems and `npm config`](#using-multiple-systems-and-npm-config)
|
||||||
- [Node - npm](#node---npm)
|
- [Node - Lerna](#node---lerna)
|
||||||
- [macOS and Ubuntu](#macos-and-ubuntu)
|
- [Node - Yarn](#node---yarn)
|
||||||
- [Windows](#windows-2)
|
- [Node - Yarn 2](#node---yarn-2)
|
||||||
- [Using multiple systems and `npm config`](#using-multiple-systems-and-npm-config)
|
- [OCaml/Reason - esy](#ocamlreason---esy)
|
||||||
- [Node - Lerna](#node---lerna)
|
- [PHP - Composer](#php---composer)
|
||||||
- [Node - Yarn](#node---yarn)
|
- [Python - pip](#python---pip)
|
||||||
- [Node - Yarn 2](#node---yarn-2)
|
- [Simple example](#simple-example)
|
||||||
- [OCaml/Reason - esy](#ocamlreason---esy)
|
- [Multiple OSes in a workflow](#multiple-oss-in-a-workflow)
|
||||||
- [PHP - Composer](#php---composer)
|
- [Using pip to get cache location](#using-pip-to-get-cache-location)
|
||||||
- [Python - pip](#python---pip)
|
- [Using a script to get cache location](#using-a-script-to-get-cache-location)
|
||||||
- [Simple example](#simple-example)
|
- [R - renv](#r---renv)
|
||||||
- [Multiple OS's in a workflow](#multiple-oss-in-a-workflow)
|
- [Simple example](#simple-example-1)
|
||||||
- [Multiple OS's in a workflow with a matrix](#multiple-oss-in-a-workflow-with-a-matrix)
|
- [Multiple OSes in a workflow](#multiple-oss-in-a-workflow-1)
|
||||||
- [Using pip to get cache location](#using-pip-to-get-cache-location)
|
- [Ruby - Bundler](#ruby---bundler)
|
||||||
- [Python - pipenv](#python---pipenv)
|
- [Rust - Cargo](#rust---cargo)
|
||||||
- [R - renv](#r---renv)
|
- [Scala - SBT](#scala---sbt)
|
||||||
- [Simple example](#simple-example-1)
|
- [Swift, Objective-C - Carthage](#swift-objective-c---carthage)
|
||||||
- [Multiple OS's in a workflow](#multiple-oss-in-a-workflow-1)
|
- [Swift, Objective-C - CocoaPods](#swift-objective-c---cocoapods)
|
||||||
- [Ruby - Bundler](#ruby---bundler)
|
- [Swift - Swift Package Manager](#swift---swift-package-manager)
|
||||||
- [Rust - Cargo](#rust---cargo)
|
|
||||||
- [Scala - SBT](#scala---sbt)
|
|
||||||
- [Swift, Objective-C - Carthage](#swift-objective-c---carthage)
|
|
||||||
- [Swift, Objective-C - CocoaPods](#swift-objective-c---cocoapods)
|
|
||||||
- [Swift - Swift Package Manager](#swift---swift-package-manager)
|
|
||||||
|
|
||||||
## C# - NuGet
|
## C# - NuGet
|
||||||
|
|
||||||
Using [NuGet lock files](https://docs.microsoft.com/nuget/consume-packages/package-references-in-project-files#locking-dependencies):
|
Using [NuGet lock files](https://docs.microsoft.com/nuget/consume-packages/package-references-in-project-files#locking-dependencies):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@ -52,11 +46,10 @@ Using [NuGet lock files](https://docs.microsoft.com/nuget/consume-packages/packa
|
|||||||
|
|
||||||
Depending on the environment, huge packages might be pre-installed in the global cache folder.
|
Depending on the environment, huge packages might be pre-installed in the global cache folder.
|
||||||
With `actions/cache@v2` you can now exclude unwanted packages with [exclude pattern](https://github.com/actions/toolkit/tree/main/packages/glob#exclude-patterns)
|
With `actions/cache@v2` you can now exclude unwanted packages with [exclude pattern](https://github.com/actions/toolkit/tree/main/packages/glob#exclude-patterns)
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.nuget/packages
|
~/.nuget/packages
|
||||||
!~/.nuget/packages/unwanted
|
!~/.nuget/packages/unwanted
|
||||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||||
@ -103,54 +96,21 @@ steps:
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Elixir - Mix
|
## Elixir - Mix
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: deps
|
||||||
deps
|
key: ${{ runner.os }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
|
||||||
_build
|
|
||||||
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }}
|
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-mix-
|
${{ runner.os }}-mix-
|
||||||
```
|
```
|
||||||
|
|
||||||
## Go - Modules
|
## Go - Modules
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: ~/go/pkg/mod
|
||||||
~/.cache/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
```
|
|
||||||
|
|
||||||
### macOS
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/Library/Caches/go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
```
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
%LocalAppData%\go-build
|
|
||||||
~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-go-
|
${{ runner.os }}-go-
|
||||||
@ -168,21 +128,18 @@ We cache the elements of the Cabal store separately, as the entirety of `~/.caba
|
|||||||
~/.cabal/packages
|
~/.cabal/packages
|
||||||
~/.cabal/store
|
~/.cabal/store
|
||||||
dist-newstyle
|
dist-newstyle
|
||||||
key: ${{ runner.os }}-${{ matrix.ghc }}-${{ hashFiles('**/*.cabal', '**/cabal.project', '**/cabal.project.freeze') }}
|
key: ${{ runner.os }}-${{ matrix.ghc }}
|
||||||
restore-keys: ${{ runner.os }}-${{ matrix.ghc }}-
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Java - Gradle
|
## Java - Gradle
|
||||||
|
|
||||||
>Note: Ensure no Gradle daemons are running anymore when your workflow completes. Creating the cache package might fail due to locks being held by Gradle. Refer to the [Gradle Daemon documentation](https://docs.gradle.org/current/userguide/gradle_daemon.html) on how to disable or stop the Gradle Daemons.
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.gradle/caches
|
~/.gradle/caches
|
||||||
~/.gradle/wrapper
|
~/.gradle/wrapper
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-gradle-
|
${{ runner.os }}-gradle-
|
||||||
```
|
```
|
||||||
@ -237,13 +194,12 @@ If using `npm config` to retrieve the cache directory, ensure you run [actions/s
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Get npm cache directory
|
- name: Get npm cache directory
|
||||||
id: npm-cache-dir
|
id: npm-cache
|
||||||
run: |
|
run: |
|
||||||
echo "::set-output name=dir::$(npm config get cache)"
|
echo "::set-output name=dir::$(npm config get cache)"
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
|
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.npm-cache-dir.outputs.dir }}
|
path: ${{ steps.npm-cache.outputs.dir }}
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-node-
|
${{ runner.os }}-node-
|
||||||
@ -278,8 +234,8 @@ The yarn cache directory will depend on your operating system and version of `ya
|
|||||||
${{ runner.os }}-yarn-
|
${{ runner.os }}-yarn-
|
||||||
```
|
```
|
||||||
|
|
||||||
## Node - Yarn 2
|
|
||||||
|
|
||||||
|
## Node - Yarn 2
|
||||||
The yarn 2 cache directory will depend on your config. See https://yarnpkg.com/configuration/yarnrc#cacheFolder for more info.
|
The yarn 2 cache directory will depend on your config. See https://yarnpkg.com/configuration/yarnrc#cacheFolder for more info.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@ -297,7 +253,6 @@ The yarn 2 cache directory will depend on your config. See https://yarnpkg.com/c
|
|||||||
```
|
```
|
||||||
|
|
||||||
## OCaml/Reason - esy
|
## OCaml/Reason - esy
|
||||||
|
|
||||||
Esy allows you to export built dependencies and import pre-built dependencies.
|
Esy allows you to export built dependencies and import pre-built dependencies.
|
||||||
```yaml
|
```yaml
|
||||||
- name: Restore Cache
|
- name: Restore Cache
|
||||||
@ -318,12 +273,13 @@ Esy allows you to export built dependencies and import pre-built dependencies.
|
|||||||
...(Build job)...
|
...(Build job)...
|
||||||
|
|
||||||
# Re-export dependencies if anything has changed or if it is the first time
|
# Re-export dependencies if anything has changed or if it is the first time
|
||||||
- name: Setting dependency cache
|
- name: Setting dependency cache
|
||||||
run: |
|
run: |
|
||||||
esy export-dependencies
|
esy export-dependencies
|
||||||
if: steps.restore-cache.outputs.cache-hit != 'true'
|
if: steps.restore-cache.outputs.cache-hit != 'true'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## PHP - Composer
|
## PHP - Composer
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@ -344,13 +300,11 @@ Esy allows you to export built dependencies and import pre-built dependencies.
|
|||||||
For pip, the cache directory will vary by OS. See https://pip.pypa.io/en/stable/reference/pip_install/#caching
|
For pip, the cache directory will vary by OS. See https://pip.pypa.io/en/stable/reference/pip_install/#caching
|
||||||
|
|
||||||
Locations:
|
Locations:
|
||||||
|
- Ubuntu: `~/.cache/pip`
|
||||||
- Ubuntu: `~/.cache/pip`
|
- Windows: `~\AppData\Local\pip\Cache`
|
||||||
- Windows: `~\AppData\Local\pip\Cache`
|
- macOS: `~/Library/Caches/pip`
|
||||||
- macOS: `~/Library/Caches/pip`
|
|
||||||
|
|
||||||
### Simple example
|
### Simple example
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
@ -390,31 +344,6 @@ Replace `~/.cache/pip` with the correct `path` if not using Ubuntu.
|
|||||||
${{ runner.os }}-pip-
|
${{ runner.os }}-pip-
|
||||||
```
|
```
|
||||||
|
|
||||||
### Multiple OS's in a workflow with a matrix
|
|
||||||
|
|
||||||
``` yaml
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
||||||
include:
|
|
||||||
- os: ubuntu-latest
|
|
||||||
path: ~/.cache/pip
|
|
||||||
- os: macos-latest
|
|
||||||
path: ~/Library/Caches/pip
|
|
||||||
- os: windows-latest
|
|
||||||
path: ~\AppData\Local\pip\Cache
|
|
||||||
steps:
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ${{ matrix.path }}
|
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pip-
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using pip to get cache location
|
### Using pip to get cache location
|
||||||
|
|
||||||
> Note: This requires pip 20.1+
|
> Note: This requires pip 20.1+
|
||||||
@ -433,64 +362,89 @@ jobs:
|
|||||||
${{ runner.os }}-pip-
|
${{ runner.os }}-pip-
|
||||||
```
|
```
|
||||||
|
|
||||||
## Python - pipenv
|
### Using a script to get cache location
|
||||||
|
|
||||||
|
> Note: This uses an internal pip API and may not always work
|
||||||
```yaml
|
```yaml
|
||||||
- name: Set up Python
|
- name: Get pip cache dir
|
||||||
# The actions/cache step below uses this id to get the exact python version
|
id: pip-cache
|
||||||
id: setup-python
|
run: |
|
||||||
uses: actions/setup-python@v2
|
python -c "from pip._internal.locations import USER_CACHE_DIR; print('::set-output name=dir::' + USER_CACHE_DIR)"
|
||||||
|
|
||||||
⋮
|
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: ~/.local/share/virtualenvs
|
path: ${{ steps.pip-cache.outputs.dir }}
|
||||||
key: ${{ runner.os }}-python-${{ steps.setup-python.outputs.python-version }}-pipenv-${{ hashFiles('Pipfile.lock') }}
|
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-pip-
|
||||||
```
|
```
|
||||||
|
|
||||||
## R - renv
|
## R - renv
|
||||||
|
|
||||||
For renv, the cache directory will vary by OS. The `RENV_PATHS_ROOT` environment variable is used to set the cache location. Have a look at https://rstudio.github.io/renv/reference/paths.html#details for more details.
|
For renv, the cache directory will vary by OS. Look at https://rstudio.github.io/renv/articles/renv.html#cache
|
||||||
|
|
||||||
|
Locations:
|
||||||
|
- Ubuntu: `~/.local/share/renv`
|
||||||
|
- macOS: `~/Library/Application Support/renv`
|
||||||
|
- Windows: `%LOCALAPPDATA%/renv`
|
||||||
|
|
||||||
|
### Simple example
|
||||||
|
```yaml
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/.local/share/renv
|
||||||
|
key: ${{ runner.os }}-renv-${{ hashFiles('**/renv.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-renv-
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `~/.local/share/renv` with the correct `path` if not using Ubuntu.
|
||||||
|
|
||||||
|
### Multiple OS's in a workflow
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Set RENV_PATHS_ROOT
|
- uses: actions/cache@v2
|
||||||
shell: bash
|
if: startsWith(runner.os, 'Linux')
|
||||||
run: |
|
|
||||||
echo "RENV_PATHS_ROOT=${{ runner.temp }}/renv" >> $GITHUB_ENV
|
|
||||||
- name: Install and activate renv
|
|
||||||
run: |
|
|
||||||
install.packages("renv")
|
|
||||||
renv::activate()
|
|
||||||
shell: Rscript {0}
|
|
||||||
- name: Get R and OS version
|
|
||||||
id: get-version
|
|
||||||
run: |
|
|
||||||
cat("##[set-output name=os-version;]", sessionInfo()$running, "\n", sep = "")
|
|
||||||
cat("##[set-output name=r-version;]", R.Version()$version.string, sep = "")
|
|
||||||
shell: Rscript {0}
|
|
||||||
- name: Restore Renv package cache
|
|
||||||
uses: actions/cache@v2
|
|
||||||
with:
|
with:
|
||||||
path: ${{ env.RENV_PATHS_ROOT }}
|
path: ~/.local/share/renv
|
||||||
key: ${{ steps.get-version.outputs.os-version }}-${{ steps.get-version.outputs.r-version }}-${{ inputs.cache-version }}-${{ hashFiles('renv.lock') }}
|
key: ${{ runner.os }}-renv-${{ hashFiles('**/renv.lock') }}
|
||||||
restore-keys: ${{ steps.get-version.outputs.os-version }}-${{ steps.get-version.outputs.r-version }}-${{inputs.cache-version }}-
|
restore-keys: |
|
||||||
|
${{ runner.os }}-renv-
|
||||||
|
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
if: startsWith(runner.os, 'macOS')
|
||||||
|
with:
|
||||||
|
path: ~/Library/Application Support/renv
|
||||||
|
key: ${{ runner.os }}-renv-${{ hashFiles('**/renv.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-renv-
|
||||||
|
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
if: startsWith(runner.os, 'Windows')
|
||||||
|
with:
|
||||||
|
path: ~\AppData\Local\renv
|
||||||
|
key: ${{ runner.os }}-renv-${{ hashFiles('**/renv.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-renv-
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruby - Bundler
|
## Ruby - Bundler
|
||||||
|
|
||||||
Caching gems with Bundler correctly is not trivial and just using `actions/cache`
|
```yaml
|
||||||
is [not enough](https://github.com/ruby/setup-ruby#caching-bundle-install-manually).
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
Instead, it is recommended to use `ruby/setup-ruby`'s
|
path: vendor/bundle
|
||||||
[`bundler-cache: true` option](https://github.com/ruby/setup-ruby#caching-bundle-install-automatically)
|
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
||||||
whenever possible:
|
restore-keys: |
|
||||||
|
${{ runner.os }}-gems-
|
||||||
|
```
|
||||||
|
When dependencies are installed later in the workflow, we must specify the same path for the bundler.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: ruby/setup-ruby@v1
|
- name: Bundle install
|
||||||
with:
|
run: |
|
||||||
ruby-version: ...
|
bundle config path vendor/bundle
|
||||||
bundler-cache: true
|
bundle install --jobs 4 --retry 3
|
||||||
```
|
```
|
||||||
|
|
||||||
## Rust - Cargo
|
## Rust - Cargo
|
||||||
@ -499,11 +453,9 @@ whenever possible:
|
|||||||
- uses: actions/cache@v2
|
- uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/bin/
|
~/.cargo/registry
|
||||||
~/.cargo/registry/index/
|
~/.cargo/git
|
||||||
~/.cargo/registry/cache/
|
target
|
||||||
~/.cargo/git/db/
|
|
||||||
target/
|
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -513,7 +465,7 @@ whenever possible:
|
|||||||
- name: Cache SBT
|
- name: Cache SBT
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.ivy2/cache
|
~/.ivy2/cache
|
||||||
~/.sbt
|
~/.sbt
|
||||||
key: ${{ runner.os }}-sbt-${{ hashFiles('**/build.sbt') }}
|
key: ${{ runner.os }}-sbt-${{ hashFiles('**/build.sbt') }}
|
||||||
|
2860
package-lock.json
generated
2860
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cache",
|
"name": "cache",
|
||||||
"version": "2.1.7",
|
"version": "2.1.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "Cache dependencies and build outputs",
|
"description": "Cache dependencies and build outputs",
|
||||||
"main": "dist/restore/index.js",
|
"main": "dist/restore/index.js",
|
||||||
@ -23,29 +23,29 @@
|
|||||||
"author": "GitHub",
|
"author": "GitHub",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^1.0.8",
|
"@actions/cache": "^1.0.4",
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "^1.0.1",
|
"@actions/exec": "^1.0.1",
|
||||||
"@actions/io": "^1.1.0"
|
"@actions/io": "^1.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^24.0.13",
|
"@types/jest": "^24.0.13",
|
||||||
"@types/nock": "^11.1.0",
|
"@types/nock": "^11.1.0",
|
||||||
"@types/node": "^12.20.7",
|
"@types/node": "^12.0.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.7.0",
|
"@typescript-eslint/eslint-plugin": "^2.7.0",
|
||||||
"@typescript-eslint/parser": "^2.7.0",
|
"@typescript-eslint/parser": "^2.7.0",
|
||||||
"@zeit/ncc": "^0.20.5",
|
"@zeit/ncc": "^0.20.5",
|
||||||
"eslint": "^6.6.0",
|
"eslint": "^6.6.0",
|
||||||
"eslint-config-prettier": "^6.15.0",
|
"eslint-config-prettier": "^6.5.0",
|
||||||
"eslint-plugin-import": "^2.22.1",
|
"eslint-plugin-import": "^2.18.2",
|
||||||
"eslint-plugin-jest": "^23.20.0",
|
"eslint-plugin-jest": "^23.0.3",
|
||||||
"eslint-plugin-prettier": "^3.3.1",
|
"eslint-plugin-prettier": "^3.1.1",
|
||||||
"eslint-plugin-simple-import-sort": "^5.0.2",
|
"eslint-plugin-simple-import-sort": "^5.0.2",
|
||||||
"jest": "^24.8.0",
|
"jest": "^24.8.0",
|
||||||
"jest-circus": "^24.7.1",
|
"jest-circus": "^24.7.1",
|
||||||
"nock": "^11.7.0",
|
"nock": "^11.7.0",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"ts-jest": "^26.5.4",
|
"ts-jest": "^24.0.2",
|
||||||
"typescript": "^3.9.9"
|
"typescript": "^3.7.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,12 @@ import * as utils from "./utils/actionUtils";
|
|||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
if (utils.isGhes()) {
|
||||||
|
utils.logWarning("Cache action is not supported on GHES");
|
||||||
|
utils.setCacheHitOutput(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Validate inputs, this can cause task failure
|
// Validate inputs, this can cause task failure
|
||||||
if (!utils.isValidEvent()) {
|
if (!utils.isValidEvent()) {
|
||||||
utils.logWarning(
|
utils.logWarning(
|
||||||
|
11
src/save.ts
11
src/save.ts
@ -4,13 +4,13 @@ import * as core from "@actions/core";
|
|||||||
import { Events, Inputs, State } from "./constants";
|
import { Events, Inputs, State } from "./constants";
|
||||||
import * as utils from "./utils/actionUtils";
|
import * as utils from "./utils/actionUtils";
|
||||||
|
|
||||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
|
||||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
|
||||||
// throw an uncaught exception. Instead of failing this action, just warn.
|
|
||||||
process.on("uncaughtException", e => utils.logWarning(e.message));
|
|
||||||
|
|
||||||
async function run(): Promise<void> {
|
async function run(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
if (utils.isGhes()) {
|
||||||
|
utils.logWarning("Cache action is not supported on GHES");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!utils.isValidEvent()) {
|
if (!utils.isValidEvent()) {
|
||||||
utils.logWarning(
|
utils.logWarning(
|
||||||
`Event Validation Error: The event type ${
|
`Event Validation Error: The event type ${
|
||||||
@ -44,7 +44,6 @@ async function run(): Promise<void> {
|
|||||||
await cache.saveCache(cachePaths, primaryKey, {
|
await cache.saveCache(cachePaths, primaryKey, {
|
||||||
uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize)
|
uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize)
|
||||||
});
|
});
|
||||||
core.info(`Cache saved with key: ${primaryKey}`);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.name === cache.ValidationError.name) {
|
if (error.name === cache.ValidationError.name) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -2,6 +2,13 @@ import * as core from "@actions/core";
|
|||||||
|
|
||||||
import { Outputs, RefKey, State } from "../constants";
|
import { Outputs, RefKey, State } from "../constants";
|
||||||
|
|
||||||
|
export function isGhes(): boolean {
|
||||||
|
const ghUrl = new URL(
|
||||||
|
process.env["GITHUB_SERVER_URL"] || "https://github.com"
|
||||||
|
);
|
||||||
|
return ghUrl.hostname.toUpperCase() !== "GITHUB.COM";
|
||||||
|
}
|
||||||
|
|
||||||
export function isExactKeyMatch(key: string, cacheKey?: string): boolean {
|
export function isExactKeyMatch(key: string, cacheKey?: string): boolean {
|
||||||
return !!(
|
return !!(
|
||||||
cacheKey &&
|
cacheKey &&
|
||||||
@ -53,8 +60,9 @@ export function getInputAsArray(
|
|||||||
return core
|
return core
|
||||||
.getInput(name, options)
|
.getInput(name, options)
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.map(s => s.trim())
|
.map(s => s.replace(/^!\s+/, "!").trim())
|
||||||
.filter(x => x !== "");
|
.filter(x => x !== "")
|
||||||
|
.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInputAsInt(
|
export function getInputAsInt(
|
||||||
|
Reference in New Issue
Block a user