Compare commits

...

13 Commits

Author SHA1 Message Date
Eman Resu
2fc5b33e85
Merge fa8c252a0b into 8b402f58fb 2026-01-20 23:18:09 +00:00
Ryan Ghadimi
8b402f58fb
Merge pull request #1692 from GhadimiR/main
Bump @actions/cache to 5.0.3
2026-01-16 17:25:13 +00:00
Ryan Ghadimi
304ab5a070 license for httpclient 2026-01-16 13:30:00 +00:00
Ryan Ghadimi
609fc19e67 Update licensed record for cache 2026-01-16 12:28:12 +00:00
Ryan Ghadimi
b22231e43d Build 2026-01-16 11:42:17 +00:00
Ryan Ghadimi
93150cdfb3 Add PR link to releases 2026-01-16 11:39:29 +00:00
Ryan Ghadimi
9b8ca9f07e Bump actions/cache to 5.0.3 2026-01-16 11:35:54 +00:00
Ella Kramer
fa8c252a0b Update tests to account for changes 2024-07-19 17:16:25 -04:00
Ella Kramer
b0a3f6e7a6 Update typescript files to implement cachePath 2024-07-19 17:16:09 -04:00
Ella Kramer
12b3b8a0b8 Don't edit index.js since that's not actually how you make changes 2024-07-19 16:23:40 -04:00
Ella Kramer
9806e2f37f Correct cachePath to be a direct output, not a state 2024-07-19 16:07:00 -04:00
Ella Kramer
b3f0756597 Update tests to expect cache-path to exist as an output 2024-07-19 15:43:01 -04:00
Ella Kramer
b6cff214f7 Add paths as an output for easier access 2024-07-19 15:35:02 -04:00
17 changed files with 198 additions and 56 deletions

View File

@ -1,6 +1,6 @@
--- ---
name: "@actions/cache" name: "@actions/cache"
version: 5.0.1 version: 5.0.3
type: npm type: npm
summary: Actions cache lib summary: Actions cache lib
homepage: https://github.com/actions/toolkit/tree/main/packages/cache homepage: https://github.com/actions/toolkit/tree/main/packages/cache

View File

@ -1,6 +1,6 @@
--- ---
name: "@actions/http-client" name: "@actions/http-client"
version: 3.0.0 version: 3.0.1
type: npm type: npm
summary: Actions Http Client summary: Actions Http Client
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client homepage: https://github.com/actions/toolkit/tree/main/packages/http-client

View File

