Skip to content

Commit e3ce749

Browse files
feat: support private mirrors (#1240)
* feat: support private mirrors * chore: change fallback message with mirrors
1 parent 40337cb commit e3ce749

File tree

14 files changed

+322
-44
lines changed

14 files changed

+322
-44
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ See [action.yml](action.yml)
7676
# Set always-auth option in npmrc file.
7777
# Default: ''
7878
always-auth: ''
79+
80+
# Optional mirror to download binaries from.
81+
# Artifacts need to match the official Node.js
82+
# Example:
83+
# V8 Canaray Build: <mirror_url>/download/v8-canary
84+
# RC Build: <mirror_url>/download/rc
85+
# Official: Build <mirror_url>/dist
86+
# Nightly build: <mirror_url>/download/nightly
87+
# Default: ''
88+
mirror: ''
89+
90+
# Optional mirror token.
91+
# The token will be used as a bearer token in the Authorization header
92+
# Default: ''
93+
mirror-token: ''
7994
```
8095
<!-- end usage -->
8196

__tests__/canary-installer.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,70 @@ describe('setup-node', () => {
498498
);
499499
}
500500
);
501+
502+
it.each([
503+
[
504+
'20.0.0-v8-canary',
505+
'20.0.0-v8-canary20221103f7e2421e91',
506+
'20.0.0-v8-canary20221030fefe1c0879',
507+
'https://my_mirror.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz'
508+
],
509+
[
510+
'20-v8-canary',
511+
'20.0.0-v8-canary20221103f7e2421e91',
512+
'20.0.0-v8-canary20221030fefe1c0879',
513+
'https://my_mirror.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz'
514+
],
515+
[
516+
'19.0.0-v8-canary',
517+
'19.0.0-v8-canary202210187d6960f23f',
518+
'19.0.0-v8-canary202210172ec229fc56',
519+
'https://my_mirror.org/download/v8-canary/v19.0.0-v8-canary202210187d6960f23f/node-v19.0.0-v8-canary202210187d6960f23f-linux-x64.tar.gz'
520+
],
521+
[
522+
'19-v8-canary',
523+
'19.0.0-v8-canary202210187d6960f23f',
524+
'19.0.0-v8-canary202210172ec229fc56',
525+
'https://my_mirror.org/download/v8-canary/v19.0.0-v8-canary202210187d6960f23f/node-v19.0.0-v8-canary202210187d6960f23f-linux-x64.tar.gz'
526+
]
527+
])(
528+
'get %s version from dist if check-latest is true',
529+
async (input, expectedVersion, foundVersion, expectedUrl) => {
530+
const foundToolPath = path.normalize(`/cache/node/${foundVersion}/x64`);
531+
const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
532+
533+
inputs['node-version'] = input;
534+
inputs['check-latest'] = 'true';
535+
os['arch'] = 'x64';
536+
os['platform'] = 'linux';
537+
inputs['mirror'] = 'https://my_mirror.org';
538+
inputs['mirror-token'] = 'faketoken';
539+
540+
findSpy.mockReturnValue(foundToolPath);
541+
findAllVersionsSpy.mockReturnValue([
542+
'20.0.0-v8-canary20221030fefe1c0879',
543+
'19.0.0-v8-canary202210172ec229fc56',
544+
'20.0.0-v8-canary2022102310ff1e5a8d'
545+
]);
546+
dlSpy.mockImplementation(async () => '/some/temp/path');
547+
exSpy.mockImplementation(async () => '/some/other/temp/path');
548+
cacheSpy.mockImplementation(async () => toolPath);
549+
550+
// act
551+
await main.run();
552+
553+
// assert
554+
expect(findAllVersionsSpy).toHaveBeenCalled();
555+
expect(logSpy).toHaveBeenCalledWith(
556+
`Acquiring ${expectedVersion} - ${os.arch} from ${expectedUrl}`
557+
);
558+
expect(logSpy).toHaveBeenCalledWith('Extracting ...');
559+
expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...');
560+
expect(cnSpy).toHaveBeenCalledWith(
561+
`::add-path::${path.join(toolPath, 'bin')}${osm.EOL}`
562+
);
563+
}
564+
);
501565
});
502566

503567
describe('setup-node v8 canary tests', () => {

__tests__/nightly-installer.test.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ describe('setup-node', () => {
315315
await main.run();
316316

317317
workingUrls.forEach(url => {
318-
expect(dlSpy).toHaveBeenCalledWith(url);
318+
expect(dlSpy).toHaveBeenCalledWith(url, undefined, undefined);
319319
});
320320
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}${osm.EOL}`);
321321
});
@@ -449,6 +449,54 @@ describe('setup-node', () => {
449449
}
450450
}, 100000);
451451

