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. |     # Set always-auth option in npmrc file. | ||||||
|     # Default: '' |     # Default: '' | ||||||
|     always-auth: '' |     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 --> | <!-- 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', () => { |   describe('setup-node v8 canary tests', () => { | ||||||
|  | |||||||
| @ -315,7 +315,7 @@ describe('setup-node', () => { | |||||||
|     await main.run(); |     await main.run(); | ||||||
| 
 | 
 | ||||||
|     workingUrls.forEach(url => { |     workingUrls.forEach(url => { | ||||||
|       expect(dlSpy).toHaveBeenCalledWith(url); |       expect(dlSpy).toHaveBeenCalledWith(url, undefined, undefined); | ||||||
|     }); |     }); | ||||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}${osm.EOL}`); |     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}${osm.EOL}`); | ||||||
|   }); |   }); | ||||||
| @ -449,6 +449,54 @@ describe('setup-node', () => { | |||||||
|     } |     } | ||||||
|   }, 100000); |   }, 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', () => { |   describe('nightly versions', () => { | ||||||
|     it.each([ |     it.each([ | ||||||
|       [ |       [ | ||||||
|  | |||||||
| @ -282,6 +282,43 @@ describe('setup-node', () => { | |||||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); |     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 () => { |   it('falls back to a version from node dist', async () => { | ||||||
|     os.platform = 'linux'; |     os.platform = 'linux'; | ||||||
|     os.arch = 'x64'; |     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.' |     description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.' | ||||||
|   cache-dependency-path: |   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.' |     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. | # 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 | #       escape valve for someone having issues or needing the absolute latest which isn't cached yet | ||||||
| outputs: | outputs: | ||||||
|  | |||||||
							
								
								
									
										54
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							| @ -97211,9 +97211,13 @@ class BaseDistribution { | |||||||
|     } |     } | ||||||
|     getNodeJsVersions() { |     getNodeJsVersions() { | ||||||
|         return __awaiter(this, void 0, void 0, function* () { |         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 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 || []; |             return response.result || []; | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| @ -97228,7 +97232,7 @@ class BaseDistribution { | |||||||
|                 ? `${fileName}.zip` |                 ? `${fileName}.zip` | ||||||
|                 : `${fileName}.7z` |                 : `${fileName}.7z` | ||||||
|             : `${fileName}.tar.gz`; |             : `${fileName}.tar.gz`; | ||||||
|         const initialUrl = this.getDistributionUrl(); |         const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror); | ||||||
|         const url = `${initialUrl}/v${version}/${urlFileName}`; |         const url = `${initialUrl}/v${version}/${urlFileName}`; | ||||||
|         return { |         return { | ||||||
|             downloadUrl: url, |             downloadUrl: url, | ||||||
| @ -97242,7 +97246,7 @@ class BaseDistribution { | |||||||
|             let downloadPath = ''; |             let downloadPath = ''; | ||||||
|             core.info(`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`); |             core.info(`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`); | ||||||
|             try { |             try { | ||||||
|                 downloadPath = yield tc.downloadTool(info.downloadUrl); |                 downloadPath = yield tc.downloadTool(info.downloadUrl, undefined, this.nodeInfo.mirrorToken); | ||||||
|             } |             } | ||||||
|             catch (err) { |             catch (err) { | ||||||
|                 if (err instanceof tc.HTTPError && |                 if (err instanceof tc.HTTPError && | ||||||
| @ -97266,7 +97270,7 @@ class BaseDistribution { | |||||||
|     } |     } | ||||||
|     acquireWindowsNodeFromFallbackLocation(version_1) { |     acquireWindowsNodeFromFallbackLocation(version_1) { | ||||||
|         return __awaiter(this, arguments, void 0, function* (version, arch = os_1.default.arch()) { |         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); |             const osArch = this.translateArchToDistUrl(arch); | ||||||
|             // Create temporary folder to download to
 |             // Create temporary folder to download to
 | ||||||
|             const tempDownloadFolder = `temp_${(0, uuid_1.v4)()}`; |             const tempDownloadFolder = `temp_${(0, uuid_1.v4)()}`; | ||||||
| @ -97280,18 +97284,18 @@ class BaseDistribution { | |||||||
|                 exeUrl = `${initialUrl}/v${version}/win-${osArch}/node.exe`; |                 exeUrl = `${initialUrl}/v${version}/win-${osArch}/node.exe`; | ||||||
|                 libUrl = `${initialUrl}/v${version}/win-${osArch}/node.lib`; |                 libUrl = `${initialUrl}/v${version}/win-${osArch}/node.lib`; | ||||||
|                 core.info(`Downloading only node binary from ${exeUrl}`); |                 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')); |                 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')); |                 yield io.cp(libPath, path.join(tempDir, 'node.lib')); | ||||||
|             } |             } | ||||||
|             catch (err) { |             catch (err) { | ||||||
|                 if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { |                 if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { | ||||||
|                     exeUrl = `${initialUrl}/v${version}/node.exe`; |                     exeUrl = `${initialUrl}/v${version}/node.exe`; | ||||||
|                     libUrl = `${initialUrl}/v${version}/node.lib`; |                     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')); |                     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')); |                     yield io.cp(libPath, path.join(tempDir, 'node.lib')); | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
| @ -97454,8 +97458,9 @@ class NightlyNodejs extends base_distribution_prerelease_1.default { | |||||||
|         super(nodeInfo); |         super(nodeInfo); | ||||||
|         this.distribution = 'nightly'; |         this.distribution = 'nightly'; | ||||||
|     } |     } | ||||||
|     getDistributionUrl() { |     getDistributionUrl(mirror) { | ||||||
|         return 'https://nodejs.org/download/nightly'; |         const url = mirror || 'https://nodejs.org'; | ||||||
|  |         return `${url}/download/nightly`; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| exports["default"] = NightlyNodejs; | 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); |                 const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, osArch, manifest); | ||||||
|                 if (versionInfo) { |                 if (versionInfo) { | ||||||
|                     core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`); |                     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) { |                     if (downloadPath) { | ||||||
|                         toolPath = yield this.extractArchive(downloadPath, versionInfo, false); |                         toolPath = yield this.extractArchive(downloadPath, versionInfo, false); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 else { |                 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) { |             catch (err) { | ||||||
| @ -97621,12 +97626,13 @@ class OfficialBuilds extends base_distribution_1.default { | |||||||
|         version = super.evaluateVersions(versions); |         version = super.evaluateVersions(versions); | ||||||
|         return version; |         return version; | ||||||
|     } |     } | ||||||
|     getDistributionUrl() { |     getDistributionUrl(mirror) { | ||||||
|         return `https://nodejs.org/dist`; |         const url = mirror || 'https://nodejs.org'; | ||||||
|  |         return `${url}/dist`; | ||||||
|     } |     } | ||||||
|     getManifest() { |     getManifest() { | ||||||
|         core.debug('Getting manifest from actions/node-versions@main'); |         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) { |     resolveLtsAliasFromManifest(versionSpec, stable, manifest) { | ||||||
|         var _a; |         var _a; | ||||||
| @ -97709,8 +97715,9 @@ class RcBuild extends base_distribution_1.default { | |||||||
|     constructor(nodeInfo) { |     constructor(nodeInfo) { | ||||||
|         super(nodeInfo); |         super(nodeInfo); | ||||||
|     } |     } | ||||||
|     getDistributionUrl() { |     getDistributionUrl(mirror) { | ||||||
|         return 'https://nodejs.org/download/rc'; |         const url = mirror || 'https://nodejs.org'; | ||||||
|  |         return `${url}/download/rc`; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| exports["default"] = RcBuild; | exports["default"] = RcBuild; | ||||||
| @ -97733,8 +97740,9 @@ class CanaryBuild extends base_distribution_prerelease_1.default { | |||||||
|         super(nodeInfo); |         super(nodeInfo); | ||||||
|         this.distribution = 'v8-canary'; |         this.distribution = 'v8-canary'; | ||||||
|     } |     } | ||||||
|     getDistributionUrl() { |     getDistributionUrl(mirror) { | ||||||
|         return 'https://nodejs.org/download/v8-canary'; |         const url = mirror || 'https://nodejs.org'; | ||||||
|  |         return `${url}/download/v8-canary`; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| exports["default"] = CanaryBuild; | exports["default"] = CanaryBuild; | ||||||
| @ -97814,6 +97822,8 @@ function run() { | |||||||
|             if (version) { |             if (version) { | ||||||
|                 const token = core.getInput('token'); |                 const token = core.getInput('token'); | ||||||
|                 const auth = !token ? undefined : `token ${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 stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; | ||||||
|                 const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; |                 const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; | ||||||
|                 const nodejsInfo = { |                 const nodejsInfo = { | ||||||
| @ -97821,7 +97831,9 @@ function run() { | |||||||
|                     checkLatest, |                     checkLatest, | ||||||
|                     auth, |                     auth, | ||||||
|                     stable, |                     stable, | ||||||
|                     arch |                     arch, | ||||||
|  |                     mirror, | ||||||
|  |                     mirrorToken | ||||||
|                 }; |                 }; | ||||||
|                 const nodeDistribution = (0, installer_factory_1.getNodejsDistribution)(nodejsInfo); |                 const nodeDistribution = (0, installer_factory_1.getNodejsDistribution)(nodejsInfo); | ||||||
|                 yield nodeDistribution.setupNodeJs(); |                 yield nodeDistribution.setupNodeJs(); | ||||||
|  | |||||||
| @ -418,3 +418,18 @@ Please refer to the [Ensuring workflow access to your package - Configuring a pa | |||||||
| 
 | 
 | ||||||
| ### always-auth input | ### 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. | 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() { |   public async setupNodeJs() { | ||||||
|     let nodeJsVersions: INodeVersion[] | undefined; |     let nodeJsVersions: INodeVersion[] | undefined; | ||||||
| @ -97,10 +97,19 @@ export default abstract class BaseDistribution { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   protected async getNodeJsVersions(): Promise<INodeVersion[]> { |   protected async getNodeJsVersions(): Promise<INodeVersion[]> { | ||||||
|     const initialUrl = this.getDistributionUrl(); |     const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror); | ||||||
|     const dataUrl = `${initialUrl}/index.json`; |     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 || []; |     return response.result || []; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -117,7 +126,7 @@ export default abstract class BaseDistribution { | |||||||
|           ? `${fileName}.zip` |           ? `${fileName}.zip` | ||||||
|           : `${fileName}.7z` |           : `${fileName}.7z` | ||||||
|         : `${fileName}.tar.gz`; |         : `${fileName}.tar.gz`; | ||||||
|     const initialUrl = this.getDistributionUrl(); |     const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror); | ||||||
|     const url = `${initialUrl}/v${version}/${urlFileName}`; |     const url = `${initialUrl}/v${version}/${urlFileName}`; | ||||||
| 
 | 
 | ||||||
|     return <INodeVersionInfo>{ |     return <INodeVersionInfo>{ | ||||||
| @ -134,7 +143,11 @@ export default abstract class BaseDistribution { | |||||||
|       `Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}` |       `Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}` | ||||||
|     ); |     ); | ||||||
|     try { |     try { | ||||||
|       downloadPath = await tc.downloadTool(info.downloadUrl); |       downloadPath = await tc.downloadTool( | ||||||
|  |         info.downloadUrl, | ||||||
|  |         undefined, | ||||||
|  |         this.nodeInfo.mirrorToken | ||||||
|  |       ); | ||||||
|     } catch (err) { |     } catch (err) { | ||||||
|       if ( |       if ( | ||||||
|         err instanceof tc.HTTPError && |         err instanceof tc.HTTPError && | ||||||
| @ -168,7 +181,7 @@ export default abstract class BaseDistribution { | |||||||
|     version: string, |     version: string, | ||||||
|     arch: string = os.arch() |     arch: string = os.arch() | ||||||
|   ): Promise<string> { |   ): Promise<string> { | ||||||
|     const initialUrl = this.getDistributionUrl(); |     const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror); | ||||||
|     const osArch: string = this.translateArchToDistUrl(arch); |     const osArch: string = this.translateArchToDistUrl(arch); | ||||||
| 
 | 
 | ||||||
|     // Create temporary folder to download to
 |     // Create temporary folder to download to
 | ||||||
| @ -185,18 +198,34 @@ export default abstract class BaseDistribution { | |||||||
| 
 | 
 | ||||||
|       core.info(`Downloading only node binary from ${exeUrl}`); |       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')); |       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')); |       await io.cp(libPath, path.join(tempDir, 'node.lib')); | ||||||
|     } catch (err) { |     } catch (err) { | ||||||
|       if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { |       if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { | ||||||
|         exeUrl = `${initialUrl}/v${version}/node.exe`; |         exeUrl = `${initialUrl}/v${version}/node.exe`; | ||||||
|         libUrl = `${initialUrl}/v${version}/node.lib`; |         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')); |         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')); |         await io.cp(libPath, path.join(tempDir, 'node.lib')); | ||||||
|       } else { |       } else { | ||||||
|         throw err; |         throw err; | ||||||
|  | |||||||
| @ -4,6 +4,8 @@ export interface NodeInputs { | |||||||
|   auth?: string; |   auth?: string; | ||||||
|   checkLatest: boolean; |   checkLatest: boolean; | ||||||
|   stable: boolean; |   stable: boolean; | ||||||
|  |   mirror: string; | ||||||
|  |   mirrorToken: string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface INodeVersionInfo { | export interface INodeVersionInfo { | ||||||
|  | |||||||
| @ -7,7 +7,8 @@ export default class NightlyNodejs extends BasePrereleaseNodejs { | |||||||
|     super(nodeInfo); |     super(nodeInfo); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   protected getDistributionUrl(): string { |   protected getDistributionUrl(mirror: string): string { | ||||||
|     return 'https://nodejs.org/download/nightly'; |     const url = mirror || 'https://nodejs.org'; | ||||||
|  |     return `${url}/download/nightly`; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -84,7 +84,7 @@ export default class OfficialBuilds extends BaseDistribution { | |||||||
|         downloadPath = await tc.downloadTool( |         downloadPath = await tc.downloadTool( | ||||||
|           versionInfo.downloadUrl, |           versionInfo.downloadUrl, | ||||||
|           undefined, |           undefined, | ||||||
|           this.nodeInfo.auth |           this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         if (downloadPath) { |         if (downloadPath) { | ||||||
| @ -96,7 +96,9 @@ export default class OfficialBuilds extends BaseDistribution { | |||||||
|         } |         } | ||||||
|       } else { |       } else { | ||||||
|         core.info( |         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) { |     } catch (err) { | ||||||
| @ -176,8 +178,9 @@ export default class OfficialBuilds extends BaseDistribution { | |||||||
|     return version; |     return version; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   protected getDistributionUrl(): string { |   protected getDistributionUrl(mirror: string): string { | ||||||
|     return `https://nodejs.org/dist`; |     const url = mirror || 'https://nodejs.org'; | ||||||
|  |     return `${url}/dist`; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private getManifest(): Promise<tc.IToolRelease[]> { |   private getManifest(): Promise<tc.IToolRelease[]> { | ||||||
| @ -185,7 +188,7 @@ export default class OfficialBuilds extends BaseDistribution { | |||||||
|     return tc.getManifestFromRepo( |     return tc.getManifestFromRepo( | ||||||
|       'actions', |       'actions', | ||||||
|       'node-versions', |       'node-versions', | ||||||
|       this.nodeInfo.auth, |       this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth, | ||||||
|       'main' |       'main' | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -6,7 +6,8 @@ export default class RcBuild extends BaseDistribution { | |||||||
|     super(nodeInfo); |     super(nodeInfo); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   getDistributionUrl(): string { |   getDistributionUrl(mirror: string): string { | ||||||
|     return 'https://nodejs.org/download/rc'; |     const url = mirror || 'https://nodejs.org'; | ||||||
|  |     return `${url}/download/rc`; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -7,7 +7,8 @@ export default class CanaryBuild extends BasePrereleaseNodejs { | |||||||
|     super(nodeInfo); |     super(nodeInfo); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   protected getDistributionUrl(): string { |   protected getDistributionUrl(mirror: string): string { | ||||||
|     return 'https://nodejs.org/download/v8-canary'; |     const url = mirror || 'https://nodejs.org'; | ||||||
|  |     return `${url}/download/v8-canary`; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -36,6 +36,8 @@ export async function run() { | |||||||
|     if (version) { |     if (version) { | ||||||
|       const token = core.getInput('token'); |       const token = core.getInput('token'); | ||||||
|       const auth = !token ? undefined : `token ${token}`; |       const auth = !token ? undefined : `token ${token}`; | ||||||
|  |       const mirror = core.getInput('mirror'); | ||||||
|  |       const mirrorToken = core.getInput('mirror-token'); | ||||||
|       const stable = |       const stable = | ||||||
|         (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; |         (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; | ||||||
|       const checkLatest = |       const checkLatest = | ||||||
| @ -45,7 +47,9 @@ export async function run() { | |||||||
|         checkLatest, |         checkLatest, | ||||||
|         auth, |         auth, | ||||||
|         stable, |         stable, | ||||||
|         arch |         arch, | ||||||
|  |         mirror, | ||||||
|  |         mirrorToken | ||||||
|       }; |       }; | ||||||
|       const nodeDistribution = getNodejsDistribution(nodejsInfo); |       const nodeDistribution = getNodejsDistribution(nodejsInfo); | ||||||
|       await nodeDistribution.setupNodeJs(); |       await nodeDistribution.setupNodeJs(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user