mirror of
				https://github.com/actions/setup-node.git
				synced 2025-10-31 16:14:00 +08:00 
			
		
		
		
	Adding Node.js version file support (#338)
This commit is contained in:
		
							
								
								
									
										15
									
								
								.github/workflows/versions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/versions.yml
									
									
									
									
										vendored
									
									
								
							| @@ -78,6 +78,21 @@ jobs: | ||||
|         run: __tests__/verify-node.sh "${{ matrix.node-version }}" | ||||
|         shell: bash | ||||
|  | ||||
|   version-file: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: [ubuntu-latest, windows-latest, macos-latest] | ||||
|     steps: | ||||
|       - uses: actions/checkout@v2 | ||||
|       - name: Setup node from node version file | ||||
|         uses: ./ | ||||
|         with: | ||||
|           node-version-file: '__tests__/data/.nvmrc' | ||||
|       - name: Verify node | ||||
|         run: __tests__/verify-node.sh 14 | ||||
|  | ||||
|   node-dist: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|   | ||||
							
								
								
									
										13
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								README.md
									
									
									
									
									
								
							| @@ -93,12 +93,13 @@ jobs: | ||||
| ## Advanced usage | ||||
|  | ||||
| 1. [Check latest version](docs/advanced-usage.md#check-latest-version) | ||||
| 2. [Using different architectures](docs/advanced-usage.md#architecture) | ||||
| 3. [Caching packages dependencies](docs/advanced-usage.md#caching-packages-dependencies) | ||||
| 4. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures) | ||||
| 5. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) | ||||
| 6. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) | ||||
| 7. [Using private packages](docs/advanced-usage.md#use-private-packages) | ||||
| 2. [Using a node version file](docs/advanced-usage.md#node-version-file) | ||||
| 3. [Using different architectures](docs/advanced-usage.md#architecture) | ||||
| 4. [Caching packages dependencies](docs/advanced-usage.md#caching-packages-dependencies) | ||||
| 5. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures) | ||||
| 6. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) | ||||
| 7. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) | ||||
| 8. [Using private packages](docs/advanced-usage.md#use-private-packages) | ||||
|  | ||||
| # License | ||||
|  | ||||
|   | ||||
							
								
								
									
										1
									
								
								__tests__/data/.nvmrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								__tests__/data/.nvmrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| v14 | ||||
| @@ -1,12 +1,12 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as io from '@actions/io'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as im from '../src/installer'; | ||||
| import fs from 'fs'; | ||||
| import cp from 'child_process'; | ||||
| import osm = require('os'); | ||||
| import path from 'path'; | ||||
| import * as main from '../src/main'; | ||||
| import * as im from '../src/installer'; | ||||
| import * as auth from '../src/authutil'; | ||||
|  | ||||
| let nodeTestManifest = require('./data/versions-manifest.json'); | ||||
| @@ -31,9 +31,11 @@ describe('setup-node', () => { | ||||
|   let dbgSpy: jest.SpyInstance; | ||||
|   let whichSpy: jest.SpyInstance; | ||||
|   let existsSpy: jest.SpyInstance; | ||||
|   let readFileSyncSpy: jest.SpyInstance; | ||||
|   let mkdirpSpy: jest.SpyInstance; | ||||
|   let execSpy: jest.SpyInstance; | ||||
|   let authSpy: jest.SpyInstance; | ||||
|   let parseNodeVersionSpy: jest.SpyInstance; | ||||
|  | ||||
|   beforeEach(() => { | ||||
|     // @actions/core | ||||
| @@ -58,6 +60,7 @@ describe('setup-node', () => { | ||||
|     cacheSpy = jest.spyOn(tc, 'cacheDir'); | ||||
|     getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo'); | ||||
|     getDistSpy = jest.spyOn(im, 'getVersionsFromDist'); | ||||
|     parseNodeVersionSpy = jest.spyOn(im, 'parseNodeVersionFile'); | ||||
|  | ||||
|     // io | ||||
|     whichSpy = jest.spyOn(io, 'which'); | ||||
| @@ -91,6 +94,10 @@ describe('setup-node', () => { | ||||
|       // uncomment to see debug output | ||||
|       // process.stderr.write(msg + '\n'); | ||||
|     }); | ||||
|     warningSpy.mockImplementation(msg => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('log:' + line + '\n'); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   afterEach(() => { | ||||
| @@ -101,6 +108,7 @@ describe('setup-node', () => { | ||||
|  | ||||
|   afterAll(async () => { | ||||
|     console.log('::stoptoken::'); // Re-enable executing of runner commands when running tests in actions | ||||
|     jest.restoreAllMocks(); | ||||
|   }, 100000); | ||||
|  | ||||
|   //-------------------------------------------------- | ||||
| @@ -343,7 +351,7 @@ describe('setup-node', () => { | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('Acquires specified architecture of node', async () => { | ||||
|   it('acquires specified architecture of node', async () => { | ||||
|     for (const {arch, version, osSpec} of [ | ||||
|       {arch: 'x86', version: '12.16.2', osSpec: 'win32'}, | ||||
|       {arch: 'x86', version: '14.0.0', osSpec: 'win32'} | ||||
| @@ -549,6 +557,93 @@ describe('setup-node', () => { | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   describe('node-version-file flag', () => { | ||||
|     it('not used if node-version is provided', async () => { | ||||
|       // Arrange | ||||
|       inputs['node-version'] = '12'; | ||||
|  | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); | ||||
|     }); | ||||
|  | ||||
|     it('not used if node-version-file not provided', async () => { | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); | ||||
|     }); | ||||
|  | ||||
|     it('reads node-version-file if provided', async () => { | ||||
|       // Arrange | ||||
|       const versionSpec = 'v14'; | ||||
|       const versionFile = '.nvmrc'; | ||||
|       const expectedVersionSpec = '14'; | ||||
|       process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data'); | ||||
|       inputs['node-version-file'] = versionFile; | ||||
|  | ||||
|       parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); | ||||
|       existsSpy.mockImplementationOnce( | ||||
|         input => input === path.join(__dirname, 'data', versionFile) | ||||
|       ); | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(existsSpy).toHaveBeenCalledTimes(1); | ||||
|       expect(existsSpy).toHaveReturnedWith(true); | ||||
|       expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec); | ||||
|       expect(logSpy).toHaveBeenCalledWith( | ||||
|         `Resolved ${versionFile} as ${expectedVersionSpec}` | ||||
|       ); | ||||
|     }); | ||||
|  | ||||
|     it('both node-version-file and node-version are provided', async () => { | ||||
|       inputs['node-version'] = '12'; | ||||
|       const versionSpec = 'v14'; | ||||
|       const versionFile = '.nvmrc'; | ||||
|       const expectedVersionSpec = '14'; | ||||
|       process.env['GITHUB_WORKSPACE'] = path.join(__dirname, '..'); | ||||
|       inputs['node-version-file'] = versionFile; | ||||
|  | ||||
|       parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); | ||||
|  | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(existsSpy).toHaveBeenCalledTimes(0); | ||||
|       expect(parseNodeVersionSpy).not.toHaveBeenCalled(); | ||||
|       expect(warningSpy).toHaveBeenCalledWith( | ||||
|         'Both node-version and node-version-file inputs are specified, only node-version will be used' | ||||
|       ); | ||||
|     }); | ||||
|  | ||||
|     it('should throw an error if node-version-file is not found', async () => { | ||||
|       const versionFile = '.nvmrc'; | ||||
|       const versionFilePath = path.join(__dirname, '..', versionFile); | ||||
|       inputs['node-version-file'] = versionFile; | ||||
|  | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       existsSpy.mockImplementationOnce( | ||||
|         input => input === path.join(__dirname, 'data', versionFile) | ||||
|       ); | ||||
|  | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(existsSpy).toHaveBeenCalled(); | ||||
|       expect(existsSpy).toHaveReturnedWith(false); | ||||
|       expect(parseNodeVersionSpy).not.toHaveBeenCalled(); | ||||
|       expect(cnSpy).toHaveBeenCalledWith( | ||||
|         `::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}` | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
|   describe('LTS version', () => { | ||||
|     beforeEach(() => { | ||||
|       os.platform = 'linux'; | ||||
|   | ||||
| @@ -7,6 +7,8 @@ inputs: | ||||
|     default: 'false' | ||||
|   node-version: | ||||
|     description: 'Version Spec of the version to use.  Examples: 12.x, 10.15.1, >=10.15.0' | ||||
|   node-version-file: | ||||
|     description: 'File containing the version Spec of the version to use.  Examples: .nvmrc, .node-version' | ||||
|   architecture: | ||||
|     description: 'Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default.' | ||||
|   check-latest: | ||||
|   | ||||
							
								
								
									
										44
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							| @@ -6938,9 +6938,13 @@ var __importStar = (this && this.__importStar) || function (mod) { | ||||
|     result["default"] = mod; | ||||
|     return result; | ||||
| }; | ||||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
|     return (mod && mod.__esModule) ? mod : { "default": mod }; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||||
| const core = __importStar(__webpack_require__(470)); | ||||
| const installer = __importStar(__webpack_require__(923)); | ||||
| const fs_1 = __importDefault(__webpack_require__(747)); | ||||
| const auth = __importStar(__webpack_require__(749)); | ||||
| const path = __importStar(__webpack_require__(622)); | ||||
| const cache_restore_1 = __webpack_require__(409); | ||||
| @@ -6953,10 +6957,7 @@ 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('node-version'); | ||||
|             if (!version) { | ||||
|                 version = core.getInput('version'); | ||||
|             } | ||||
|             let version = resolveVersionInput(); | ||||
|             let arch = core.getInput('architecture'); | ||||
|             const cache = core.getInput('cache'); | ||||
|             // if architecture supplied but node-version is not
 | ||||
| @@ -6991,8 +6992,8 @@ function run() { | ||||
|             core.info(`##[add-matcher]${path.join(matchersPath, 'eslint-stylish.json')}`); | ||||
|             core.info(`##[add-matcher]${path.join(matchersPath, 'eslint-compact.json')}`); | ||||
|         } | ||||
|         catch (error) { | ||||
|             core.setFailed(error.message); | ||||
|         catch (err) { | ||||
|             core.setFailed(err.message); | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| @@ -7001,6 +7002,25 @@ function isGhes() { | ||||
|     const ghUrl = new url_1.URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com'); | ||||
|     return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'; | ||||
| } | ||||
| function resolveVersionInput() { | ||||
|     let version = core.getInput('node-version') || core.getInput('version'); | ||||
|     const versionFileInput = core.getInput('node-version-file'); | ||||
|     if (version && versionFileInput) { | ||||
|         core.warning('Both node-version and node-version-file inputs are specified, only node-version will be used'); | ||||
|     } | ||||
|     if (version) { | ||||
|         return version; | ||||
|     } | ||||
|     if (versionFileInput) { | ||||
|         const versionFilePath = path.join(process.env.GITHUB_WORKSPACE, versionFileInput); | ||||
|         if (!fs_1.default.existsSync(versionFilePath)) { | ||||
|             throw new Error(`The specified node version file at: ${versionFilePath} does not exist`); | ||||
|         } | ||||
|         version = installer.parseNodeVersionFile(fs_1.default.readFileSync(versionFilePath, 'utf8')); | ||||
|         core.info(`Resolved ${versionFileInput} as ${version}`); | ||||
|     } | ||||
|     return version; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
| @@ -65340,7 +65360,7 @@ exports.NOOP_TEXT_MAP_PROPAGATOR = new NoopTextMapPropagator(); | ||||
| /* 921 */, | ||||
| /* 922 */, | ||||
| /* 923 */ | ||||
| /***/ (function(module, exports, __webpack_require__) { | ||||
| /***/ (function(__unusedmodule, exports, __webpack_require__) { | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| @@ -65617,7 +65637,7 @@ function queryDistForMatch(versionSpec, arch = os.arch()) { | ||||
|                 throw new Error(`Unexpected OS '${osPlat}'`); | ||||
|         } | ||||
|         let versions = []; | ||||
|         let nodeVersions = yield module.exports.getVersionsFromDist(); | ||||
|         let nodeVersions = yield getVersionsFromDist(); | ||||
|         nodeVersions.forEach((nodeVersion) => { | ||||
|             // ensure this version supports your os and platform
 | ||||
|             if (nodeVersion.files.indexOf(dataFileName) >= 0) { | ||||
| @@ -65705,6 +65725,14 @@ function translateArchToDistUrl(arch) { | ||||
|             return arch; | ||||
|     } | ||||
| } | ||||
| function parseNodeVersionFile(contents) { | ||||
|     let nodeVersion = contents.trim(); | ||||
|     if (/^v\d/.test(nodeVersion)) { | ||||
|         nodeVersion = nodeVersion.substring(1); | ||||
|     } | ||||
|     return nodeVersion; | ||||
| } | ||||
| exports.parseNodeVersionFile = parseNodeVersionFile; | ||||
| 
 | ||||
| 
 | ||||
| /***/ }), | ||||
|   | ||||
| @@ -19,6 +19,22 @@ steps: | ||||
| - run: npm test | ||||
| ``` | ||||
|  | ||||
| ## Node version file | ||||
|    | ||||
| The `node-version-file` input accepts a path to a file containing the version of Node.js to be used by a project, for example `.nvmrc` or `.node-version`. If both the `node-version` and the `node-version-file` inputs are provided then the `node-version` input is used.  | ||||
| See [supported version syntax](https://github.com/actions/setup-node#supported-version-syntax)  | ||||
| > The action will search for the node version file relative to the repository root. | ||||
|  | ||||
| ```yaml | ||||
| steps: | ||||
| - uses: actions/checkout@v2 | ||||
| - uses: actions/setup-node@v2 | ||||
|   with: | ||||
|     node-version-file: '.nvmrc' | ||||
| - run: npm install | ||||
| - run: npm test | ||||
| ``` | ||||
|  | ||||
| ## Architecture | ||||
|  | ||||
| You can use any of the [supported operating systems](https://docs.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners), and the compatible `architecture` can be selected using `architecture`. Values are `x86`, `x64`, `arm64`, `armv6l`, `armv7l`, `ppc64le`, `s390x` (not all of the architectures are available on all platforms). | ||||
|   | ||||
| @@ -371,7 +371,7 @@ async function queryDistForMatch( | ||||
|   } | ||||
|  | ||||
|   let versions: string[] = []; | ||||
|   let nodeVersions = await module.exports.getVersionsFromDist(); | ||||
|   let nodeVersions = await getVersionsFromDist(); | ||||
|  | ||||
|   nodeVersions.forEach((nodeVersion: INodeVersion) => { | ||||
|     // ensure this version supports your os and platform | ||||
| @@ -464,3 +464,12 @@ function translateArchToDistUrl(arch: string): string { | ||||
|       return arch; | ||||
|   } | ||||
| } | ||||
|  | ||||
| export function parseNodeVersionFile(contents: string): string { | ||||
|   let nodeVersion = contents.trim(); | ||||
|  | ||||
|   if (/^v\d/.test(nodeVersion)) { | ||||
|     nodeVersion = nodeVersion.substring(1); | ||||
|   } | ||||
|   return nodeVersion; | ||||
| } | ||||
|   | ||||
							
								
								
									
										43
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								src/main.ts
									
									
									
									
									
								
							| @@ -1,5 +1,6 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as installer from './installer'; | ||||
| import fs from 'fs'; | ||||
| import * as auth from './authutil'; | ||||
| import * as path from 'path'; | ||||
| import {restoreCache} from './cache-restore'; | ||||
| @@ -12,10 +13,7 @@ export 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('node-version'); | ||||
|     if (!version) { | ||||
|       version = core.getInput('version'); | ||||
|     } | ||||
|     let version = resolveVersionInput(); | ||||
|  | ||||
|     let arch = core.getInput('architecture'); | ||||
|     const cache = core.getInput('cache'); | ||||
| @@ -63,8 +61,8 @@ export async function run() { | ||||
|     core.info( | ||||
|       `##[add-matcher]${path.join(matchersPath, 'eslint-compact.json')}` | ||||
|     ); | ||||
|   } catch (error) { | ||||
|     core.setFailed(error.message); | ||||
|   } catch (err) { | ||||
|     core.setFailed(err.message); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -74,3 +72,36 @@ function isGhes(): boolean { | ||||
|   ); | ||||
|   return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'; | ||||
| } | ||||
|  | ||||
| function resolveVersionInput(): string { | ||||
|   let version = core.getInput('node-version') || core.getInput('version'); | ||||
|   const versionFileInput = core.getInput('node-version-file'); | ||||
|  | ||||
|   if (version && versionFileInput) { | ||||
|     core.warning( | ||||
|       'Both node-version and node-version-file inputs are specified, only node-version will be used' | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   if (version) { | ||||
|     return version; | ||||
|   } | ||||
|  | ||||
|   if (versionFileInput) { | ||||
|     const versionFilePath = path.join( | ||||
|       process.env.GITHUB_WORKSPACE!, | ||||
|       versionFileInput | ||||
|     ); | ||||
|     if (!fs.existsSync(versionFilePath)) { | ||||
|       throw new Error( | ||||
|         `The specified node version file at: ${versionFilePath} does not exist` | ||||
|       ); | ||||
|     } | ||||
|     version = installer.parseNodeVersionFile( | ||||
|       fs.readFileSync(versionFilePath, 'utf8') | ||||
|     ); | ||||
|     core.info(`Resolved ${versionFileInput} as ${version}`); | ||||
|   } | ||||
|  | ||||
|   return version; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Hargun Kaur
					Hargun Kaur