452+
it('acquires specified architecture of node from mirror', async () => {
453+
for (const {arch, version, osSpec} of [
454+
{
455+
arch: 'x86',
456+
version: '18.0.0-nightly202110204cb3e06ed8',
457+
osSpec: 'win32'
458+
},
459+
{
460+
arch: 'x86',
461+
version: '20.0.0-nightly2022101987cdf7d412',
462+
osSpec: 'win32'
463+
}
464+
]) {
465+
os.platform = osSpec;
466+
os.arch = arch;
467+
const fileExtension = os.platform === 'win32' ? '7z' : 'tar.gz';
468+
const platform = {
469+
linux: 'linux',
470+
darwin: 'darwin',
471+
win32: 'win'
472+
}[os.platform];
473+
474+
inputs['node-version'] = version;
475+
inputs['architecture'] = arch;
476+
inputs['always-auth'] = false;
477+
inputs['token'] = 'faketoken';
478+
inputs['mirror'] = 'https://my-mirror.org';
479+
inputs['mirror-token'] = 'my-mirror-token';
480+
481+
const expectedUrl = `https://my-mirror.org/download/nightly/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;
482+
483+
// ... but not in the local cache
484+
findSpy.mockImplementation(() => '');
485+
findAllVersionsSpy.mockImplementation(() => []);
486+
487+
dlSpy.mockImplementation(async () => '/some/temp/path');
488+
const toolPath = path.normalize(`/cache/node/${version}/${arch}`);
489+
exSpy.mockImplementation(async () => '/some/other/temp/path');
490+
cacheSpy.mockImplementation(async () => toolPath);
491+
492+
await main.run();
493+
expect(dlSpy).toHaveBeenCalled();
494+
expect(logSpy).toHaveBeenCalledWith(
495+
`Acquiring ${version} - ${arch} from ${expectedUrl}`
496+
);
497+
}
498+
}, 100000);
499+
452500
describe('nightly versions', () => {
453501
it.each([
454502
[

__tests__/official-installer.test.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,43 @@ describe('setup-node', () => {
282282
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
283283
});
284284

285+
it('falls back to a version from node dist from mirror', async () => {
286+
os.platform = 'linux';
287+
os.arch = 'x64';
288+
289+
// a version which is not in the manifest but is in node dist
290+
const versionSpec = '11.15.0';
291+
const mirror = 'https://my_mirror_url';
292+
inputs['node-version'] = versionSpec;
293+
inputs['always-auth'] = false;
294+
inputs['token'] = 'faketoken';
295+
inputs['mirror'] = mirror;
296+
inputs['mirror-token'] = 'faketoken';
297+
298+
// ... but not in the local cache
299+
findSpy.mockImplementation(() => '');
300+
301+
dlSpy.mockImplementation(async () => '/some/temp/path');
302+
const toolPath = path.normalize('/cache/node/11.15.0/x64');
303+
exSpy.mockImplementation(async () => '/some/other/temp/path');
304+
cacheSpy.mockImplementation(async () => toolPath);
305+
306+
await main.run();
307+
308+
const expPath = path.join(toolPath, 'bin');
309+
310+
expect(getManifestSpy).toHaveBeenCalled();
311+
expect(logSpy).toHaveBeenCalledWith(
312+
`Attempting to download ${versionSpec}...`
313+
);
314+
expect(logSpy).toHaveBeenCalledWith(
315+
`Not found in manifest. Falling back to download directly from ${mirror}`
316+
);
317+
expect(dlSpy).toHaveBeenCalled();
318+
expect(exSpy).toHaveBeenCalled();
319+
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
320+
});
321+
285322
it('falls back to a version from node dist', async () => {
286323
os.platform = 'linux';
287324
os.arch = 'x64';
@@ -828,4 +865,46 @@ describe('setup-node', () => {
828865
}
829866
);
830867
});
868+
869+
it('acquires specified architecture of node from mirror', async () => {
870+
for (const {arch, version, osSpec} of [
871+
{arch: 'x86', version: '12.16.2', osSpec: 'win32'},
872+
{arch: 'x86', version: '14.0.0', osSpec: 'win32'}
873+
]) {
874+
os.platform = osSpec;
875+
os.arch = arch;
876+
const fileExtension = os.platform === 'win32' ? '7z' : 'tar.gz';
877+
const platform = {
878+
linux: 'linux',
879+
darwin: 'darwin',
880+
win32: 'win'
881+
}[os.platform];
882+
883+
inputs['node-version'] = version;
884+
inputs['architecture'] = arch;
885+
inputs['always-auth'] = false;
886+
inputs['token'] = 'faketoken';
887+
inputs['mirror'] = 'https://my_mirror_url';
888+
inputs['mirror-token'] = 'faketoken';
889+
890+
const expectedUrl =
891+
arch === 'x64'
892+
? `https://github.com/actions/node-versions/releases/download/${version}/node-${version}-${platform}-${arch}.zip`
893+
: `https://my_mirror_url/dist/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;
894+
895+
// ... but not in the local cache
896+
findSpy.mockImplementation(() => '');
897+
898+
dlSpy.mockImplementation(async () => '/some/temp/path');
899+
const toolPath = path.normalize(`/cache/node/${version}/${arch}`);
900+
exSpy.mockImplementation(async () => '/some/other/temp/path');
901+
cacheSpy.mockImplementation(async () => toolPath);
902+
903+
await main.run();
904+
expect(dlSpy).toHaveBeenCalled();
905+
expect(logSpy).toHaveBeenCalledWith(
906+
`Acquiring ${version} - ${arch} from ${expectedUrl}`
907+
);
908+
}
909+
}, 100000);
831910
});

action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ inputs:
2525
description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.'
2626
cache-dependency-path:
2727
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.'
28+
mirror:
29+
description: 'Used to specify an alternative mirror to downlooad Node.js binaries from'
30+
mirror-token:
31+
description: 'The token used as Authorization header when fetching from the mirror'
2832
# TODO: add input to control forcing to pull from cloud or dist.
2933
# escape valve for someone having issues or needing the absolute latest which isn't cached yet
3034
outputs:

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy