-
Notifications
You must be signed in to change notification settings - Fork 28
chore(deps): update actions/setup-node action to v4.4.0 - autoclosed #1058
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
[puLL-Merge] - actions/[email protected] Diffdiff --git .github/eslint-compact.json .github/eslint-compact.json
index 72173f0c0..d577d4989 100644
--- .github/eslint-compact.json
+++ .github/eslint-compact.json
@@ -4,7 +4,7 @@
"owner": "eslint-compact",
"pattern": [
{
- "regexp": "^(.+):\\sline\\s(\\d+),\\scol\\s(\\d+),\\s(Error|Warning|Info)\\s-\\s(.+)\\s\\((.+)\\)$",
+ "regexp": "^(.+):\\sline\\s(\\d+),\\scol\\s(\\d+),\\s([Ee]rror|[Ww]arning|[Ii]nfo)\\s-\\s(.+)\\s\\((.+)\\)$",
"file": 1,
"line": 2,
"column": 3,
diff --git .github/eslint-stylish.json .github/eslint-stylish.json
index 1d75d6c30..db9655b62 100644
--- .github/eslint-stylish.json
+++ .github/eslint-stylish.json
@@ -4,7 +4,7 @@
"owner": "eslint-stylish",
"pattern": [
{
- "regexp": "^([^\\s].*)$",
+ "regexp": "^\\s*([^\\s].*)$",
"file": 1
},
{
diff --git .licenses/npm/@actions/cache.dep.yml .licenses/npm/@actions/cache.dep.yml
index 6e21be6a2..f70b140d2 100644
--- .licenses/npm/@actions/cache.dep.yml
+++ .licenses/npm/@actions/cache.dep.yml
@@ -1,6 +1,6 @@
---
name: "@actions/cache"
-version: 4.0.2
+version: 4.0.3
type: npm
summary: Actions cache lib
homepage: https://github.com/actions/toolkit/tree/main/packages/cache
diff --git .licenses/npm/@octokit/auth-token.dep.yml .licenses/npm/@octokit/auth-token.dep.yml
index 1ffe43e99..71f6dbf76 100644
--- .licenses/npm/@octokit/auth-token.dep.yml
+++ .licenses/npm/@octokit/auth-token.dep.yml
@@ -31,4 +31,4 @@ licenses:
THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/core.dep.yml .licenses/npm/@octokit/core.dep.yml
index d6657a245..77713295c 100644
--- .licenses/npm/@octokit/core.dep.yml
+++ .licenses/npm/@octokit/core.dep.yml
@@ -31,4 +31,4 @@ licenses:
THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/endpoint.dep.yml .licenses/npm/@octokit/endpoint.dep.yml
index 74b7649ec..748a61c57 100644
--- .licenses/npm/@octokit/endpoint.dep.yml
+++ .licenses/npm/@octokit/endpoint.dep.yml
@@ -31,4 +31,4 @@ licenses:
THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/graphql.dep.yml .licenses/npm/@octokit/graphql.dep.yml
index c4faad910..268991d01 100644
--- .licenses/npm/@octokit/graphql.dep.yml
+++ .licenses/npm/@octokit/graphql.dep.yml
@@ -31,4 +31,4 @@ licenses:
THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/openapi-types.dep.yml .licenses/npm/@octokit/openapi-types.dep.yml
index f2891938f..798f9e617 100644
--- .licenses/npm/@octokit/openapi-types.dep.yml
+++ .licenses/npm/@octokit/openapi-types.dep.yml
@@ -17,4 +17,4 @@ licenses:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/plugin-paginate-rest.dep.yml .licenses/npm/@octokit/plugin-paginate-rest.dep.yml
index 9f8cf25b9..f8090226f 100644
--- .licenses/npm/@octokit/plugin-paginate-rest.dep.yml
+++ .licenses/npm/@octokit/plugin-paginate-rest.dep.yml
@@ -17,4 +17,4 @@ licenses:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/plugin-rest-endpoint-methods.dep.yml .licenses/npm/@octokit/plugin-rest-endpoint-methods.dep.yml
index 922034848..02cb6c4ca 100644
--- .licenses/npm/@octokit/plugin-rest-endpoint-methods.dep.yml
+++ .licenses/npm/@octokit/plugin-rest-endpoint-methods.dep.yml
@@ -17,4 +17,4 @@ licenses:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/request-error.dep.yml .licenses/npm/@octokit/request-error.dep.yml
index 41a28b4e5..1141bf42d 100644
--- .licenses/npm/@octokit/request-error.dep.yml
+++ .licenses/npm/@octokit/request-error.dep.yml
@@ -31,4 +31,4 @@ licenses:
THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/request.dep.yml .licenses/npm/@octokit/request.dep.yml
index 73a8abce3..179ed420f 100644
--- .licenses/npm/@octokit/request.dep.yml
+++ .licenses/npm/@octokit/request.dep.yml
@@ -32,4 +32,4 @@ licenses:
THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/@octokit/types.dep.yml .licenses/npm/@octokit/types.dep.yml
index d13289b29..d146cd916 100644
--- .licenses/npm/@octokit/types.dep.yml
+++ .licenses/npm/@octokit/types.dep.yml
@@ -17,4 +17,4 @@ licenses:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- sources: README.md
text: "[MIT](LICENSE)"
-notices: []
+notices: []
\ No newline at end of file
diff --git .licenses/npm/universal-user-agent.dep.yml .licenses/npm/universal-user-agent.dep.yml
index 9cf02a9d5..c07307b84 100644
--- .licenses/npm/universal-user-agent.dep.yml
+++ .licenses/npm/universal-user-agent.dep.yml
@@ -1,9 +1,9 @@
---
name: universal-user-agent
-version: 6.0.0
+version: 6.0.1
type: npm
summary: Get a user agent string in both browser and node
-homepage:
+homepage:
license: isc
licenses:
- sources: LICENSE.md
diff --git README.md README.md
index 0c5548981..92804e94e 100644
--- README.md
+++ README.md
@@ -76,6 +76,21 @@ See [action.yml](action.yml)
# Set always-auth option in npmrc file.
# Default: ''
always-auth: ''
+
+ # Optional mirror to download binaries from.
+ # Artifacts need to match the official Node.js
+ # Example:
+ # V8 Canaray Build: <mirror_url>/download/v8-canary
+ # RC Build: <mirror_url>/download/rc
+ # Official: Build <mirror_url>/dist
+ # Nightly build: <mirror_url>/download/nightly
+ # Default: ''
+ mirror: ''
+
+ # Optional mirror token.
+ # The token will be used as a bearer token in the Authorization header
+ # Default: ''
+ mirror-token: ''
```
<!-- end usage -->
diff --git __tests__/canary-installer.test.ts __tests__/canary-installer.test.ts
index 6d141fc3c..4393d7ef2 100644
--- __tests__/canary-installer.test.ts
+++ __tests__/canary-installer.test.ts
@@ -498,6 +498,70 @@ describe('setup-node', () => {
);
}
);
+
+ it.each([
+ [
+ '20.0.0-v8-canary',
+ '20.0.0-v8-canary20221103f7e2421e91',
+ '20.0.0-v8-canary20221030fefe1c0879',
+ 'https://my_mirror.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz'
+ ],
+ [
+ '20-v8-canary',
+ '20.0.0-v8-canary20221103f7e2421e91',
+ '20.0.0-v8-canary20221030fefe1c0879',
+ 'https://my_mirror.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz'
+ ],
+ [
+ '19.0.0-v8-canary',
+ '19.0.0-v8-canary202210187d6960f23f',
+ '19.0.0-v8-canary202210172ec229fc56',
+ 'https://my_mirror.org/download/v8-canary/v19.0.0-v8-canary202210187d6960f23f/node-v19.0.0-v8-canary202210187d6960f23f-linux-x64.tar.gz'
+ ],
+ [
+ '19-v8-canary',
+ '19.0.0-v8-canary202210187d6960f23f',
+ '19.0.0-v8-canary202210172ec229fc56',
+ 'https://my_mirror.org/download/v8-canary/v19.0.0-v8-canary202210187d6960f23f/node-v19.0.0-v8-canary202210187d6960f23f-linux-x64.tar.gz'
+ ]
+ ])(
+ 'get %s version from dist if check-latest is true',
+ async (input, expectedVersion, foundVersion, expectedUrl) => {
+ const foundToolPath = path.normalize(`/cache/node/${foundVersion}/x64`);
+ const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
+
+ inputs['node-version'] = input;
+ inputs['check-latest'] = 'true';
+ os['arch'] = 'x64';
+ os['platform'] = 'linux';
+ inputs['mirror'] = 'https://my_mirror.org';
+ inputs['mirror-token'] = 'faketoken';
+
+ findSpy.mockReturnValue(foundToolPath);
+ findAllVersionsSpy.mockReturnValue([
+ '20.0.0-v8-canary20221030fefe1c0879',
+ '19.0.0-v8-canary202210172ec229fc56',
+ '20.0.0-v8-canary2022102310ff1e5a8d'
+ ]);
+ dlSpy.mockImplementation(async () => '/some/temp/path');
+ exSpy.mockImplementation(async () => '/some/other/temp/path');
+ cacheSpy.mockImplementation(async () => toolPath);
+
+ // act
+ await main.run();
+
+ // assert
+ expect(findAllVersionsSpy).toHaveBeenCalled();
+ expect(logSpy).toHaveBeenCalledWith(
+ `Acquiring ${expectedVersion} - ${os.arch} from ${expectedUrl}`
+ );
+ expect(logSpy).toHaveBeenCalledWith('Extracting ...');
+ expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...');
+ expect(cnSpy).toHaveBeenCalledWith(
+ `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}`
+ );
+ }
+ );
});
describe('setup-node v8 canary tests', () => {
diff --git __tests__/nightly-installer.test.ts __tests__/nightly-installer.test.ts
index 87c437957..eece2c344 100644
--- __tests__/nightly-installer.test.ts
+++ __tests__/nightly-installer.test.ts
@@ -315,7 +315,7 @@ describe('setup-node', () => {
await main.run();
workingUrls.forEach(url => {
- expect(dlSpy).toHaveBeenCalledWith(url);
+ expect(dlSpy).toHaveBeenCalledWith(url, undefined, undefined);
});
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}${osm.EOL}`);
});
@@ -449,6 +449,54 @@ describe('setup-node', () => {
}
}, 100000);
+ it('acquires specified architecture of node from mirror', async () => {
+ for (const {arch, version, osSpec} of [
+ {
+ arch: 'x86',
+ version: '18.0.0-nightly202110204cb3e06ed8',
+ osSpec: 'win32'
+ },
+ {
+ arch: 'x86',
+ version: '20.0.0-nightly2022101987cdf7d412',
+ osSpec: 'win32'
+ }
+ ]) {
+ os.platform = osSpec;
+ os.arch = arch;
+ const fileExtension = os.platform === 'win32' ? '7z' : 'tar.gz';
+ const platform = {
+ linux: 'linux',
+ darwin: 'darwin',
+ win32: 'win'
+ }[os.platform];
+
+ inputs['node-version'] = version;
+ inputs['architecture'] = arch;
+ inputs['always-auth'] = false;
+ inputs['token'] = 'faketoken';
+ inputs['mirror'] = 'https://my-mirror.org';
+ inputs['mirror-token'] = 'my-mirror-token';
+
+ const expectedUrl = `https://my-mirror.org/download/nightly/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;
+
+ // ... but not in the local cache
+ findSpy.mockImplementation(() => '');
+ findAllVersionsSpy.mockImplementation(() => []);
+
+ dlSpy.mockImplementation(async () => '/some/temp/path');
+ const toolPath = path.normalize(`/cache/node/${version}/${arch}`);
+ exSpy.mockImplementation(async () => '/some/other/temp/path');
+ cacheSpy.mockImplementation(async () => toolPath);
+
+ await main.run();
+ expect(dlSpy).toHaveBeenCalled();
+ expect(logSpy).toHaveBeenCalledWith(
+ `Acquiring ${version} - ${arch} from ${expectedUrl}`
+ );
+ }
+ }, 100000);
+
describe('nightly versions', () => {
it.each([
[
diff --git __tests__/official-installer.test.ts __tests__/official-installer.test.ts
index 2d8f17cfa..f23183d33 100644
--- __tests__/official-installer.test.ts
+++ __tests__/official-installer.test.ts
@@ -282,6 +282,43 @@ describe('setup-node', () => {
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
});
+ it('falls back to a version from node dist from mirror', async () => {
+ os.platform = 'linux';
+ os.arch = 'x64';
+
+ // a version which is not in the manifest but is in node dist
+ const versionSpec = '11.15.0';
+ const mirror = 'https://my_mirror_url';
+ inputs['node-version'] = versionSpec;
+ inputs['always-auth'] = false;
+ inputs['token'] = 'faketoken';
+ inputs['mirror'] = mirror;
+ inputs['mirror-token'] = 'faketoken';
+
+ // ... but not in the local cache
+ findSpy.mockImplementation(() => '');
+
+ dlSpy.mockImplementation(async () => '/some/temp/path');
+ const toolPath = path.normalize('/cache/node/11.15.0/x64');
+ exSpy.mockImplementation(async () => '/some/other/temp/path');
+ cacheSpy.mockImplementation(async () => toolPath);
+
+ await main.run();
+
+ const expPath = path.join(toolPath, 'bin');
+
+ expect(getManifestSpy).toHaveBeenCalled();
+ expect(logSpy).toHaveBeenCalledWith(
+ `Attempting to download ${versionSpec}...`
+ );
+ expect(logSpy).toHaveBeenCalledWith(
+ `Not found in manifest. Falling back to download directly from ${mirror}`
+ );
+ expect(dlSpy).toHaveBeenCalled();
+ expect(exSpy).toHaveBeenCalled();
+ expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
+ });
+
it('falls back to a version from node dist', async () => {
os.platform = 'linux';
os.arch = 'x64';
@@ -828,4 +865,46 @@ describe('setup-node', () => {
}
);
});
+
+ it('acquires specified architecture of node from mirror', async () => {
+ for (const {arch, version, osSpec} of [
+ {arch: 'x86', version: '12.16.2', osSpec: 'win32'},
+ {arch: 'x86', version: '14.0.0', osSpec: 'win32'}
+ ]) {
+ os.platform = osSpec;
+ os.arch = arch;
+ const fileExtension = os.platform === 'win32' ? '7z' : 'tar.gz';
+ const platform = {
+ linux: 'linux',
+ darwin: 'darwin',
+ win32: 'win'
+ }[os.platform];
+
+ inputs['node-version'] = version;
+ inputs['architecture'] = arch;
+ inputs['always-auth'] = false;
+ inputs['token'] = 'faketoken';
+ inputs['mirror'] = 'https://my_mirror_url';
+ inputs['mirror-token'] = 'faketoken';
+
+ const expectedUrl =
+ arch === 'x64'
+ ? `https://github.com/actions/node-versions/releases/download/${version}/node-${version}-${platform}-${arch}.zip`
+ : `https://my_mirror_url/dist/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;
+
+ // ... but not in the local cache
+ findSpy.mockImplementation(() => '');
+
+ dlSpy.mockImplementation(async () => '/some/temp/path');
+ const toolPath = path.normalize(`/cache/node/${version}/${arch}`);
+ exSpy.mockImplementation(async () => '/some/other/temp/path');
+ cacheSpy.mockImplementation(async () => toolPath);
+
+ await main.run();
+ expect(dlSpy).toHaveBeenCalled();
+ expect(logSpy).toHaveBeenCalledWith(
+ `Acquiring ${version} - ${arch} from ${expectedUrl}`
+ );
+ }
+ }, 100000);
});
diff --git action.yml action.yml
index 99db5869f..ef58e6991 100644
--- action.yml
+++ action.yml
@@ -25,6 +25,10 @@ inputs:
description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.'
cache-dependency-path:
description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.'
+ mirror:
+ description: 'Used to specify an alternative mirror to downlooad Node.js binaries from'
+ mirror-token:
+ description: 'The token used as Authorization header when fetching from the mirror'
# TODO: add input to control forcing to pull from cloud or dist.
# escape valve for someone having issues or needing the absolute latest which isn't cached yet
outputs:
diff --git dist/cache-save/index.js dist/cache-save/index.js
index 51fadc3fe..b12e8abb8 100644
--- dist/cache-save/index.js
+++ dist/cache-save/index.js
@@ -220,7 +220,7 @@ function restoreCacheV2(paths, primaryKey, restoreKeys, options, enableCrossOsAr
};
const response = yield twirpClient.GetCacheEntryDownloadURL(request);
if (!response.ok) {
- core.debug(`Cache not found for keys: ${keys.join(', ')}`);
+ core.debug(`Cache not found for version ${request.version} of keys: ${keys.join(', ')}`);
return undefined;
}
core.info(`Cache hit for: ${request.key}`);
@@ -2204,6 +2204,7 @@ const cacheUtils_1 = __nccwpck_require__(680);
const auth_1 = __nccwpck_require__(4552);
const http_client_1 = __nccwpck_require__(4844);
const cache_twirp_client_1 = __nccwpck_require__(1486);
+const util_1 = __nccwpck_require__(7564);
/**
* This class is a wrapper around the CacheServiceClientJSON class generated by Twirp.
*
@@ -2263,6 +2264,7 @@ class CacheServiceClient {
(0, core_1.debug)(`[Response] - ${response.message.statusCode}`);
(0, core_1.debug)(`Headers: ${JSON.stringify(response.message.headers, null, 2)}`);
const body = JSON.parse(rawBody);
+ (0, util_1.maskSecretUrls)(body);
(0, core_1.debug)(`Body: ${JSON.stringify(body, null, 2)}`);
if (this.isSuccessStatusCode(statusCode)) {
return { response, body };
@@ -2444,6 +2446,87 @@ exports.getUserAgentString = getUserAgentString;
/***/ }),
+/***/ 7564:
+/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
+
+"use strict";
+
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+exports.maskSecretUrls = exports.maskSigUrl = void 0;
+const core_1 = __nccwpck_require__(7484);
+/**
+ * Masks the `sig` parameter in a URL and sets it as a secret.
+ *
+ * @param url - The URL containing the signature parameter to mask
+ * @remarks
+ * This function attempts to parse the provided URL and identify the 'sig' query parameter.
+ * If found, it registers both the raw and URL-encoded signature values as secrets using
+ * the Actions `setSecret` API, which prevents them from being displayed in logs.
+ *
+ * The function handles errors gracefully if URL parsing fails, logging them as debug messages.
+ *
+ * @example
+ * ```typescript
+ * // Mask a signature in an Azure SAS token URL
+ * maskSigUrl('https://example.blob.core.windows.net/container/file.txt?sig=abc123&se=2023-01-01');
+ * ```
+ */
+function maskSigUrl(url) {
+ if (!url)
+ return;
+ try {
+ const parsedUrl = new URL(url);
+ const signature = parsedUrl.searchParams.get('sig');
+ if (signature) {
+ (0, core_1.setSecret)(signature);
+ (0, core_1.setSecret)(encodeURIComponent(signature));
+ }
+ }
+ catch (error) {
+ (0, core_1.debug)(`Failed to parse URL: ${url} ${error instanceof Error ? error.message : String(error)}`);
+ }
+}
+exports.maskSigUrl = maskSigUrl;
+/**
+ * Masks sensitive information in URLs containing signature parameters.
+ * Currently supports masking 'sig' parameters in the 'signed_upload_url'
+ * and 'signed_download_url' properties of the provided object.
+ *
+ * @param body - The object should contain a signature
+ * @remarks
+ * This function extracts URLs from the object properties and calls maskSigUrl
+ * on each one to redact sensitive signature information. The function doesn't
+ * modify the original object; it only marks the signatures as secrets for
+ * logging purposes.
+ *
+ * @example
+ * ```typescript
+ * const responseBody = {
+ * signed_upload_url: 'https://blob.core.windows.net/?sig=abc123',
+ * signed_download_url: 'https://blob.core/windows.net/?sig=def456'
+ * };
+ * maskSecretUrls(responseBody);
+ * ```
+ */
+function maskSecretUrls(body) {
+ if (typeof body !== 'object' || body === null) {
+ (0, core_1.debug)('body is not an object or is null');
+ return;
+ }
+ if ('signed_upload_url' in body &&
+ typeof body.signed_upload_url === 'string') {
+ maskSigUrl(body.signed_upload_url);
+ }
+ if ('signed_download_url' in body &&
+ typeof body.signed_download_url === 'string') {
+ maskSigUrl(body.signed_download_url);
+ }
+}
+exports.maskSecretUrls = maskSecretUrls;
+//# sourceMappingURL=util.js.map
+
+/***/ }),
+
/***/ 5321:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
@@ -90234,7 +90317,7 @@ module.exports = parseParams
/***/ ((module) => {
"use strict";
-module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"4.0.2","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":"^1.11.1","@actions/exec":"^1.0.1","@actions/glob":"^0.1.0","@actions/http-client":"^2.1.1","@actions/io":"^1.0.1","@azure/abort-controller":"^1.1.0","@azure/ms-rest-js":"^2.6.0","@azure/storage-blob":"^12.13.0","@protobuf-ts/plugin":"^2.9.4","semver":"^6.3.1"},"devDependencies":{"@types/semver":"^6.0.0","typescript":"^5.2.2"}}');
+module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"4.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":"^1.11.1","@actions/exec":"^1.0.1","@actions/glob":"^0.1.0","@actions/http-client":"^2.1.1","@actions/io":"^1.0.1","@azure/abort-controller":"^1.1.0","@azure/ms-rest-js":"^2.6.0","@azure/storage-blob":"^12.13.0","@protobuf-ts/plugin":"^2.9.4","semver":"^6.3.1"},"devDependencies":{"@types/node":"^22.13.9","@types/semver":"^6.0.0","typescript":"^5.2.2"}}');
/***/ }),
diff --git dist/setup/index.js dist/setup/index.js
index 93bc3bb64..81bbe3faf 100644
--- dist/setup/index.js
+++ dist/setup/index.js
@@ -220,7 +220,7 @@ function restoreCacheV2(paths, primaryKey, restoreKeys, options, enableCrossOsAr
};
const response = yield twirpClient.GetCacheEntryDownloadURL(request);
if (!response.ok) {
- core.debug(`Cache not found for keys: ${keys.join(', ')}`);
+ core.debug(`Cache not found for version ${request.version} of keys: ${keys.join(', ')}`);
return undefined;
}
core.info(`Cache hit for: ${request.key}`);
@@ -2204,6 +2204,7 @@ const cacheUtils_1 = __nccwpck_require__(680);
const auth_1 = __nccwpck_require__(4552);
const http_client_1 = __nccwpck_require__(4844);
const cache_twirp_client_1 = __nccwpck_require__(1486);
+const util_1 = __nccwpck_require__(7564);
/**
* This class is a wrapper around the CacheServiceClientJSON class generated by Twirp.
*
@@ -2263,6 +2264,7 @@ class CacheServiceClient {
(0, core_1.debug)(`[Response] - ${response.message.statusCode}`);
(0, core_1.debug)(`Headers: ${JSON.stringify(response.message.headers, null, 2)}`);
const body = JSON.parse(rawBody);
+ (0, util_1.maskSecretUrls)(body);
(0, core_1.debug)(`Body: ${JSON.stringify(body, null, 2)}`);
if (this.isSuccessStatusCode(statusCode)) {
return { response, body };
@@ -2444,6 +2446,87 @@ exports.getUserAgentString = getUserAgentString;
/***/ }),
+/***/ 7564:
+/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
+
+"use strict";
+
+Object.defineProperty(exports, "__esModule", ({ value: true }));
+exports.maskSecretUrls = exports.maskSigUrl = void 0;
+const core_1 = __nccwpck_require__(7484);
+/**
+ * Masks the `sig` parameter in a URL and sets it as a secret.
+ *
+ * @param url - The URL containing the signature parameter to mask
+ * @remarks
+ * This function attempts to parse the provided URL and identify the 'sig' query parameter.
+ * If found, it registers both the raw and URL-encoded signature values as secrets using
+ * the Actions `setSecret` API, which prevents them from being displayed in logs.
+ *
+ * The function handles errors gracefully if URL parsing fails, logging them as debug messages.
+ *
+ * @example
+ * ```typescript
+ * // Mask a signature in an Azure SAS token URL
+ * maskSigUrl('https://example.blob.core.windows.net/container/file.txt?sig=abc123&se=2023-01-01');
+ * ```
+ */
+function maskSigUrl(url) {
+ if (!url)
+ return;
+ try {
+ const parsedUrl = new URL(url);
+ const signature = parsedUrl.searchParams.get('sig');
+ if (signature) {
+ (0, core_1.setSecret)(signature);
+ (0, core_1.setSecret)(encodeURIComponent(signature));
+ }
+ }
+ catch (error) {
+ (0, core_1.debug)(`Failed to parse URL: ${url} ${error instanceof Error ? error.message : String(error)}`);
+ }
+}
+exports.maskSigUrl = maskSigUrl;
+/**
+ * Masks sensitive information in URLs containing signature parameters.
+ * Currently supports masking 'sig' parameters in the 'signed_upload_url'
+ * and 'signed_download_url' properties of the provided object.
+ *
+ * @param body - The object should contain a signature
+ * @remarks
+ * This function extracts URLs from the object properties and calls maskSigUrl
+ * on each one to redact sensitive signature information. The function doesn't
+ * modify the original object; it only marks the signatures as secrets for
+ * logging purposes.
+ *
+ * @example
+ * ```typescript
+ * const responseBody = {
+ * signed_upload_url: 'https://blob.core.windows.net/?sig=abc123',
+ * signed_download_url: 'https://blob.core/windows.net/?sig=def456'
+ * };
+ * maskSecretUrls(responseBody);
+ * ```
+ */
+function maskSecretUrls(body) {
+ if (typeof body !== 'object' || body === null) {
+ (0, core_1.debug)('body is not an object or is null');
+ return;
+ }
+ if ('signed_upload_url' in body &&
+ typeof body.signed_upload_url === 'string') {
+ maskSigUrl(body.signed_upload_url);
+ }
+ if ('signed_download_url' in body &&
+ typeof body.signed_download_url === 'string') {
+ maskSigUrl(body.signed_download_url);
+ }
+}
+exports.maskSecretUrls = maskSecretUrls;
+//# sourceMappingURL=util.js.map
+
+/***/ }),
+
/***/ 5321:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
@@ -88838,7 +88921,7 @@ function getUserAgent() {
return navigator.userAgent;
}
- if (typeof process === "object" && "version" in process) {
+ if (typeof process === "object" && process.version !== undefined) {
return `Node.js/${process.version.substr(1)} (${process.platform}; ${process.arch})`;
}
@@ -97211,9 +97294,13 @@ class BaseDistribution {
}
getNodeJsVersions() {
return __awaiter(this, void 0, void 0, function* () {
- const initialUrl = this.getDistributionUrl();
+ const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const dataUrl = `${initialUrl}/index.json`;
- const response = yield this.httpClient.getJson(dataUrl);
+ const headers = {};
+ if (this.nodeInfo.mirrorToken) {
+ headers['Authorization'] = `Bearer ${this.nodeInfo.mirrorToken}`;
+ }
+ const response = yield this.httpClient.getJson(dataUrl, headers);
return response.result || [];
});
}
@@ -97228,7 +97315,7 @@ class BaseDistribution {
? `${fileName}.zip`
: `${fileName}.7z`
: `${fileName}.tar.gz`;
- const initialUrl = this.getDistributionUrl();
+ const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const url = `${initialUrl}/v${version}/${urlFileName}`;
return {
downloadUrl: url,
@@ -97242,7 +97329,7 @@ class BaseDistribution {
let downloadPath = '';
core.info(`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`);
try {
- downloadPath = yield tc.downloadTool(info.downloadUrl);
+ downloadPath = yield tc.downloadTool(info.downloadUrl, undefined, this.nodeInfo.mirrorToken);
}
catch (err) {
if (err instanceof tc.HTTPError &&
@@ -97266,7 +97353,7 @@ class BaseDistribution {
}
acquireWindowsNodeFromFallbackLocation(version_1) {
return __awaiter(this, arguments, void 0, function* (version, arch = os_1.default.arch()) {
- const initialUrl = this.getDistributionUrl();
+ const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const osArch = this.translateArchToDistUrl(arch);
// Create temporary folder to download to
const tempDownloadFolder = `temp_${(0, uuid_1.v4)()}`;
@@ -97280,18 +97367,18 @@ class BaseDistribution {
exeUrl = `${initialUrl}/v${version}/win-${osArch}/node.exe`;
libUrl = `${initialUrl}/v${version}/win-${osArch}/node.lib`;
core.info(`Downloading only node binary from ${exeUrl}`);
- const exePath = yield tc.downloadTool(exeUrl);
+ const exePath = yield tc.downloadTool(exeUrl, undefined, this.nodeInfo.mirrorToken);
yield io.cp(exePath, path.join(tempDir, 'node.exe'));
- const libPath = yield tc.downloadTool(libUrl);
+ const libPath = yield tc.downloadTool(libUrl, undefined, this.nodeInfo.mirrorToken);
yield io.cp(libPath, path.join(tempDir, 'node.lib'));
}
catch (err) {
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
exeUrl = `${initialUrl}/v${version}/node.exe`;
libUrl = `${initialUrl}/v${version}/node.lib`;
- const exePath = yield tc.downloadTool(exeUrl);
+ const exePath = yield tc.downloadTool(exeUrl, undefined, this.nodeInfo.mirrorToken);
yield io.cp(exePath, path.join(tempDir, 'node.exe'));
- const libPath = yield tc.downloadTool(libUrl);
+ const libPath = yield tc.downloadTool(libUrl, undefined, this.nodeInfo.mirrorToken);
yield io.cp(libPath, path.join(tempDir, 'node.lib'));
}
else {
@@ -97454,8 +97541,9 @@ class NightlyNodejs extends base_distribution_prerelease_1.default {
super(nodeInfo);
this.distribution = 'nightly';
}
- getDistributionUrl() {
- return 'https://nodejs.org/download/nightly';
+ getDistributionUrl(mirror) {
+ const url = mirror || 'https://nodejs.org';
+ return `${url}/download/nightly`;
}
}
exports["default"] = NightlyNodejs;
@@ -97553,13 +97641,13 @@ class OfficialBuilds extends base_distribution_1.default {
const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, osArch, manifest);
if (versionInfo) {
core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`);
- downloadPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.auth);
+ downloadPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth);
if (downloadPath) {
toolPath = yield this.extractArchive(downloadPath, versionInfo, false);
}
}
else {
- core.info('Not found in manifest. Falling back to download directly from Node');
+ core.info(`Not found in manifest. Falling back to download directly from ${this.nodeInfo.mirror || 'Node'}`);
}
}
catch (err) {
@@ -97621,12 +97709,13 @@ class OfficialBuilds extends base_distribution_1.default {
version = super.evaluateVersions(versions);
return version;
}
- getDistributionUrl() {
- return `https://nodejs.org/dist`;
+ getDistributionUrl(mirror) {
+ const url = mirror || 'https://nodejs.org';
+ return `${url}/dist`;
}
getManifest() {
core.debug('Getting manifest from actions/node-versions@main');
- return tc.getManifestFromRepo('actions', 'node-versions', this.nodeInfo.auth, 'main');
+ return tc.getManifestFromRepo('actions', 'node-versions', this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth, 'main');
}
resolveLtsAliasFromManifest(versionSpec, stable, manifest) {
var _a;
@@ -97709,8 +97798,9 @@ class RcBuild extends base_distribution_1.default {
constructor(nodeInfo) {
super(nodeInfo);
}
- getDistributionUrl() {
- return 'https://nodejs.org/download/rc';
+ getDistributionUrl(mirror) {
+ const url = mirror || 'https://nodejs.org';
+ return `${url}/download/rc`;
}
}
exports["default"] = RcBuild;
@@ -97733,8 +97823,9 @@ class CanaryBuild extends base_distribution_prerelease_1.default {
super(nodeInfo);
this.distribution = 'v8-canary';
}
- getDistributionUrl() {
- return 'https://nodejs.org/download/v8-canary';
+ getDistributionUrl(mirror) {
+ const url = mirror || 'https://nodejs.org';
+ return `${url}/download/v8-canary`;
}
}
exports["default"] = CanaryBuild;
@@ -97814,6 +97905,8 @@ function run() {
if (version) {
const token = core.getInput('token');
const auth = !token ? undefined : `token ${token}`;
+ const mirror = core.getInput('mirror');
+ const mirrorToken = core.getInput('mirror-token');
const stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE';
const nodejsInfo = {
@@ -97821,7 +97914,9 @@ function run() {
checkLatest,
auth,
stable,
- arch
+ arch,
+ mirror,
+ mirrorToken
};
const nodeDistribution = (0, installer_factory_1.getNodejsDistribution)(nodejsInfo);
yield nodeDistribution.setupNodeJs();
@@ -99910,7 +100005,7 @@ module.exports = parseParams
/***/ ((module) => {
"use strict";
-module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"4.0.2","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":"^1.11.1","@actions/exec":"^1.0.1","@actions/glob":"^0.1.0","@actions/http-client":"^2.1.1","@actions/io":"^1.0.1","@azure/abort-controller":"^1.1.0","@azure/ms-rest-js":"^2.6.0","@azure/storage-blob":"^12.13.0","@protobuf-ts/plugin":"^2.9.4","semver":"^6.3.1"},"devDependencies":{"@types/semver":"^6.0.0","typescript":"^5.2.2"}}');
+module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"4.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":"^1.11.1","@actions/exec":"^1.0.1","@actions/glob":"^0.1.0","@actions/http-client":"^2.1.1","@actions/io":"^1.0.1","@azure/abort-controller":"^1.1.0","@azure/ms-rest-js":"^2.6.0","@azure/storage-blob":"^12.13.0","@protobuf-ts/plugin":"^2.9.4","semver":"^6.3.1"},"devDependencies":{"@types/node":"^22.13.9","@types/semver":"^6.0.0","typescript":"^5.2.2"}}');
/***/ }),
diff --git docs/advanced-usage.md docs/advanced-usage.md
index bf62e0713..856c5efac 100644
--- docs/advanced-usage.md
+++ docs/advanced-usage.md
@@ -418,3 +418,18 @@ Please refer to the [Ensuring workflow access to your package - Configuring a pa
### always-auth input
The always-auth input sets `always-auth=true` in .npmrc file. With this option set [npm](https://docs.npmjs.com/cli/v6/using-npm/config#always-auth)/yarn sends the authentication credentials when making a request to the registries.
+
+## Use private mirror
+
+It is possible to use a private mirror hosting Node.js binaries. This mirror must be a full mirror of the official Node.js distribution.
+The mirror URL can be set using the `mirror` input.
+It is possible to specify a token to authenticate with the mirror using the `mirror-token` input.
+The token will be passed as a bearer token in the `Authorization` header.
+
+```yaml
+- uses: actions/setup-node@v4
+ with:
+ node-version: '14.x'
+ mirror: 'https://nodejs.org/dist'
+ mirror-token: 'your-mirror-token'
+```
diff --git package.json package.json
index 5fb0c3873..0abcfe381 100644
--- package.json
+++ package.json
@@ -25,7 +25,7 @@
"author": "GitHub",
"license": "MIT",
"dependencies": {
- "@actions/cache": "^4.0.2",
+ "@actions/cache": "^4.0.3",
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
diff --git src/distributions/base-distribution.ts src/distributions/base-distribution.ts
index 70b4b5724..0a99f3a8c 100644
--- src/distributions/base-distribution.ts
+++ src/distributions/base-distribution.ts
@@ -24,7 +24,7 @@ export default abstract class BaseDistribution {
});
}
- protected abstract getDistributionUrl(): string;
+ protected abstract getDistributionUrl(mirror: string): string;
public async setupNodeJs() {
let nodeJsVersions: INodeVersion[] | undefined;
@@ -97,10 +97,19 @@ export default abstract class BaseDistribution {
}
protected async getNodeJsVersions(): Promise<INodeVersion[]> {
- const initialUrl = this.getDistributionUrl();
+ const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const dataUrl = `${initialUrl}/index.json`;
- const response = await this.httpClient.getJson<INodeVersion[]>(dataUrl);
+ const headers = {};
+
+ if (this.nodeInfo.mirrorToken) {
+ headers['Authorization'] = `Bearer ${this.nodeInfo.mirrorToken}`;
+ }
+
+ const response = await this.httpClient.getJson<INodeVersion[]>(
+ dataUrl,
+ headers
+ );
return response.result || [];
}
@@ -117,7 +126,7 @@ export default abstract class BaseDistribution {
? `${fileName}.zip`
: `${fileName}.7z`
: `${fileName}.tar.gz`;
- const initialUrl = this.getDistributionUrl();
+ const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const url = `${initialUrl}/v${version}/${urlFileName}`;
return <INodeVersionInfo>{
@@ -134,7 +143,11 @@ export default abstract class BaseDistribution {
`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`
);
try {
- downloadPath = await tc.downloadTool(info.downloadUrl);
+ downloadPath = await tc.downloadTool(
+ info.downloadUrl,
+ undefined,
+ this.nodeInfo.mirrorToken
+ );
} catch (err) {
if (
err instanceof tc.HTTPError &&
@@ -168,7 +181,7 @@ export default abstract class BaseDistribution {
version: string,
arch: string = os.arch()
): Promise<string> {
- const initialUrl = this.getDistributionUrl();
+ const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const osArch: string = this.translateArchToDistUrl(arch);
// Create temporary folder to download to
@@ -185,18 +198,34 @@ export default abstract class BaseDistribution {
core.info(`Downloading only node binary from ${exeUrl}`);
- const exePath = await tc.downloadTool(exeUrl);
+ const exePath = await tc.downloadTool(
+ exeUrl,
+ undefined,
+ this.nodeInfo.mirrorToken
+ );
await io.cp(exePath, path.join(tempDir, 'node.exe'));
- const libPath = await tc.downloadTool(libUrl);
+ const libPath = await tc.downloadTool(
+ libUrl,
+ undefined,
+ this.nodeInfo.mirrorToken
+ );
await io.cp(libPath, path.join(tempDir, 'node.lib'));
} catch (err) {
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
exeUrl = `${initialUrl}/v${version}/node.exe`;
libUrl = `${initialUrl}/v${version}/node.lib`;
- const exePath = await tc.downloadTool(exeUrl);
+ const exePath = await tc.downloadTool(
+ exeUrl,
+ undefined,
+ this.nodeInfo.mirrorToken
+ );
await io.cp(exePath, path.join(tempDir, 'node.exe'));
- const libPath = await tc.downloadTool(libUrl);
+ const libPath = await tc.downloadTool(
+ libUrl,
+ undefined,
+ this.nodeInfo.mirrorToken
+ );
await io.cp(libPath, path.join(tempDir, 'node.lib'));
} else {
throw err;
diff --git src/distributions/base-models.ts src/distributions/base-models.ts
index 0be93b635..61778cf9b 100644
--- src/distributions/base-models.ts
+++ src/distributions/base-models.ts
@@ -4,6 +4,8 @@ export interface NodeInputs {
auth?: string;
checkLatest: boolean;
stable: boolean;
+ mirror: string;
+ mirrorToken: string;
}
export interface INodeVersionInfo {
diff --git src/distributions/nightly/nightly_builds.ts src/distributions/nightly/nightly_builds.ts
index 86a89eed9..b3c366fa7 100644
--- src/distributions/nightly/nightly_builds.ts
+++ src/distributions/nightly/nightly_builds.ts
@@ -7,7 +7,8 @@ export default class NightlyNodejs extends BasePrereleaseNodejs {
super(nodeInfo);
}
- protected getDistributionUrl(): string {
- return 'https://nodejs.org/download/nightly';
+ protected getDistributionUrl(mirror: string): string {
+ const url = mirror || 'https://nodejs.org';
+ return `${url}/download/nightly`;
}
}
diff --git src/distributions/official_builds/official_builds.ts src/distributions/official_builds/official_builds.ts
index e56eaf812..62999c334 100644
--- src/distributions/official_builds/official_builds.ts
+++ src/distributions/official_builds/official_builds.ts
@@ -84,7 +84,7 @@ export default class OfficialBuilds extends BaseDistribution {
downloadPath = await tc.downloadTool(
versionInfo.downloadUrl,
undefined,
- this.nodeInfo.auth
+ this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth
);
if (downloadPath) {
@@ -96,7 +96,9 @@ export default class OfficialBuilds extends BaseDistribution {
}
} else {
core.info(
- 'Not found in manifest. Falling back to download directly from Node'
+ `Not found in manifest. Falling back to download directly from ${
+ this.nodeInfo.mirror || 'Node'
+ }`
);
}
} catch (err) {
@@ -176,8 +178,9 @@ export default class OfficialBuilds extends BaseDistribution {
return version;
}
- protected getDistributionUrl(): string {
- return `https://nodejs.org/dist`;
+ protected getDistributionUrl(mirror: string): string {
+ const url = mirror || 'https://nodejs.org';
+ return `${url}/dist`;
}
private getManifest(): Promise<tc.IToolRelease[]> {
@@ -185,7 +188,7 @@ export default class OfficialBuilds extends BaseDistribution {
return tc.getManifestFromRepo(
'actions',
'node-versions',
- this.nodeInfo.auth,
+ this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth,
'main'
);
}
diff --git src/distributions/rc/rc_builds.ts src/distributions/rc/rc_builds.ts
index 40cdb192a..38a6b0166 100644
--- src/distributions/rc/rc_builds.ts
+++ src/distributions/rc/rc_builds.ts
@@ -6,7 +6,8 @@ export default class RcBuild extends BaseDistribution {
super(nodeInfo);
}
- getDistributionUrl(): string {
- return 'https://nodejs.org/download/rc';
+ getDistributionUrl(mirror: string): string {
+ const url = mirror || 'https://nodejs.org';
+ return `${url}/download/rc`;
}
}
diff --git src/distributions/v8-canary/canary_builds.ts src/distributions/v8-canary/canary_builds.ts
index 257151b45..b714b67d4 100644
--- src/distributions/v8-canary/canary_builds.ts
+++ src/distributions/v8-canary/canary_builds.ts
@@ -7,7 +7,8 @@ export default class CanaryBuild extends BasePrereleaseNodejs {
super(nodeInfo);
}
- protected getDistributionUrl(): string {
- return 'https://nodejs.org/download/v8-canary';
+ protected getDistributionUrl(mirror: string): string {
+ const url = mirror || 'https://nodejs.org';
+ return `${url}/download/v8-canary`;
}
}
diff --git src/main.ts src/main.ts
index c55c3b005..c36d8ec5a 100644
--- src/main.ts
+++ src/main.ts
@@ -36,6 +36,8 @@ export async function run() {
if (version) {
const token = core.getInput('token');
const auth = !token ? undefined : `token ${token}`;
+ const mirror = core.getInput('mirror');
+ const mirrorToken = core.getInput('mirror-token');
const stable =
(core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
const checkLatest =
@@ -45,7 +47,9 @@ export async function run() {
checkLatest,
auth,
stable,
- arch
+ arch,
+ mirror,
+ mirrorToken
};
const nodeDistribution = getNodejsDistribution(nodejsInfo);
await nodeDistribution.setupNodeJs();
DescriptionThis PR adds support for downloading Node.js binaries from alternative mirrors by introducing two new input parameters: ChangesChanges
sequenceDiagram
actor User
participant Action as setup-node Action
participant Distribution as Node Distribution Classes
participant Mirror as Custom Mirror
participant DefaultMirror as Default Node.js Servers
participant Tool as tool-cache
User->>Action: Run with mirror parameters
Action->>Action: Parse inputs (mirror, mirror-token)
Action->>Distribution: Create distribution with mirror config
alt mirror is specified
Distribution->>Mirror: Request Node.js version info with mirror-token
Mirror->>Distribution: Return version data
Distribution->>Mirror: Download Node.js binary with mirror-token
Mirror->>Distribution: Return binary data
else mirror not specified
Distribution->>DefaultMirror: Request Node.js version info
DefaultMirror->>Distribution: Return version data
Distribution->>DefaultMirror: Download Node.js binary
DefaultMirror->>Distribution: Return binary data
end
Distribution->>Tool: Extract and cache binary
Tool->>Distribution: Return tool path
Distribution->>Action: Return success
Action->>User: Node.js successfully set up
|
👋 Thanks for Submitting! This PR is available for preview at the link below. ✅ PR tip preview: https://1058.pr.nala.bravesoftware.com/ - ./tokens/css/variables-android.old.css: 7390 bytes
+ ./tokens/css/variables-android.css: 7390 bytes
---
- ./tokens/css/variables-browser.old.css: 6644 bytes
+ ./tokens/css/variables-browser.css: 6644 bytes
---
- ./tokens/css/variables-ios.old.css: 7033 bytes
+ ./tokens/css/variables-ios.css: 7033 bytes
---
- ./tokens/css/variables-marketing.old.css: 13501 bytes
+ ./tokens/css/variables-marketing.css: 13501 bytes
---
- ./tokens/css/variables-news.old.css: 526 bytes
+ ./tokens/css/variables-news.css: 526 bytes
---
- ./tokens/css/variables-newtab.old.css: 1933 bytes
+ ./tokens/css/variables-newtab.css: 1933 bytes
---
- ./tokens/css/variables-search.old.css: 2409 bytes
+ ./tokens/css/variables-search.css: 2409 bytes
---
- ./tokens/css/variables-web3.old.css: 893 bytes
+ ./tokens/css/variables-web3.css: 893 bytes
---
- ./tokens/css/variables.old.css: 120612 bytes
+ ./tokens/css/variables.css: 120612 bytes
Variables Diff: variables-android.diff--- ./tokens/css/variables-android.old.css 2025-04-15 02:48:46.987925962 +0000
+++ ./tokens/css/variables-android.css 2025-04-15 02:48:15.215041041 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
:root {
Variables Diff: variables-browser.diff--- ./tokens/css/variables-browser.old.css 2025-04-15 02:48:47.196925227 +0000
+++ ./tokens/css/variables-browser.css 2025-04-15 02:48:15.203041075 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
:root {
Variables Diff: variables-ios.diff--- ./tokens/css/variables-ios.old.css 2025-04-15 02:48:47.521924081 +0000
+++ ./tokens/css/variables-ios.css 2025-04-15 02:48:15.237040979 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
:root {
Variables Diff: variables-marketing.diff--- ./tokens/css/variables-marketing.old.css 2025-04-15 02:48:47.752923269 +0000
+++ ./tokens/css/variables-marketing.css 2025-04-15 02:48:15.253040934 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
:root {
Variables Diff: variables-news.diff--- ./tokens/css/variables-news.old.css 2025-04-15 02:48:47.985922446 +0000
+++ ./tokens/css/variables-news.css 2025-04-15 02:48:15.272040880 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
:root {
Variables Diff: variables-newtab.diff--- ./tokens/css/variables-newtab.old.css 2025-04-15 02:48:48.191921700 +0000
+++ ./tokens/css/variables-newtab.css 2025-04-15 02:48:15.279040860 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
:root {
Variables Diff: variables-search.diff--- ./tokens/css/variables-search.old.css 2025-04-15 02:48:48.376921031 +0000
+++ ./tokens/css/variables-search.css 2025-04-15 02:48:15.268040892 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
:root {
Variables Diff: variables-web3.diff--- ./tokens/css/variables-web3.old.css 2025-04-15 02:48:48.578920301 +0000
+++ ./tokens/css/variables-web3.css 2025-04-15 02:48:15.283040849 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
@media (prefers-color-scheme: light) {
Variables Diff: variables.diff--- ./tokens/css/variables.old.css 2025-04-15 02:48:48.889919178 +0000
+++ ./tokens/css/variables.css 2025-04-15 02:48:15.079041425 +0000
@@ -1,6 +1,6 @@
/**
* Do not edit directly
- * Generated on Wed Apr 09 2025 19:26:34 GMT+0000 (Coordinated Universal Time)
+ * Generated on Tue Apr 15 2025 02:48:15 GMT+0000 (Coordinated Universal Time)
*/
:root {
|
Pull request was closed
This PR contains the following updates:
v4.3.0
->v4.4.0
Release Notes
actions/setup-node (actions/setup-node)
v4.4.0
Compare Source
Configuration
📅 Schedule: Branch creation - "* * * * 2-4" (UTC), Automerge - At any time (no schedule defined).
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.