mirror of
				https://gitea.com/actions/setup-node.git
				synced 2025-10-29 15:52:42 +08:00 
			
		
		
		
	wip
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -2,6 +2,9 @@ node_modules/ | ||||
| lib/ | ||||
| __tests__/runner/* | ||||
|  | ||||
| validate/temp | ||||
| validate/node | ||||
|  | ||||
| # Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore | ||||
| # Logs | ||||
| logs | ||||
|   | ||||
							
								
								
									
										10
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								action.yml
									
									
									
									
									
								
							| @@ -1,17 +1,21 @@ | ||||
| name: 'Setup Node.js environment' | ||||
| description: 'Setup a Node.js environment and add it to the PATH, additionally providing proxy support' | ||||
| description: 'Setup a Node.js environment by adding problem matchers and optionally downloading and adding it to the PATH' | ||||
| author: 'GitHub' | ||||
| inputs: | ||||
|   always-auth: | ||||
|     description: 'Set always-auth in npmrc' | ||||
|     default: 'false' | ||||
|   node-version: | ||||
|     description: 'Version Spec of the version to use.  Examples: 10.x, 10.15.1, >=10.15.0' | ||||
|     default: '10.x' | ||||
|     description: 'Version Spec of the version to use.  Examples: 12.x, 10.15.1, >=10.15.0' | ||||
|   registry-url: | ||||
|     description: 'Optional registry to set up for auth. Will set the registry in a project level .npmrc and .yarnrc file, and set up auth to read in from env.NODE_AUTH_TOKEN' | ||||
|   scope: | ||||
|     description: 'Optional scope for authenticating against scoped registries' | ||||
|   token: | ||||
|     description: Used to pull node distributions from node-versions.  Since there's a default, this is typically not supplied by the user. | ||||
|     default: ${{ github.token }} | ||||
| # 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 | ||||
| # Deprecated option, do not use. Will not be supported after October 1, 2019 | ||||
|   version: | ||||
|     description: 'Deprecated. Use node-version instead. Will not be supported after October 1, 2019' | ||||
|   | ||||
							
								
								
									
										1066
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1066
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										20
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										20
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "setup-node", | ||||
|   "version": "1.0.0", | ||||
|   "version": "2.0.0", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
| @@ -40,16 +40,26 @@ | ||||
|       "integrity": "sha512-J8KuFqVPr3p6U8W93DOXlXW6zFvrQAJANdS+vw0YhusLIq+bszW8zmK2Fh1C2kDPX8FMvwIl1OUcFgvJoXLbAg==" | ||||
|     }, | ||||
|     "@actions/tool-cache": { | ||||
|       "version": "1.3.3", | ||||
|       "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.3.3.tgz", | ||||
|       "integrity": "sha512-AFVyTLcIxusDVI1gMhbZW8m/On7YNJG+xYaxorV+qic+f7lO7h37aT2mfzxqAq7mwHxtP1YlVFNrXe9QDf/bPg==", | ||||
|       "version": "1.5.2", | ||||
|       "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.5.2.tgz", | ||||
|       "integrity": "sha512-40A1St0GEo+QvHV1YRjStEoQcKKMaip+zNXPgGHcjYXCdZ7cl1LGlwOpsVVqwk+6ue/shFTS76KC1A02mVVCQA==", | ||||
|       "requires": { | ||||
|         "@actions/core": "^1.2.0", | ||||
|         "@actions/exec": "^1.0.0", | ||||
|         "@actions/http-client": "^1.0.3", | ||||
|         "@actions/http-client": "^1.0.8", | ||||
|         "@actions/io": "^1.0.1", | ||||
|         "semver": "^6.1.0", | ||||
|         "uuid": "^3.3.2" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "@actions/http-client": { | ||||
|           "version": "1.0.8", | ||||
|           "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz", | ||||
|           "integrity": "sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==", | ||||
|           "requires": { | ||||
|             "tunnel": "0.0.6" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "@babel/code-frame": { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "setup-node", | ||||
|   "version": "1.0.0", | ||||
|   "version": "2.0.0", | ||||
|   "private": true, | ||||
|   "description": "setup node action", | ||||
|   "main": "lib/setup-node.js", | ||||
| @@ -27,7 +27,7 @@ | ||||
|     "@actions/github": "^1.1.0", | ||||
|     "@actions/http-client": "^1.0.6", | ||||
|     "@actions/io": "^1.0.2", | ||||
|     "@actions/tool-cache": "^1.3.3", | ||||
|     "@actions/tool-cache": "^1.5.2", | ||||
|     "semver": "^6.1.1" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|   | ||||
							
								
								
									
										222
									
								
								src/installer.ts
									
									
									
									
									
								
							
							
						
						
									
										222
									
								
								src/installer.ts
									
									
									
									
									
								
							| @@ -6,6 +6,7 @@ import * as tc from '@actions/tool-cache'; | ||||
| import * as os from 'os'; | ||||
| import * as path from 'path'; | ||||
| import * as semver from 'semver'; | ||||
| import { Url } from 'url'; | ||||
|  | ||||
| let osPlat: string = os.platform(); | ||||
| let osArch: string = translateArchToDistUrl(os.arch()); | ||||
| @@ -19,36 +20,64 @@ interface INodeVersion { | ||||
|   files: string[]; | ||||
| } | ||||
|  | ||||
| export async function getNode(versionSpec: string) { | ||||
| interface INodeVersionInfo { | ||||
|   downloadUrl: string; | ||||
|   token: string | null; | ||||
|   resolvedVersion: string; | ||||
|   fileName: string; | ||||
| } | ||||
|  | ||||
| export async function getNode(versionSpec: string, stable: boolean, token: string) { | ||||
|   // check cache | ||||
|   let info: INodeVersionInfo | null = null; | ||||
|   let toolPath: string; | ||||
|   toolPath = tc.find('node', versionSpec); | ||||
|  | ||||
|   // If not found in cache, download | ||||
|   if (!toolPath) { | ||||
|     let version: string; | ||||
|     const c = semver.clean(versionSpec) || ''; | ||||
|     // If explicit version | ||||
|     if (semver.valid(c) != null) { | ||||
|       // version to download | ||||
|       version = versionSpec; | ||||
|     } else { | ||||
|       // query nodejs.org for a matching version | ||||
|       version = await queryLatestMatch(versionSpec); | ||||
|       if (!version) { | ||||
|         throw new Error( | ||||
|           `Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.` | ||||
|         ); | ||||
|   if (toolPath) { | ||||
|     console.log(`Found in cache @ ${toolPath}`); | ||||
|   } else { | ||||
|     console.log(`Attempting to download ${versionSpec}...`) | ||||
|     let info = await getInfoFromManifest(versionSpec, stable, token); | ||||
|     if (!info) { | ||||
|       console.log('Not found in manifest.  Falling back to download directly from Node') | ||||
|       info = await getInfoFromDist(versionSpec); | ||||
|     }    | ||||
|    | ||||
|     if (!info) { | ||||
|       throw new Error( | ||||
|         `Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.` | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     console.log(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`); | ||||
|  | ||||
|     let downloadPath = "" | ||||
|     try { | ||||
|       downloadPath = await tc.downloadTool(info.downloadUrl, undefined, token); | ||||
|     } catch (err) { | ||||
|       if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { | ||||
|         return await acquireNodeFromFallbackLocation(info.resolvedVersion); | ||||
|       } | ||||
|  | ||||
|       // check cache | ||||
|       toolPath = tc.find('node', version); | ||||
|       throw err; | ||||
|     } | ||||
|  | ||||
|     if (!toolPath) { | ||||
|       // download, extract, cache | ||||
|       toolPath = await acquireNode(version); | ||||
|     // | ||||
|     // Extract | ||||
|     // | ||||
|     let extPath: string; | ||||
|     if (osPlat == 'win32') { | ||||
|       let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe'); | ||||
|       extPath = await tc.extract7z(downloadPath, undefined, _7zPath); | ||||
|     } else { | ||||
|       extPath = await tc.extractTar(downloadPath); | ||||
|     } | ||||
|  | ||||
|     // | ||||
|     // Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded | ||||
|     // | ||||
|     toolPath = await tc.cacheDir(extPath, 'node', info.resolvedVersion);     | ||||
|   } | ||||
|  | ||||
|   // | ||||
| @@ -65,7 +94,87 @@ export async function getNode(versionSpec: string) { | ||||
|   core.addPath(toolPath); | ||||
| } | ||||
|  | ||||
| async function queryLatestMatch(versionSpec: string): Promise<string> { | ||||
| async function getInfoFromManifest(versionSpec: string, stable: boolean, token: string): Promise<INodeVersionInfo | null> { | ||||
|   let info: INodeVersionInfo | null = null; | ||||
|   const releases = await tc.getManifestFromRepo("actions", "node-versions", token) | ||||
|   console.log(`matching ${versionSpec}...`) | ||||
|   const rel = await tc.findFromManifest(versionSpec, stable, releases); | ||||
|    | ||||
|   if (rel && rel.files.length > 0) { | ||||
|     info = <INodeVersionInfo>{}; | ||||
|     info.resolvedVersion = rel.version; | ||||
|     info.downloadUrl = rel.files[0].download_url; | ||||
|     info.fileName = rel.files[0].filename; | ||||
|     info.token = token; | ||||
|   } | ||||
|  | ||||
|   return info; | ||||
| } | ||||
|  | ||||
| async function getInfoFromDist(versionSpec: string): Promise<INodeVersionInfo | null> { | ||||
|   let info: INodeVersionInfo | null = null; | ||||
|   let version: string; | ||||
|    | ||||
|   // If explicit version don't query | ||||
|   if (semver.clean(versionSpec) != null) { | ||||
|     // version to download | ||||
|     version = versionSpec; | ||||
|   } else { | ||||
|     // query nodejs.org for a matching version | ||||
|     version = await queryDistForMatch(versionSpec); | ||||
|     if (!version) { | ||||
|       return null; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // | ||||
|   // Download - a tool installer intimately knows how to get the tool (and construct urls) | ||||
|   // | ||||
|   version = semver.clean(version) || ''; | ||||
|   let fileName: string = | ||||
|     osPlat == 'win32' | ||||
|       ? `node-v${version}-win-${osArch}` | ||||
|       : `node-v${version}-${osPlat}-${osArch}`; | ||||
|   let urlFileName: string = | ||||
|     osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; | ||||
|   let url = `https://nodejs.org/dist/v${version}/${urlFileName}`; | ||||
|  | ||||
|   return <INodeVersionInfo>{ | ||||
|     downloadUrl: url, | ||||
|     resolvedVersion: version, | ||||
|     fileName: fileName | ||||
|   } | ||||
| } | ||||
|  | ||||
| // TODO - should we just export this from @actions/tool-cache? Lifted directly from there | ||||
| function evaluateVersions(versions: string[], versionSpec: string): string { | ||||
|   let version = ''; | ||||
|   core.debug(`evaluating ${versions.length} versions`); | ||||
|   versions = versions.sort((a, b) => { | ||||
|     if (semver.gt(a, b)) { | ||||
|       return 1; | ||||
|     } | ||||
|     return -1; | ||||
|   }); | ||||
|   for (let i = versions.length - 1; i >= 0; i--) { | ||||
|     const potential: string = versions[i]; | ||||
|     const satisfied: boolean = semver.satisfies(potential, versionSpec); | ||||
|     if (satisfied) { | ||||
|       version = potential; | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (version) { | ||||
|     core.debug(`matched: ${version}`); | ||||
|   } else { | ||||
|     core.debug('match not found'); | ||||
|   } | ||||
|  | ||||
|   return version; | ||||
| } | ||||
|  | ||||
| async function queryDistForMatch(versionSpec: string): Promise<string> { | ||||
|   // node offers a json list of versions | ||||
|   let dataFileName: string; | ||||
|   switch (osPlat) { | ||||
| @@ -102,77 +211,6 @@ async function queryLatestMatch(versionSpec: string): Promise<string> { | ||||
|   return version; | ||||
| } | ||||
|  | ||||
| // TODO - should we just export this from @actions/tool-cache? Lifted directly from there | ||||
| function evaluateVersions(versions: string[], versionSpec: string): string { | ||||
|   let version = ''; | ||||
|   core.debug(`evaluating ${versions.length} versions`); | ||||
|   versions = versions.sort((a, b) => { | ||||
|     if (semver.gt(a, b)) { | ||||
|       return 1; | ||||
|     } | ||||
|     return -1; | ||||
|   }); | ||||
|   for (let i = versions.length - 1; i >= 0; i--) { | ||||
|     const potential: string = versions[i]; | ||||
|     const satisfied: boolean = semver.satisfies(potential, versionSpec); | ||||
|     if (satisfied) { | ||||
|       version = potential; | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (version) { | ||||
|     core.debug(`matched: ${version}`); | ||||
|   } else { | ||||
|     core.debug('match not found'); | ||||
|   } | ||||
|  | ||||
|   return version; | ||||
| } | ||||
|  | ||||
| async function acquireNode(version: string): Promise<string> { | ||||
|   // | ||||
|   // Download - a tool installer intimately knows how to get the tool (and construct urls) | ||||
|   // | ||||
|   version = semver.clean(version) || ''; | ||||
|   let fileName: string = | ||||
|     osPlat == 'win32' | ||||
|       ? `node-v${version}-win-${osArch}` | ||||
|       : `node-v${version}-${osPlat}-${osArch}`; | ||||
|   let urlFileName: string = | ||||
|     osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; | ||||
|   let downloadUrl = `https://nodejs.org/dist/v${version}/${urlFileName}`; | ||||
|  | ||||
|   let downloadPath: string; | ||||
|  | ||||
|   try { | ||||
|     downloadPath = await tc.downloadTool(downloadUrl); | ||||
|   } catch (err) { | ||||
|     if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { | ||||
|       return await acquireNodeFromFallbackLocation(version); | ||||
|     } | ||||
|  | ||||
|     throw err; | ||||
|   } | ||||
|  | ||||
|   // | ||||
|   // Extract | ||||
|   // | ||||
|   let extPath: string; | ||||
|   if (osPlat == 'win32') { | ||||
|     let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe'); | ||||
|     extPath = await tc.extract7z(downloadPath, undefined, _7zPath); | ||||
|   } else { | ||||
|     extPath = await tc.extractTar(downloadPath); | ||||
|   } | ||||
|  | ||||
|   // | ||||
|   // Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded | ||||
|   // | ||||
|   let toolRoot = path.join(extPath, fileName); | ||||
|   return await tc.cacheDir(toolRoot, 'node', version); | ||||
| } | ||||
|  | ||||
| // For non LTS versions of Node, the files we need (for Windows) are sometimes located | ||||
| // in a different folder than they normally are for other versions. | ||||
| // Normally the format is similar to: https://nodejs.org/dist/v5.10.1/node-v5.10.1-win-x64.7z | ||||
|   | ||||
| @@ -9,12 +9,16 @@ async function run() { | ||||
|     // Version is optional.  If supplied, install / use from the tool cache | ||||
|     // If not supplied then task is still used to setup proxy, auth, etc... | ||||
|     // | ||||
|     let version = core.getInput('version'); | ||||
|     let version = core.getInput('node-version'); | ||||
|     if (!version) { | ||||
|       version = core.getInput('node-version'); | ||||
|       version = core.getInput('version');   | ||||
|     } | ||||
|  | ||||
|     console.log(`version: ${version}`); | ||||
|     if (version) { | ||||
|       await installer.getNode(version); | ||||
|       let token = core.getInput('token'); | ||||
|       let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; | ||||
|       await installer.getNode(version, stable, token); | ||||
|     } | ||||
|  | ||||
|     const registryUrl: string = core.getInput('registry-url'); | ||||
|   | ||||
							
								
								
									
										22
									
								
								validate/test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								validate/test.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,22 @@ | ||||
|  | ||||
| #/bin/bash | ||||
|  | ||||
| set -e | ||||
|  | ||||
| rm -rf ./temp | ||||
| rm -rf ./node | ||||
|  | ||||
| # uncomment to use charles proxy or other debugging proxy | ||||
| # export NODE_TLS_REJECT_UNAUTHORIZED=0 | ||||
| # export https_proxy=http://127.0.0.1:8888 | ||||
|  | ||||
| export RUNNER_TOOL_CACHE=$(pwd) | ||||
| export RUNNER_TEMP="${RUNNER_TOOL_CACHE}/temp" | ||||
| export INPUT_STABLE=true | ||||
| export INPUT_VERSION="12.x" | ||||
| # export your PAT with repo scope before running | ||||
| export INPUT_TOKEN=$GITHUB_TOKEN | ||||
|  | ||||
| echo "Getting ${INPUT_VERSION} ($INPUT_STABLE) with ${INPUT_TOKEN}..." | ||||
|  | ||||
| node ../dist/index.js | ||||
		Reference in New Issue
	
	Block a user