Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 5 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
[![e2e-cache](https://github.com/actions/setup-node/actions/workflows/e2e-cache.yml/badge.svg?branch=main)](https://github.com/actions/setup-node/actions/workflows/e2e-cache.yml)
[![proxy](https://github.com/actions/setup-node/actions/workflows/proxy.yml/badge.svg)](https://github.com/actions/setup-node/actions/workflows/proxy.yml)

> **Fork of [actions/setup-node](https://github.com/actions/setup-node)** — Node.js binaries are downloaded from the [cnpm mirror](https://cdn.npmmirror.com/binaries/node/) instead of the official Node.js dist, which significantly improves download speed in some self-hosted network environments.

This action provides the following functionality for GitHub Actions users:

- Optionally downloading and caching distribution of the requested Node.js version, and adding it to the PATH
- Optionally downloading and caching distribution of the requested Node.js version **via cnpm mirror**, and adding it to the PATH
- Optionally caching npm/yarn/pnpm dependencies
- Registering problem matchers for error output
- Configuring authentication for GPR or npm
Expand Down Expand Up @@ -94,20 +96,6 @@ See [action.yml](action.yml)
# Default: ''
scope: ''

# Optional mirror to download binaries from.
# Artifacts need to match the official Node.js
# Example:
# V8 Canary 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 -->

Expand All @@ -125,7 +113,7 @@ steps:

The `node-version` input is optional. If not supplied, the node version from PATH will be used. However, it is recommended to always specify Node.js version and not rely on the system one.

The action will first check the local cache for a semver match. If unable to find a specific version in the cache, the action will attempt to download a version of Node.js. It will pull LTS versions from [node-versions releases](https://github.com/actions/node-versions/releases) and on miss or failure will fall back to downloading directly from [npm Mirror Node dist](https://cdn.npmmirror.com/binaries/node/).
The action will first check the local cache for a semver match. If unable to find a specific version in the cache, the action will attempt to download a version of Node.js. It will pull LTS versions from [node-versions releases](https://github.com/actions/node-versions/releases) and on miss or failure will fall back to downloading directly from the [cnpm mirror](https://cdn.npmmirror.com/binaries/node/).

For information regarding locally cached versions of Node.js on GitHub hosted runners, check out [GitHub Actions Runner Images](https://github.com/actions/runner-images).

Expand All @@ -143,7 +131,7 @@ Examples:
**Note:** Like the other values, `*` will get the latest [locally-cached Node.js version](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md#nodejs), or the latest version from [actions/node-versions](https://github.com/actions/node-versions/blob/main/versions-manifest.json), depending on the [`check-latest`](docs/advanced-usage.md#check-latest-version) input.

`current`/`latest`/`node` always resolve to the latest [dist version](https://nodejs.org/dist/index.json).
That version is then downloaded from actions/node-versions if possible, or directly from https://cdn.npmmirror.com/binaries/node if not.
That version is then downloaded from actions/node-versions if possible, or directly from the [cnpm mirror](https://cdn.npmmirror.com/binaries/node/) if not.
Since it will not be cached always, there is possibility of hitting rate limit when downloading from dist

### Checking in lockfiles
Expand Down Expand Up @@ -249,7 +237,6 @@ 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 private mirror](docs/advanced-usage.md#use-private-mirror)

## Recommended permissions

Expand Down
4 changes: 0 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ inputs:
default: true
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 download 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:
Expand Down
32 changes: 12 additions & 20 deletions dist/setup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -112561,13 +112561,9 @@ class BaseDistribution {
return tc.find('node', this.nodeInfo.versionSpec, this.translateArchToDistUrl(this.nodeInfo.arch));
}
async getNodeJsVersions() {
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const initialUrl = this.getDistributionUrl();
const dataUrl = `${initialUrl}/index.json`;
const headers = {};
if (this.nodeInfo.mirrorToken) {
headers['Authorization'] = this.nodeInfo.mirrorToken;
}
const response = await this.httpClient.getJson(dataUrl, headers);
const response = await this.httpClient.getJson(dataUrl);
return response.result || [];
}
getNodejsDistInfo(version) {
Expand All @@ -112581,7 +112577,7 @@ class BaseDistribution {
? `${fileName}.zip`
: `${fileName}.7z`
: `${fileName}.tar.gz`;
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const initialUrl = this.getDistributionUrl();
const url = `${initialUrl}/v${version}/${urlFileName}`;
return {
downloadUrl: url,
Expand All @@ -112594,7 +112590,7 @@ class BaseDistribution {
let downloadPath = '';
core.info(`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`);
try {
downloadPath = await tc.downloadTool(info.downloadUrl, undefined, this.nodeInfo.mirrorToken);
downloadPath = await tc.downloadTool(info.downloadUrl);
}
catch (err) {
if (err instanceof tc.HTTPError &&
Expand All @@ -112615,7 +112611,7 @@ class BaseDistribution {
return { range: valid, options };
}
async acquireWindowsNodeFromFallbackLocation(version, arch = os_1.default.arch()) {
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const initialUrl = this.getDistributionUrl();
const osArch = this.translateArchToDistUrl(arch);
// Create temporary folder to download to
const tempDownloadFolder = `temp_${crypto.randomUUID()}`;
Expand All @@ -112629,18 +112625,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 = await tc.downloadTool(exeUrl, undefined, this.nodeInfo.mirrorToken);
const exePath = await tc.downloadTool(exeUrl);
await io.cp(exePath, path.join(tempDir, 'node.exe'));
const libPath = await tc.downloadTool(libUrl, undefined, this.nodeInfo.mirrorToken);
const libPath = await tc.downloadTool(libUrl);
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, undefined, this.nodeInfo.mirrorToken);
const exePath = await tc.downloadTool(exeUrl);
await io.cp(exePath, path.join(tempDir, 'node.exe'));
const libPath = await tc.downloadTool(libUrl, undefined, this.nodeInfo.mirrorToken);
const libPath = await tc.downloadTool(libUrl);
await io.cp(libPath, path.join(tempDir, 'node.lib'));
}
else {
Expand Down Expand Up @@ -112926,15 +112922,15 @@ class OfficialBuilds extends base_distribution_1.default {
version = super.evaluateVersions(versions);
return version;
}
getDistributionUrl(mirror) {
getDistributionUrl() {
return constants_1.DEFAULT_NODE_MIRROR;
}
getFallbackDisplayUrl() {
return constants_1.DEFAULT_NODE_MIRROR;
}
getManifest() {
core.debug('Getting manifest from actions/node-versions@main');
return tc.getManifestFromRepo('actions', 'node-versions', this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth, 'main');
return tc.getManifestFromRepo('actions', 'node-versions', this.nodeInfo.auth, 'main');
}
resolveLtsAliasFromManifest(versionSpec, stable, manifest) {
const alias = versionSpec.split('lts/')[1]?.toLowerCase();
Expand Down Expand Up @@ -113074,18 +113070,14 @@ 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 = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE';
const nodejsInfo = {
versionSpec: version,
checkLatest,
auth,
stable,
arch,
mirror,
mirrorToken
arch
};
const nodeDistribution = (0, installer_factory_1.getNodejsDistribution)(nodejsInfo);
await nodeDistribution.setupNodeJs();
Expand Down
15 changes: 0 additions & 15 deletions docs/advanced-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -474,18 +474,3 @@ steps:
To access private GitHub Packages within the same organization, go to "Manage Actions access" in Package settings and set the repositories you want to access.

Please refer to the [Ensuring workflow access to your package - Configuring a package's access control and visibility](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#ensuring-workflow-access-to-your-package) for more details.

## 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 in the `Authorization` header.

```yaml
- uses: actions/setup-node@v6
with:
node-version: '24.x'
mirror: 'https://nodejs.org/dist'
mirror-token: 'your-mirror-token'
```
49 changes: 10 additions & 39 deletions src/distributions/base-distribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import fs from 'fs';

import {NodeInputs, INodeVersion, INodeVersionInfo} from './base-models';
import {DEFAULT_NODE_MIRROR} from '../constants';

Check warning on line 14 in src/distributions/base-distribution.ts

View workflow job for this annotation

GitHub Actions / Basic validation / build (macos-latest)

'DEFAULT_NODE_MIRROR' is defined but never used

Check warning on line 14 in src/distributions/base-distribution.ts

View workflow job for this annotation

GitHub Actions / Basic validation / build (ubuntu-latest)

'DEFAULT_NODE_MIRROR' is defined but never used

Check warning on line 14 in src/distributions/base-distribution.ts

View workflow job for this annotation

GitHub Actions / Basic validation / build (windows-latest)

'DEFAULT_NODE_MIRROR' is defined but never used

export default abstract class BaseDistribution {
protected httpClient: hc.HttpClient;
Expand All @@ -24,7 +24,7 @@
});
}

protected abstract getDistributionUrl(mirror: string): string;
protected abstract getDistributionUrl(): string;

public async setupNodeJs() {
let nodeJsVersions: INodeVersion[] | undefined;
Expand Down Expand Up @@ -97,19 +97,10 @@
}

protected async getNodeJsVersions(): Promise<INodeVersion[]> {
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const initialUrl = this.getDistributionUrl();
const dataUrl = `${initialUrl}/index.json`;

const headers = {};

if (this.nodeInfo.mirrorToken) {
headers['Authorization'] = this.nodeInfo.mirrorToken;
}

const response = await this.httpClient.getJson<INodeVersion[]>(
dataUrl,
headers
);
const response = await this.httpClient.getJson<INodeVersion[]>(dataUrl);
return response.result || [];
}

Expand All @@ -126,7 +117,7 @@
? `${fileName}.zip`
: `${fileName}.7z`
: `${fileName}.tar.gz`;
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const initialUrl = this.getDistributionUrl();
const url = `${initialUrl}/v${version}/${urlFileName}`;

return <INodeVersionInfo>{
Expand All @@ -143,11 +134,7 @@
`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`
);
try {
downloadPath = await tc.downloadTool(
info.downloadUrl,
undefined,
this.nodeInfo.mirrorToken
);
downloadPath = await tc.downloadTool(info.downloadUrl);
} catch (err) {
if (
err instanceof tc.HTTPError &&
Expand Down Expand Up @@ -181,7 +168,7 @@
version: string,
arch: string = os.arch()
): Promise<string> {
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const initialUrl = this.getDistributionUrl();
const osArch: string = this.translateArchToDistUrl(arch);

// Create temporary folder to download to
Expand All @@ -198,34 +185,18 @@

core.info(`Downloading only node binary from ${exeUrl}`);

const exePath = await tc.downloadTool(
exeUrl,
undefined,
this.nodeInfo.mirrorToken
);
const exePath = await tc.downloadTool(exeUrl);
await io.cp(exePath, path.join(tempDir, 'node.exe'));
const libPath = await tc.downloadTool(
libUrl,
undefined,
this.nodeInfo.mirrorToken
);
const libPath = await tc.downloadTool(libUrl);
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,
undefined,
this.nodeInfo.mirrorToken
);
const exePath = await tc.downloadTool(exeUrl);
await io.cp(exePath, path.join(tempDir, 'node.exe'));
const libPath = await tc.downloadTool(
libUrl,
undefined,
this.nodeInfo.mirrorToken
);
const libPath = await tc.downloadTool(libUrl);
await io.cp(libPath, path.join(tempDir, 'node.lib'));
} else {
throw err;
Expand Down
2 changes: 0 additions & 2 deletions src/distributions/base-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ export interface NodeInputs {
auth?: string;
checkLatest: boolean;
stable: boolean;
mirror: string;
mirrorToken: string;
}

export interface INodeVersionInfo {
Expand Down
4 changes: 2 additions & 2 deletions src/distributions/official_builds/official_builds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export default class OfficialBuilds extends BaseDistribution {
return version;
}

protected getDistributionUrl(mirror: string): string {
protected getDistributionUrl(): string {
return DEFAULT_NODE_MIRROR;
}

Expand All @@ -179,7 +179,7 @@ export default class OfficialBuilds extends BaseDistribution {
return tc.getManifestFromRepo(
'actions',
'node-versions',
this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth,
this.nodeInfo.auth,
'main'
);
}
Expand Down
6 changes: 1 addition & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ 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 =
Expand All @@ -51,9 +49,7 @@ export async function run() {
checkLatest,
auth,
stable,
arch,
mirror,
mirrorToken
arch
};
const nodeDistribution = getNodejsDistribution(nodejsInfo);
await nodeDistribution.setupNodeJs();
Expand Down
Loading