Skip to content

Commit cdd5708

Browse files
committed
ci: namespace fixture cache keys
1 parent 9317dae commit cdd5708

6 files changed

Lines changed: 48 additions & 4 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ jobs:
1313
steps:
1414
- uses: actions/checkout@v6
1515

16-
- uses: actions/setup-node@v6
16+
- uses: ./
1717
with:
1818
node-version: 22.x
19-
package-manager-cache: false
2019

2120
- name: Run unit tests
2221
run: npm test
@@ -55,6 +54,7 @@ jobs:
5554
uses: ./
5655
with:
5756
working-directory: ${{ matrix.fixture }}
57+
cache-key-suffix: fixture-tests
5858
lookup-only: "true"
5959

6060
- name: Assert resolved action outputs
@@ -110,6 +110,7 @@ jobs:
110110
uses: ./
111111
with:
112112
working-directory: ${{ matrix.fixture }}
113+
cache-key-suffix: fixture-tests
113114

114115
- name: Assert restore behavior
115116
shell: bash

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ steps:
5454
| `node-version` | `22.x` | Node.js version to install with `actions/setup-node` |
5555
| `package-manager` | `""` | Explicit override for `npm`, `pnpm`, or `yarn` |
5656
| `working-directory` | `"."` | Repository-relative directory containing `package.json` and the lockfile |
57+
| `cache-key-suffix` | `""` | Optional suffix appended to the dependency cache key when you want to namespace cache entries |
5758
| `lookup-only` | `"false"` | When `true`, only checks whether the cache exists and skips downloading it |
5859

5960
## Outputs

action.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ inputs:
1111
working-directory:
1212
description: "Repository-relative directory containing package.json and lockfile"
1313
default: "."
14+
cache-key-suffix:
15+
description: "Optional suffix appended to the dependency cache key for namespacing"
16+
default: ""
1417
lookup-only:
1518
description: "If true, only checks if the dependency cache exists and skips download. Does not change save cache behavior"
1619
default: "false"
@@ -62,6 +65,7 @@ runs:
6265
node "$GITHUB_ACTION_PATH/scripts/resolve-cache-paths.mjs" \
6366
--cwd "$GITHUB_WORKSPACE" \
6467
--working-directory "${{ inputs.working-directory }}" \
68+
--cache-key-suffix "${{ inputs.cache-key-suffix }}" \
6569
--github-output "$GITHUB_OUTPUT"
6670
6771
- name: Resolve package manager
@@ -83,7 +87,7 @@ runs:
8387
uses: actions/cache@v5
8488
with:
8589
path: ${{ steps.resolve-cache-paths.outputs.cachePaths }}
86-
key: node-modules-${{ inputs.node-version }}-${{ runner.os }}-${{ runner.arch }}-${{ steps.resolve-cache-paths.outputs.workingDirectoryKey }}-${{ steps.resolve-package-manager.outputs.managerCacheKey }}-${{ steps.resolve-package-manager.outputs.lockfileSha }}
90+
key: node-modules-${{ inputs.node-version }}-${{ runner.os }}-${{ runner.arch }}-${{ steps.resolve-cache-paths.outputs.workingDirectoryKey }}-${{ steps.resolve-package-manager.outputs.managerCacheKey }}-${{ steps.resolve-package-manager.outputs.lockfileSha }}${{ steps.resolve-cache-paths.outputs.cacheKeySuffixSegment }}
8791
lookup-only: ${{ inputs.lookup-only }}
8892

