This commit is contained in:
Guillermo Mazzola 2026-07-31 11:16:17 +02:00 committed by GitHub
commit 3ae35bcf6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 95201 additions and 17 deletions

View File

@ -10,6 +10,11 @@ jest.unstable_mockModule("@actions/core", () => ({
} }
return val.trim(); return val.trim();
}), }),
getBooleanInput: jest.fn(
(name: string, options?: { required?: boolean }) => {
return core.getInput(name, options).toLowerCase() === "true";
}
),
setOutput: jest.fn(), setOutput: jest.fn(),
setFailed: jest.fn(), setFailed: jest.fn(),
info: jest.fn(), info: jest.fn(),
@ -129,3 +134,39 @@ test("save failing logs the debug message", async () => {
expect(warningMock).not.toHaveBeenCalled(); expect(warningMock).not.toHaveBeenCalled();
expect(failedMock).not.toHaveBeenCalled(); expect(failedMock).not.toHaveBeenCalled();
}); });
test.each([
[true, false],
[true, true],
[false, true],
[false, false]
])("save honors post behavior", async (postInput, postMode) => {
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
const inputPath = "node_modules";
testUtils.setInput(Inputs.Key, primaryKey);
testUtils.setInput(Inputs.Path, inputPath);
testUtils.setInput(Inputs.Post, `${postInput}`);
const cacheId = 4;
(cache.saveCache as jest.Mock).mockResolvedValue(cacheId);
await saveOnlyRun(undefined, postMode);
if (postInput === postMode) {
// expects cache to run
expect(cache.saveCache).toHaveBeenCalledTimes(1);
expect(cache.saveCache).toHaveBeenCalledWith(
[inputPath],
primaryKey,
{},
false
);
expect(core.setFailed).toHaveBeenCalledTimes(0);
} else {
// expect to be no-op
expect(cache.saveCache).not.toHaveBeenCalled();
expect(core.setFailed).not.toHaveBeenCalled();
}
});

View File

