mirror of
				https://github.com/actions/setup-node.git
				synced 2025-10-31 16:23:34 +00:00 
			
		
		
		
	feat: support private mirrors (#1240)
* feat: support private mirrors * chore: change fallback message with mirrors
This commit is contained in:
		
							parent
							
								
									40337cb8f7
								
							
						
					
					
						commit
						e3ce749e20
					
				
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								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 --> | ||||
| 
 | ||||
|  | ||||
| @ -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', () => { | ||||
|  | ||||
| @ -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([ | ||||
|       [ | ||||
|  | ||||
| @ -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); | ||||
| }); | ||||
|  | ||||
| @ -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: | ||||
|  | ||||
							
								
								
									
										54
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							| @ -97211,9 +97211,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 +97232,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 +97246,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 +97270,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 +97284,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 +97458,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 +97558,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 +97626,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 +97715,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 +97740,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 +97822,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 +97831,9 @@ function run() { | ||||
|                     checkLatest, | ||||
|                     auth, | ||||
|                     stable, | ||||
|                     arch | ||||
|                     arch, | ||||
|                     mirror, | ||||
|                     mirrorToken | ||||
|                 }; | ||||
|                 const nodeDistribution = (0, installer_factory_1.getNodejsDistribution)(nodejsInfo); | ||||
|                 yield nodeDistribution.setupNodeJs(); | ||||
|  | ||||
| @ -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' | ||||
| ``` | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -4,6 +4,8 @@ export interface NodeInputs { | ||||
|   auth?: string; | ||||
|   checkLatest: boolean; | ||||
|   stable: boolean; | ||||
|   mirror: string; | ||||
|   mirrorToken: string; | ||||
| } | ||||
| 
 | ||||
| export interface INodeVersionInfo { | ||||
|  | ||||
| @ -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`; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -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' | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| @ -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`; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -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`; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -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(); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user