Skip to content

Commit 2d459fd

Browse files
authored
feat: add cache-matched-key output (#68)
* feat: add cache-matched-key output * test: verify cache-matched-key output in CI workflows * fix: guard cache-matched-key assertions on successful restore Only assert cache-matched-key value when cache-hit is true, since transient S3 failures result in empty output by design.
1 parent 618ea8b commit 2d459fd

11 files changed

Lines changed: 99 additions & 0 deletions

File tree

.github/workflows/lookup-only.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,17 @@ jobs:
6767
env:
6868
CACHE_HIT: ${{ steps.lookup.outputs.cache-hit }}
6969
CACHE_SIZE: ${{ steps.lookup.outputs.cache-size }}
70+
CACHE_MATCHED_KEY: ${{ steps.lookup.outputs.cache-matched-key }}
71+
EXPECTED_KEY: test-${{ runner.os }}-${{ github.run_id }}
7072
shell: bash
7173
run: |
7274
echo "CACHE_HIT $CACHE_HIT"
7375
echo "CACHE_SIZE $CACHE_SIZE"
76+
echo "CACHE_MATCHED_KEY $CACHE_MATCHED_KEY"
77+
if [ "$CACHE_HIT" = "true" ] && [ "$CACHE_MATCHED_KEY" != "$EXPECTED_KEY" ]; then
78+
echo "cache-matched-key mismatch: got '$CACHE_MATCHED_KEY', expected '$EXPECTED_KEY'"
79+
exit 1
80+
fi
7481
ls -R ~/test-cache || true
7582
ls -R test-cache || true
7683
src/create-cache-files.sh ${{ runner.os }} test-cache check_not_exist

.github/workflows/test-env.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ jobs:
4949
- name: Checkout
5050
uses: actions/checkout@v6
5151
- name: Restore cache
52+
id: restore
5253
uses: ./
5354
env:
5455
AWS_ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY }}
@@ -62,6 +63,17 @@ jobs:
6263
path: |
6364
test-cache
6465
~/test-cache
66+
- name: Verify cache-matched-key output
67+
if: steps.restore.outputs.cache-hit == 'true'
68+
shell: bash
69+
env:
70+
CACHE_MATCHED_KEY: ${{ steps.restore.outputs.cache-matched-key }}
71+
EXPECTED_KEY: test-${{ runner.os }}-${{ github.run_id }}
72+
run: |
73+
if [ "$CACHE_MATCHED_KEY" != "$EXPECTED_KEY" ]; then
74+
echo "cache-matched-key mismatch: got '$CACHE_MATCHED_KEY', expected '$EXPECTED_KEY'"
75+
exit 1
76+
fi
6577
- name: Verify cache files in working directory
6678
shell: bash
6779
run: src/verify-cache-files.sh ${{ runner.os }} test-cache

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ jobs:
4646
- name: Checkout
4747
uses: actions/checkout@v6
4848
- name: Restore cache
49+
id: restore
4950
uses: ./
5051
with:
5152
endpoint: ${{ secrets.ENDPOINT }}
@@ -57,6 +58,17 @@ jobs:
5758
path: |
5859
test-cache
5960
~/test-cache
61+
- name: Verify cache-matched-key output
62+
if: steps.restore.outputs.cache-hit == 'true'
63+
shell: bash
64+
env:
65+
CACHE_MATCHED_KEY: ${{ steps.restore.outputs.cache-matched-key }}
66+
EXPECTED_KEY: test-${{ runner.os }}-${{ github.run_id }}
67+
run: |
68+
if [ "$CACHE_MATCHED_KEY" != "$EXPECTED_KEY" ]; then
69+
echo "cache-matched-key mismatch: got '$CACHE_MATCHED_KEY', expected '$EXPECTED_KEY'"
70+
exit 1
71+
fi
6072
- name: Verify cache files in working directory
6173
shell: bash
6274
run: src/verify-cache-files.sh ${{ runner.os }} test-cache
@@ -75,6 +87,7 @@ jobs:
7587
- name: Checkout
7688
uses: actions/checkout@v6
7789
- name: Restore cache
90+
id: restore-keys
7891
uses: ./
7992
with:
8093
endpoint: ${{ secrets.ENDPOINT }}
@@ -87,6 +100,13 @@ jobs:
87100
test-cache
88101
~/test-cache
89102
restore-keys: test-${{ runner.os }}-
103+
- name: Verify cache-matched-key output
104+
if: steps.restore-keys.outputs.cache-matched-key != ''
105+
shell: bash
106+
env:
107+
CACHE_MATCHED_KEY: ${{ steps.restore-keys.outputs.cache-matched-key }}
108+
run: |
109+
echo "cache-matched-key is set to: $CACHE_MATCHED_KEY"
90110
- name: Verify cache files in working directory
91111
shell: bash
92112
run: src/verify-cache-files.sh ${{ runner.os }} test-cache
@@ -194,6 +214,7 @@ jobs:
194214
- name: Checkout
195215
uses: actions/checkout@v6
196216
- name: Restore cache
217+
id: restore-only
197218
uses: ./restore/
198219
with:
199220
endpoint: ${{ secrets.ENDPOINT }}
@@ -205,6 +226,17 @@ jobs:
205226
path: |
206227
test-cache
207228
~/test-cache
229+
- name: Verify cache-matched-key output
230+
if: steps.restore-only.outputs.cache-hit == 'true'
231+
shell: bash
232+
env:
233+
CACHE_MATCHED_KEY: ${{ steps.restore-only.outputs.cache-matched-key }}
234+
EXPECTED_KEY: test-save-only-${{ runner.os }}-${{ github.run_id }}
235+
run: |
236+
if [ "$CACHE_MATCHED_KEY" != "$EXPECTED_KEY" ]; then
237+
echo "cache-matched-key mismatch: got '$CACHE_MATCHED_KEY', expected '$EXPECTED_KEY'"
238+
exit 1
239+
fi
208240
- name: Verify cache files in working directory
209241
shell: bash
210242
run: src/verify-cache-files.sh ${{ runner.os }} test-cache

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,27 @@ To check if cache hits and size is not zero without downloading:
117117
`restore-keys` works similar to how github's `@actions/cache@v5` works: It search each item in `restore-keys`
118118
as prefix in object names and use the latest one
119119