@ -2,6 +2,10 @@
## Changelog ## Changelog
### 5.0.2
- Bump `@actions/cache` to v5.0.3 [#1692](https://github.com/actions/cache/pull/1692)
### 5.0.1 ### 5.0.1
- Update `@azure/storage-blob` to `^12.29.1` via `@actions/cache@5.0.1` [#1685](https://github.com/actions/cache/pull/1685) - Update `@azure/storage-blob` to `^12.29.1` via `@actions/cache@5.0.1` [#1685](https://github.com/actions/cache/pull/1685)

View File

@ -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}`

View File

@ -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");

View File

@ -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}`

View File

@ -2398,6 +2398,18 @@ class CacheServiceClient {
} }
errorMessage = `${errorMessage}: ${body.msg}`; errorMessage = `${errorMessage}: ${body.msg}`;
} }
// Handle rate limiting - don't retry, just warn and exit
// For more info, see https://docs.github.com/en/actions/reference/limits
if (statusCode === http_client_1.HttpCodes.TooManyRequests) {
const retryAfterHeader = response.message.headers['retry-after'];
if (retryAfterHeader) {
const parsedSeconds = parseInt(retryAfterHeader, 10);
if (!isNaN(parsedSeconds) && parsedSeconds > 0) {
(0, core_1.warning)(`You've hit a rate limit, your rate limit will reset in ${parsedSeconds} seconds`);
}
}
throw new errors_1.RateLimitError(`Rate limited: ${errorMessage}`);
}
} }
catch (error) { catch (error) {
if (error instanceof SyntaxError) { if (error instanceof SyntaxError) {
@ -2406,6 +2418,9 @@ class CacheServiceClient {
if (error instanceof errors_1.UsageError) { if (error instanceof errors_1.UsageError) {
throw error; throw error;
} }
if (error instanceof errors_1.RateLimitError) {
throw error;
}
if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) { if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) {
throw new errors_1.NetworkError(error === null || error === void 0 ? void 0 : error.code); throw new errors_1.NetworkError(error === null || error === void 0 ? void 0 : error.code);
} }
@ -2438,8 +2453,7 @@ class CacheServiceClient {
http_client_1.HttpCodes.BadGateway, http_client_1.HttpCodes.BadGateway,
http_client_1.HttpCodes.GatewayTimeout, http_client_1.HttpCodes.GatewayTimeout,
http_client_1.HttpCodes.InternalServerError, http_client_1.HttpCodes.InternalServerError,
http_client_1.HttpCodes.ServiceUnavailable, http_client_1.HttpCodes.ServiceUnavailable
http_client_1.HttpCodes.TooManyRequests
]; ];
return retryableStatusCodes.includes(statusCode); return retryableStatusCodes.includes(statusCode);
} }
@ -2475,7 +2489,7 @@ function internalCacheTwirpClient(options) {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.UsageError = exports.NetworkError = exports.GHESNotSupportedError = exports.CacheNotFoundError = exports.InvalidResponseError = exports.FilesNotFoundError = void 0; exports.RateLimitError = exports.UsageError = exports.NetworkError = exports.GHESNotSupportedError = exports.CacheNotFoundError = exports.InvalidResponseError = exports.FilesNotFoundError = void 0;
class FilesNotFoundError extends Error { class FilesNotFoundError extends Error {
constructor(files = []) { constructor(files = []) {
let message = 'No files were found to upload'; let message = 'No files were found to upload';
@ -2542,6 +2556,13 @@ UsageError.isUsageErrorMessage = (msg) => {
return false; return false;
return msg.includes('insufficient usage'); return msg.includes('insufficient usage');
}; };
class RateLimitError extends Error {
constructor(message) {
super(message);
this.name = 'RateLimitError';
}
}
exports.RateLimitError = RateLimitError;
//# sourceMappingURL=errors.js.map //# sourceMappingURL=errors.js.map
/***/ }), /***/ }),
@ -9902,7 +9923,7 @@ class HttpClient {
this._maxRetries = 1; this._maxRetries = 1;
this._keepAlive = false; this._keepAlive = false;
this._disposed = false; this._disposed = false;
this.userAgent = userAgent; this.userAgent = this._getUserAgentWithOrchestrationId(userAgent);
this.handlers = handlers || []; this.handlers = handlers || [];
this.requestOptions = requestOptions; this.requestOptions = requestOptions;
if (requestOptions) { if (requestOptions) {
@ -10382,6 +10403,17 @@ class HttpClient {
} }
return proxyAgent; return proxyAgent;
} }
_getUserAgentWithOrchestrationId(userAgent) {
const baseUserAgent = userAgent || 'actions/http-client';
const orchId = process.env['ACTIONS_ORCHESTRATION_ID'];
if (orchId) {
// Sanitize the orchestration ID to ensure it contains only valid characters
// Valid characters: 0-9, a-z, _, -, .
const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, '_');
return `${baseUserAgent} actions_orchestration_id/${sanitizedId}`;
}
return baseUserAgent;
}
_performExponentialBackoff(retryNumber) { _performExponentialBackoff(retryNumber) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber);
@ -87398,7 +87430,7 @@ function randomUUID() {
/***/ ((module) => { /***/ ((module) => {
"use strict"; "use strict";
module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.0.1","preview":true,"description":"Actions cache lib","keywords":["github","actions","cache"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/cache","license":"MIT","main":"lib/cache.js","types":"lib/cache.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/cache"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"echo \\"Error: run tests from root\\" && exit 1","tsc":"tsc"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^2.0.0","@actions/exec":"^2.0.0","@actions/glob":"^0.5.0","@protobuf-ts/runtime-rpc":"^2.11.1","@actions/http-client":"^3.0.0","@actions/io":"^2.0.0","@azure/abort-controller":"^1.1.0","@azure/core-rest-pipeline":"^1.22.0","@azure/storage-blob":"^12.29.1","semver":"^6.3.1"},"devDependencies":{"@types/node":"^24.1.0","@types/semver":"^6.0.0","@protobuf-ts/plugin":"^2.9.4","typescript":"^5.2.2"},"overrides":{"uri-js":"npm:uri-js-replace@^1.0.1","node-fetch":"^3.3.2"}}'); module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.0.3","preview":true,"description":"Actions cache lib","keywords":["github","actions","cache"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/cache","license":"MIT","main":"lib/cache.js","types":"lib/cache.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/cache"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"echo \\"Error: run tests from root\\" && exit 1","tsc":"tsc"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^2.0.0","@actions/exec":"^2.0.0","@actions/glob":"^0.5.0","@protobuf-ts/runtime-rpc":"^2.11.1","@actions/http-client":"^3.0.1","@actions/io":"^2.0.0","@azure/abort-controller":"^1.1.0","@azure/core-rest-pipeline":"^1.22.0","@azure/storage-blob":"^12.29.1","semver":"^6.3.1"},"devDependencies":{"@types/node":"^24.1.0","@types/semver":"^6.0.0","@protobuf-ts/plugin":"^2.9.4","typescript":"^5.2.2"},"overrides":{"uri-js":"npm:uri-js-replace@^1.0.1","node-fetch":"^3.3.2"}}');
/***/ }) /***/ })

