mirror of
https://github.com/actions/cache.git
synced 2026-01-13 09:03:06 +08:00
Compare commits
9 Commits
0910293238
...
5b757de529
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b757de529 | ||
|
|
36f1e144e1 | ||
|
|
53aa38c736 | ||
|
|
fa8c252a0b | ||
|
|
b0a3f6e7a6 | ||
|
|
12b3b8a0b8 | ||
|
|
9806e2f37f | ||
|
|
b3f0756597 | ||
|
|
b6cff214f7 |
@ -85,7 +85,8 @@ test("restore with no cache found", async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||||
expect(stateMock).toHaveBeenCalledTimes(1);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_PATH", path);
|
||||||
|
expect(stateMock).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
@ -128,7 +129,8 @@ test("restore with restore keys and no cache found", async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||||
expect(stateMock).toHaveBeenCalledTimes(1);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_PATH", path);
|
||||||
|
expect(stateMock).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
@ -171,7 +173,8 @@ test("restore with cache found for key", async () => {
|
|||||||
|
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
|
||||||
expect(stateMock).toHaveBeenCalledTimes(2);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_PATH", path);
|
||||||
|
expect(stateMock).toHaveBeenCalledTimes(3);
|
||||||
|
|
||||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
|
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
|
||||||
@ -216,7 +219,8 @@ test("restore with cache found for restore key", async () => {
|
|||||||
|
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
|
||||||
expect(stateMock).toHaveBeenCalledTimes(2);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_PATH", path);
|
||||||
|
expect(stateMock).toHaveBeenCalledTimes(3);
|
||||||
|
|
||||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||||
@ -304,7 +308,8 @@ test("restore when fail on cache miss is enabled and primary key doesn't match r
|
|||||||
|
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
|
||||||
expect(stateMock).toHaveBeenCalledTimes(2);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_PATH", path);
|
||||||
|
expect(stateMock).toHaveBeenCalledTimes(3);
|
||||||
|
|
||||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||||
@ -349,7 +354,8 @@ test("restore with fail on cache miss disabled and no cache found", async () =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||||
expect(stateMock).toHaveBeenCalledTimes(1);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_PATH", path);
|
||||||
|
expect(stateMock).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
expect(infoMock).toHaveBeenCalledWith(
|
expect(infoMock).toHaveBeenCalledWith(
|
||||||
`Cache not found for input keys: ${key}, ${restoreKey}`
|
`Cache not found for input keys: ${key}, ${restoreKey}`
|
||||||
|
|||||||
@ -439,7 +439,8 @@ test("restore with lookup-only set", async () => {
|
|||||||
|
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||||
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
|
||||||
expect(stateMock).toHaveBeenCalledTimes(2);
|
expect(stateMock).toHaveBeenCalledWith("CACHE_PATH", path);
|
||||||
|
expect(stateMock).toHaveBeenCalledTimes(3);
|
||||||
|
|
||||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
|
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
|
||||||
|
|||||||
@ -86,7 +86,8 @@ test("restore with no cache found", async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
||||||
expect(outputMock).toHaveBeenCalledTimes(1);
|
expect(outputMock).toHaveBeenCalledWith("cache-path", path);
|
||||||
|
expect(outputMock).toHaveBeenCalledTimes(2);
|
||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
expect(infoMock).toHaveBeenCalledWith(
|
expect(infoMock).toHaveBeenCalledWith(
|
||||||
@ -128,6 +129,7 @@ test("restore with restore keys and no cache found", async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
||||||
|
expect(outputMock).toHaveBeenCalledWith("cache-path", path);
|
||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
expect(infoMock).toHaveBeenCalledWith(
|
expect(infoMock).toHaveBeenCalledWith(
|
||||||
@ -169,8 +171,9 @@ test("restore with cache found for key", async () => {
|
|||||||
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
||||||
expect(outputMock).toHaveBeenCalledWith("cache-hit", "true");
|
expect(outputMock).toHaveBeenCalledWith("cache-hit", "true");
|
||||||
expect(outputMock).toHaveBeenCalledWith("cache-matched-key", key);
|
expect(outputMock).toHaveBeenCalledWith("cache-matched-key", key);
|
||||||
|
expect(outputMock).toHaveBeenCalledWith("cache-path", path);
|
||||||
|
|
||||||
expect(outputMock).toHaveBeenCalledTimes(3);
|
expect(outputMock).toHaveBeenCalledTimes(4);
|
||||||
|
|
||||||
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
|
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
|
||||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||||
@ -212,8 +215,9 @@ test("restore with cache found for restore key", async () => {
|
|||||||
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
||||||
expect(outputMock).toHaveBeenCalledWith("cache-hit", "false");
|
expect(outputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||||
expect(outputMock).toHaveBeenCalledWith("cache-matched-key", restoreKey);
|
expect(outputMock).toHaveBeenCalledWith("cache-matched-key", restoreKey);
|
||||||
|
expect(outputMock).toHaveBeenCalledWith("cache-path", path);
|
||||||
|
|
||||||
expect(outputMock).toHaveBeenCalledTimes(3);
|
expect(outputMock).toHaveBeenCalledTimes(4);
|
||||||
|
|
||||||
expect(infoMock).toHaveBeenCalledWith(
|
expect(infoMock).toHaveBeenCalledWith(
|
||||||
`Cache restored from key: ${restoreKey}`
|
`Cache restored from key: ${restoreKey}`
|
||||||
|
|||||||
@ -102,7 +102,7 @@ The [GitHub Context](https://docs.github.com/en/actions/learn-github-actions/con
|
|||||||
|
|
||||||
While setting paths for caching dependencies it is important to give correct path depending on the hosted runner you are using or whether the action is running in a container job. Assigning different `path` for save and restore will result in cache miss.
|
While setting paths for caching dependencies it is important to give correct path depending on the hosted runner you are using or whether the action is running in a container job. Assigning different `path` for save and restore will result in cache miss.
|
||||||
|
|
||||||
Below are GiHub hosted runner specific paths one should take care of when writing a workflow which saves/restores caches across OS.
|
Below are GitHub hosted runner specific paths one should take care of when writing a workflow which saves/restores caches across OS.
|
||||||
|
|
||||||
#### Ubuntu Paths
|
#### Ubuntu Paths
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@ The restore action restores a cache. It works similarly to the `cache` action ex
|
|||||||
* `cache-hit` - A boolean value to indicate an exact match was found for the key.
|
* `cache-hit` - A boolean value to indicate an exact match was found for the key.
|
||||||
* `cache-primary-key` - Cache primary key passed in the input to use in subsequent steps of the workflow.
|
* `cache-primary-key` - Cache primary key passed in the input to use in subsequent steps of the workflow.
|
||||||
* `cache-matched-key` - Key of the cache that was restored, it could either be the primary key on cache-hit or a partial/complete match of one of the restore keys.
|
* `cache-matched-key` - Key of the cache that was restored, it could either be the primary key on cache-hit or a partial/complete match of one of the restore keys.
|
||||||
|
* `cache-path` - The list of files, directories, and wildcard patterns passed in the input.
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
`cache-hit` will be set to `true` only when cache hit occurs for the exact `key` match. For a partial key match via `restore-keys` or a cache miss, it will be set to `false`.
|
`cache-hit` will be set to `true` only when cache hit occurs for the exact `key` match. For a partial key match via `restore-keys` or a cache miss, it will be set to `false`.
|
||||||
|
|||||||
@ -30,6 +30,8 @@ outputs:
|
|||||||
description: 'A resolved cache key for which cache match was attempted'
|
description: 'A resolved cache key for which cache match was attempted'
|
||||||
cache-matched-key:
|
cache-matched-key:
|
||||||
description: 'Key of the cache that was restored, it could either be the primary key on cache-hit or a partial/complete match of one of the restore keys'
|
description: 'Key of the cache that was restored, it could either be the primary key on cache-hit or a partial/complete match of one of the restore keys'
|
||||||
|
cache-path:
|
||||||
|
description: 'The list of files, directories, and wildcard patterns passed in the input'
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: 'node20'
|
||||||
main: '../dist/restore-only/index.js'
|
main: '../dist/restore-only/index.js'
|
||||||
|
|||||||
@ -79,8 +79,10 @@ To avoid saving a cache that already exists, the `cache-hit` output from a resto
|
|||||||
The `cache-primary-key` output from the restore step should also be used to ensure
|
The `cache-primary-key` output from the restore step should also be used to ensure
|
||||||
the cache key does not change during the build if it's calculated based on file contents.
|
the cache key does not change during the build if it's calculated based on file contents.
|
||||||
|
|
||||||
|
Here's an example where we imagine we're calculating a lot of prime numbers and want to cache them:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: Always Caching Primes
|
name: Always Caching Prime Numbers
|
||||||
|
|
||||||
on: push
|
on: push
|
||||||
|
|
||||||
@ -91,23 +93,23 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Restore cached Primes
|
- name: Restore cached Prime Numbers
|
||||||
id: cache-primes-restore
|
id: cache-prime-numbers-restore
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
with:
|
with:
|
||||||
key: ${{ runner.os }}-primes
|
key: ${{ runner.os }}-prime-numbers
|
||||||
path: |
|
path: |
|
||||||
path/to/dependencies
|
path/to/dependencies
|
||||||
some/other/dependencies
|
some/other/dependencies
|
||||||
|
|
||||||
# Intermediate workflow steps
|
# Intermediate workflow steps
|
||||||
|
|
||||||
- name: Always Save Primes
|
- name: Always Save Prime Numbers
|
||||||
id: cache-primes-save
|
id: cache-prime-numbers-save
|
||||||
if: always() && steps.cache-primes-restore.outputs.cache-hit != 'true'
|
if: always() && steps.cache-prime-numbers-restore.outputs.cache-hit != 'true'
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v4
|
||||||
with:
|
with:
|
||||||
key: ${{ steps.cache-primes-restore.outputs.cache-primary-key }}
|
key: ${{ steps.cache-prime-numbers-restore.outputs.cache-primary-key }}
|
||||||
path: |
|
path: |
|
||||||
path/to/dependencies
|
path/to/dependencies
|
||||||
some/other/dependencies
|
some/other/dependencies
|
||||||
|
|||||||
@ -11,12 +11,14 @@ export enum Inputs {
|
|||||||
export enum Outputs {
|
export enum Outputs {
|
||||||
CacheHit = "cache-hit", // Output from cache, restore action
|
CacheHit = "cache-hit", // Output from cache, restore action
|
||||||
CachePrimaryKey = "cache-primary-key", // Output from restore action
|
CachePrimaryKey = "cache-primary-key", // Output from restore action
|
||||||
CacheMatchedKey = "cache-matched-key" // Output from restore action
|
CacheMatchedKey = "cache-matched-key", // Output from restore action
|
||||||
|
CachePath = "cache-path" // Output from restore action
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum State {
|
export enum State {
|
||||||
CachePrimaryKey = "CACHE_KEY",
|
CachePrimaryKey = "CACHE_KEY",
|
||||||
CacheMatchedKey = "CACHE_RESULT"
|
CacheMatchedKey = "CACHE_RESULT",
|
||||||
|
CachePath = "CACHE_PATH"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum Events {
|
export enum Events {
|
||||||
|
|||||||
@ -32,6 +32,8 @@ export async function restoreImpl(
|
|||||||
const primaryKey = core.getInput(Inputs.Key, { required: true });
|
const primaryKey = core.getInput(Inputs.Key, { required: true });
|
||||||
stateProvider.setState(State.CachePrimaryKey, primaryKey);
|
stateProvider.setState(State.CachePrimaryKey, primaryKey);
|
||||||
|
|
||||||
|
stateProvider.setState(State.CachePath, core.getInput(Inputs.Path)); // Output path unchanged from input
|
||||||
|
|
||||||
const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
|
const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
|
||||||
const cachePaths = utils.getInputAsArray(Inputs.Path, {
|
const cachePaths = utils.getInputAsArray(Inputs.Path, {
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@ -35,7 +35,8 @@ export class StateProvider extends StateProviderBase {
|
|||||||
export class NullStateProvider extends StateProviderBase {
|
export class NullStateProvider extends StateProviderBase {
|
||||||
stateToOutputMap = new Map<string, string>([
|
stateToOutputMap = new Map<string, string>([
|
||||||
[State.CacheMatchedKey, Outputs.CacheMatchedKey],
|
[State.CacheMatchedKey, Outputs.CacheMatchedKey],
|
||||||
[State.CachePrimaryKey, Outputs.CachePrimaryKey]
|
[State.CachePrimaryKey, Outputs.CachePrimaryKey],
|
||||||
|
[State.CachePath, Outputs.CachePath]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setState = (key: string, value: string) => {
|
setState = (key: string, value: string) => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user