mirror of
				https://gitea.com/actions/setup-node.git
				synced 2025-10-31 07:47:14 +00:00 
			
		
		
		
	wip
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -2,6 +2,9 @@ node_modules/ | |||||||
| lib/ | lib/ | ||||||
| __tests__/runner/* | __tests__/runner/* | ||||||
|  |  | ||||||
|  | validate/temp | ||||||
|  | validate/node | ||||||
|  |  | ||||||
| # Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore | # Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore | ||||||
| # Logs | # Logs | ||||||
| logs | logs | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								action.yml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								action.yml
									
									
									
									
									
								
							| @@ -1,17 +1,21 @@ | |||||||
| name: 'Setup Node.js environment' | 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' | author: 'GitHub' | ||||||
| inputs: | inputs: | ||||||
|   always-auth: |   always-auth: | ||||||
|     description: 'Set always-auth in npmrc' |     description: 'Set always-auth in npmrc' | ||||||
|     default: 'false' |     default: 'false' | ||||||
|   node-version: |   node-version: | ||||||
|     description: 'Version Spec of the version to use.  Examples: 10.x, 10.15.1, >=10.15.0' |     description: 'Version Spec of the version to use.  Examples: 12.x, 10.15.1, >=10.15.0' | ||||||
|     default: '10.x' |  | ||||||
|   registry-url: |   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' |     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: |   scope: | ||||||
|     description: 'Optional scope for authenticating against scoped registries' |     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 | # Deprecated option, do not use. Will not be supported after October 1, 2019 | ||||||
|   version: |   version: | ||||||
|     description: 'Deprecated. Use node-version instead. Will not be supported after October 1, 2019' |     description: 'Deprecated. Use node-version instead. Will not be supported after October 1, 2019' | ||||||
|   | |||||||
							
								
								
									
										1060
									
								
								dist/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1060
									
								
								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", |   "name": "setup-node", | ||||||
|   "version": "1.0.0", |   "version": "2.0.0", | ||||||
|   "lockfileVersion": 1, |   "lockfileVersion": 1, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
| @@ -40,16 +40,26 @@ | |||||||
|       "integrity": "sha512-J8KuFqVPr3p6U8W93DOXlXW6zFvrQAJANdS+vw0YhusLIq+bszW8zmK2Fh1C2kDPX8FMvwIl1OUcFgvJoXLbAg==" |       "integrity": "sha512-J8KuFqVPr3p6U8W93DOXlXW6zFvrQAJANdS+vw0YhusLIq+bszW8zmK2Fh1C2kDPX8FMvwIl1OUcFgvJoXLbAg==" | ||||||
|     }, |     }, | ||||||
|     "@actions/tool-cache": { |     "@actions/tool-cache": { | ||||||
|       "version": "1.3.3", |       "version": "1.5.2", | ||||||
|       "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.3.3.tgz", |       "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.5.2.tgz", | ||||||
|       "integrity": "sha512-AFVyTLcIxusDVI1gMhbZW8m/On7YNJG+xYaxorV+qic+f7lO7h37aT2mfzxqAq7mwHxtP1YlVFNrXe9QDf/bPg==", |       "integrity": "sha512-40A1St0GEo+QvHV1YRjStEoQcKKMaip+zNXPgGHcjYXCdZ7cl1LGlwOpsVVqwk+6ue/shFTS76KC1A02mVVCQA==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@actions/core": "^1.2.0", |         "@actions/core": "^1.2.0", | ||||||
|         "@actions/exec": "^1.0.0", |         "@actions/exec": "^1.0.0", | ||||||
|         "@actions/http-client": "^1.0.3", |         "@actions/http-client": "^1.0.8", | ||||||
|         "@actions/io": "^1.0.1", |         "@actions/io": "^1.0.1", | ||||||
|         "semver": "^6.1.0", |         "semver": "^6.1.0", | ||||||
|         "uuid": "^3.3.2" |         "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": { |     "@babel/code-frame": { | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "setup-node", |   "name": "setup-node", | ||||||
|   "version": "1.0.0", |   "version": "2.0.0", | ||||||
|   "private": true, |   "private": true, | ||||||
|   "description": "setup node action", |   "description": "setup node action", | ||||||
|   "main": "lib/setup-node.js", |   "main": "lib/setup-node.js", | ||||||
| @@ -27,7 +27,7 @@ | |||||||
|     "@actions/github": "^1.1.0", |     "@actions/github": "^1.1.0", | ||||||
|     "@actions/http-client": "^1.0.6", |     "@actions/http-client": "^1.0.6", | ||||||
|     "@actions/io": "^1.0.2", |     "@actions/io": "^1.0.2", | ||||||
|     "@actions/tool-cache": "^1.3.3", |     "@actions/tool-cache": "^1.5.2", | ||||||
|     "semver": "^6.1.1" |     "semver": "^6.1.1" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|   | |||||||
							
								
								
									
										214
									
								
								src/installer.ts
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								src/installer.ts
									
									
									
									
									
								
							| @@ -6,6 +6,7 @@ import * as tc from '@actions/tool-cache'; | |||||||
| import * as os from 'os'; | import * as os from 'os'; | ||||||
| import * as path from 'path'; | import * as path from 'path'; | ||||||
| import * as semver from 'semver'; | import * as semver from 'semver'; | ||||||
|  | import { Url } from 'url'; | ||||||
|  |  | ||||||
| let osPlat: string = os.platform(); | let osPlat: string = os.platform(); | ||||||
| let osArch: string = translateArchToDistUrl(os.arch()); | let osArch: string = translateArchToDistUrl(os.arch()); | ||||||
| @@ -19,36 +20,64 @@ interface INodeVersion { | |||||||
|   files: string[]; |   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 |   // check cache | ||||||
|  |   let info: INodeVersionInfo | null = null; | ||||||
|   let toolPath: string; |   let toolPath: string; | ||||||
|   toolPath = tc.find('node', versionSpec); |   toolPath = tc.find('node', versionSpec); | ||||||
|  |  | ||||||
|   // If not found in cache, download |   // If not found in cache, download | ||||||
|   if (!toolPath) { |   if (toolPath) { | ||||||
|     let version: string; |     console.log(`Found in cache @ ${toolPath}`); | ||||||
|     const c = semver.clean(versionSpec) || ''; |  | ||||||
|     // If explicit version |  | ||||||
|     if (semver.valid(c) != null) { |  | ||||||
|       // version to download |  | ||||||
|       version = versionSpec; |  | ||||||
|   } else { |   } else { | ||||||
|       // query nodejs.org for a matching version |     console.log(`Attempting to download ${versionSpec}...`) | ||||||
|       version = await queryLatestMatch(versionSpec); |     let info = await getInfoFromManifest(versionSpec, stable, token); | ||||||
|       if (!version) { |     if (!info) { | ||||||
|  |       console.log('Not found in manifest.  Falling back to download directly from Node') | ||||||
|  |       info = await getInfoFromDist(versionSpec); | ||||||
|  |     }    | ||||||
|  |    | ||||||
|  |     if (!info) { | ||||||
|       throw new Error( |       throw new Error( | ||||||
|         `Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.` |         `Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.` | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|       // check cache |     console.log(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`); | ||||||
|       toolPath = tc.find('node', version); |  | ||||||
|  |     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); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|     if (!toolPath) { |       throw err; | ||||||
|       // 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); |   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 |   // node offers a json list of versions | ||||||
|   let dataFileName: string; |   let dataFileName: string; | ||||||
|   switch (osPlat) { |   switch (osPlat) { | ||||||
| @@ -102,77 +211,6 @@ async function queryLatestMatch(versionSpec: string): Promise<string> { | |||||||
|   return version; |   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 | // 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. | // 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 | // 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 |     // Version is optional.  If supplied, install / use from the tool cache | ||||||
|     // If not supplied then task is still used to setup proxy, auth, etc... |     // 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) { |     if (!version) { | ||||||
|       version = core.getInput('node-version'); |       version = core.getInput('version');   | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     console.log(`version: ${version}`); | ||||||
|     if (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'); |     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
	 Bryan MacFarlane
					Bryan MacFarlane