42
dist/restore/index.js vendored
View File

@ -2398,6 +2398,18 @@ class CacheServiceClient {
} }
errorMessage = `${errorMessage}: ${body.msg}`; errorMessage = `${errorMessage}: ${body.msg}`;
} }
// Handle rate limiting - don't retry, just warn and exit
// For more info, see https://docs.github.com/en/actions/reference/limits
if (statusCode === http_client_1.HttpCodes.TooManyRequests) {
const retryAfterHeader = response.message.headers['retry-after'];
if (retryAfterHeader) {
const parsedSeconds = parseInt(retryAfterHeader, 10);
if (!isNaN(parsedSeconds) && parsedSeconds > 0) {
(0, core_1.warning)(`You've hit a rate limit, your rate limit will reset in ${parsedSeconds} seconds`);
}
}
throw new errors_1.RateLimitError(`Rate limited: ${errorMessage}`);
}
} }
catch (error) { catch (error) {
if (error instanceof SyntaxError) { if (error instanceof SyntaxError) {
@ -2406,6 +2418,9 @@ class CacheServiceClient {
if (error instanceof errors_1.UsageError) { if (error instanceof errors_1.UsageError) {
throw error; throw error;
} }
if (error instanceof errors_1.RateLimitError) {
throw error;
}
if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) { if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) {
throw new errors_1.NetworkError(error === null || error === void 0 ? void 0 : error.code); throw new errors_1.NetworkError(error === null || error === void 0 ? void 0 : error.code);
} }
@ -2438,8 +2453,7 @@ class CacheServiceClient {
http_client_1.HttpCodes.BadGateway, http_client_1.HttpCodes.BadGateway,
http_client_1.HttpCodes.GatewayTimeout, http_client_1.HttpCodes.GatewayTimeout,
http_client_1.HttpCodes.InternalServerError, http_client_1.HttpCodes.InternalServerError,
http_client_1.HttpCodes.ServiceUnavailable, http_client_1.HttpCodes.ServiceUnavailable
http_client_1.HttpCodes.TooManyRequests
]; ];
return retryableStatusCodes.includes(statusCode); return retryableStatusCodes.includes(statusCode);
} }
@ -2475,7 +2489,7 @@ function internalCacheTwirpClient(options) {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.UsageError = exports.NetworkError = exports.GHESNotSupportedError = exports.CacheNotFoundError = exports.InvalidResponseError = exports.FilesNotFoundError = void 0; exports.RateLimitError = exports.UsageError = exports.NetworkError = exports.GHESNotSupportedError = exports.CacheNotFoundError = exports.InvalidResponseError = exports.FilesNotFoundError = void 0;
class FilesNotFoundError extends Error { class FilesNotFoundError extends Error {
constructor(files = []) { constructor(files = []) {
let message = 'No files were found to upload'; let message = 'No files were found to upload';
@ -2542,6 +2556,13 @@ UsageError.isUsageErrorMessage = (msg) => {
return false; return false;
return msg.includes('insufficient usage'); return msg.includes('insufficient usage');
}; };
class RateLimitError extends Error {
constructor(message) {
super(message);
this.name = 'RateLimitError';
}
}
exports.RateLimitError = RateLimitError;
//# sourceMappingURL=errors.js.map //# sourceMappingURL=errors.js.map
/***/ }), /***/ }),
@ -9902,7 +9923,7 @@ class HttpClient {
this._maxRetries = 1; this._maxRetries = 1;
this._keepAlive = false; this._keepAlive = false;
this._disposed = false; this._disposed = false;
this.userAgent = userAgent; this.userAgent = this._getUserAgentWithOrchestrationId(userAgent);
this.handlers = handlers || []; this.handlers = handlers || [];
this.requestOptions = requestOptions; this.requestOptions = requestOptions;
if (requestOptions) { if (requestOptions) {
@ -10382,6 +10403,17 @@ class HttpClient {
} }
return proxyAgent; return proxyAgent;
} }
_getUserAgentWithOrchestrationId(userAgent) {
const baseUserAgent = userAgent || 'actions/http-client';
const orchId = process.env['ACTIONS_ORCHESTRATION_ID'];
if (orchId) {
// Sanitize the orchestration ID to ensure it contains only valid characters
// Valid characters: 0-9, a-z, _, -, .
const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, '_');
return `${baseUserAgent} actions_orchestration_id/${sanitizedId}`;
}
return baseUserAgent;
}
_performExponentialBackoff(retryNumber) { _performExponentialBackoff(retryNumber) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber);
@ -87398,7 +87430,7 @@ function randomUUID() {
/***/ ((module) => { /***/ ((module) => {
"use strict"; "use strict";
module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.0.1","preview":true,"description":"Actions cache lib","keywords":["github","actions","cache"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/cache","license":"MIT","main":"lib/cache.js","types":"lib/cache.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/cache"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"echo \\"Error: run tests from root\\" && exit 1","tsc":"tsc"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^2.0.0","@actions/exec":"^2.0.0","@actions/glob":"^0.5.0","@protobuf-ts/runtime-rpc":"^2.11.1","@actions/http-client":"^3.0.0","@actions/io":"^2.0.0","@azure/abort-controller":"^1.1.0","@azure/core-rest-pipeline":"^1.22.0","@azure/storage-blob":"^12.29.1","semver":"^6.3.1"},"devDependencies":{"@types/node":"^24.1.0","@types/semver":"^6.0.0","@protobuf-ts/plugin":"^2.9.4","typescript":"^5.2.2"},"overrides":{"uri-js":"npm:uri-js-replace@^1.0.1","node-fetch":"^3.3.2"}}'); module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.0.3","preview":true,"description":"Actions cache lib","keywords":["github","actions","cache"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/cache","license":"MIT","main":"lib/cache.js","types":"lib/cache.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/cache"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"echo \\"Error: run tests from root\\" && exit 1","tsc":"tsc"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^2.0.0","@actions/exec":"^2.0.0","@actions/glob":"^0.5.0","@protobuf-ts/runtime-rpc":"^2.11.1","@actions/http-client":"^3.0.1","@actions/io":"^2.0.0","@azure/abort-controller":"^1.1.0","@azure/core-rest-pipeline":"^1.22.0","@azure/storage-blob":"^12.29.1","semver":"^6.3.1"},"devDependencies":{"@types/node":"^24.1.0","@types/semver":"^6.0.0","@protobuf-ts/plugin":"^2.9.4","typescript":"^5.2.2"},"overrides":{"uri-js":"npm:uri-js-replace@^1.0.1","node-fetch":"^3.3.2"}}');
/***/ }) /***/ })

