Compare commits

..

18 Commits

Author SHA1 Message Date
aparnajyothi-y
39fe50ed67 Merge e91964252d into a7c2d9473e 2025-03-11 10:21:08 -05:00
Aparna Jyothi
e91964252d Documentation update 2025-03-10 18:19:35 +05:30
Aparna Jyothi
f338189333 improvements 2025-03-04 16:31:53 +05:30
Aparna Jyothi
8b9906e7bf update 2025-03-04 13:07:51 +05:30
Aparna Jyothi
8495358ea6 added check-latest 2025-03-04 12:50:08 +05:30
Aparna Jyothi
d8619e6d5a suppress warnings 2025-03-04 12:21:43 +05:30
Aparna Jyothi
87063ef0ad npm run format 2025-02-28 16:16:00 +05:30
Aparna Jyothi
5d5d8e9b58 code improvements 2025-02-28 16:11:26 +05:30
Aparna Jyothi
30c33f0409 version update to fix check failures 2025-02-27 18:39:11 +05:30
Aparna Jyothi
a4f5538cea version update from 20.11.0-nightly202312211a0be537da to 20.11.0-nightly 2025-02-27 18:33:27 +05:30
Aparna Jyothi
dd2fa9d9f8 checks update 2025-02-27 18:20:13 +05:30
Aparna Jyothi
d61dc50c40 test case update 2025-02-26 19:00:38 +05:30
Aparna Jyothi
b903bc8693 test cases update 2025-02-26 18:53:51 +05:30
Aparna Jyothi
092c6400ca check failures fix 2025-02-24 13:08:15 +05:30
Aparna Jyothi
7a5031f96f updated test cases 2025-02-24 12:40:37 +05:30
Aparna Jyothi
e5561a4d32 npm run test update 2025-02-21 13:16:46 +05:30
Aparna Jyothi
07b84a2324 check failures fix 2025-02-19 19:28:51 +05:30
Aparna Jyothi
1b0ef2d227 mirror-url -implementation 2025-02-19 19:10:42 +05:30
19 changed files with 3898 additions and 3406 deletions

View File

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

39
.licenses/npm/uuid-3.4.0.dep.yml generated Normal file
View File

@@ -0,0 +1,39 @@
---
name: uuid
version: 3.4.0
type: npm
summary: RFC4122 (v1, v4, and v5) UUIDs
homepage: https://github.com/uuidjs/uuid#readme
license: mit
licenses:
- sources: LICENSE.md
text: |
The MIT License (MIT)
Copyright (c) 2010-2016 Robert Kieffer and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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.
notices:
- sources: AUTHORS
text: |-
Robert Kieffer <robert@broofa.com>
Christoph Tavan <dev@tavan.de>
AJ ONeal <coolaj86@gmail.com>
Vincent Voyer <vincent@zeroload.net>
Roman Shtylman <shtylman@gmail.com>

View File

@@ -1,3 +1,4 @@
# setup-node
[![basic-validation](https://github.com/actions/setup-node/actions/workflows/basic-validation.yml/badge.svg)](https://github.com/actions/setup-node/actions/workflows/basic-validation.yml)
@@ -76,6 +77,10 @@ See [action.yml](action.yml)
# Set always-auth option in npmrc file.
# Default: ''
always-auth: ''
# Optional mirror to download nodejs binaries from.
# Default: ''
mirror-url: ''
```
<!-- end usage -->
@@ -86,7 +91,7 @@ steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 22
- run: npm ci
- run: npm test
```
@@ -103,7 +108,7 @@ The `node-version` input supports the Semantic Versioning Specification, for mor
Examples:
- Major versions: `18`, `20`
- Major versions: `20`, `22`
- More specific versions: `10.15`, `16.15.1` , `18.4.0`
- NVM LTS syntax: `lts/erbium`, `lts/fermium`, `lts/*`, `lts/-n`
- Latest release: `*` or `latest`/`current`/`node`
@@ -163,7 +168,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: [ 14, 16, 18 ]
node: [ 18, 20, 22 ]
name: Node ${{ matrix.node }} sample
steps:
- uses: actions/checkout@v4
@@ -203,6 +208,7 @@ If the runner is not able to access github.com, any Nodejs versions requested du
- [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm)
- [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn)
- [Using private packages](docs/advanced-usage.md#use-private-packages)
- [Using mirror-url)](https://github.com/aparnajyothi-y/setup-node/edit/add-mirror-url/docs/advanced-usage.md#node-mirrors-nodejs-version-mirrors)
## Recommended permissions
@@ -224,3 +230,5 @@ Contributions are welcome! See [Contributor's Guide](docs/contributors.md)
## Code of Conduct
:wave: Be nice. See [our code of conduct](CODE_OF_CONDUCT.md)

View File

@@ -13,6 +13,7 @@ import each from 'jest-each';
import * as main from '../src/main';
import * as util from '../src/util';
import OfficialBuilds from '../src/distributions/official_builds/official_builds';
import {validateMirrorURL} from '../src/util';
describe('main tests', () => {
let inputs = {} as any;
@@ -280,4 +281,36 @@ describe('main tests', () => {
);
});
});
describe('mirror-url parameter', () => {
beforeEach(() => {
inputs['mirror-url'] = 'https://custom-mirror-url.com';
});
afterEach(() => {
delete inputs['mirror-url'];
});
it('Read mirror-url if mirror-url is provided', async () => {
// Arrange
inputs['mirror-url'] = 'https://custom-mirror-url.com';
// Act
await main.run();
// Assert
expect(inputs['mirror-url']).toBeDefined();
});
it('should throw an error if mirror-url is empty', async () => {
// Arrange
inputs['mirror-url'] = ' ';
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); // Mock the log function
// Act & Assert
expect(() => validateMirrorURL(inputs['mirror-url'])).toThrow(
'Mirror URL is empty. Please provide a valid mirror URL.'
);
});
});
});

