Skip to content

Commit 5a01179

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents 4096f07 + 2a814b5 commit 5a01179

File tree

12 files changed

+136
-41
lines changed

12 files changed

+136
-41
lines changed

.github/workflows/versions.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,13 @@ jobs:
9292
fail-fast: false
9393
matrix:
9494
os: [ubuntu-latest, windows-latest, macos-latest]
95+
node-version-file: [.nvmrc, .tool-versions]
9596
steps:
9697
- uses: actions/checkout@v3
9798
- name: Setup node from node version file
9899
uses: ./
99100
with:
100-
node-version-file: '__tests__/data/.nvmrc'
101+
node-version-file: '__tests__/data/${{ matrix.node-version-file }}'
101102
- name: Verify node
102103
run: __tests__/verify-node.sh 14
103104

README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ steps:
2222
- uses: actions/checkout@v3
2323
- uses: actions/setup-node@v3
2424
with:
25-
node-version: 14
25+
node-version: 16
2626
- run: npm ci
2727
- run: npm test
2828
```
@@ -39,8 +39,8 @@ The `node-version` input supports the Semantic Versioning Specification, for mor
3939

4040
Examples:
4141

42-
- Major versions: `12`, `14`, `16`
43-
- More specific versions: `10.15`, `14.2.0`, `16.3.0`
42+
- Major versions: `14`, `16`, `18`
43+
- More specific versions: `10.15`, `16.15.1` , `18.4.0`
4444
- NVM LTS syntax: `lts/erbium`, `lts/fermium`, `lts/*`, `lts/-n`
4545
- Latest release: `*` or `latest`/`current`/`node`
4646

@@ -58,7 +58,7 @@ It's **always** recommended to commit the lockfile of your package manager for s
5858

5959
The action has a built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/cache) under the hood for caching global packages data but requires less configuration settings. Supported package managers are `npm`, `yarn`, `pnpm` (v6.10+). The `cache` input is optional, and caching is turned off by default.
6060

61-
The action defaults to search for the dependency file (`package-lock.json` or `yarn.lock`) in the repository root, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases when multiple dependency files are used, or they are located in different subdirectories.
61+
The action defaults to search for the dependency file (`package-lock.json`, `npm-shrinkwrap.json` or `yarn.lock`) in the repository root, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases when multiple dependency files are used, or they are located in different subdirectories.
6262

6363
**Note:** The action does not cache `node_modules`
6464

@@ -71,7 +71,7 @@ steps:
7171
- uses: actions/checkout@v3
7272
- uses: actions/setup-node@v3
7373
with:
74-
node-version: 14
74+
node-version: 16
7575
cache: 'npm'
7676
- run: npm ci
7777
- run: npm test
@@ -84,7 +84,7 @@ steps:
8484
- uses: actions/checkout@v3
8585
- uses: actions/setup-node@v3
8686
with:
87-
node-version: 14
87+
node-version: 16
8888
cache: 'npm'
8989
cache-dependency-path: subdir/package-lock.json
9090
- run: npm ci
@@ -99,7 +99,7 @@ jobs:
9999
runs-on: ubuntu-latest
100100
strategy:
101101
matrix:
102-
node: [ 12, 14, 16 ]
102+
node: [ 14, 16, 18 ]
103103
name: Node ${{ matrix.node }} sample
104104
steps:
105105
- uses: actions/checkout@v3

__tests__/data/.tool-versions

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
nodejs 14.0.0

__tests__/data/package.json

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
{
2-
"name": "test",
3-
"version": "1.0.0",
4-
"private": true,
5-
"scripts": {
6-
"test": "echo test"
7-
},
8-
"volta": {
9-
"node": "16.15.1"
2+
"engines": {
3+
"node": ">=14.0.0"
104
}
115
}

__tests__/installer.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import * as core from '@actions/core';
22
import * as io from '@actions/io';
33
import * as tc from '@actions/tool-cache';
4+
import * as exec from '@actions/exec';
45
import * as im from '../src/installer';
56
import * as cache from '@actions/cache';
67
import fs from 'fs';
78
import cp from 'child_process';
89
import osm = require('os');
910
import path from 'path';
11+
import each from 'jest-each';
1012
import * as main from '../src/main';
1113
import * as auth from '../src/authutil';
1214

@@ -38,6 +40,7 @@ describe('setup-node', () => {
3840
let authSpy: jest.SpyInstance;
3941
let parseNodeVersionSpy: jest.SpyInstance;
4042
let isCacheActionAvailable: jest.SpyInstance;
43+
let getExecOutputSpy: jest.SpyInstance;
4144

4245
beforeEach(() => {
4346
// @actions/core
@@ -103,6 +106,10 @@ describe('setup-node', () => {
103106
// uncomment to debug
104107
// process.stderr.write('log:' + line + '\n');
105108
});
109+
110+
// @actions/exec
111+
getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
112+
getExecOutputSpy.mockImplementation(() => 'v16.15.0');
106113
});
107114

108115
afterEach(() => {
@@ -613,6 +620,33 @@ describe('setup-node', () => {
613620
);
614621
});
615622

623+
it('reads package.json as node-version-file if provided', async () => {
624+
// Arrange
625+
const versionSpec = fs.readFileSync(
626+
path.join(__dirname, 'data/package.json'),
627+
'utf-8'
628+
);
629+
const versionFile = 'package.json';
630+
const expectedVersionSpec = '14';
631+
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
632+
inputs['node-version-file'] = versionFile;
633+
634+
parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec);
635+
existsSpy.mockImplementationOnce(
636+
input => input === path.join(__dirname, 'data', versionFile)
637+
);
638+
// Act
639+
await main.run();
640+
641+
// Assert
642+
expect(existsSpy).toHaveBeenCalledTimes(1);
643+
expect(existsSpy).toHaveReturnedWith(true);
644+
expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec);
645+
expect(logSpy).toHaveBeenCalledWith(
646+
`Resolved ${versionFile} as ${expectedVersionSpec}`
647+
);
648+
});
649+
616650
it('both node-version-file and node-version are provided', async () => {
617651
inputs['node-version'] = '12';
618652
const versionSpec = 'v14';
@@ -927,3 +961,23 @@ describe('setup-node', () => {
927961
);
928962
});
929963
});
964+
965+
describe('helper methods', () => {
966+
describe('parseNodeVersionFile', () => {
967+
each`
968+
contents | expected
969+
${'12'} | ${'12'}
970+
${'12.3'} | ${'12.3'}
971+
${'12.3.4'} | ${'12.3.4'}
972+
${'v12.3.4'} | ${'12.3.4'}
973+
${'lts/erbium'} | ${'lts/erbium'}
974+
${'lts/*'} | ${'lts/*'}
975+
${'nodejs 12.3.4'} | ${'12.3.4'}
976+
${'ruby 2.3.4\nnodejs 12.3.4\npython 3.4.5'} | ${'12.3.4'}
977+
${''} | ${''}
978+
${'unknown format'} | ${'unknown format'}
979+
`.it('parses "$contents"', ({contents, expected}) => {
980+
expect(im.parseNodeVersionFile(contents)).toBe(expected);
981+
});
982+
});
983+
});

action.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ inputs:
88
node-version:
99
description: 'Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0.'
1010
node-version-file:
11-
description: 'File containing the version Spec of the version to use. Examples: .nvmrc, .node-version.'
11+
description: 'File containing the version Spec of the version to use. Examples: .nvmrc, .node-version, .tool-versions.'
1212
architecture:
1313
description: 'Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default.'
1414
check-latest:
@@ -30,6 +30,8 @@ inputs:
3030
outputs:
3131
cache-hit:
3232
description: 'A boolean value to indicate if a cache was hit.'
33+
node-version:
34+
description: 'The installed node version.'
3335
runs:
3436
using: 'node16'
3537
main: 'dist/setup/index.js'

dist/cache-save/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -59926,12 +59926,12 @@ const exec = __importStar(__nccwpck_require__(1514));
5992659926
const cache = __importStar(__nccwpck_require__(7799));
5992759927
exports.supportedPackageManagers = {
5992859928
npm: {
59929-
lockFilePatterns: ['package-lock.json', 'yarn.lock'],
59929+
lockFilePatterns: ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'],
5993059930
getCacheFolderCommand: 'npm config get cache'
5993159931
},
5993259932
pnpm: {
5993359933
lockFilePatterns: ['pnpm-lock.yaml'],
59934-
getCacheFolderCommand: 'pnpm store path'
59934+
getCacheFolderCommand: 'pnpm store path --silent'
5993559935
},
5993659936
yarn1: {
5993759937
lockFilePatterns: ['yarn.lock'],
@@ -59986,7 +59986,7 @@ exports.getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaite
5998659986
throw new Error(`Could not get cache folder path for ${packageManager}`);
5998759987
}
5998859988
core.debug(`${packageManager} path is ${stdOut}`);
59989-
return stdOut;
59989+
return stdOut.trim();
5999059990
});
5999159991
function isGhes() {
5999259992
const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');

dist/setup/index.js

+29-9
Original file line numberDiff line numberDiff line change
@@ -71272,12 +71272,12 @@ const exec = __importStar(__nccwpck_require__(1514));
7127271272
const cache = __importStar(__nccwpck_require__(7799));
7127371273
exports.supportedPackageManagers = {
7127471274
npm: {
71275-
lockFilePatterns: ['package-lock.json', 'yarn.lock'],
71275+
lockFilePatterns: ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'],
7127671276
getCacheFolderCommand: 'npm config get cache'
7127771277
},
7127871278
pnpm: {
7127971279
lockFilePatterns: ['pnpm-lock.yaml'],
71280-
getCacheFolderCommand: 'pnpm store path'
71280+
getCacheFolderCommand: 'pnpm store path --silent'
7128171281
},
7128271282
yarn1: {
7128371283
lockFilePatterns: ['yarn.lock'],
@@ -71332,7 +71332,7 @@ exports.getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaite
7133271332
throw new Error(`Could not get cache folder path for ${packageManager}`);
7133371333
}
7133471334
core.debug(`${packageManager} path is ${stdOut}`);
71335-
return stdOut;
71335+
return stdOut.trim();
7133671336
});
7133771337
function isGhes() {
7133871338
const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
@@ -71768,12 +71768,23 @@ function translateArchToDistUrl(arch) {
7176871768
}
7176971769
}
7177071770
function parseNodeVersionFile(contents) {
71771-
let nodeVersion = contents.trim();
71772-
if (contents.includes('volta')) {
71773-
nodeVersion = JSON.parse(contents).volta.node;
71774-
}
71775-
if (/^v\d/.test(nodeVersion)) {
71776-
nodeVersion = nodeVersion.substring(1);
71771+
var _a, _b;
71772+
let nodeVersion;
71773+
const found = contents.match(/^(?:nodejs\s+)?v?(?<version>[^\s]+)$/m);
71774+
nodeVersion = (_a = found === null || found === void 0 ? void 0 : found.groups) === null || _a === void 0 ? void 0 : _a.version;
71775+
if (!nodeVersion) {
71776+
try {
71777+
// Try parsing the file as an NPM `package.json`
71778+
// file.
71779+
nodeVersion = (_b = JSON.parse(contents).engines) === null || _b === void 0 ? void 0 : _b.node;
71780+
if (!nodeVersion)
71781+
throw new Error();
71782+
}
71783+
catch (err) {
71784+
// In the case of an unknown format,
71785+
// return as is and evaluate the version separately.
71786+
nodeVersion = contents.trim();
71787+
}
7177771788
}
7177871789
return nodeVersion;
7177971790
}
@@ -71811,6 +71822,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
7181171822
};
7181271823
Object.defineProperty(exports, "__esModule", ({ value: true }));
7181371824
const core = __importStar(__nccwpck_require__(2186));
71825+
const exec = __importStar(__nccwpck_require__(1514));
7181471826
const installer = __importStar(__nccwpck_require__(2574));
7181571827
const fs_1 = __importDefault(__nccwpck_require__(7147));
7181671828
const auth = __importStar(__nccwpck_require__(7573));
@@ -71843,6 +71855,14 @@ function run() {
7184371855
const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE';
7184471856
yield installer.getNode(version, stable, checkLatest, auth, arch);
7184571857
}
71858+
// Output version of node is being used
71859+
try {
71860+
const { stdout: installedVersion } = yield exec.getExecOutput('node', ['--version'], { ignoreReturnCode: true, silent: true });
71861+
core.setOutput('node-version', installedVersion.trim());
71862+
}
71863+
catch (err) {
71864+
core.setOutput('node-version', '');
71865+
}
7184671866
const registryUrl = core.getInput('registry-url');
7184771867
const alwaysAuth = core.getInput('always-auth');
7184871868
if (registryUrl) {

docs/advanced-usage.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ steps:
5656
5757
## Node version file
5858
59-
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. In the special case of using `package.json`, the action will look for keys like `volta.node` key to receive the version.
60-
59+
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`, `.node-version` or `.tool-versions`. If both the `node-version` and the `node-version-file` inputs are provided then the `node-version` input is used.
6160
See [supported version syntax](https://github.com/actions/setup-node#supported-version-syntax)
6261

6362
> The action will search for the node version file relative to the repository root.
@@ -249,3 +248,5 @@ steps:
249248
# `npm rebuild` will run all those post-install scripts for us.
250249
- run: npm rebuild && npm run prepare --if-present
251250
```
251+
252+
NOTE: As per https://github.com/actions/setup-node/issues/49 you cannot use `secrets.GITHUB_TOKEN` to access private GitHub Packages within the same organisation but in a different repository.

src/cache-utils.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ export interface PackageManagerInfo {
1313

1414
export const supportedPackageManagers: SupportedPackageManagers = {
1515
npm: {
16-
lockFilePatterns: ['package-lock.json', 'yarn.lock'],
16+
lockFilePatterns: ['package-lock.json', 'npm-shrinkwrap.json', 'yarn.lock'],
1717
getCacheFolderCommand: 'npm config get cache'
1818
},
1919
pnpm: {
2020
lockFilePatterns: ['pnpm-lock.yaml'],
21-
getCacheFolderCommand: 'pnpm store path'
21+
getCacheFolderCommand: 'pnpm store path --silent'
2222
},
2323
yarn1: {
2424
lockFilePatterns: ['yarn.lock'],
@@ -94,7 +94,7 @@ export const getCacheDirectoryPath = async (
9494

9595
core.debug(`${packageManager} path is ${stdOut}`);
9696

97-
return stdOut;
97+
return stdOut.trim();
9898
};
9999

100100
export function isGhes(): boolean {

src/installer.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -495,17 +495,26 @@ function translateArchToDistUrl(arch: string): string {
495495
}
496496

497497
export function parseNodeVersionFile(contents: string): string {
498-
let nodeVersion = contents.trim();
498+
let nodeVersion: string | undefined;
499499

500-
if (contents.includes('volta')) {
501-
nodeVersion = JSON.parse(contents).volta.node;
502-
}
500+
const found = contents.match(/^(?:nodejs\s+)?v?(?<version>[^\s]+)$/m);
501+
nodeVersion = found?.groups?.version;
502+
503+
if (!nodeVersion) {
504+
try {
505+
// Try parsing the file as an NPM `package.json`
506+
// file.
507+
nodeVersion = JSON.parse(contents).engines?.node;
503508

504-
if (/^v\d/.test(nodeVersion)) {
505-
nodeVersion = nodeVersion.substring(1);
509+
if (!nodeVersion) throw new Error();
510+
} catch (err) {
511+
// In the case of an unknown format,
512+
// return as is and evaluate the version separately.
513+
nodeVersion = contents.trim();
514+
}
506515
}
507516

508-
return nodeVersion;
517+
return nodeVersion as string;
509518
}
510519

511520
function isLatestSyntax(versionSpec): boolean {

src/main.ts

+13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as core from '@actions/core';
2+
import * as exec from '@actions/exec';
23
import * as installer from './installer';
34
import fs from 'fs';
45
import * as auth from './authutil';
@@ -39,6 +40,18 @@ export async function run() {
3940
await installer.getNode(version, stable, checkLatest, auth, arch);
4041
}
4142

43+
// Output version of node is being used
44+
try {
45+
const {stdout: installedVersion} = await exec.getExecOutput(
46+
'node',
47+
['--version'],
48+
{ignoreReturnCode: true, silent: true}
49+
);
50+
core.setOutput('node-version', installedVersion.trim());
51+
} catch (err) {
52+
core.setOutput('node-version', '');
53+
}
54+
4255
const registryUrl: string = core.getInput('registry-url');
4356
const alwaysAuth: string = core.getInput('always-auth');
4457
if (registryUrl) {

0 commit comments

Comments
 (0)