View File

@ -2398,6 +2398,18 @@ class CacheServiceClient {
} }
errorMessage = `${errorMessage}: ${body.msg}`; errorMessage = `${errorMessage}: ${body.msg}`;
} }
// Handle rate limiting - don't retry, just warn and exit
// For more info, see https://docs.github.com/en/actions/reference/limits
if (statusCode === http_client_1.HttpCodes.TooManyRequests) {
const retryAfterHeader = response.message.headers['retry-after'];
if (retryAfterHeader) {
const parsedSeconds = parseInt(retryAfterHeader, 10);
if (!isNaN(parsedSeconds) && parsedSeconds > 0) {
(0, core_1.warning)(`You've hit a rate limit, your rate limit will reset in ${parsedSeconds} seconds`);
}
}
throw new errors_1.RateLimitError(`Rate limited: ${errorMessage}`);
}
} }
catch (error) { catch (error) {
if (error instanceof SyntaxError) { if (error instanceof SyntaxError) {
@ -2406,6 +2418,9 @@ class CacheServiceClient {
if (error instanceof errors_1.UsageError) { if (error instanceof errors_1.UsageError) {
throw error; throw error;
} }
if (error instanceof errors_1.RateLimitError) {
throw error;
}
if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) { if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) {
throw new errors_1.NetworkError(error === null || error === void 0 ? void 0 : error.code); throw new errors_1.NetworkError(error === null || error === void 0 ? void 0 : error.code);
} }
@ -2438,8 +2453,7 @@ class CacheServiceClient {
http_client_1.HttpCodes.BadGateway, http_client_1.HttpCodes.BadGateway,
http_client_1.HttpCodes.GatewayTimeout, http_client_1.HttpCodes.GatewayTimeout,
http_client_1.HttpCodes.InternalServerError, http_client_1.HttpCodes.InternalServerError,
http_client_1.HttpCodes.ServiceUnavailable, http_client_1.HttpCodes.ServiceUnavailable
http_client_1.HttpCodes.TooManyRequests
]; ];
return retryableStatusCodes.includes(statusCode); return retryableStatusCodes.includes(statusCode);
} }
@ -2475,7 +2489,7 @@ function internalCacheTwirpClient(options) {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.UsageError = exports.NetworkError = exports.GHESNotSupportedError = exports.CacheNotFoundError = exports.InvalidResponseError = exports.FilesNotFoundError = void 0; exports.RateLimitError = exports.UsageError = exports.NetworkError = exports.GHESNotSupportedError = exports.CacheNotFoundError = exports.InvalidResponseError = exports.FilesNotFoundError = void 0;
class FilesNotFoundError extends Error { class FilesNotFoundError extends Error {
constructor(files = []) { constructor(files = []) {
let message = 'No files were found to upload'; let message = 'No files were found to upload';
@ -2542,6 +2556,13 @@ UsageError.isUsageErrorMessage = (msg) => {
return false; return false;
return msg.includes('insufficient usage'); return msg.includes('insufficient usage');
}; };
class RateLimitError extends Error {
constructor(message) {
super(message);
this.name = 'RateLimitError';
}
}
exports.RateLimitError = RateLimitError;
//# sourceMappingURL=errors.js.map //# sourceMappingURL=errors.js.map
/***/ }), /***/ }),
@ -9902,7 +9923,7 @@ class HttpClient {
this._maxRetries = 1; this._maxRetries = 1;
this._keepAlive = false; this._keepAlive = false;
this._disposed = false; this._disposed = false;
this.userAgent = userAgent; this.userAgent = this._getUserAgentWithOrchestrationId(userAgent);
this.handlers = handlers || []; this.handlers = handlers || [];
this.requestOptions = requestOptions; this.requestOptions = requestOptions;
if (requestOptions) { if (requestOptions) {
@ -10382,6 +10403,17 @@ class HttpClient {
} }
return proxyAgent; return proxyAgent;
} }
_getUserAgentWithOrchestrationId(userAgent) {
const baseUserAgent = userAgent || 'actions/http-client';
const orchId = process.env['ACTIONS_ORCHESTRATION_ID'];
if (orchId) {
// Sanitize the orchestration ID to ensure it contains only valid characters
// Valid characters: 0-9, a-z, _, -, .
const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, '_');
return `${baseUserAgent} actions_orchestration_id/${sanitizedId}`;
}
return baseUserAgent;
}
_performExponentialBackoff(retryNumber) { _performExponentialBackoff(retryNumber) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber);
@ -87411,7 +87443,7 @@ function randomUUID() {
/***/ ((module) => { /***/ ((module) => {
"use strict"; "use strict";
module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.0.1","preview":true,"description":"Actions cache lib","keywords":["github","actions","cache"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/cache","license":"MIT","main":"lib/cache.js","types":"lib/cache.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/cache"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"echo \\"Error: run tests from root\\" && exit 1","tsc":"tsc"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^2.0.0","@actions/exec":"^2.0.0","@actions/glob":"^0.5.0","@protobuf-ts/runtime-rpc":"^2.11.1","@actions/http-client":"^3.0.0","@actions/io":"^2.0.0","@azure/abort-controller":"^1.1.0","@azure/core-rest-pipeline":"^1.22.0","@azure/storage-blob":"^12.29.1","semver":"^6.3.1"},"devDependencies":{"@types/node":"^24.1.0","@types/semver":"^6.0.0","@protobuf-ts/plugin":"^2.9.4","typescript":"^5.2.2"},"overrides":{"uri-js":"npm:uri-js-replace@^1.0.1","node-fetch":"^3.3.2"}}'); module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.0.3","preview":true,"description":"Actions cache lib","keywords":["github","actions","cache"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/cache","license":"MIT","main":"lib/cache.js","types":"lib/cache.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/cache"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"echo \\"Error: run tests from root\\" && exit 1","tsc":"tsc"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^2.0.0","@actions/exec":"^2.0.0","@actions/glob":"^0.5.0","@protobuf-ts/runtime-rpc":"^2.11.1","@actions/http-client":"^3.0.1","@actions/io":"^2.0.0","@azure/abort-controller":"^1.1.0","@azure/core-rest-pipeline":"^1.22.0","@azure/storage-blob":"^12.29.1","semver":"^6.3.1"},"devDependencies":{"@types/node":"^24.1.0","@types/semver":"^6.0.0","@protobuf-ts/plugin":"^2.9.4","typescript":"^5.2.2"},"overrides":{"uri-js":"npm:uri-js-replace@^1.0.1","node-fetch":"^3.3.2"}}');
/***/ }) /***/ })