View File

@@ -10,6 +10,8 @@ import osm from 'os';
import path from 'path';
import * as main from '../src/main';
import * as auth from '../src/authutil';
import isLtsAlias from '../src/distributions/official_builds/official_builds';
import OfficialBuilds from '../src/distributions/official_builds/official_builds';
import {INodeVersion} from '../src/distributions/base-models';
@@ -828,4 +830,35 @@ describe('setup-node', () => {
}
);
});
describe('mirror-url parameter', () => {
it('default if mirror url is not provided', async () => {
os.platform = 'linux';
os.arch = 'x64';
inputs['node-version'] = '11';
inputs['check-latest'] = 'true';
inputs['always-auth'] = false;
inputs['token'] = 'faketoken';
dlSpy.mockImplementation(async () => '/some/temp/path');
const toolPath = path.normalize('/cache/node/12.11.0/x64');
exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath);
const dlmirrorSpy = jest.fn();
dlmirrorSpy.mockImplementation(async () => 'mocked-download-path');
await main.run();
const expPath = path.join(toolPath, 'bin');
expect(dlSpy).toHaveBeenCalled();
expect(exSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
'Attempt to resolve the latest version from manifest...'
);
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
});
});
});

View File

@@ -16,6 +16,9 @@ inputs:
default: false
registry-url:
description: 'Optional registry to set up for auth. Will set the registry in a project level .npmrc and .yarnrc file, and set up auth to read in from env.NODE_AUTH_TOKEN.'
mirror-url:
description: 'Custom mirror URL to download Node.js'
required: false
scope:
description: 'Optional scope for authenticating against scoped registries. Will fall back to the repository owner when using the GitHub Packages registry (https://npm.pkg.github.com/).'
token:

2847
dist/cache-save/index.js vendored

File diff suppressed because one or more lines are too long

