Compare commits
32 commits
main
...
node-versi
Author | SHA1 | Date | |
---|---|---|---|
|
e73ffbcdec | ||
|
2ae9264901 | ||
|
2a0fbec10d | ||
|
0a9e8b1d0f | ||
|
a875da2574 | ||
|
a80a170798 | ||
|
5e7b076d00 | ||
|
8e221092f3 | ||
|
6a1b66a606 | ||
|
9fcef3fcea | ||
|
beb2155295 | ||
|
11f920585c | ||
|
dd6f5ab66c | ||
|
f7c5caf605 | ||
|
a4145577de | ||
|
42746a4f3c | ||
|
c8617ac6ae | ||
|
1b2d431484 | ||
|
5e5ef8fd55 | ||
|
2fb08c4f31 | ||
|
e3ad114cc4 | ||
|
501fd29d66 | ||
|
2bdb2ab1c9 | ||
|
ed3a918d25 | ||
|
efab84ad3c | ||
|
8a1d983ace | ||
|
22c0aea623 | ||
|
1c2f59fb67 | ||
|
ec6092f7d2 | ||
|
889def385d | ||
|
8885b7194e | ||
|
ecf0ce62f9 |
20 changed files with 6445 additions and 1237 deletions
32
.github/workflows/build-test.yml
vendored
Normal file
32
.github/workflows/build-test.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
name: build-test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- releases/*
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Setup node 12
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 12.x
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build
|
||||||
|
- run: npm run format-check
|
||||||
|
- run: npm test
|
||||||
|
- name: Verify no unstaged changes
|
||||||
|
if: runner.os != 'windows'
|
||||||
|
run: __tests__/verify-no-unstaged-changes.sh
|
56
.github/workflows/proxy.yml
vendored
Normal file
56
.github/workflows/proxy.yml
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
name: proxy
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- releases/*
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-proxy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
container:
|
||||||
|
image: ubuntu:latest
|
||||||
|
options: --dns 127.0.0.1
|
||||||
|
services:
|
||||||
|
squid-proxy:
|
||||||
|
image: datadog/squid:latest
|
||||||
|
ports:
|
||||||
|
- 3128:3128
|
||||||
|
env:
|
||||||
|
https_proxy: http://squid-proxy:3128
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Clear tool cache
|
||||||
|
run: rm -rf $RUNNER_TOOL_CACHE/*
|
||||||
|
- name: Setup node 10
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: 10.x
|
||||||
|
- name: Verify node and npm
|
||||||
|
run: __tests__/verify-node.sh 10
|
||||||
|
|
||||||
|
test-bypass-proxy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
env:
|
||||||
|
https_proxy: http://no-such-proxy:3128
|
||||||
|
no_proxy: api.github.com,github.com,nodejs.org,registry.npmjs.org,*.s3.amazonaws.com,s3.amazonaws.com
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Clear tool cache
|
||||||
|
run: rm -rf $RUNNER_TOOL_CACHE/*
|
||||||
|
- name: Setup node 11
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: 11
|
||||||
|
- name: Verify node and npm
|
||||||
|
run: __tests__/verify-node.sh 11
|
47
.github/workflows/versions.yml
vendored
Normal file
47
.github/workflows/versions.yml
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
name: versions
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- releases/*
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
versions:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest]
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
# test version that falls through to node dist
|
||||||
|
- name: Setup node 11 from dist
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: 11
|
||||||
|
- name: Verify node and npm
|
||||||
|
run: __tests__/verify-node.sh 11
|
||||||
|
# test old versions which didn't have npm and layout different
|
||||||
|
- name: Setup node 0.12.18 from dist
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: 0.12.18
|
||||||
|
- name: Verify node
|
||||||
|
shell: bash
|
||||||
|
run: __tests__/verify-node.sh 0.12.18 SKIP_NPM
|
||||||
|
# test version from node manifest
|
||||||
|
- name: Setup node 12.16.2 from manifest
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: 12.16.2
|
||||||
|
- name: Verify node and npm
|
||||||
|
run: __tests__/verify-node.sh 12
|
100
.github/workflows/workflow.yml
vendored
100
.github/workflows/workflow.yml
vendored
|
@ -1,100 +0,0 @@
|
||||||
name: Main workflow
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- releases/*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
operating-system: [ubuntu-latest, windows-latest]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Setup node 12
|
|
||||||
uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: 12.x
|
|
||||||
- run: npm ci
|
|
||||||
- run: npm run build
|
|
||||||
- run: npm run format-check
|
|
||||||
- run: npm test
|
|
||||||
- name: Verify no unstaged changes
|
|
||||||
if: runner.os != 'windows'
|
|
||||||
run: __tests__/verify-no-unstaged-changes.sh
|
|
||||||
|
|
||||||
test:
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
operating-system: [ubuntu-latest, windows-latest]
|
|
||||||
defaults:
|
|
||||||
run:
|
|
||||||
shell: bash
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Clear tool cache
|
|
||||||
run: rm -rf $RUNNER_TOOL_CACHE/*
|
|
||||||
- name: Setup node 10
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
node-version: 10.x
|
|
||||||
- name: Verify node and npm
|
|
||||||
run: __tests__/verify-node.sh 10
|
|
||||||
|
|
||||||
test-fallback:
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Clear tool cache
|
|
||||||
run: mv "${{ runner.tool_cache }}" "${{ runner.tool_cache }}.old"
|
|
||||||
- name: Setup node 0.12.18 # For non LTS versions of Node, the zip is not always available
|
|
||||||
uses: ./ # and falls back to downloading node.exe and node.lib
|
|
||||||
with:
|
|
||||||
node-version: 0.12.18
|
|
||||||
- name: Verify node
|
|
||||||
shell: bash
|
|
||||||
run: __tests__/verify-node.sh 0.12.18 SKIP_NPM
|
|
||||||
|
|
||||||
test-proxy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: ubuntu:latest
|
|
||||||
options: --dns 127.0.0.1
|
|
||||||
services:
|
|
||||||
squid-proxy:
|
|
||||||
image: datadog/squid:latest
|
|
||||||
ports:
|
|
||||||
- 3128:3128
|
|
||||||
env:
|
|
||||||
https_proxy: http://squid-proxy:3128
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Clear tool cache
|
|
||||||
run: rm -rf $RUNNER_TOOL_CACHE/*
|
|
||||||
- name: Setup node 10
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
node-version: 10.x
|
|
||||||
- name: Verify node and npm
|
|
||||||
run: __tests__/verify-node.sh 10
|
|
||||||
|
|
||||||
test-bypass-proxy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
https_proxy: http://no-such-proxy:3128
|
|
||||||
no_proxy: github.com,nodejs.org,registry.npmjs.org
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Clear tool cache
|
|
||||||
run: rm -rf $RUNNER_TOOL_CACHE/*
|
|
||||||
- name: Setup node 10
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
node-version: 10.x
|
|
||||||
- name: Verify node and npm
|
|
||||||
run: __tests__/verify-node.sh 10
|
|
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
|
||||||
|
|
21
.vscode/launch.json
vendored
Normal file
21
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug Jest Tests on Nix",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"runtimeArgs": [
|
||||||
|
"--inspect-brk",
|
||||||
|
"${workspaceRoot}/node_modules/.bin/jest",
|
||||||
|
"--runInBand"
|
||||||
|
],
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"port": 9229
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,31 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`installer tests Appends trailing slash to registry 1`] = `
|
|
||||||
"//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}
|
|
||||||
registry=https://registry.npmjs.org/
|
|
||||||
always-auth=false"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`installer tests Automatically configures GPR scope 1`] = `
|
|
||||||
"npm.pkg.github.com/:_authToken=\${NODE_AUTH_TOKEN}
|
|
||||||
@ownername:registry=npm.pkg.github.com/
|
|
||||||
always-auth=false"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`installer tests Configures scoped npm registries 1`] = `
|
|
||||||
"//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}
|
|
||||||
@myscope:registry=https://registry.npmjs.org/
|
|
||||||
always-auth=false"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`installer tests Sets up npmrc for always-auth true 1`] = `
|
|
||||||
"//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}
|
|
||||||
registry=https://registry.npmjs.org/
|
|
||||||
always-auth=true"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`installer tests Sets up npmrc for npmjs 1`] = `
|
|
||||||
"//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}
|
|
||||||
registry=https://registry.npmjs.org/
|
|
||||||
always-auth=false"
|
|
||||||
`;
|
|
|
@ -1,22 +1,26 @@
|
||||||
import * as io from '@actions/io';
|
import os = require('os');
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
import * as io from '@actions/io';
|
||||||
import * as auth from '../src/authutil';
|
import * as auth from '../src/authutil';
|
||||||
|
|
||||||
let rcFile: string;
|
let rcFile: string;
|
||||||
|
|
||||||
describe('installer tests', () => {
|
describe('authutil tests', () => {
|
||||||
|
const _runnerDir = path.join(__dirname, 'runner');
|
||||||
|
|
||||||
|
let cnSpy: jest.SpyInstance;
|
||||||
|
let logSpy: jest.SpyInstance;
|
||||||
|
let dbgSpy: jest.SpyInstance;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const tempDir = path.join(
|
const randPath = path.join(
|
||||||
__dirname,
|
Math.random()
|
||||||
'runner',
|
.toString(36)
|
||||||
path.join(
|
.substring(7)
|
||||||
Math.random()
|
|
||||||
.toString(36)
|
|
||||||
.substring(7)
|
|
||||||
),
|
|
||||||
'temp'
|
|
||||||
);
|
);
|
||||||
|
const tempDir = path.join(_runnerDir, randPath, 'temp');
|
||||||
await io.rmRF(tempDir);
|
await io.rmRF(tempDir);
|
||||||
await io.mkdirP(tempDir);
|
await io.mkdirP(tempDir);
|
||||||
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
|
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
|
||||||
|
@ -24,44 +28,96 @@ describe('installer tests', () => {
|
||||||
rcFile = path.join(tempDir, '.npmrc');
|
rcFile = path.join(tempDir, '.npmrc');
|
||||||
}, 100000);
|
}, 100000);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
if (fs.existsSync(rcFile)) {
|
await io.rmRF(rcFile);
|
||||||
fs.unlinkSync(rcFile);
|
// if (fs.existsSync(rcFile)) {
|
||||||
}
|
// fs.unlinkSync(rcFile);
|
||||||
|
// }
|
||||||
process.env['INPUT_SCOPE'] = '';
|
process.env['INPUT_SCOPE'] = '';
|
||||||
});
|
|
||||||
|
// writes
|
||||||
|
cnSpy = jest.spyOn(process.stdout, 'write');
|
||||||
|
logSpy = jest.spyOn(console, 'log');
|
||||||
|
dbgSpy = jest.spyOn(core, 'debug');
|
||||||
|
cnSpy.mockImplementation(line => {
|
||||||
|
// uncomment to debug
|
||||||
|
// process.stderr.write('write:' + line + '\n');
|
||||||
|
});
|
||||||
|
logSpy.mockImplementation(line => {
|
||||||
|
// uncomment to debug
|
||||||
|
// process.stderr.write('log:' + line + '\n');
|
||||||
|
});
|
||||||
|
dbgSpy.mockImplementation(msg => {
|
||||||
|
// uncomment to see debug output
|
||||||
|
// process.stderr.write(msg + '\n');
|
||||||
|
});
|
||||||
|
}, 100000);
|
||||||
|
|
||||||
|
function dbg(message: string) {
|
||||||
|
process.stderr.write('dbg::' + message + '::\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
if (_runnerDir) {
|
||||||
|
await io.rmRF(_runnerDir);
|
||||||
|
}
|
||||||
|
}, 100000);
|
||||||
|
|
||||||
|
function readRcFile(rcFile: string) {
|
||||||
|
let rc = {};
|
||||||
|
let contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
|
||||||
|
for (const line of contents.split(os.EOL)) {
|
||||||
|
let parts = line.split('=');
|
||||||
|
if (parts.length == 2) {
|
||||||
|
rc[parts[0].trim()] = parts[1].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
it('Sets up npmrc for npmjs', async () => {
|
it('Sets up npmrc for npmjs', async () => {
|
||||||
await auth.configAuthentication('https://registry.npmjs.org/', 'false');
|
await auth.configAuthentication('https://registry.npmjs.org/', 'false');
|
||||||
expect(fs.existsSync(rcFile)).toBe(true);
|
|
||||||
expect(fs.readFileSync(rcFile, {encoding: 'utf8'})).toMatchSnapshot();
|
expect(fs.statSync(rcFile)).toBeDefined();
|
||||||
|
let contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
|
||||||
|
let rc = readRcFile(rcFile);
|
||||||
|
expect(rc['registry']).toBe('https://registry.npmjs.org/');
|
||||||
|
expect(rc['always-auth']).toBe('false');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Appends trailing slash to registry', async () => {
|
it('Appends trailing slash to registry', async () => {
|
||||||
await auth.configAuthentication('https://registry.npmjs.org', 'false');
|
await auth.configAuthentication('https://registry.npmjs.org', 'false');
|
||||||
|
|
||||||
expect(fs.existsSync(rcFile)).toBe(true);
|
expect(fs.statSync(rcFile)).toBeDefined();
|
||||||
expect(fs.readFileSync(rcFile, {encoding: 'utf8'})).toMatchSnapshot();
|
let rc = readRcFile(rcFile);
|
||||||
|
expect(rc['registry']).toBe('https://registry.npmjs.org/');
|
||||||
|
expect(rc['always-auth']).toBe('false');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Configures scoped npm registries', async () => {
|
it('Configures scoped npm registries', async () => {
|
||||||
process.env['INPUT_SCOPE'] = 'myScope';
|
process.env['INPUT_SCOPE'] = 'myScope';
|
||||||
await auth.configAuthentication('https://registry.npmjs.org', 'false');
|
await auth.configAuthentication('https://registry.npmjs.org', 'false');
|
||||||
|
|
||||||
expect(fs.existsSync(rcFile)).toBe(true);
|
expect(fs.statSync(rcFile)).toBeDefined();
|
||||||
expect(fs.readFileSync(rcFile, {encoding: 'utf8'})).toMatchSnapshot();
|
let rc = readRcFile(rcFile);
|
||||||
|
expect(rc['@myscope:registry']).toBe('https://registry.npmjs.org/');
|
||||||
|
expect(rc['always-auth']).toBe('false');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Automatically configures GPR scope', async () => {
|
it('Automatically configures GPR scope', async () => {
|
||||||
await auth.configAuthentication('npm.pkg.github.com', 'false');
|
await auth.configAuthentication('npm.pkg.github.com', 'false');
|
||||||
|
|
||||||
expect(fs.existsSync(rcFile)).toBe(true);
|
expect(fs.statSync(rcFile)).toBeDefined();
|
||||||
expect(fs.readFileSync(rcFile, {encoding: 'utf8'})).toMatchSnapshot();
|
let rc = readRcFile(rcFile);
|
||||||
|
expect(rc['@ownername:registry']).toBe('npm.pkg.github.com/');
|
||||||
|
expect(rc['always-auth']).toBe('false');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Sets up npmrc for always-auth true', async () => {
|
it('Sets up npmrc for always-auth true', async () => {
|
||||||
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
|
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
|
||||||
expect(fs.existsSync(rcFile)).toBe(true);
|
expect(fs.statSync(rcFile)).toBeDefined();
|
||||||
expect(fs.readFileSync(rcFile, {encoding: 'utf8'})).toMatchSnapshot();
|
let rc = readRcFile(rcFile);
|
||||||
|
expect(rc['registry']).toBe('https://registry.npmjs.org/');
|
||||||
|
expect(rc['always-auth']).toBe('true');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
770
__tests__/data/node-dist-index.json
Normal file
770
__tests__/data/node-dist-index.json
Normal file
|
@ -0,0 +1,770 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"version": "v14.1.0",
|
||||||
|
"date": "2020-04-29",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.14.4",
|
||||||
|
"v8": "8.1.307.31",
|
||||||
|
"uv": "1.37.0",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1g",
|
||||||
|
"modules": "83",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v14.0.0",
|
||||||
|
"date": "2020-04-21",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.14.4",
|
||||||
|
"v8": "8.1.307.30",
|
||||||
|
"uv": "1.37.0",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1f",
|
||||||
|
"modules": "83",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v13.14.0",
|
||||||
|
"date": "2020-04-28",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.14.4",
|
||||||
|
"v8": "7.9.317.25",
|
||||||
|
"uv": "1.37.0",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1g",
|
||||||
|
"modules": "79",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v13.13.0",
|
||||||
|
"date": "2020-04-14",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.14.4",
|
||||||
|
"v8": "7.9.317.25",
|
||||||
|
"uv": "1.35.0",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1f",
|
||||||
|
"modules": "79",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v12.16.3",
|
||||||
|
"date": "2020-04-28",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.14.4",
|
||||||
|
"v8": "7.8.279.23",
|
||||||
|
"uv": "1.34.2",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1g",
|
||||||
|
"modules": "72",
|
||||||
|
"lts": "Erbium",
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v12.16.2",
|
||||||
|
"date": "2020-04-08",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.14.4",
|
||||||
|
"v8": "7.8.279.23",
|
||||||
|
"uv": "1.34.2",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1e",
|
||||||
|
"modules": "72",
|
||||||
|
"lts": "Erbium",
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v12.1.0",
|
||||||
|
"date": "2019-04-29",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.9.0",
|
||||||
|
"v8": "7.4.288.21",
|
||||||
|
"uv": "1.28.0",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1b",
|
||||||
|
"modules": "72",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v11.15.0",
|
||||||
|
"date": "2019-04-30",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.7.0",
|
||||||
|
"v8": "7.0.276.38",
|
||||||
|
"uv": "1.27.0",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1b",
|
||||||
|
"modules": "67",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v10.20.1",
|
||||||
|
"date": "2020-04-10",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.14.4",
|
||||||
|
"v8": "6.8.275.32",
|
||||||
|
"uv": "1.34.2",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1e",
|
||||||
|
"modules": "64",
|
||||||
|
"lts": "Dubnium",
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v10.20.0",
|
||||||
|
"date": "2020-03-24",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.14.4",
|
||||||
|
"v8": "6.8.275.32",
|
||||||
|
"uv": "1.34.2",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.1.1e",
|
||||||
|
"modules": "64",
|
||||||
|
"lts": "Dubnium",
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v9.11.2",
|
||||||
|
"date": "2018-06-12",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "5.6.0",
|
||||||
|
"v8": "6.2.414.46",
|
||||||
|
"uv": "1.19.2",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2o",
|
||||||
|
"modules": "59",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v9.11.1",
|
||||||
|
"date": "2018-04-05",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "5.6.0",
|
||||||
|
"v8": "6.2.414.46",
|
||||||
|
"uv": "1.19.2",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2o",
|
||||||
|
"modules": "59",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v8.17.0",
|
||||||
|
"date": "2019-12-17",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.13.4",
|
||||||
|
"v8": "6.2.414.78",
|
||||||
|
"uv": "1.23.2",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2s",
|
||||||
|
"modules": "57",
|
||||||
|
"lts": "Carbon",
|
||||||
|
"security": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v8.16.2",
|
||||||
|
"date": "2019-10-08",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "6.4.1",
|
||||||
|
"v8": "6.2.414.78",
|
||||||
|
"uv": "1.23.2",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2s",
|
||||||
|
"modules": "57",
|
||||||
|
"lts": "Carbon",
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v7.10.1",
|
||||||
|
"date": "2017-07-11",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "4.2.0",
|
||||||
|
"v8": "5.5.372.43",
|
||||||
|
"uv": "1.11.0",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2k",
|
||||||
|
"modules": "51",
|
||||||
|
"lts": false,
|
||||||
|
"security": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v7.10.0",
|
||||||
|
"date": "2017-05-02",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "4.2.0",
|
||||||
|
"v8": "5.5.372.43",
|
||||||
|
"uv": "1.11.0",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2k",
|
||||||
|
"modules": "51",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v6.17.1",
|
||||||
|
"date": "2019-04-03",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "3.10.10",
|
||||||
|
"v8": "5.1.281.111",
|
||||||
|
"uv": "1.16.1",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2r",
|
||||||
|
"modules": "48",
|
||||||
|
"lts": "Boron",
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v6.17.0",
|
||||||
|
"date": "2019-02-28",
|
||||||
|
"files": [
|
||||||
|
"aix-ppc64",
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-s390x",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "3.10.10",
|
||||||
|
"v8": "5.1.281.111",
|
||||||
|
"uv": "1.16.1",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2r",
|
||||||
|
"modules": "48",
|
||||||
|
"lts": "Boron",
|
||||||
|
"security": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v5.12.0",
|
||||||
|
"date": "2016-06-23",
|
||||||
|
"files": [
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi"
|
||||||
|
],
|
||||||
|
"npm": "3.8.6",
|
||||||
|
"v8": "4.6.85.32",
|
||||||
|
"uv": "1.8.0",
|
||||||
|
"zlib": "1.2.8",
|
||||||
|
"openssl": "1.0.2h",
|
||||||
|
"modules": "47",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v4.9.1",
|
||||||
|
"date": "2018-03-29",
|
||||||
|
"files": [
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "2.15.11",
|
||||||
|
"v8": "4.5.103.53",
|
||||||
|
"uv": "1.9.1",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2o",
|
||||||
|
"modules": "46",
|
||||||
|
"lts": "Argon",
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v4.9.0",
|
||||||
|
"date": "2018-03-28",
|
||||||
|
"files": [
|
||||||
|
"headers",
|
||||||
|
"linux-arm64",
|
||||||
|
"linux-armv6l",
|
||||||
|
"linux-armv7l",
|
||||||
|
"linux-ppc64le",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-7z",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x64-msi",
|
||||||
|
"win-x64-zip",
|
||||||
|
"win-x86-7z",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi",
|
||||||
|
"win-x86-zip"
|
||||||
|
],
|
||||||
|
"npm": "2.15.11",
|
||||||
|
"v8": "4.5.103.53",
|
||||||
|
"uv": "1.9.1",
|
||||||
|
"zlib": "1.2.11",
|
||||||
|
"openssl": "1.0.2o",
|
||||||
|
"modules": "46",
|
||||||
|
"lts": "Argon",
|
||||||
|
"security": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v0.12.18",
|
||||||
|
"date": "2017-02-22",
|
||||||
|
"files": [
|
||||||
|
"headers",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"osx-x86-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi"
|
||||||
|
],
|
||||||
|
"npm": "2.15.11",
|
||||||
|
"v8": "3.28.71.20",
|
||||||
|
"uv": "1.6.1",
|
||||||
|
"zlib": "1.2.8",
|
||||||
|
"openssl": "1.0.1u",
|
||||||
|
"modules": "14",
|
||||||
|
"lts": false,
|
||||||
|
"security": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "v0.12.17",
|
||||||
|
"date": "2016-10-18",
|
||||||
|
"files": [
|
||||||
|
"headers",
|
||||||
|
"linux-x64",
|
||||||
|
"linux-x86",
|
||||||
|
"osx-x64-pkg",
|
||||||
|
"osx-x64-tar",
|
||||||
|
"osx-x86-tar",
|
||||||
|
"src",
|
||||||
|
"sunos-x64",
|
||||||
|
"sunos-x86",
|
||||||
|
"win-x64-exe",
|
||||||
|
"win-x86-exe",
|
||||||
|
"win-x86-msi"
|
||||||
|
],
|
||||||
|
"npm": "2.15.1",
|
||||||
|
"v8": "3.28.71.19",
|
||||||
|
"uv": "1.6.1",
|
||||||
|
"zlib": "1.2.8",
|
||||||
|
"openssl": "1.0.1u",
|
||||||
|
"modules": "14",
|
||||||
|
"lts": false,
|
||||||
|
"security": true
|
||||||
|
}
|
||||||
|
]
|
152
__tests__/data/versions-manifest.json
Normal file
152
__tests__/data/versions-manifest.json
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"version": "14.0.0",
|
||||||
|
"stable": true,
|
||||||
|
"release_url": "https://github.com/actions/node-versions/releases/tag/14.0.0-20200423.30",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"filename": "node-14.0.0-darwin-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "darwin",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/14.0.0-20200423.30/node-14.0.0-darwin-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-14.0.0-linux-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "linux",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/14.0.0-20200423.30/node-14.0.0-linux-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-14.0.0-win32-x64.zip",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "win32",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/14.0.0-20200423.30/node-14.0.0-win32-x64.zip"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "13.13.0",
|
||||||
|
"stable": true,
|
||||||
|
"release_url": "https://github.com/actions/node-versions/releases/tag/13.13.0-20200423.29",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"filename": "node-13.13.0-darwin-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "darwin",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/13.13.0-20200423.29/node-13.13.0-darwin-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-13.13.0-linux-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "linux",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/13.13.0-20200423.29/node-13.13.0-linux-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-13.13.0-win32-x64.zip",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "win32",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/13.13.0-20200423.29/node-13.13.0-win32-x64.zip"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "12.16.2",
|
||||||
|
"stable": true,
|
||||||
|
"release_url": "https://github.com/actions/node-versions/releases/tag/12.16.2-20200423.28",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"filename": "node-12.16.2-darwin-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "darwin",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-darwin-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-12.16.2-linux-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "linux",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-linux-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-12.16.2-win32-x64.zip",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "win32",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-win32-x64.zip"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "10.20.1",
|
||||||
|
"stable": true,
|
||||||
|
"release_url": "https://github.com/actions/node-versions/releases/tag/10.20.1-20200423.27",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"filename": "node-10.20.1-darwin-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "darwin",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/10.20.1-20200423.27/node-10.20.1-darwin-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-10.20.1-linux-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "linux",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/10.20.1-20200423.27/node-10.20.1-linux-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-10.20.1-win32-x64.zip",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "win32",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/10.20.1-20200423.27/node-10.20.1-win32-x64.zip"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "8.17.0",
|
||||||
|
"stable": true,
|
||||||
|
"release_url": "https://github.com/actions/node-versions/releases/tag/8.17.0-20200423.26",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"filename": "node-8.17.0-darwin-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "darwin",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/8.17.0-20200423.26/node-8.17.0-darwin-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-8.17.0-linux-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "linux",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/8.17.0-20200423.26/node-8.17.0-linux-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-8.17.0-win32-x64.zip",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "win32",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/8.17.0-20200423.26/node-8.17.0-win32-x64.zip"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "6.17.1",
|
||||||
|
"stable": true,
|
||||||
|
"release_url": "https://github.com/actions/node-versions/releases/tag/6.17.1-20200423.25",
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"filename": "node-6.17.1-darwin-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "darwin",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/6.17.1-20200423.25/node-6.17.1-darwin-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-6.17.1-linux-x64.tar.gz",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "linux",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/6.17.1-20200423.25/node-6.17.1-linux-x64.tar.gz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "node-6.17.1-win32-x64.zip",
|
||||||
|
"arch": "x64",
|
||||||
|
"platform": "win32",
|
||||||
|
"download_url": "https://github.com/actions/node-versions/releases/download/6.17.1-20200423.25/node-6.17.1-win32-x64.zip"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
|
@ -1,123 +1,336 @@
|
||||||
|
import * as core from '@actions/core';
|
||||||
import * as io from '@actions/io';
|
import * as io from '@actions/io';
|
||||||
import * as tc from '@actions/tool-cache';
|
import * as tc from '@actions/tool-cache';
|
||||||
import * as fs from 'fs';
|
import fs from 'fs';
|
||||||
import * as os from 'os';
|
import cp from 'child_process';
|
||||||
import * as path from 'path';
|
import osm = require('os');
|
||||||
import * as installer from '../src/installer';
|
import path from 'path';
|
||||||
|
import * as main from '../src/main';
|
||||||
|
import * as im from '../src/installer';
|
||||||
|
import * as auth from '../src/authutil';
|
||||||
|
|
||||||
const isWindows = process.platform === 'win32';
|
let nodeTestManifest = require('./data/versions-manifest.json');
|
||||||
let toolDir: string;
|
let nodeTestDist = require('./data/node-dist-index.json');
|
||||||
|
|
||||||
describe('installer tests', () => {
|
// let matchers = require('../matchers.json');
|
||||||
beforeAll(async () => {
|
// let matcherPattern = matchers.problemMatcher[0].pattern[0];
|
||||||
toolDir = path.join(
|
// let matcherRegExp = new RegExp(matcherPattern.regexp);
|
||||||
__dirname,
|
|
||||||
'runner',
|
describe('setup-node', () => {
|
||||||
path.join(
|
let inputs = {} as any;
|
||||||
Math.random()
|
let os = {} as any;
|
||||||
.toString(36)
|
|
||||||
.substring(7)
|
let inSpy: jest.SpyInstance;
|
||||||
),
|
let findSpy: jest.SpyInstance;
|
||||||
'tools'
|
let cnSpy: jest.SpyInstance;
|
||||||
|
let logSpy: jest.SpyInstance;
|
||||||
|
let getManifestSpy: jest.SpyInstance;
|
||||||
|
let getDistSpy: jest.SpyInstance;
|
||||||
|
let platSpy: jest.SpyInstance;
|
||||||
|
let archSpy: jest.SpyInstance;
|
||||||
|
let dlSpy: jest.SpyInstance;
|
||||||
|
let exSpy: jest.SpyInstance;
|
||||||
|
let cacheSpy: jest.SpyInstance;
|
||||||
|
let dbgSpy: jest.SpyInstance;
|
||||||
|
let whichSpy: jest.SpyInstance;
|
||||||
|
let existsSpy: jest.SpyInstance;
|
||||||
|
let mkdirpSpy: jest.SpyInstance;
|
||||||
|
let execSpy: jest.SpyInstance;
|
||||||
|
let authSpy: jest.SpyInstance;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// @actions/core
|
||||||
|
inputs = {};
|
||||||
|
inSpy = jest.spyOn(core, 'getInput');
|
||||||
|
inSpy.mockImplementation(name => inputs[name]);
|
||||||
|
|
||||||
|
// node
|
||||||
|
os = {};
|
||||||
|
platSpy = jest.spyOn(osm, 'platform');
|
||||||
|
platSpy.mockImplementation(() => os['platform']);
|
||||||
|
archSpy = jest.spyOn(osm, 'arch');
|
||||||
|
archSpy.mockImplementation(() => os['arch']);
|
||||||
|
execSpy = jest.spyOn(cp, 'execSync');
|
||||||
|
|
||||||
|
// @actions/tool-cache
|
||||||
|
findSpy = jest.spyOn(tc, 'find');
|
||||||
|
dlSpy = jest.spyOn(tc, 'downloadTool');
|
||||||
|
exSpy = jest.spyOn(tc, 'extractTar');
|
||||||
|
cacheSpy = jest.spyOn(tc, 'cacheDir');
|
||||||
|
getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo');
|
||||||
|
getDistSpy = jest.spyOn(im, 'getVersionsFromDist');
|
||||||
|
|
||||||
|
// io
|
||||||
|
whichSpy = jest.spyOn(io, 'which');
|
||||||
|
existsSpy = jest.spyOn(fs, 'existsSync');
|
||||||
|
mkdirpSpy = jest.spyOn(io, 'mkdirP');
|
||||||
|
|
||||||
|
// disable authentication portion for installer tests
|
||||||
|
authSpy = jest.spyOn(auth, 'configAuthentication');
|
||||||
|
authSpy.mockImplementation(() => {});
|
||||||
|
|
||||||
|
// gets
|
||||||
|
getManifestSpy.mockImplementation(
|
||||||
|
() => <tc.IToolRelease[]>nodeTestManifest
|
||||||
);
|
);
|
||||||
const tempDir = path.join(
|
getDistSpy.mockImplementation(() => <im.INodeVersion>nodeTestDist);
|
||||||
__dirname,
|
|
||||||
'runner',
|
// writes
|
||||||
path.join(
|
cnSpy = jest.spyOn(process.stdout, 'write');
|
||||||
Math.random()
|
logSpy = jest.spyOn(console, 'log');
|
||||||
.toString(36)
|
dbgSpy = jest.spyOn(core, 'debug');
|
||||||
.substring(7)
|
cnSpy.mockImplementation(line => {
|
||||||
),
|
// uncomment to debug
|
||||||
'temp'
|
// process.stderr.write('write:' + line + '\n');
|
||||||
|
});
|
||||||
|
logSpy.mockImplementation(line => {
|
||||||
|
// uncomment to debug
|
||||||
|
// process.stderr.write('log:' + line + '\n');
|
||||||
|
});
|
||||||
|
dbgSpy.mockImplementation(msg => {
|
||||||
|
// uncomment to see debug output
|
||||||
|
// process.stderr.write(msg + '\n');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.resetAllMocks();
|
||||||
|
jest.clearAllMocks();
|
||||||
|
//jest.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {}, 100000);
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// Manifest find tests
|
||||||
|
//--------------------------------------------------
|
||||||
|
it('can mock manifest versions', async () => {
|
||||||
|
let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo(
|
||||||
|
'actions',
|
||||||
|
'node-versions',
|
||||||
|
'mocktoken'
|
||||||
);
|
);
|
||||||
await io.rmRF(toolDir);
|
expect(versions).toBeDefined();
|
||||||
await io.rmRF(tempDir);
|
expect(versions?.length).toBe(6);
|
||||||
process.env['RUNNER_TOOL_CACHE'] = toolDir;
|
|
||||||
process.env['RUNNER_TEMP'] = tempDir;
|
|
||||||
}, 100000);
|
|
||||||
|
|
||||||
it('Acquires version of node if no matching version is installed', async () => {
|
|
||||||
await installer.getNode('10.16.0');
|
|
||||||
const nodeDir = path.join(toolDir, 'node', '10.16.0', os.arch());
|
|
||||||
|
|
||||||
expect(fs.existsSync(`${nodeDir}.complete`)).toBe(true);
|
|
||||||
if (isWindows) {
|
|
||||||
expect(fs.existsSync(path.join(nodeDir, 'node.exe'))).toBe(true);
|
|
||||||
} else {
|
|
||||||
expect(fs.existsSync(path.join(nodeDir, 'bin', 'node'))).toBe(true);
|
|
||||||
}
|
|
||||||
}, 100000);
|
|
||||||
|
|
||||||
if (isWindows) {
|
|
||||||
it('Falls back to backup location if first one doesnt contain correct version', async () => {
|
|
||||||
await installer.getNode('5.10.1');
|
|
||||||
const nodeDir = path.join(toolDir, 'node', '5.10.1', os.arch());
|
|
||||||
|
|
||||||
expect(fs.existsSync(`${nodeDir}.complete`)).toBe(true);
|
|
||||||
expect(fs.existsSync(path.join(nodeDir, 'node.exe'))).toBe(true);
|
|
||||||
}, 100000);
|
|
||||||
|
|
||||||
it('Falls back to third location if second one doesnt contain correct version', async () => {
|
|
||||||
await installer.getNode('0.12.18');
|
|
||||||
const nodeDir = path.join(toolDir, 'node', '0.12.18', os.arch());
|
|
||||||
|
|
||||||
expect(fs.existsSync(`${nodeDir}.complete`)).toBe(true);
|
|
||||||
expect(fs.existsSync(path.join(nodeDir, 'node.exe'))).toBe(true);
|
|
||||||
}, 100000);
|
|
||||||
}
|
|
||||||
|
|
||||||
it('Throws if no location contains correct node version', async () => {
|
|
||||||
let thrown = false;
|
|
||||||
try {
|
|
||||||
await installer.getNode('1000');
|
|
||||||
} catch {
|
|
||||||
thrown = true;
|
|
||||||
}
|
|
||||||
expect(thrown).toBe(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Acquires version of node with long paths', async () => {
|
it('can mock dist versions', async () => {
|
||||||
const toolpath = await installer.getNode('8.8.1');
|
let versions: im.INodeVersion[] = await im.getVersionsFromDist();
|
||||||
const nodeDir = path.join(toolDir, 'node', '8.8.1', os.arch());
|
expect(versions).toBeDefined();
|
||||||
|
expect(versions?.length).toBe(23);
|
||||||
expect(fs.existsSync(`${nodeDir}.complete`)).toBe(true);
|
|
||||||
if (isWindows) {
|
|
||||||
expect(fs.existsSync(path.join(nodeDir, 'node.exe'))).toBe(true);
|
|
||||||
} else {
|
|
||||||
expect(fs.existsSync(path.join(nodeDir, 'bin', 'node'))).toBe(true);
|
|
||||||
}
|
|
||||||
}, 100000);
|
|
||||||
|
|
||||||
it('Uses version of node installed in cache', async () => {
|
|
||||||
const nodeDir: string = path.join(toolDir, 'node', '250.0.0', os.arch());
|
|
||||||
await io.mkdirP(nodeDir);
|
|
||||||
fs.writeFileSync(`${nodeDir}.complete`, 'hello');
|
|
||||||
// This will throw if it doesn't find it in the cache (because no such version exists)
|
|
||||||
await installer.getNode('250.0.0');
|
|
||||||
return;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Doesnt use version of node that was only partially installed in cache', async () => {
|
it('can find 12.16.2 from manifest on osx', async () => {
|
||||||
const nodeDir: string = path.join(toolDir, 'node', '251.0.0', os.arch());
|
os.platform = 'darwin';
|
||||||
await io.mkdirP(nodeDir);
|
os.arch = 'x64';
|
||||||
let thrown = false;
|
let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo(
|
||||||
try {
|
'actions',
|
||||||
// This will throw if it doesn't find it in the cache (because no such version exists)
|
'node-versions',
|
||||||
await installer.getNode('251.0.0');
|
'mocktoken'
|
||||||
} catch {
|
);
|
||||||
thrown = true;
|
expect(versions).toBeDefined();
|
||||||
}
|
let match = await tc.findFromManifest('12.16.2', true, versions);
|
||||||
expect(thrown).toBe(true);
|
expect(match).toBeDefined();
|
||||||
return;
|
expect(match?.version).toBe('12.16.2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Resolves semantic versions of node installed in cache', async () => {
|
it('can find 12 from manifest on linux', async () => {
|
||||||
const nodeDir: string = path.join(toolDir, 'node', '252.0.0', os.arch());
|
os.platform = 'linux';
|
||||||
await io.mkdirP(nodeDir);
|
os.arch = 'x64';
|
||||||
fs.writeFileSync(`${nodeDir}.complete`, 'hello');
|
let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo(
|
||||||
// These will throw if it doesn't find it in the cache (because no such version exists)
|
'actions',
|
||||||
await installer.getNode('252.0.0');
|
'node-versions',
|
||||||
await installer.getNode('252');
|
'mocktoken'
|
||||||
await installer.getNode('252.0');
|
);
|
||||||
|
expect(versions).toBeDefined();
|
||||||
|
let match = await tc.findFromManifest('12.16.2', true, versions);
|
||||||
|
expect(match).toBeDefined();
|
||||||
|
expect(match?.version).toBe('12.16.2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can find 10 from manifest on windows', async () => {
|
||||||
|
os.platform = 'win32';
|
||||||
|
os.arch = 'x64';
|
||||||
|
let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo(
|
||||||
|
'actions',
|
||||||
|
'node-versions',
|
||||||
|
'mocktoken'
|
||||||
|
);
|
||||||
|
expect(versions).toBeDefined();
|
||||||
|
let match = await tc.findFromManifest('10', true, versions);
|
||||||
|
expect(match).toBeDefined();
|
||||||
|
expect(match?.version).toBe('10.20.1');
|
||||||
|
});
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// Found in cache tests
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
it('finds version in cache with stable true', async () => {
|
||||||
|
inputs['node-version'] = '12';
|
||||||
|
inputs.stable = 'true';
|
||||||
|
|
||||||
|
let toolPath = path.normalize('/cache/node/12.16.1/x64');
|
||||||
|
findSpy.mockImplementation(() => toolPath);
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('finds version in cache with stable not supplied', async () => {
|
||||||
|
inputs['node-version'] = '12';
|
||||||
|
|
||||||
|
inSpy.mockImplementation(name => inputs[name]);
|
||||||
|
|
||||||
|
let toolPath = path.normalize('/cache/node/12.16.1/x64');
|
||||||
|
findSpy.mockImplementation(() => toolPath);
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('finds version in cache and adds it to the path', async () => {
|
||||||
|
inputs['node-version'] = '12';
|
||||||
|
|
||||||
|
inSpy.mockImplementation(name => inputs[name]);
|
||||||
|
|
||||||
|
let toolPath = path.normalize('/cache/node/12.16.1/x64');
|
||||||
|
findSpy.mockImplementation(() => toolPath);
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
let expPath = path.join(toolPath, 'bin');
|
||||||
|
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles unhandled find error and reports error', async () => {
|
||||||
|
let errMsg = 'unhandled error message';
|
||||||
|
inputs['node-version'] = '12';
|
||||||
|
|
||||||
|
findSpy.mockImplementation(() => {
|
||||||
|
throw new Error(errMsg);
|
||||||
|
});
|
||||||
|
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
expect(cnSpy).toHaveBeenCalledWith('::error::' + errMsg + osm.EOL);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('downloads a version from a manifest match', async () => {
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
// a version which is in the manifest
|
||||||
|
let versionSpec = '12.16.2';
|
||||||
|
let resolvedVersion = versionSpec;
|
||||||
|
|
||||||
|
inputs['node-version'] = versionSpec;
|
||||||
|
inputs['always-auth'] = false;
|
||||||
|
inputs['token'] = 'faketoken';
|
||||||
|
|
||||||
|
let expectedUrl =
|
||||||
|
'https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-linux-x64.tar.gz';
|
||||||
|
|
||||||
|
// ... but not in the local cache
|
||||||
|
findSpy.mockImplementation(() => '');
|
||||||
|
|
||||||
|
dlSpy.mockImplementation(async () => '/some/temp/path');
|
||||||
|
let toolPath = path.normalize('/cache/node/12.16.2/x64');
|
||||||
|
exSpy.mockImplementation(async () => '/some/other/temp/path');
|
||||||
|
cacheSpy.mockImplementation(async () => toolPath);
|
||||||
|
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
let expPath = path.join(toolPath, 'bin');
|
||||||
|
|
||||||
|
expect(dlSpy).toHaveBeenCalled();
|
||||||
|
expect(exSpy).toHaveBeenCalled();
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Acquiring ${resolvedVersion} from ${expectedUrl}`
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Attempting to download ${versionSpec}...`
|
||||||
|
);
|
||||||
|
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('falls back to a version from node dist', async () => {
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
// a version which is not in the manifest but is in node dist
|
||||||
|
let versionSpec = '11.15.0';
|
||||||
|
let resolvedVersion = versionSpec;
|
||||||
|
|
||||||
|
inputs['node-version'] = versionSpec;
|
||||||
|
inputs['always-auth'] = false;
|
||||||
|
inputs['token'] = 'faketoken';
|
||||||
|
|
||||||
|
let expectedUrl =
|
||||||
|
'https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-linux-x64.tar.gz';
|
||||||
|
|
||||||
|
// ... but not in the local cache
|
||||||
|
findSpy.mockImplementation(() => '');
|
||||||
|
|
||||||
|
dlSpy.mockImplementation(async () => '/some/temp/path');
|
||||||
|
let toolPath = path.normalize('/cache/node/11.11.0/x64');
|
||||||
|
exSpy.mockImplementation(async () => '/some/other/temp/path');
|
||||||
|
cacheSpy.mockImplementation(async () => toolPath);
|
||||||
|
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
let expPath = path.join(toolPath, 'bin');
|
||||||
|
|
||||||
|
expect(dlSpy).toHaveBeenCalled();
|
||||||
|
expect(exSpy).toHaveBeenCalled();
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
'Not found in manifest. Falling back to download directly from Node'
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Attempting to download ${versionSpec}...`
|
||||||
|
);
|
||||||
|
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not find a version that does not exist', async () => {
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
let versionSpec = '9.99.9';
|
||||||
|
inputs['node-version'] = versionSpec;
|
||||||
|
|
||||||
|
findSpy.mockImplementation(() => '');
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
'Not found in manifest. Falling back to download directly from Node'
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Attempting to download ${versionSpec}...`
|
||||||
|
);
|
||||||
|
expect(cnSpy).toHaveBeenCalledWith(
|
||||||
|
`::error::Unable to find Node version '${versionSpec}' for platform ${os.platform} and architecture ${os.arch}.${osm.EOL}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reports a failed download', async () => {
|
||||||
|
let errMsg = 'unhandled download message';
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
// a version which is in the manifest
|
||||||
|
let versionSpec = '12.16.2';
|
||||||
|
let resolvedVersion = versionSpec;
|
||||||
|
|
||||||
|
inputs['node-version'] = versionSpec;
|
||||||
|
inputs['always-auth'] = false;
|
||||||
|
inputs['token'] = 'faketoken';
|
||||||
|
|
||||||
|
findSpy.mockImplementation(() => '');
|
||||||
|
dlSpy.mockImplementation(() => {
|
||||||
|
throw new Error(errMsg);
|
||||||
|
});
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
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: '12.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'
|
||||||
|
|
1625
dist/index.js
vendored
1625
dist/index.js
vendored
File diff suppressed because it is too large
Load diff
3877
package-lock.json
generated
3877
package-lock.json
generated
File diff suppressed because it is too large
Load diff
12
package.json
12
package.json
|
@ -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",
|
||||||
|
@ -28,7 +28,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.4",
|
||||||
"semver": "^6.1.1"
|
"semver": "^6.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -36,10 +36,10 @@
|
||||||
"@types/node": "^12.0.4",
|
"@types/node": "^12.0.4",
|
||||||
"@types/semver": "^6.0.0",
|
"@types/semver": "^6.0.0",
|
||||||
"@zeit/ncc": "^0.21.0",
|
"@zeit/ncc": "^0.21.0",
|
||||||
"jest": "^24.8.0",
|
"jest": "^24.9.0",
|
||||||
"jest-circus": "^24.7.1",
|
"jest-circus": "^24.7.1",
|
||||||
"prettier": "^1.17.1",
|
"prettier": "^1.19.1",
|
||||||
"ts-jest": "^24.0.2",
|
"ts-jest": "^24.3.0",
|
||||||
"typescript": "^3.5.1"
|
"typescript": "^3.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
286
src/installer.ts
286
src/installer.ts
|
@ -1,54 +1,130 @@
|
||||||
|
import os = require('os');
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as hc from '@actions/http-client';
|
import * as hc from '@actions/http-client';
|
||||||
import * as io from '@actions/io';
|
import * as io from '@actions/io';
|
||||||
import * as tc from '@actions/tool-cache';
|
import * as tc from '@actions/tool-cache';
|
||||||
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 fs = require('fs');
|
||||||
let osPlat: string = os.platform();
|
|
||||||
let osArch: string = translateArchToDistUrl(os.arch());
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Node versions interface
|
// Node versions interface
|
||||||
// see https://nodejs.org/dist/index.json
|
// see https://nodejs.org/dist/index.json
|
||||||
//
|
//
|
||||||
interface INodeVersion {
|
export interface INodeVersion {
|
||||||
version: string;
|
version: string;
|
||||||
files: string[];
|
files: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getNode(versionSpec: string) {
|
interface INodeVersionInfo {
|
||||||
|
downloadUrl: string;
|
||||||
|
resolvedVersion: string;
|
||||||
|
fileName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getNode(
|
||||||
|
versionSpec: string,
|
||||||
|
stable: boolean,
|
||||||
|
auth: string | undefined
|
||||||
|
) {
|
||||||
|
let osPlat: string = os.platform();
|
||||||
|
let osArch: string = translateArchToDistUrl(os.arch());
|
||||||
|
|
||||||
// check cache
|
// check cache
|
||||||
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) || '';
|
} else {
|
||||||
// If explicit version
|
console.log(`Attempting to download ${versionSpec}...`);
|
||||||
if (semver.valid(c) != null) {
|
let downloadPath = '';
|
||||||
// version to download
|
let info: INodeVersionInfo | null = null;
|
||||||
version = versionSpec;
|
|
||||||
} else {
|
//
|
||||||
// query nodejs.org for a matching version
|
// Try download from internal distribution (popular versions only)
|
||||||
version = await queryLatestMatch(versionSpec);
|
//
|
||||||
if (!version) {
|
try {
|
||||||
|
info = await getInfoFromManifest(versionSpec, stable, auth);
|
||||||
|
if (info) {
|
||||||
|
console.log(
|
||||||
|
`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`
|
||||||
|
);
|
||||||
|
downloadPath = await tc.downloadTool(info.downloadUrl, undefined, auth);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
'Not found in manifest. Falling back to download directly from Node'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// Rate limit?
|
||||||
|
if (
|
||||||
|
err instanceof tc.HTTPError &&
|
||||||
|
(err.httpStatusCode === 403 || err.httpStatusCode === 429)
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.log(err.message);
|
||||||
|
}
|
||||||
|
core.debug(err.stack);
|
||||||
|
console.log('Falling back to download directly from Node');
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Download from nodejs.org
|
||||||
|
//
|
||||||
|
if (!downloadPath) {
|
||||||
|
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);
|
try {
|
||||||
|
downloadPath = await tc.downloadTool(info.downloadUrl);
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
|
||||||
|
return await acquireNodeFromFallbackLocation(info.resolvedVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!toolPath) {
|
//
|
||||||
// download, extract, cache
|
// Extract
|
||||||
toolPath = await acquireNode(version);
|
//
|
||||||
|
console.log('Extracting ...');
|
||||||
|
let extPath: string;
|
||||||
|
info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here
|
||||||
|
if (osPlat == 'win32') {
|
||||||
|
let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
|
||||||
|
extPath = await tc.extract7z(downloadPath, undefined, _7zPath);
|
||||||
|
// 7z extracts to folder matching file name
|
||||||
|
let nestedPath = path.join(extPath, path.basename(info.fileName, '.7z'));
|
||||||
|
if (fs.existsSync(nestedPath)) {
|
||||||
|
extPath = nestedPath;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
extPath = await tc.extractTar(downloadPath, undefined, [
|
||||||
|
'xz',
|
||||||
|
'--strip',
|
||||||
|
'1'
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
|
||||||
|
//
|
||||||
|
console.log('Adding to the cache ...');
|
||||||
|
toolPath = await tc.cacheDir(extPath, 'node', info.resolvedVersion);
|
||||||
|
console.log('Done');
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -65,41 +141,60 @@ export async function getNode(versionSpec: string) {
|
||||||
core.addPath(toolPath);
|
core.addPath(toolPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function queryLatestMatch(versionSpec: string): Promise<string> {
|
async function getInfoFromManifest(
|
||||||
// node offers a json list of versions
|
versionSpec: string,
|
||||||
let dataFileName: string;
|
stable: boolean,
|
||||||
switch (osPlat) {
|
auth: string | undefined
|
||||||
case 'linux':
|
): Promise<INodeVersionInfo | null> {
|
||||||
dataFileName = `linux-${osArch}`;
|
let info: INodeVersionInfo | null = null;
|
||||||
break;
|
const releases = await tc.getManifestFromRepo(
|
||||||
case 'darwin':
|
'actions',
|
||||||
dataFileName = `osx-${osArch}-tar`;
|
'node-versions',
|
||||||
break;
|
auth
|
||||||
case 'win32':
|
);
|
||||||
dataFileName = `win-${osArch}-exe`;
|
console.log(`matching ${versionSpec}...`);
|
||||||
break;
|
const rel = await tc.findFromManifest(versionSpec, stable, releases);
|
||||||
default:
|
|
||||||
throw new Error(`Unexpected OS '${osPlat}'`);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
let versions: string[] = [];
|
return info;
|
||||||
let dataUrl = 'https://nodejs.org/dist/index.json';
|
}
|
||||||
let httpClient = new hc.HttpClient('setup-node', [], {
|
|
||||||
allowRetries: true,
|
|
||||||
maxRetries: 3
|
|
||||||
});
|
|
||||||
let response = await httpClient.getJson<INodeVersion[]>(dataUrl);
|
|
||||||
let nodeVersions = response.result || [];
|
|
||||||
nodeVersions.forEach((nodeVersion: INodeVersion) => {
|
|
||||||
// ensure this version supports your os and platform
|
|
||||||
if (nodeVersion.files.indexOf(dataFileName) >= 0) {
|
|
||||||
versions.push(nodeVersion.version);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// get the latest version that matches the version spec
|
async function getInfoFromDist(
|
||||||
let version: string = evaluateVersions(versions, versionSpec);
|
versionSpec: string
|
||||||
return version;
|
): Promise<INodeVersionInfo | null> {
|
||||||
|
let osPlat: string = os.platform();
|
||||||
|
let osArch: string = translateArchToDistUrl(os.arch());
|
||||||
|
|
||||||
|
let version: string;
|
||||||
|
|
||||||
|
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
|
// TODO - should we just export this from @actions/tool-cache? Lifted directly from there
|
||||||
|
@ -130,47 +225,49 @@ function evaluateVersions(versions: string[], versionSpec: string): string {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function acquireNode(version: string): Promise<string> {
|
async function queryDistForMatch(versionSpec: string): Promise<string> {
|
||||||
//
|
let osPlat: string = os.platform();
|
||||||
// Download - a tool installer intimately knows how to get the tool (and construct urls)
|
let osArch: string = translateArchToDistUrl(os.arch());
|
||||||
//
|
|
||||||
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;
|
// node offers a json list of versions
|
||||||
|
let dataFileName: string;
|
||||||
|
switch (osPlat) {
|
||||||
|
case 'linux':
|
||||||
|
dataFileName = `linux-${osArch}`;
|
||||||
|
break;
|
||||||
|
case 'darwin':
|
||||||
|
dataFileName = `osx-${osArch}-tar`;
|
||||||
|
break;
|
||||||
|
case 'win32':
|
||||||
|
dataFileName = `win-${osArch}-exe`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unexpected OS '${osPlat}'`);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
let versions: string[] = [];
|
||||||
downloadPath = await tc.downloadTool(downloadUrl);
|
let nodeVersions = await module.exports.getVersionsFromDist();
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
|
nodeVersions.forEach((nodeVersion: INodeVersion) => {
|
||||||
return await acquireNodeFromFallbackLocation(version);
|
// ensure this version supports your os and platform
|
||||||
|
if (nodeVersion.files.indexOf(dataFileName) >= 0) {
|
||||||
|
versions.push(nodeVersion.version);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
throw err;
|
// get the latest version that matches the version spec
|
||||||
}
|
let version: string = evaluateVersions(versions, versionSpec);
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
export async function getVersionsFromDist(): Promise<INodeVersion[]> {
|
||||||
// Extract
|
let dataUrl = 'https://nodejs.org/dist/index.json';
|
||||||
//
|
let httpClient = new hc.HttpClient('setup-node', [], {
|
||||||
let extPath: string;
|
allowRetries: true,
|
||||||
if (osPlat == 'win32') {
|
maxRetries: 3
|
||||||
let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
|
});
|
||||||
extPath = await tc.extract7z(downloadPath, undefined, _7zPath);
|
let response = await httpClient.getJson<INodeVersion[]>(dataUrl);
|
||||||
} else {
|
return response.result || [];
|
||||||
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
|
||||||
|
@ -188,6 +285,9 @@ async function acquireNode(version: string): Promise<string> {
|
||||||
async function acquireNodeFromFallbackLocation(
|
async function acquireNodeFromFallbackLocation(
|
||||||
version: string
|
version: string
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
|
let osPlat: string = os.platform();
|
||||||
|
let osArch: string = translateArchToDistUrl(os.arch());
|
||||||
|
|
||||||
// Create temporary folder to download in to
|
// Create temporary folder to download in to
|
||||||
const tempDownloadFolder: string =
|
const tempDownloadFolder: string =
|
||||||
'temp_' + Math.floor(Math.random() * 2000000000);
|
'temp_' + Math.floor(Math.random() * 2000000000);
|
||||||
|
@ -201,6 +301,8 @@ async function acquireNodeFromFallbackLocation(
|
||||||
exeUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.exe`;
|
exeUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.exe`;
|
||||||
libUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.lib`;
|
libUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.lib`;
|
||||||
|
|
||||||
|
console.log(`Downloading only node binary from ${exeUrl}`);
|
||||||
|
|
||||||
const exePath = await tc.downloadTool(exeUrl);
|
const exePath = await tc.downloadTool(exeUrl);
|
||||||
await io.cp(exePath, path.join(tempDir, 'node.exe'));
|
await io.cp(exePath, path.join(tempDir, 'node.exe'));
|
||||||
const libPath = await tc.downloadTool(libUrl);
|
const libPath = await tc.downloadTool(libUrl);
|
||||||
|
@ -218,7 +320,9 @@ async function acquireNodeFromFallbackLocation(
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return await tc.cacheDir(tempDir, 'node', version);
|
let toolPath = await tc.cacheDir(tempDir, 'node', version);
|
||||||
|
core.addPath(toolPath);
|
||||||
|
return toolPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
// os.arch does not always match the relative download url, e.g.
|
// os.arch does not always match the relative download url, e.g.
|
||||||
|
|
50
src/main.ts
Normal file
50
src/main.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
import * as installer from './installer';
|
||||||
|
import * as auth from './authutil';
|
||||||
|
import * as path from 'path';
|
||||||
|
import {URL} from 'url';
|
||||||
|
|
||||||
|
export async function run() {
|
||||||
|
try {
|
||||||
|
//
|
||||||
|
// 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');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`version: ${version}`);
|
||||||
|
if (version) {
|
||||||
|
let token = core.getInput('token');
|
||||||
|
let auth = !token || isGhes() ? undefined : `token ${token}`;
|
||||||
|
let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
|
||||||
|
await installer.getNode(version, stable, auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
const registryUrl: string = core.getInput('registry-url');
|
||||||
|
const alwaysAuth: string = core.getInput('always-auth');
|
||||||
|
if (registryUrl) {
|
||||||
|
auth.configAuthentication(registryUrl, alwaysAuth);
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchersPath = path.join(__dirname, '..', '.github');
|
||||||
|
console.log(`##[add-matcher]${path.join(matchersPath, 'tsc.json')}`);
|
||||||
|
console.log(
|
||||||
|
`##[add-matcher]${path.join(matchersPath, 'eslint-stylish.json')}`
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
`##[add-matcher]${path.join(matchersPath, 'eslint-compact.json')}`
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isGhes(): boolean {
|
||||||
|
const ghUrl = new URL(
|
||||||
|
process.env['GITHUB_SERVER_URL'] || 'https://github.com'
|
||||||
|
);
|
||||||
|
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
|
||||||
|
}
|
|
@ -1,49 +1,3 @@
|
||||||
import * as core from '@actions/core';
|
import {run} from './main';
|
||||||
import * as exec from '@actions/exec';
|
|
||||||
import * as io from '@actions/io';
|
|
||||||
import * as installer from './installer';
|
|
||||||
import * as auth from './authutil';
|
|
||||||
import * as path from 'path';
|
|
||||||
|
|
||||||
async function run() {
|
|
||||||
try {
|
|
||||||
//
|
|
||||||
// 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');
|
|
||||||
if (!version) {
|
|
||||||
version = core.getInput('node-version');
|
|
||||||
}
|
|
||||||
if (version) {
|
|
||||||
await installer.getNode(version);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output version of node and npm that are being used
|
|
||||||
await exec.exec('node', ['--version']);
|
|
||||||
|
|
||||||
// Older versions of Node don't include npm, so don't let this call fail
|
|
||||||
await exec.exec('npm', ['--version'], {
|
|
||||||
ignoreReturnCode: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const registryUrl: string = core.getInput('registry-url');
|
|
||||||
const alwaysAuth: string = core.getInput('always-auth');
|
|
||||||
if (registryUrl) {
|
|
||||||
auth.configAuthentication(registryUrl, alwaysAuth);
|
|
||||||
}
|
|
||||||
|
|
||||||
const matchersPath = path.join(__dirname, '..', '.github');
|
|
||||||
console.log(`##[add-matcher]${path.join(matchersPath, 'tsc.json')}`);
|
|
||||||
console.log(
|
|
||||||
`##[add-matcher]${path.join(matchersPath, 'eslint-stylish.json')}`
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
`##[add-matcher]${path.join(matchersPath, 'eslint-compact.json')}`
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
core.setFailed(error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
],
|
],
|
||||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
|
"sourceMap": true,
|
||||||
"strict": true, /* Enable all strict type-checking options. */
|
"strict": true, /* Enable all strict type-checking options. */
|
||||||
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||||
|
|
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" #"0.12.7" #"12" #"11.15.0"
|
||||||
|
# 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
|
Loading…
Reference in a new issue