42
dist/save/index.js vendored
View File

@ -2398,6 +2398,18 @@ class CacheServiceClient {
} }
errorMessage = `${errorMessage}: ${body.msg}`; errorMessage = `${errorMessage}: ${body.msg}`;
} }
// Handle rate limiting - don't retry, just warn and exit
// For more info, see https://docs.github.com/en/actions/reference/limits
if (statusCode === http_client_1.HttpCodes.TooManyRequests) {
const retryAfterHeader = response.message.headers['retry-after'];
if (retryAfterHeader) {
const parsedSeconds = parseInt(retryAfterHeader, 10);
if (!isNaN(parsedSeconds) && parsedSeconds > 0) {
(0, core_1.warning)(`You've hit a rate limit, your rate limit will reset in ${parsedSeconds} seconds`);
}
}
throw new errors_1.RateLimitError(`Rate limited: ${errorMessage}`);
}
} }
catch (error) { catch (error) {
if (error instanceof SyntaxError) { if (error instanceof SyntaxError) {
@ -2406,6 +2418,9 @@ class CacheServiceClient {
if (error instanceof errors_1.UsageError) { if (error instanceof errors_1.UsageError) {
throw error; throw error;
} }
if (error instanceof errors_1.RateLimitError) {
throw error;
}
if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) { if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) {
throw new errors_1.NetworkError(error === null || error === void 0 ? void 0 : error.code); throw new errors_1.NetworkError(error === null || error === void 0 ? void 0 : error.code);
} }
@ -2438,8 +2453,7 @@ class CacheServiceClient {
http_client_1.HttpCodes.BadGateway, http_client_1.HttpCodes.BadGateway,
http_client_1.HttpCodes.GatewayTimeout, http_client_1.HttpCodes.GatewayTimeout,
http_client_1.HttpCodes.InternalServerError, http_client_1.HttpCodes.InternalServerError,
http_client_1.HttpCodes.ServiceUnavailable, http_client_1.HttpCodes.ServiceUnavailable
http_client_1.HttpCodes.TooManyRequests
]; ];
return retryableStatusCodes.includes(statusCode); return retryableStatusCodes.includes(statusCode);
} }
@ -2475,7 +2489,7 @@ function internalCacheTwirpClient(options) {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.UsageError = exports.NetworkError = exports.GHESNotSupportedError = exports.CacheNotFoundError = exports.InvalidResponseError = exports.FilesNotFoundError = void 0; exports.RateLimitError = exports.UsageError = exports.NetworkError = exports.GHESNotSupportedError = exports.CacheNotFoundError = exports.InvalidResponseError = exports.FilesNotFoundError = void 0;
class FilesNotFoundError extends Error { class FilesNotFoundError extends Error {
constructor(files = []) { constructor(files = []) {
let message = 'No files were found to upload'; let message = 'No files were found to upload';
@ -2542,6 +2556,13 @@ UsageError.isUsageErrorMessage = (msg) => {
return false; return false;
return msg.includes('insufficient usage'); return msg.includes('insufficient usage');
}; };
class RateLimitError extends Error {
constructor(message) {
super(message);
this.name = 'RateLimitError';
}
}
exports.RateLimitError = RateLimitError;
//# sourceMappingURL=errors.js.map //# sourceMappingURL=errors.js.map
/***/ }), /***/ }),
@ -9902,7 +9923,7 @@ class HttpClient {
this._maxRetries = 1; this._maxRetries = 1;
this._keepAlive = false; this._keepAlive = false;
this._disposed = false; this._disposed = false;
this.userAgent = userAgent; this.userAgent = this._getUserAgentWithOrchestrationId(userAgent);
this.handlers = handlers || []; this.handlers = handlers || [];
this.requestOptions = requestOptions; this.requestOptions = requestOptions;
if (requestOptions) { if (requestOptions) {
@ -10382,6 +10403,17 @@ class HttpClient {
} }
return proxyAgent; return proxyAgent;
} }
_getUserAgentWithOrchestrationId(userAgent) {
const baseUserAgent = userAgent || 'actions/http-client';
const orchId = process.env['ACTIONS_ORCHESTRATION_ID'];
if (orchId) {
// Sanitize the orchestration ID to ensure it contains only valid characters
// Valid characters: 0-9, a-z, _, -, .
const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, '_');
return `${baseUserAgent} actions_orchestration_id/${sanitizedId}`;
}
return baseUserAgent;
}
_performExponentialBackoff(retryNumber) { _performExponentialBackoff(retryNumber) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber);
@ -87411,7 +87443,7 @@ function randomUUID() {
/***/ ((module) => { /***/ ((module) => {
"use strict"; "use strict";
module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.0.1","preview":true,"description":"Actions cache lib","keywords":["github","actions","cache"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/cache","license":"MIT","main":"lib/cache.js","types":"lib/cache.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/cache"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"echo \\"Error: run tests from root\\" && exit 1","tsc":"tsc"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^2.0.0","@actions/exec":"^2.0.0","@actions/glob":"^0.5.0","@protobuf-ts/runtime-rpc":"^2.11.1","@actions/http-client":"^3.0.0","@actions/io":"^2.0.0","@azure/abort-controller":"^1.1.0","@azure/core-rest-pipeline":"^1.22.0","@azure/storage-blob":"^12.29.1","semver":"^6.3.1"},"devDependencies":{"@types/node":"^24.1.0","@types/semver":"^6.0.0","@protobuf-ts/plugin":"^2.9.4","typescript":"^5.2.2"},"overrides":{"uri-js":"npm:uri-js-replace@^1.0.1","node-fetch":"^3.3.2"}}'); module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.0.3","preview":true,"description":"Actions cache lib","keywords":["github","actions","cache"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/cache","license":"MIT","main":"lib/cache.js","types":"lib/cache.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/cache"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"echo \\"Error: run tests from root\\" && exit 1","tsc":"tsc"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^2.0.0","@actions/exec":"^2.0.0","@actions/glob":"^0.5.0","@protobuf-ts/runtime-rpc":"^2.11.1","@actions/http-client":"^3.0.1","@actions/io":"^2.0.0","@azure/abort-controller":"^1.1.0","@azure/core-rest-pipeline":"^1.22.0","@azure/storage-blob":"^12.29.1","semver":"^6.3.1"},"devDependencies":{"@types/node":"^24.1.0","@types/semver":"^6.0.0","@protobuf-ts/plugin":"^2.9.4","typescript":"^5.2.2"},"overrides":{"uri-js":"npm:uri-js-replace@^1.0.1","node-fetch":"^3.3.2"}}');
/***/ }) /***/ })