3905
dist/setup/index.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,5 @@
## Working with lockfiles
All supported package managers recommend that you **always** commit the lockfile, although implementations vary doing so generally provides the following benefits:
@@ -76,10 +78,10 @@ When using the `package.json` input, the action will look for `volta.node` first
```json
{
"engines": {
"node": ">=16.0.0"
"node": ">=18.0.0"
},
"volta": {
"node": "16.0.0"
"node": "22.0.0"
}
}
```
@@ -100,7 +102,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14'
node-version: '22'
architecture: 'x64' # optional, x64 or x86. If not specified, x64 will be used by default
- run: npm ci
- run: npm test
@@ -239,7 +241,7 @@ steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14'
node-version: '22'
cache: 'yarn'
- run: yarn install --frozen-lockfile # optional, --immutable
- run: yarn test
@@ -261,7 +263,7 @@ steps:
version: 6.32.9
- uses: actions/setup-node@v4
with:
node-version: '14'
node-version: '22'
cache: 'pnpm'
- run: pnpm install
- run: pnpm test
@@ -277,7 +279,7 @@ steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14'
node-version: '22'
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
- run: npm ci
@@ -290,7 +292,7 @@ steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14'
node-version: '22'
cache: 'npm'
cache-dependency-path: |
server/app/package-lock.json
@@ -312,9 +314,9 @@ jobs:
- macos-latest
- windows-latest
node_version:
- 12
- 14
- 16
- 18
- 20
- 22
architecture:
- x64
# an extra windows-x86 run:
@@ -340,7 +342,7 @@ steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14.x'
node-version: '22'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm publish
@@ -360,7 +362,7 @@ steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14.x'
node-version: '22'
registry-url: <registry url>
- run: yarn install --frozen-lockfile
- run: yarn publish
@@ -380,7 +382,7 @@ steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14.x'
node-version: '22'
registry-url: 'https://registry.npmjs.org'
# Skip post-install scripts here, as a malicious
# script could steal NODE_AUTH_TOKEN.
@@ -418,3 +420,15 @@ 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.
### Using mirror-url
You can use the new mirror-url parameter to specify a custom mirror for downloading node.js versions from a different location
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
mirror-url: 'https://mirror.example.com/node'
```

32
package-lock.json generated
View File

@@ -16,7 +16,7 @@
"@actions/glob": "^0.5.0",
"@actions/http-client": "^2.2.1",
"@actions/io": "^1.0.2",
"@actions/tool-cache": "^2.0.2",
"@actions/tool-cache": "^2.0.1",
"semver": "^7.6.3",
"uuid": "^9.0.1"
},
@@ -26,7 +26,7 @@
"@types/semver": "^7.5.8",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"@vercel/ncc": "^0.38.3",
"@vercel/ncc": "^0.38.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-jest": "^27.9.0",
@@ -138,16 +138,16 @@
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
},
"node_modules/@actions/tool-cache": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.2.tgz",
"integrity": "sha512-fBhNNOWxuoLxztQebpOaWu6WeVmuwa77Z+DxIZ1B+OYvGkGQon6kTVg6Z32Cb13WCuw0szqonK+hh03mJV7Z6w==",
"license": "MIT",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.1.tgz",
"integrity": "sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA==",
"dependencies": {
"@actions/core": "^1.11.1",
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.0",
"@actions/http-client": "^2.0.1",
"@actions/io": "^1.1.1",
"semver": "^6.1.0"
"semver": "^6.1.0",
"uuid": "^3.3.2"
}
},
"node_modules/@actions/tool-cache/node_modules/semver": {
@@ -158,6 +158,15 @@
"semver": "bin/semver.js"
}
},
"node_modules/@actions/tool-cache/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
@@ -2123,11 +2132,10 @@
"dev": true
},
"node_modules/@vercel/ncc": {
"version": "0.38.3",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.3.tgz",
"integrity": "sha512-rnK6hJBS6mwc+Bkab+PGPs9OiS0i/3kdTO+CkI8V0/VrW3vmz7O2Pxjw/owOlmo6PKEIxRSeZKv/kuL9itnpYA==",
"version": "0.38.1",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz",
"integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==",
"dev": true,
"license": "MIT",
"bin": {
"ncc": "dist/ncc/cli.js"
}

View File

@@ -32,7 +32,7 @@
"@actions/glob": "^0.5.0",
"@actions/http-client": "^2.2.1",
"@actions/io": "^1.0.2",
"@actions/tool-cache": "^2.0.2",
"@actions/tool-cache": "^2.0.1",
"semver": "^7.6.3",
"uuid": "^9.0.1"
},
@@ -42,7 +42,7 @@
"@types/semver": "^7.5.8",
"@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0",
"@vercel/ncc": "^0.38.3",
"@vercel/ncc": "^0.38.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-jest": "^27.9.0",

View File

@@ -104,6 +104,34 @@ export default abstract class BaseDistribution {
return response.result || [];
}
protected async getMirrorUrlVersions(): Promise<INodeVersion[]> {
const initialUrl = this.getDistributionUrl();
const dataUrl = `${initialUrl}/index.json`;
try {
const response = await this.httpClient.getJson<INodeVersion[]>(dataUrl);
return response.result || [];
} catch (err) {
if (
err instanceof Error &&
err.message.includes('getaddrinfo EAI_AGAIN')
) {
core.setFailed(
`Network error: Failed to resolve the server at ${dataUrl}.Please check your DNS settings or verify that the URL is correct.`
);
} else if (err instanceof hc.HttpClientError && err.statusCode === 404) {
core.setFailed(
`404 Error: Unable to find versions at ${dataUrl}.Please verify that the mirror URL is valid.`
);
} else {
core.setFailed(
`Failed to fetch Node.js versions from ${dataUrl}.Please check the URL and try again.}`
);
}
throw err;
}
}
protected getNodejsDistInfo(version: string) {
const osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch);
version = semver.clean(version) || '';
@@ -128,6 +156,33 @@ export default abstract class BaseDistribution {
};
}
protected getNodejsMirrorURLInfo(version: string) {
const mirrorURL = this.nodeInfo.mirrorURL;
const osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch);
version = semver.clean(version) || '';
const fileName: string =
this.osPlat == 'win32'
? `node-v${version}-win-${osArch}`
: `node-v${version}-${this.osPlat}-${osArch}`;
const urlFileName: string =
this.osPlat == 'win32'
? this.nodeInfo.arch === 'arm64'
? `${fileName}.zip`
: `${fileName}.7z`
: `${fileName}.tar.gz`;
const url = `${mirrorURL}/v${version}/${urlFileName}`;
return <INodeVersionInfo>{
downloadUrl: url,
resolvedVersion: version,
arch: osArch,
fileName: fileName
};
}
protected async downloadNodejs(info: INodeVersionInfo) {
let downloadPath = '';
core.info(
@@ -143,9 +198,23 @@ export default abstract class BaseDistribution {
) {
return await this.acquireWindowsNodeFromFallbackLocation(
info.resolvedVersion,
info.arch
info.arch,
info.downloadUrl
);
}
// Handle network-related issues (e.g., DNS resolution failures)
if (
err instanceof Error &&
err.message.includes('getaddrinfo EAI_AGAIN')
) {
core.error(
`Network error: Failed to resolve the server at ${info.downloadUrl}.
This could be due to a DNS resolution issue. Please verify the URL or check your network connection.`
);
}
core.error(
`Download failed from ${info.downloadUrl}. Please check the URl and try again.`
);
throw err;
}
@@ -166,9 +235,11 @@ export default abstract class BaseDistribution {
protected async acquireWindowsNodeFromFallbackLocation(
version: string,
arch: string = os.arch()
arch: string = os.arch(),
downloadUrl: string
): Promise<string> {
const initialUrl = this.getDistributionUrl();
core.info('url: ' + initialUrl);
const osArch: string = this.translateArchToDistUrl(arch);
// Create temporary folder to download to
@@ -185,6 +256,12 @@ export default abstract class BaseDistribution {
core.info(`Downloading only node binary from ${exeUrl}`);
if (downloadUrl != exeUrl) {
core.error(
'unable to download node binary with the provided URL. Please check and try again'
);
}
const exePath = await tc.downloadTool(exeUrl);
await io.cp(exePath, path.join(tempDir, 'node.exe'));
const libPath = await tc.downloadTool(libUrl);

View File

@@ -4,6 +4,7 @@ export interface NodeInputs {
auth?: string;
checkLatest: boolean;
stable: boolean;
mirrorURL?: string;
}
export interface INodeVersionInfo {

View File

@@ -3,11 +3,16 @@ import {NodeInputs} from '../base-models';
export default class NightlyNodejs extends BasePrereleaseNodejs {
protected distribution = 'nightly';
constructor(nodeInfo: NodeInputs) {
super(nodeInfo);
}
protected getDistributionUrl(): string {
return 'https://nodejs.org/download/nightly';
if (this.nodeInfo.mirrorURL) {
return this.nodeInfo.mirrorURL;
} else {
return 'https://nodejs.org/download/nightly';
}
}
}

View File

@@ -15,115 +15,125 @@ export default class OfficialBuilds extends BaseDistribution {
}
public async setupNodeJs() {
let manifest: tc.IToolRelease[] | undefined;
let nodeJsVersions: INodeVersion[] | undefined;
const osArch = this.translateArchToDistUrl(this.nodeInfo.arch);
if (this.nodeInfo.mirrorURL) {
try {
core.info(`Attempting to download using mirror URL...`);
await this.downloadFromMirrorURL(); // Attempt to download from the mirror
} catch (err) {
core.setFailed((err as Error).message);
}
} else {
core.info('Setup Node.js');
let manifest: tc.IToolRelease[] | undefined;
let nodeJsVersions: INodeVersion[] | undefined;
const osArch = this.translateArchToDistUrl(this.nodeInfo.arch);
if (this.isLtsAlias(this.nodeInfo.versionSpec)) {
core.info('Attempt to resolve LTS alias from manifest...');
if (this.isLtsAlias(this.nodeInfo.versionSpec)) {
core.info('Attempt to resolve LTS alias from manifest...');
// No try-catch since it's not possible to resolve LTS alias without manifest
manifest = await this.getManifest();
// No try-catch since it's not possible to resolve LTS alias without manifest
manifest = await this.getManifest();
this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest(
this.nodeInfo.versionSpec,
this.nodeInfo.stable,
manifest
);
}
if (this.isLatestSyntax(this.nodeInfo.versionSpec)) {
nodeJsVersions = await this.getNodeJsVersions();
const versions = this.filterVersions(nodeJsVersions);
this.nodeInfo.versionSpec = this.evaluateVersions(versions);
core.info('getting latest node version...');
}
if (this.nodeInfo.checkLatest) {
core.info('Attempt to resolve the latest version from manifest...');
const resolvedVersion = await this.resolveVersionFromManifest(
this.nodeInfo.versionSpec,
this.nodeInfo.stable,
osArch,
manifest
);
if (resolvedVersion) {
this.nodeInfo.versionSpec = resolvedVersion;
core.info(`Resolved as '${resolvedVersion}'`);
} else {
core.info(
`Failed to resolve version ${this.nodeInfo.versionSpec} from manifest`
this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest(
this.nodeInfo.versionSpec,
this.nodeInfo.stable,
manifest
);
}
}
let toolPath = this.findVersionInHostedToolCacheDirectory();
if (this.isLatestSyntax(this.nodeInfo.versionSpec)) {
nodeJsVersions = await this.getNodeJsVersions();
const versions = this.filterVersions(nodeJsVersions);
this.nodeInfo.versionSpec = this.evaluateVersions(versions);
if (toolPath) {
core.info(`Found in cache @ ${toolPath}`);
this.addToolPath(toolPath);
return;
}
core.info('getting latest node version...');
}
let downloadPath = '';
try {
core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`);
const versionInfo = await this.getInfoFromManifest(
this.nodeInfo.versionSpec,
this.nodeInfo.stable,
osArch,
manifest
);
if (versionInfo) {
core.info(
`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`
if (this.nodeInfo.checkLatest) {
core.info('Attempt to resolve the latest version from manifest...');
const resolvedVersion = await this.resolveVersionFromManifest(
this.nodeInfo.versionSpec,
this.nodeInfo.stable,
osArch,
manifest
);
downloadPath = await tc.downloadTool(
versionInfo.downloadUrl,
undefined,
this.nodeInfo.auth
);
if (downloadPath) {
toolPath = await this.extractArchive(
downloadPath,
versionInfo,
false
if (resolvedVersion) {
this.nodeInfo.versionSpec = resolvedVersion;
core.info(`Resolved as '${resolvedVersion}'`);
} else {
core.info(
`Failed to resolve version ${this.nodeInfo.versionSpec} from manifest`
);
}
} else {
core.info(
'Not found in manifest. Falling back to download directly from Node'
);
}
} catch (err) {
// Rate limit?
if (
err instanceof tc.HTTPError &&
(err.httpStatusCode === 403 || err.httpStatusCode === 429)
) {
core.info(
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
);
} else {
core.info((err as Error).message);
let toolPath = this.findVersionInHostedToolCacheDirectory();
if (toolPath) {
core.info(`Found in cache @ ${toolPath}`);
this.addToolPath(toolPath);
return;
}
core.debug((err as Error).stack ?? 'empty stack');
core.info('Falling back to download directly from Node');
}
if (!toolPath) {
toolPath = await this.downloadDirectlyFromNode();
}
let downloadPath = '';
try {
core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`);
if (this.osPlat != 'win32') {
toolPath = path.join(toolPath, 'bin');
}
const versionInfo = await this.getInfoFromManifest(
this.nodeInfo.versionSpec,
this.nodeInfo.stable,
osArch,
manifest
);
core.addPath(toolPath);
if (versionInfo) {
core.info(
`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`
);
downloadPath = await tc.downloadTool(
versionInfo.downloadUrl,
undefined,
this.nodeInfo.auth
);
if (downloadPath) {
toolPath = await this.extractArchive(
downloadPath,
versionInfo,
false
);
}
} else {
core.info(
'Not found in manifest. Falling back to download directly from Node'
);
}
} catch (err) {
// Rate limit?
if (
err instanceof tc.HTTPError &&
(err.httpStatusCode === 403 || err.httpStatusCode === 429)
) {
core.info(
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
);
} else {
core.info((err as Error).message);
}
core.debug((err as Error).stack ?? 'empty stack');
core.info('Falling back to download directly from Node');
}
if (!toolPath) {
toolPath = await this.downloadDirectlyFromNode();
}
if (this.osPlat != 'win32') {
toolPath = path.join(toolPath, 'bin');
}
core.addPath(toolPath);
}
}
protected addToolPath(toolPath: string) {
@@ -177,6 +187,9 @@ export default class OfficialBuilds extends BaseDistribution {
}
protected getDistributionUrl(): string {
if (this.nodeInfo.mirrorURL) {
return this.nodeInfo.mirrorURL;
}
return `https://nodejs.org/dist`;
}
@@ -291,4 +304,39 @@ export default class OfficialBuilds extends BaseDistribution {
private isLatestSyntax(versionSpec): boolean {
return ['current', 'latest', 'node'].includes(versionSpec);
}
protected async downloadFromMirrorURL() {
const nodeJsVersions = await this.getMirrorUrlVersions();
const versions = this.filterVersions(nodeJsVersions);
const evaluatedVersion = this.evaluateVersions(versions);
if (!evaluatedVersion) {
throw new Error(
`Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch} from the provided mirror-url ${this.nodeInfo.mirrorURL}. Please check the mirror-url`
);
}
const toolName = this.getNodejsMirrorURLInfo(evaluatedVersion);
try {
const toolPath = await this.downloadNodejs(toolName);
return toolPath;
} catch (error) {
if (error instanceof tc.HTTPError && error.httpStatusCode === 404) {
core.setFailed(
`Node version ${this.nodeInfo.versionSpec} for platform ${this.osPlat} and architecture ${this.nodeInfo.arch} was found but failed to download. ` +
'This usually happens when downloadable binaries are not fully updated in the provided mirror-url' +
'To resolve this issue you may either fall back to the older version or try again later.'
);
} else {
core.setFailed(
`An unexpected error occurred like url might not correct`
);
}
throw error;
}
}
}

View File

@@ -5,8 +5,11 @@ export default class RcBuild extends BaseDistribution {
constructor(nodeInfo: NodeInputs) {
super(nodeInfo);
}
getDistributionUrl(): string {
return 'https://nodejs.org/download/rc';
protected getDistributionUrl(): string {
if (this.nodeInfo.mirrorURL) {
return this.nodeInfo.mirrorURL;
} else {
return 'https://nodejs.org/download/rc';
}
}
}

View File

@@ -1,6 +1,5 @@
import BasePrereleaseNodejs from '../base-distribution-prerelease';
import {NodeInputs} from '../base-models';
export default class CanaryBuild extends BasePrereleaseNodejs {
protected distribution = 'v8-canary';
constructor(nodeInfo: NodeInputs) {
@@ -8,6 +7,10 @@ export default class CanaryBuild extends BasePrereleaseNodejs {
}
protected getDistributionUrl(): string {
return 'https://nodejs.org/download/v8-canary';
if (this.nodeInfo.mirrorURL) {
return this.nodeInfo.mirrorURL;
} else {
return 'https://nodejs.org/download/v8-canary';
}
}
}

View File

@@ -33,6 +33,8 @@ export async function run() {
arch = os.arch();
}
const mirrorURL = core.getInput('mirror-url');
if (version) {
const token = core.getInput('token');
const auth = !token ? undefined : `token ${token}`;
@@ -45,7 +47,8 @@ export async function run() {
checkLatest,
auth,
stable,
arch
arch,
mirrorURL
};
const nodeDistribution = getNodejsDistribution(nodejsInfo);
await nodeDistribution.setupNodeJs();

View File

@@ -97,7 +97,13 @@ async function getToolVersion(tool: string, options: string[]) {
return '';
}
}
export function validateMirrorURL(mirrorURL) {
if (mirrorURL === ' ' || mirrorURL.trim() === 'undefined') {
throw new Error('Mirror URL is empty. Please provide a valid mirror URL.');
} else {
return mirrorURL;
}
}
export const unique = () => {
const encountered = new Set();
return (value: unknown): boolean => {