8993
- name: Install dependencies

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/resolve-cache-paths.mjs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export function parseArgs(argv) {
77
const args = {
88
cwd: process.cwd(),
99
workingDirectory: '.',
10+
cacheKeySuffix: '',
1011
githubOutput: process.env.GITHUB_OUTPUT ?? '',
1112
};
1213

@@ -19,6 +20,9 @@ export function parseArgs(argv) {
1920
} else if (arg === '--working-directory') {
2021
args.workingDirectory = argv[index + 1] ?? '.';
2122
index += 1;
23+
} else if (arg === '--cache-key-suffix') {
24+
args.cacheKeySuffix = argv[index + 1] ?? '';
25+
index += 1;
2226
} else if (arg === '--github-output') {
2327
args.githubOutput = argv[index + 1] ?? '';
2428
index += 1;
@@ -76,6 +80,15 @@ export function buildWorkingDirectoryKey(workingDirectory) {
7680
return `${slug}-${digest}`;
7781
}
7882

83+
export function normalizeCacheKeySuffix(cacheKeySuffix) {
84+
const normalized = cacheKeySuffix.trim();
85+
if (normalized === '') {
86+
return '';
87+
}
88+
89+
return normalized.replace(/[^A-Za-z0-9_.-]+/g, '-');
90+
}
91+
7992
export function buildCachePaths(workingDirectory) {
8093
const base = workingDirectory === '.' ? '' : `${workingDirectory}/`;
8194
return [
@@ -86,8 +99,9 @@ export function buildCachePaths(workingDirectory) {
8699
];
87100
}
88101

89-
export function buildResult({ cwd, workingDirectory }) {
102+
export function buildResult({ cwd, workingDirectory, cacheKeySuffix = '' }) {
90103
const resolvedWorkingDirectory = resolveWorkingDirectory(cwd, workingDirectory);
104+
const normalizedCacheKeySuffix = normalizeCacheKeySuffix(cacheKeySuffix);
91105

92106
return {
93107
absoluteWorkingDirectory: resolvedWorkingDirectory.absoluteWorkingDirectory,
@@ -96,6 +110,9 @@ export function buildResult({ cwd, workingDirectory }) {
96110
resolvedWorkingDirectory.workingDirectory,
97111
),
98112
cachePaths: buildCachePaths(resolvedWorkingDirectory.workingDirectory),
113+
cacheKeySuffix: normalizedCacheKeySuffix,
114+
cacheKeySuffixSegment:
115+
normalizedCacheKeySuffix === '' ? '' : `-${normalizedCacheKeySuffix}`,
99116
};
100117
}
101118

@@ -122,6 +139,7 @@ export function main(argv = process.argv.slice(2)) {
122139
const result = buildResult({
123140
cwd: args.cwd,
124141
workingDirectory: args.workingDirectory,
142+
cacheKeySuffix: args.cacheKeySuffix,
125143
});
126144

127145
writeGithubOutput(args.githubOutput, result);

test/resolve-cache-paths.test.mjs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
buildCachePaths,
99
buildResult,
1010
buildWorkingDirectoryKey,
11+
normalizeCacheKeySuffix,
1112
resolveWorkingDirectory,
1213
} from '../scripts/resolve-cache-paths.mjs';
1314

@@ -67,6 +68,12 @@ test('buildWorkingDirectoryKey generates a stable root key and nested slug', ()
6768
);
6869
});
6970

71+
test('normalizeCacheKeySuffix preserves safe values and normalizes separators', () => {
72+
assert.equal(normalizeCacheKeySuffix('fixture-tests'), 'fixture-tests');
73+
assert.equal(normalizeCacheKeySuffix(' fixture tests / ci '), 'fixture-tests-ci');
74+
assert.equal(normalizeCacheKeySuffix(' '), '');
75+
});
76+
7077
test('buildCachePaths scopes cache globs to the resolved working directory', () => {
7178
assert.deepEqual(buildCachePaths('.'), [
7279
'node_modules',
@@ -90,10 +97,13 @@ test('buildResult combines normalized working-directory and cache metadata', ()
9097
const result = buildResult({
9198
cwd: tempDir,
9299
workingDirectory: 'fixtures/npm-basic',
100+
cacheKeySuffix: 'fixture tests',
93101
});
94102

95103
assert.equal(result.workingDirectory, 'fixtures/npm-basic');
96104
assert.match(result.workingDirectoryKey, /^fixtures__npm-basic-[a-f0-9]{8}$/);
97105
assert.equal(result.cachePaths[0], 'fixtures/npm-basic/node_modules');
106+
assert.equal(result.cacheKeySuffix, 'fixture-tests');
107+
assert.equal(result.cacheKeySuffixSegment, '-fixture-tests');
98108
});
99109
});

0 commit comments

Comments
 (0)