29
package-lock.json generated
View File

@ -1,15 +1,15 @@
{ {
"name": "cache", "name": "cache",
"version": "5.0.1", "version": "5.0.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "cache", "name": "cache",
"version": "5.0.1", "version": "5.0.2",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/cache": "^5.0.1", "@actions/cache": "^5.0.3",
"@actions/core": "^2.0.0", "@actions/core": "^2.0.0",
"@actions/exec": "^2.0.0", "@actions/exec": "^2.0.0",
"@actions/io": "^2.0.0" "@actions/io": "^2.0.0"
@ -39,15 +39,15 @@
} }
}, },
"node_modules/@actions/cache": { "node_modules/@actions/cache": {
"version": "5.0.1", "version": "5.0.3",
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-5.0.1.tgz", "resolved": "https://registry.npmjs.org/@actions/cache/-/cache-5.0.3.tgz",
"integrity": "sha512-c+oH047Z2zmXLhjMZfEKjxZfv6Ou7T0sn5fhz6yupICXm5OOR47oZn5zxNO8MP7ttkxv5TOg3WsMrffri5Xhfw==", "integrity": "sha512-9joY8Oup+nIpksSBlkuf9/mltnhWx3lydk1tA2PVnXaxFLIIrKqrWDN2CZXlJ+PEErcBARKYn4mHiUCTyMh4Vg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^2.0.0", "@actions/core": "^2.0.0",
"@actions/exec": "^2.0.0", "@actions/exec": "^2.0.0",
"@actions/glob": "^0.5.0", "@actions/glob": "^0.5.0",
"@actions/http-client": "^3.0.0", "@actions/http-client": "^3.0.1",
"@actions/io": "^2.0.0", "@actions/io": "^2.0.0",
"@azure/abort-controller": "^1.1.0", "@azure/abort-controller": "^1.1.0",
"@azure/core-rest-pipeline": "^1.22.0", "@azure/core-rest-pipeline": "^1.22.0",
@ -121,9 +121,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@actions/http-client": { "node_modules/@actions/http-client": {
"version": "3.0.0", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.0.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.1.tgz",
"integrity": "sha512-1s3tXAfVMSz9a4ZEBkXXRQD4QhY3+GAsWSbaYpeknPOKEeyRiU3lH+bHiLMZdo2x/fIeQ/hscL1wCkDLVM2DZQ==", "integrity": "sha512-SbGS8c/vySbNO3kjFgSW77n83C4MQx/Yoe+b1hAdpuvfHxnkHzDq2pWljUpAA56Si1Gae/7zjeZsV0CYjmLo/w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"tunnel": "^0.0.6", "tunnel": "^0.0.6",
@ -1762,7 +1762,6 @@
"integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/scope-manager": "7.18.0",
@ -1797,7 +1796,6 @@
"integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==",
"dev": true, "dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/scope-manager": "7.18.0",
"@typescript-eslint/types": "7.18.0", "@typescript-eslint/types": "7.18.0",
@ -2027,7 +2025,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@ -2480,7 +2477,6 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.9.0", "baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759", "caniuse-lite": "^1.0.30001759",
@ -3185,7 +3181,6 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1", "@eslint-community/regexpp": "^4.6.1",
@ -3242,7 +3237,6 @@
"integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"eslint-config-prettier": "bin/cli.js" "eslint-config-prettier": "bin/cli.js"
}, },
@ -4995,7 +4989,6 @@
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@jest/core": "^29.7.0", "@jest/core": "^29.7.0",
"@jest/types": "^29.6.3", "@jest/types": "^29.6.3",
@ -6354,7 +6347,6 @@
"integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"prettier": "bin/prettier.cjs" "prettier": "bin/prettier.cjs"
}, },
@ -7472,7 +7464,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"

View File

@ -1,6 +1,6 @@
{ {
"name": "cache", "name": "cache",
"version": "5.0.1", "version": "5.0.2",
"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",
@ -23,7 +23,7 @@
"author": "GitHub", "author": "GitHub",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/cache": "^5.0.1", "@actions/cache": "^5.0.3",
"@actions/core": "^2.0.0", "@actions/core": "^2.0.0",
"@actions/exec": "^2.0.0", "@actions/exec": "^2.0.0",
"@actions/io": "^2.0.0" "@actions/io": "^2.0.0"

View File

@ -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`.

View File

@ -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: 'node24' using: 'node24'
main: '../dist/restore-only/index.js' main: '../dist/restore-only/index.js'

View File

@ -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 {

View File

@ -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

View File

@ -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) => {