mirror of https://github.com/actions/cache.git
Compare commits
8 Commits
8d58649cc8
...
504e1162a1
Author | SHA1 | Date |
---|---|---|
Marco | 504e1162a1 | |
Josh Gross | 2cdf405574 | |
Eman Resu | a11fb02296 | |
mackey0225 | cf7a75e7b9 | |
Josh Gross | c74ca4022c | |
Joel Ambass | f8a7ab490b | |
Joel Ambass | 45b7be0774 | |
Napster134 | 0eb01d12a1 |
|
@ -0,0 +1,20 @@
|
||||||
|
name: 'Publish Immutable Action Version'
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
id-token: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checking out
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Publish
|
||||||
|
id: publish
|
||||||
|
uses: actions/publish-immutable-action@0.0.3
|
|
@ -17,7 +17,6 @@ See ["Caching dependencies to speed up workflows"](https://docs.github.com/en/ac
|
||||||
### v4
|
### v4
|
||||||
|
|
||||||
* Updated to node 20
|
* Updated to node 20
|
||||||
* Added a `save-always` flag to save the cache even if a prior step fails
|
|
||||||
|
|
||||||
### v3
|
### v3
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
# Releases
|
# Releases
|
||||||
|
|
||||||
|
### 4.1.0
|
||||||
|
- Ensure `cache-hit` output is set when a cache is missed - [#1404](https://github.com/actions/cache/pull/1404)
|
||||||
|
- Deprecate `save-always` input - [#1452](https://github.com/actions/cache/pull/1452)
|
||||||
|
|
||||||
### 4.0.2
|
### 4.0.2
|
||||||
|
|
||||||
- Fixed restore `fail-on-cache-miss` not working.
|
- Fixed restore `fail-on-cache-miss` not working.
|
||||||
|
|
|
@ -29,7 +29,11 @@ inputs:
|
||||||
save-always:
|
save-always:
|
||||||
description: 'Run the post step to save the cache even if another step before fails'
|
description: 'Run the post step to save the cache even if another step before fails'
|
||||||
default: 'false'
|
default: 'false'
|
||||||
required: false
|
required: false
|
||||||
|
deprecationMessage: |
|
||||||
|
save-always does not work as intended and will be removed in a future release.
|
||||||
|
A separate `actions/cache/restore` step should be used instead.
|
||||||
|
See https://github.com/actions/cache/tree/main/save#always-save-cache for more details.
|
||||||
outputs:
|
outputs:
|
||||||
cache-hit:
|
cache-hit:
|
||||||
description: 'A boolean value to indicate an exact match was found for the primary key'
|
description: 'A boolean value to indicate an exact match was found for the primary key'
|
||||||
|
@ -37,7 +41,7 @@ runs:
|
||||||
using: 'node20'
|
using: 'node20'
|
||||||
main: 'dist/restore/index.js'
|
main: 'dist/restore/index.js'
|
||||||
post: 'dist/save/index.js'
|
post: 'dist/save/index.js'
|
||||||
post-if: "success() || github.event.inputs.save-always"
|
post-if: "success()"
|
||||||
branding:
|
branding:
|
||||||
icon: 'archive'
|
icon: 'archive'
|
||||||
color: 'gray-dark'
|
color: 'gray-dark'
|
||||||
|
|
|
@ -81,7 +81,7 @@ On similar lines, commit sha can be used to create a very specialized and short
|
||||||
key: cache-${{ github.sha }}
|
key: cache-${{ github.sha }}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Using multiple factors while forming a key depening on the need
|
### Using multiple factors while forming a key depending on the need
|
||||||
|
|
||||||
Cache key can be formed by combination of more than one metadata, evaluated info.
|
Cache key can be formed by combination of more than one metadata, evaluated info.
|
||||||
|
|
||||||
|
@ -243,24 +243,7 @@ with:
|
||||||
|
|
||||||
### Saving cache even if the build fails
|
### Saving cache even if the build fails
|
||||||
|
|
||||||
There can be cases where a cache should be saved even if the build job fails. For example, a job can fail due to flaky tests but the caches can still be re-used. You can use `actions/cache/save` action to save the cache by using `if: always()` condition.
|
See [Always save cache](./save/README.md#always-save-cache).
|
||||||
|
|
||||||
Similarly, `actions/cache/save` action can be conditionally used based on the output of the previous steps. This way you get more control on when to save the cache.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
.
|
|
||||||
. // restore if need be
|
|
||||||
.
|
|
||||||
- name: Build
|
|
||||||
run: /build.sh
|
|
||||||
- uses: actions/cache/save@v4
|
|
||||||
if: always() // or any other condition to invoke the save action
|
|
||||||
with:
|
|
||||||
path: path/to/dependencies
|
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Saving cache once and reusing in multiple workflows
|
### Saving cache once and reusing in multiple workflows
|
||||||
|
|
||||||
|
|
|
@ -189,12 +189,13 @@ function saveCache(paths, key, options, enableCrossOsArchive = false) {
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
yield (0, tar_1.listTar)(archivePath, compressionMethod);
|
yield (0, tar_1.listTar)(archivePath, compressionMethod);
|
||||||
}
|
}
|
||||||
const fileSizeLimit = 10 * 1024 * 1024 * 1024; // 10GB per repo limit
|
const fileSizeMultiplierGb = 10 // 10GB per repo limit
|
||||||
|
const fileSizeLimit = fileSizeMultiplierGb * 1024 * 1024 * 1024;
|
||||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
||||||
core.debug(`File Size: ${archiveFileSize}`);
|
core.debug(`File Size: ${archiveFileSize}`);
|
||||||
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
||||||
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
||||||
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the 10GB limit, not saving cache.`);
|
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the ${fileSizeMultiplierGb}GB limit, not saving cache.`);
|
||||||
}
|
}
|
||||||
core.debug('Reserving Cache');
|
core.debug('Reserving Cache');
|
||||||
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
||||||
|
|
|
@ -189,12 +189,13 @@ function saveCache(paths, key, options, enableCrossOsArchive = false) {
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
yield (0, tar_1.listTar)(archivePath, compressionMethod);
|
yield (0, tar_1.listTar)(archivePath, compressionMethod);
|
||||||
}
|
}
|
||||||
const fileSizeLimit = 10 * 1024 * 1024 * 1024; // 10GB per repo limit
|
const fileSizeMultiplierGb = 10 // 10GB per repo limit
|
||||||
|
const fileSizeLimit = fileSizeMultiplierGb * 1024 * 1024 * 1024;
|
||||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
||||||
core.debug(`File Size: ${archiveFileSize}`);
|
core.debug(`File Size: ${archiveFileSize}`);
|
||||||
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
||||||
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
||||||
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the 10GB limit, not saving cache.`);
|
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the ${fileSizeMultiplierGb}GB limit, not saving cache.`);
|
||||||
}
|
}
|
||||||
core.debug('Reserving Cache');
|
core.debug('Reserving Cache');
|
||||||
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
||||||
|
|
|
@ -189,12 +189,13 @@ function saveCache(paths, key, options, enableCrossOsArchive = false) {
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
yield (0, tar_1.listTar)(archivePath, compressionMethod);
|
yield (0, tar_1.listTar)(archivePath, compressionMethod);
|
||||||
}
|
}
|
||||||
const fileSizeLimit = 10 * 1024 * 1024 * 1024; // 10GB per repo limit
|
const fileSizeMultiplierGb = 10 // 10GB per repo limit
|
||||||
|
const fileSizeLimit = fileSizeMultiplierGb * 1024 * 1024 * 1024;
|
||||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
||||||
core.debug(`File Size: ${archiveFileSize}`);
|
core.debug(`File Size: ${archiveFileSize}`);
|
||||||
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
||||||
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
||||||
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the 10GB limit, not saving cache.`);
|
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the ${fileSizeMultiplierGb}GB limit, not saving cache.`);
|
||||||
}
|
}
|
||||||
core.debug('Reserving Cache');
|
core.debug('Reserving Cache');
|
||||||
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
||||||
|
|
|
@ -189,12 +189,13 @@ function saveCache(paths, key, options, enableCrossOsArchive = false) {
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
yield (0, tar_1.listTar)(archivePath, compressionMethod);
|
yield (0, tar_1.listTar)(archivePath, compressionMethod);
|
||||||
}
|
}
|
||||||
const fileSizeLimit = 10 * 1024 * 1024 * 1024; // 10GB per repo limit
|
const fileSizeMultiplierGb = 10 // 10GB per repo limit
|
||||||
|
const fileSizeLimit = fileSizeMultiplierGb * 1024 * 1024 * 1024;
|
||||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath);
|
||||||
core.debug(`File Size: ${archiveFileSize}`);
|
core.debug(`File Size: ${archiveFileSize}`);
|
||||||
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
||||||
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
if (archiveFileSize > fileSizeLimit && !utils.isGhes()) {
|
||||||
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the 10GB limit, not saving cache.`);
|
throw new Error(`Cache size of ~${Math.round(archiveFileSize / (1024 * 1024))} MB (${archiveFileSize} B) is over the ${fileSizeMultiplierGb}GB limit, not saving cache.`);
|
||||||
}
|
}
|
||||||
core.debug('Reserving Cache');
|
core.debug('Reserving Cache');
|
||||||
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "cache",
|
"name": "cache",
|
||||||
"version": "4.0.2",
|
"version": "4.1.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cache",
|
"name": "cache",
|
||||||
"version": "4.0.2",
|
"version": "4.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/cache": "^3.2.3",
|
"@actions/cache": "^3.2.3",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cache",
|
"name": "cache",
|
||||||
"version": "4.0.2",
|
"version": "4.1.0",
|
||||||
"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",
|
||||||
|
|
|
@ -70,19 +70,45 @@ with:
|
||||||
|
|
||||||
### Always save cache
|
### Always save cache
|
||||||
|
|
||||||
There are instances where some flaky test cases would fail the entire workflow and users would get frustrated because the builds would run for hours and the cache couldn't be saved as the workflow failed in between. For such use-cases, users now have the ability to use the `actions/cache/save` action to save the cache by using an `if: always()` condition. This way the cache will always be saved if generated, or a warning will be generated that nothing is found on the cache path. Users can also use the `if` condition to only execute the `actions/cache/save` action depending on the output of previous steps. This way they get more control of when to save the cache.
|
There are instances where some flaky test cases would fail the entire workflow and users would get frustrated because the builds would run for hours and the cache couldn't be saved as the workflow failed in between.
|
||||||
|
For such use-cases, users now have the ability to use the `actions/cache/save` action to save the cache by using an [`always()`](https://docs.github.com/actions/writing-workflows/choosing-what-your-workflow-does/expressions#always) condition.
|
||||||
|
This way the cache will always be saved if generated, or a warning will be generated that nothing is found on the cache path. Users can also use the `if` condition to only execute the `actions/cache/save` action depending on the output of previous steps. This way they get more control of when to save the cache.
|
||||||
|
|
||||||
|
To avoid saving a cache that already exists, the `cache-hit` output from a restore step should be checked.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
steps:
|
name: Always Caching Primes
|
||||||
- uses: actions/checkout@v4
|
|
||||||
.
|
on: push
|
||||||
. // restore if need be
|
|
||||||
.
|
jobs:
|
||||||
- name: Build
|
build:
|
||||||
run: /build.sh
|
runs-on: ubuntu-latest
|
||||||
- uses: actions/cache/save@v4
|
|
||||||
if: always() // or any other condition to invoke the save action
|
steps:
|
||||||
with:
|
- uses: actions/checkout@v4
|
||||||
path: path/to/dependencies
|
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
- name: Restore cached Primes
|
||||||
|
id: cache-primes-restore
|
||||||
|
uses: actions/cache/restore@v4
|
||||||
|
with:
|
||||||
|
key: ${{ runner.os }}-primes
|
||||||
|
path: |
|
||||||
|
path/to/dependencies
|
||||||
|
some/other/dependencies
|
||||||
|
|
||||||
|
# Intermediate workflow steps
|
||||||
|
|
||||||
|
- name: Always Save Primes
|
||||||
|
id: cache-primes-save
|
||||||
|
if: always() && steps.cache-primes-restore.outputs.cache-hit != 'true'
|
||||||
|
uses: actions/cache/save@v4
|
||||||
|
with:
|
||||||
|
key: ${{ steps.cache-primes-restore.outputs.cache-primary-key }}
|
||||||
|
path: |
|
||||||
|
path/to/dependencies
|
||||||
|
some/other/dependencies
|
||||||
```
|
```
|
||||||
|
|
Loading…
Reference in New Issue