diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index cb2b210e6..607a58cea 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -78,6 +78,18 @@ 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 test + uses: ./ + with: + node-version-file: '.nvmrc' node-dist: runs-on: ${{ matrix.os }} strategy: diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..b009dfb9d --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +lts/* diff --git a/README.md b/README.md index 8b405f9ea..286362689 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ # setup-node -
@@ -72,6 +71,7 @@ steps: - run: npm test ``` + ## Matrix Testing: ```yaml jobs: @@ -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 diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 994892365..bbbe53772 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -1,14 +1,14 @@ +import fs from 'fs'; + import * as core from '@actions/core'; import * as io from '@actions/io'; import * as tc from '@actions/tool-cache'; -import fs from 'fs'; +import * as im from '../src/installer'; 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'); let nodeTestDist = require('./data/node-dist-index.json'); @@ -31,9 +31,12 @@ describe('setup-node', () => { let dbgSpy: jest.SpyInstance; let whichSpy: jest.SpyInstance; let existsSpy: jest.SpyInstance; + let readFileSyncSpy: jest.SpyInstance; + let jestExistsSync: jest.SpyInstance; let mkdirpSpy: jest.SpyInstance; let execSpy: jest.SpyInstance; let authSpy: jest.SpyInstance; + let parseNodeVersionSpy: jest.SpyInstance; beforeEach(() => { // @actions/core @@ -58,10 +61,12 @@ 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'); existsSpy = jest.spyOn(fs, 'existsSync'); + readFileSyncSpy = jest.spyOn(fs, 'readFileSync'); mkdirpSpy = jest.spyOn(io, 'mkdirP'); // disable authentication portion for installer tests @@ -100,6 +105,7 @@ describe('setup-node', () => { }); afterAll(async () => { + jest.restoreAllMocks(); console.log('::stoptoken::'); // Re-enable executing of runner commands when running tests in actions }, 100000); @@ -546,6 +552,8 @@ describe('setup-node', () => { `Attempting to download ${versionSpec}...` ); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); + + console.log(process.env); }); }); @@ -766,4 +774,63 @@ describe('setup-node', () => { ); }); }); + + describe('node-version-file flag', () => { + it('Not used if node-version is provided', async () => { + // Arrange + inputs['node-version'] = '12'; + + let toolPath = path.normalize('/cache/node/12.16.1/x64'); + findSpy.mockImplementation(() => toolPath); + + // Act + await main.run(); + + // Assert + expect(readFileSyncSpy).toHaveBeenCalledTimes(0); + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + }); + + it('Not used if node-version-file not provided', async () => { + console.log(`inputs is ${inputs}`); + // Act + await main.run(); + + // Assert + expect(readFileSyncSpy).toHaveBeenCalledTimes(0); + }); + + it('Reads node-version-file if provided', async () => { + // Arrange + const versionSpec = 'v12'; + const versionFile = '.nvmrc'; + const expectedVersionSpec = '12'; + process.env['GITHUB_WORKSPACE'] = path.join(__dirname, '..'); + console.log(`GITHUB_WORKSPACE ${process.env['GITHUB_WORKSPACE']}`); + console.log(`second check ${path.join(__dirname, '..', versionFile)}`); + + inputs['node-version-file'] = versionFile; + console.log(inputs); + + readFileSyncSpy.mockImplementation(() => versionSpec); + parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); + + let toolPath = path.normalize('/cache/node/12.16.1/x64'); + findSpy.mockImplementation(() => toolPath); + + // Act + await main.run(); + + // Assert + expect(readFileSyncSpy).toHaveBeenCalledTimes(1); + expect(readFileSyncSpy).toHaveBeenCalledWith( + path.join(__dirname, '..', versionFile), + 'utf8' + ); + expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec); + expect(logSpy).toHaveBeenCalledWith( + `Resolved ${versionFile} as ${expectedVersionSpec}` + ); + }); + }); }); diff --git a/action.yml b/action.yml index e50fa0e62..66b170ca0 100644 --- a/action.yml +++ b/action.yml @@ -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' architecture: description: 'Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default.' check-latest: diff --git a/dist/setup/index.js b/dist/setup/index.js index e649b3583..952365ad3 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -6849,9 +6849,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); @@ -6867,6 +6871,14 @@ function run() { let version = core.getInput('node-version'); if (!version) { version = core.getInput('version'); + if (!version) { + const versionFile = core.getInput('node-version-file'); + if (versionFile) { + const versionFilePath = path.join(process.env.GITHUB_WORKSPACE, versionFile); + version = installer.parseNodeVersionFile(fs_1.default.readFileSync(versionFilePath, 'utf8')); + core.info(`Resolved ${versionFile} as ${version}`); + } + } } let arch = core.getInput('architecture'); const cache = core.getInput('cache'); @@ -65036,7 +65048,7 @@ exports.NOOP_TEXT_MAP_PROPAGATOR = new NoopTextMapPropagator(); /* 921 */, /* 922 */, /* 923 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; @@ -65060,8 +65072,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); const os = __webpack_require__(87); const assert = __importStar(__webpack_require__(357)); const core = __importStar(__webpack_require__(470)); -const hc = __importStar(__webpack_require__(539)); const io = __importStar(__webpack_require__(1)); +const hc = __importStar(__webpack_require__(539)); const tc = __importStar(__webpack_require__(533)); const path = __importStar(__webpack_require__(622)); const semver = __importStar(__webpack_require__(280)); @@ -65313,7 +65325,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) { @@ -65401,6 +65413,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; /***/ }), diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index c84918fab..6cba78bfc 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -19,6 +19,21 @@ steps: - run: npm test ``` +## Node version file + +The `node-version-file` input allows you to use a file within your repository which contains the version of node your project uses for example `.nvmrc`. If both the `node-version` and the `node-version-file` inputs are provided the `node-version` input is used. +> The node version file is read from the project 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). diff --git a/src/installer.ts b/src/installer.ts index e2084b95a..ea854a30f 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -1,8 +1,8 @@ import os = require('os'); import * as assert from 'assert'; import * as core from '@actions/core'; -import * as hc from '@actions/http-client'; import * as io from '@actions/io'; +import * as hc from '@actions/http-client'; import * as tc from '@actions/tool-cache'; import * as path from 'path'; import * as semver from 'semver'; @@ -12,6 +12,7 @@ import fs = require('fs'); // Node versions interface // see https://nodejs.org/dist/index.json // + export interface INodeVersion { version: string; files: string[]; @@ -371,7 +372,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 +465,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; +} diff --git a/src/main.ts b/src/main.ts index 956bc1449..d37f6e020 100644 --- a/src/main.ts +++ b/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'; @@ -15,6 +16,21 @@ export async function run() { let version = core.getInput('node-version'); if (!version) { version = core.getInput('version'); + + if (!version) { + const versionFile = core.getInput('node-version-file'); + + if (versionFile) { + const versionFilePath = path.join( + process.env.GITHUB_WORKSPACE!, + versionFile + ); + version = installer.parseNodeVersionFile( + fs.readFileSync(versionFilePath, 'utf8') + ); + core.info(`Resolved ${versionFile} as ${version}`); + } + } } let arch = core.getInput('architecture');