120+
To restore from the cache using a `restore-key` prefix if the `key` restore fails:
121+
122+
```yaml
123+
- uses: tespkg/actions-cache/restore@v1
124+
with:
125+
accessKey: "Q3AM3UQ867SPQQA43P2F" # required
126+
secretKey: "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" # required
127+
bucket: actions-cache # required
128+
# actions/cache compatible properties: https://github.com/actions/cache
129+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
130+
restore-keys: |
131+
${{ runner.os }}-yarn-
132+
${{ runner.os }}-
133+
path: |
134+
node_modules
135+
```
136+
137+
If a match is found using one of the `restore-keys` options, then `cache-hit` will be FALSE but the
138+
`cache-matched-key` output will be set to the key that matched. See the
139+
[actions/cache](https://github.com/actions/cache/blob/main/restore/README.md#outputs) notes.
140+
120141
## Amazon S3 permissions
121142

122143
When using this with Amazon S3, the following permissions are necessary:

action.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ outputs:
6565
description: "A boolean value to indicate an exact match was found for the primary key"
6666
cache-size:
6767
description: "A integer value denoting the size of the cache object found (measured in bytes)"
68+
cache-matched-key:
69+
description: "The key of the cache object found, if any"
6870
runs:
6971
using: node24
7072
main: "dist/restore/index.js"

dist/restore/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86081,6 +86081,7 @@ function restoreCache() {
8608186081
const cacheHit = matchingKey === key;
8608286082
(0, utils_1.setCacheHitOutput)(cacheHit);
8608386083
(0, utils_1.setCacheSizeOutput)(obj.size);
86084+
(0, utils_1.setCacheMatchedKeyOutput)(matchingKey);
8608486085
if (lookupOnly) {
8608586086
if (cacheHit && obj.size > 0) {
8608686087
core.info(`Cache Hit. NOT Downloading cache from s3 because lookup-only is set. bucket: ${bucket}, object: ${obj.name}`);
@@ -86103,6 +86104,7 @@ function restoreCache() {
8610386104
catch (e) {
8610486105
core.info("Restore s3 cache failed: " + e.message);
8610586106
(0, utils_1.setCacheHitOutput)(false);
86107+
(0, utils_1.setCacheMatchedKeyOutput)("");
8610686108
if (useFallback) {
8610786109
if ((0, utils_1.isGhes)()) {
8610886110
core.warning("Cache fallback is not supported on Github Enterpise.");
@@ -86112,6 +86114,7 @@ function restoreCache() {
8611286114
const fallbackMatchingKey = yield cache.restoreCache(paths, key, restoreKeys);
8611386115
if (fallbackMatchingKey) {
8611486116
(0, utils_1.setCacheHitOutput)(fallbackMatchingKey === key);
86117+
(0, utils_1.setCacheMatchedKeyOutput)(fallbackMatchingKey);
8611586118
core.info("Fallback cache restored successfully");
8611686119
}
8611786120
else {
@@ -86212,6 +86215,7 @@ exports.getInputAsInt = getInputAsInt;
8621286215
exports.formatSize = formatSize;
8621386216
exports.setCacheHitOutput = setCacheHitOutput;
8621486217
exports.setCacheSizeOutput = setCacheSizeOutput;
86218+
exports.setCacheMatchedKeyOutput = setCacheMatchedKeyOutput;
8621586219
exports.findObject = findObject;
8621686220
exports.listObjects = listObjects;
8621786221
exports.saveMatchedKey = saveMatchedKey;
@@ -86296,6 +86300,9 @@ function setCacheHitOutput(isCacheHit) {
8629686300
function setCacheSizeOutput(cacheSize) {
8629786301
core.setOutput("cache-size", cacheSize.toString());
8629886302
}
86303+
function setCacheMatchedKeyOutput(cacheMatchedKey) {
86304+
core.setOutput("cache-matched-key", cacheMatchedKey);
86305+
}
8629986306
function findObject(mc, bucket, key, restoreKeys, compressionMethod) {
8630086307
return __awaiter(this, void 0, void 0, function* () {
8630186308
core.debug("Key: " + JSON.stringify(key));

dist/save/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86127,6 +86127,7 @@ exports.getInputAsInt = getInputAsInt;
8612786127
exports.formatSize = formatSize;
8612886128
exports.setCacheHitOutput = setCacheHitOutput;
8612986129
exports.setCacheSizeOutput = setCacheSizeOutput;
86130+
exports.setCacheMatchedKeyOutput = setCacheMatchedKeyOutput;
8613086131
exports.findObject = findObject;
8613186132
exports.listObjects = listObjects;
8613286133
exports.saveMatchedKey = saveMatchedKey;
@@ -86211,6 +86212,9 @@ function setCacheHitOutput(isCacheHit) {
8621186212
function setCacheSizeOutput(cacheSize) {
8621286213
core.setOutput("cache-size", cacheSize.toString());
8621386214
}
86215+
function setCacheMatchedKeyOutput(cacheMatchedKey) {
86216+
core.setOutput("cache-matched-key", cacheMatchedKey);
86217+
}
8621486218
function findObject(mc, bucket, key, restoreKeys, compressionMethod) {
8621586219
return __awaiter(this, void 0, void 0, function* () {
8621686220
core.debug("Key: " + JSON.stringify(key));

dist/saveOnly/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86127,6 +86127,7 @@ exports.getInputAsInt = getInputAsInt;
8612786127
exports.formatSize = formatSize;
8612886128
exports.setCacheHitOutput = setCacheHitOutput;
8612986129
exports.setCacheSizeOutput = setCacheSizeOutput;
86130+
exports.setCacheMatchedKeyOutput = setCacheMatchedKeyOutput;
8613086131
exports.findObject = findObject;
8613186132
exports.listObjects = listObjects;
8613286133
exports.saveMatchedKey = saveMatchedKey;
@@ -86211,6 +86212,9 @@ function setCacheHitOutput(isCacheHit) {
8621186212
function setCacheSizeOutput(cacheSize) {
8621286213
core.setOutput("cache-size", cacheSize.toString());
8621386214
}
86215+
function setCacheMatchedKeyOutput(cacheMatchedKey) {
86216+
core.setOutput("cache-matched-key", cacheMatchedKey);
86217+
}
8621486218
function findObject(mc, bucket, key, restoreKeys, compressionMethod) {
8621586219
return __awaiter(this, void 0, void 0, function* () {
8621686220
core.debug("Key: " + JSON.stringify(key));

restore/action.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ outputs:
6565
description: "A boolean value to indicate an exact match was found for the primary key"
6666
cache-size:
6767
description: "A integer value denoting the size of the cache object found (measured in bytes)"
68+
cache-matched-key:
69+
description: "The key of the cache object found, if any"
6870
runs:
6971
using: node24
7072
main: "../dist/restore/index.js"

src/restore.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
isGhes,
1313
newMinio,
1414
setCacheHitOutput,
15+
setCacheMatchedKeyOutput,
1516
setCacheSizeOutput,
1617
saveMatchedKey,
1718
getInput,
@@ -67,6 +68,7 @@ async function restoreCache() {
6768
const cacheHit = matchingKey === key;
6869
setCacheHitOutput(cacheHit);
6970
setCacheSizeOutput(obj.size);
71+
setCacheMatchedKeyOutput(matchingKey);
7072
if (lookupOnly) {
7173
if (cacheHit && obj.size > 0) {
7274
core.info(
@@ -95,6 +97,7 @@ async function restoreCache() {
9597
} catch (e) {
9698
core.info("Restore s3 cache failed: " + e.message);
9799
setCacheHitOutput(false);
100+
setCacheMatchedKeyOutput("");
98101
if (useFallback) {
99102
if (isGhes()) {
100103
core.warning("Cache fallback is not supported on Github Enterpise.");
@@ -107,6 +110,7 @@ async function restoreCache() {
107110
);
108111
if (fallbackMatchingKey) {
109112
setCacheHitOutput(fallbackMatchingKey === key);
113+
setCacheMatchedKeyOutput(fallbackMatchingKey);
110114
core.info("Fallback cache restored successfully");
111115
} else {
112116
core.info("Fallback cache restore failed");

0 commit comments

Comments
 (0)