@ -94887,7 +94887,8 @@ var Inputs;
Inputs["UploadChunkSize"] = "upload-chunk-size"; Inputs["UploadChunkSize"] = "upload-chunk-size";
Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive"; Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive";
Inputs["FailOnCacheMiss"] = "fail-on-cache-miss"; Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action Inputs["LookupOnly"] = "lookup-only";
Inputs["Post"] = "post"; // Input for save action
})(Inputs || (Inputs = {})); })(Inputs || (Inputs = {}));
var Outputs; var Outputs;
(function (Outputs) { (function (Outputs) {

View File

@ -94887,7 +94887,8 @@ var Inputs;
Inputs["UploadChunkSize"] = "upload-chunk-size"; Inputs["UploadChunkSize"] = "upload-chunk-size";
Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive"; Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive";
Inputs["FailOnCacheMiss"] = "fail-on-cache-miss"; Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action Inputs["LookupOnly"] = "lookup-only";
Inputs["Post"] = "post"; // Input for save action
})(Inputs || (Inputs = {})); })(Inputs || (Inputs = {}));
var constants_Outputs; var constants_Outputs;
(function (Outputs) { (function (Outputs) {

View File

@ -94892,7 +94892,8 @@ var Inputs;
Inputs["UploadChunkSize"] = "upload-chunk-size"; Inputs["UploadChunkSize"] = "upload-chunk-size";
Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive"; Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive";
Inputs["FailOnCacheMiss"] = "fail-on-cache-miss"; Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action Inputs["LookupOnly"] = "lookup-only";
Inputs["Post"] = "post"; // Input for save action
})(Inputs || (Inputs = {})); })(Inputs || (Inputs = {}));
var Outputs; var Outputs;
(function (Outputs) { (function (Outputs) {
@ -95052,7 +95053,11 @@ async function saveImpl(stateProvider) {
} }
return cacheId; return cacheId;
} }
async function saveOnlyRun(earlyExit) { async function saveOnlyRun(earlyExit, postStep) {
if (postStep !== undefined &&
postStep !== getInputAsBool(Inputs.Post)) {
return;
}
try { try {
const cacheId = await saveImpl(new NullStateProvider()); const cacheId = await saveImpl(new NullStateProvider());
if (cacheId === -1) { if (cacheId === -1) {
@ -95100,5 +95105,5 @@ async function saveRun(earlyExit) {
;// CONCATENATED MODULE: ./src/saveOnly.ts ;// CONCATENATED MODULE: ./src/saveOnly.ts
saveOnlyRun(true); saveOnlyRun(true, false);

95109
dist/save-only/post/index.js vendored Normal file

File diff suppressed because one or more lines are too long

3
dist/save-only/post/package.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"type": "module"
}

21
dist/save/index.js vendored
View File

@ -94884,7 +94884,7 @@ function saveCacheV2(paths_1, key_1, options_1) {
} }
//# sourceMappingURL=cache.js.map //# sourceMappingURL=cache.js.map
;// CONCATENATED MODULE: ./src/constants.ts ;// CONCATENATED MODULE: ./src/constants.ts
var Inputs; var constants_Inputs;
(function (Inputs) { (function (Inputs) {
Inputs["Key"] = "key"; Inputs["Key"] = "key";
Inputs["Path"] = "path"; Inputs["Path"] = "path";
@ -94892,8 +94892,9 @@ var Inputs;
Inputs["UploadChunkSize"] = "upload-chunk-size"; Inputs["UploadChunkSize"] = "upload-chunk-size";
Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive"; Inputs["EnableCrossOsArchive"] = "enableCrossOsArchive";
Inputs["FailOnCacheMiss"] = "fail-on-cache-miss"; Inputs["FailOnCacheMiss"] = "fail-on-cache-miss";
Inputs["LookupOnly"] = "lookup-only"; // Input for cache, restore action Inputs["LookupOnly"] = "lookup-only";
})(Inputs || (Inputs = {})); Inputs["Post"] = "post"; // Input for save action
})(constants_Inputs || (constants_Inputs = {}));
var constants_Outputs; var constants_Outputs;
(function (Outputs) { (function (Outputs) {
Outputs["CacheHit"] = "cache-hit"; Outputs["CacheHit"] = "cache-hit";
@ -95026,7 +95027,7 @@ async function saveImpl(stateProvider) {
// If restore has stored a primary key in state, reuse that // If restore has stored a primary key in state, reuse that
// Else re-evaluate from inputs // Else re-evaluate from inputs
const primaryKey = stateProvider.getState(constants_State.CachePrimaryKey) || const primaryKey = stateProvider.getState(constants_State.CachePrimaryKey) ||
getInput(Inputs.Key); getInput(constants_Inputs.Key);
if (!primaryKey) { if (!primaryKey) {
logWarning(`Key is not specified.`); logWarning(`Key is not specified.`);
return; return;
@ -95038,11 +95039,11 @@ async function saveImpl(stateProvider) {
info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`); info(`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`);
return; return;
} }
const cachePaths = getInputAsArray(Inputs.Path, { const cachePaths = getInputAsArray(constants_Inputs.Path, {
required: true required: true
}); });
const enableCrossOsArchive = getInputAsBool(Inputs.EnableCrossOsArchive); const enableCrossOsArchive = getInputAsBool(constants_Inputs.EnableCrossOsArchive);
cacheId = await cache_saveCache(cachePaths, primaryKey, { uploadChunkSize: getInputAsInt(Inputs.UploadChunkSize) }, enableCrossOsArchive); cacheId = await cache_saveCache(cachePaths, primaryKey, { uploadChunkSize: getInputAsInt(constants_Inputs.UploadChunkSize) }, enableCrossOsArchive);
if (cacheId != -1) { if (cacheId != -1) {
info(`Cache saved with key: ${primaryKey}`); info(`Cache saved with key: ${primaryKey}`);
} }
@ -95052,7 +95053,11 @@ async function saveImpl(stateProvider) {
} }
return cacheId; return cacheId;
} }
async function saveOnlyRun(earlyExit) { async function saveOnlyRun(earlyExit, postStep) {
if (postStep !== undefined &&
postStep !== utils.getInputAsBool(Inputs.Post)) {
return;
}
try { try {
const cacheId = await saveImpl(new NullStateProvider()); const cacheId = await saveImpl(new NullStateProvider());
if (cacheId === -1) { if (cacheId === -1) {

View File

@ -6,7 +6,7 @@
"type": "module", "type": "module",
"main": "dist/restore/index.js", "main": "dist/restore/index.js",
"scripts": { "scripts": {
"build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && ncc build -o dist/restore-only src/restoreOnly.ts && ncc build -o dist/save-only src/saveOnly.ts", "build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && ncc build -o dist/restore-only src/restoreOnly.ts && ncc build -o dist/save-only src/saveOnly.ts && ncc build -o dist/save-only/post src/saveOnlyPost.ts",
"test": "tsc --noEmit && node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage", "test": "tsc --noEmit && node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage",
"lint": "eslint **/*.ts --cache", "lint": "eslint **/*.ts --cache",
"format": "prettier --write **/*.ts", "format": "prettier --write **/*.ts",

View File

@ -9,6 +9,7 @@ The save action saves a cache. It works similarly to the `cache` action except t
* `key` - An explicit key for a cache entry. See [creating a cache key](../README.md#creating-a-cache-key). * `key` - An explicit key for a cache entry. See [creating a cache key](../README.md#creating-a-cache-key).
* `path` - A list of files, directories, and wildcard patterns to cache. See [`@actions/glob`](https://github.com/actions/toolkit/tree/main/packages/glob) for supported patterns. * `path` - A list of files, directories, and wildcard patterns to cache. See [`@actions/glob`](https://github.com/actions/toolkit/tree/main/packages/glob) for supported patterns.
* `upload-chunk-size` - The chunk size used to split up large files during upload, in bytes * `upload-chunk-size` - The chunk size used to split up large files during upload, in bytes
* `post` - If set to `true` the action will run as a post-step, after the job has finished.
### Outputs ### Outputs

View File

@ -15,9 +15,15 @@ inputs:
description: 'An optional boolean when enabled, allows windows runners to save caches that can be restored on other platforms' description: 'An optional boolean when enabled, allows windows runners to save caches that can be restored on other platforms'
default: 'false' default: 'false'
required: false required: false
post:
description: 'An optional boolean when enabled, allows the action to run after the job has completed'
default: 'false'
required: false
runs: runs:
using: 'node24' using: 'node24'
main: '../dist/save-only/index.js' main: '../dist/save-only/index.js'
post: '../dist/save-only/post/index.js'
post-if: "success()"
branding: branding:
icon: 'archive' icon: 'archive'
color: 'gray-dark' color: 'gray-dark'

View File

@ -5,7 +5,8 @@ export enum Inputs {
UploadChunkSize = "upload-chunk-size", // Input for cache, save action UploadChunkSize = "upload-chunk-size", // Input for cache, save action
EnableCrossOsArchive = "enableCrossOsArchive", // Input for cache, restore, save action EnableCrossOsArchive = "enableCrossOsArchive", // Input for cache, restore, save action
FailOnCacheMiss = "fail-on-cache-miss", // Input for cache, restore action FailOnCacheMiss = "fail-on-cache-miss", // Input for cache, restore action
LookupOnly = "lookup-only" // Input for cache, restore action LookupOnly = "lookup-only", // Input for cache, restore action
Post = "post" // Input for save action
} }
export enum Outputs { export enum Outputs {

View File

@ -79,8 +79,16 @@ export async function saveImpl(
} }
export async function saveOnlyRun( export async function saveOnlyRun(
earlyExit?: boolean | undefined earlyExit?: boolean | undefined,
postStep?: boolean | undefined
): Promise<void> { ): Promise<void> {
if (
postStep !== undefined &&
postStep !== utils.getInputAsBool(Inputs.Post)
) {
return;
}
try { try {
const cacheId = await saveImpl(new NullStateProvider()); const cacheId = await saveImpl(new NullStateProvider());
if (cacheId === -1) { if (cacheId === -1) {

View File

@ -1,3 +1,3 @@
import { saveOnlyRun } from "./saveImpl"; import { saveOnlyRun } from "./saveImpl";
saveOnlyRun(true); saveOnlyRun(true, false);

3
src/saveOnlyPost.ts Normal file
View File

@ -0,0 +1,3 @@
import { saveOnlyRun } from "./saveImpl";
saveOnlyRun(true, true);