Compare commits

...

12 Commits

Author SHA1 Message Date
efab84ad3c dist 2020-05-02 11:12:54 -04:00
8a1d983ace format 2020-05-02 11:08:26 -04:00
22c0aea623 cya snapshot 2020-05-02 11:06:05 -04:00
1c2f59fb67 format 2020-05-02 10:46:48 -04:00
ec6092f7d2 dbg 2020-05-02 10:45:32 -04:00
889def385d update ts-jest 2020-05-02 10:38:09 -04:00
8885b7194e updated tests 2020-05-02 09:51:47 -04:00
ecf0ce62f9 wip 2020-04-24 08:58:38 -04:00
339aa41a8d Readme update 2020-04-16 18:43:02 -04:00
641e88986e add code of conduct 2020-04-16 14:00:00 -04:00
83c9f7a7df Update tool-cache for download retries (#120) 2020-03-10 11:51:57 -04:00
ada4b782b3 chore: Use checkout@v2 for code examples (#107) 2020-02-06 14:52:33 -05:00
20 changed files with 6122 additions and 1233 deletions

View File

@ -40,6 +40,20 @@ jobs:
- 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:

3
.gitignore vendored
View File

@ -2,6 +2,9 @@ node_modules/
lib/
__tests__/runner/*
validate/temp
validate/node
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
# Logs
logs

21
.vscode/launch.json vendored Normal file
View 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
}
]
}

76
CONDUCT Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all project spaces, and it also applies when
an individual is representing the project or its community in public spaces.
Examples of representing a project or community include using an official
project e-mail address, posting via an official social media account, or acting
as an appointed representative at an online or offline event. Representation of
a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at opensource@github.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@ -16,7 +16,7 @@ See [action.yml](action.yml)
Basic:
```yaml
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '10.x'
@ -34,7 +34,7 @@ jobs:
node: [ '10', '8' ]
name: Node ${{ matrix.node }} sample
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v1
with:
@ -46,7 +46,7 @@ jobs:
Publish to npmjs and GPR with npm:
```yaml
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '10.x'
@ -66,7 +66,7 @@ steps:
Publish to npmjs and GPR with yarn:
```yaml
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '10.x'
@ -86,7 +86,7 @@ steps:
Use private packages:
```yaml
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '10.x'
@ -108,3 +108,7 @@ The scripts and documentation in this project are released under the [MIT Licens
# Contributions
Contributions are welcome! See [Contributor's Guide](docs/contributors.md)
## Code of Conduct
:wave: Be nice. See [our code of conduct](CONDUCT)

View File

@ -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"
`;

View File

@ -1,68 +1,123 @@
import io = require('@actions/io');
import fs = require('fs');
import path = require('path');
const tempDir = path.join(
__dirname,
'runner',
path.join(
Math.random()
.toString(36)
.substring(7)
),
'temp'
);
const rcFile = path.join(tempDir, '.npmrc');
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
process.env['RUNNER_TEMP'] = tempDir;
import os = require('os');
import * as fs from 'fs';
import * as path from 'path';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as auth from '../src/authutil';
describe('installer tests', () => {
let rcFile: string;
describe('authutil tests', () => {
const _runnerDir = path.join(__dirname, 'runner');
let cnSpy: jest.SpyInstance;
let logSpy: jest.SpyInstance;
let dbgSpy: jest.SpyInstance;
beforeAll(async () => {
const randPath = path.join(
Math.random()
.toString(36)
.substring(7)
);
const tempDir = path.join(_runnerDir, randPath, 'temp');
await io.rmRF(tempDir);
await io.mkdirP(tempDir);
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
process.env['RUNNER_TEMP'] = tempDir;
rcFile = path.join(tempDir, '.npmrc');
}, 100000);
beforeEach(() => {
if (fs.existsSync(rcFile)) {
fs.unlinkSync(rcFile);
}
beforeEach(async () => {
await io.rmRF(rcFile);
// if (fs.existsSync(rcFile)) {
// fs.unlinkSync(rcFile);
// }
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 () => {
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 () => {
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 rc = readRcFile(rcFile);
expect(rc['registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('false');
});
it('Configures scoped npm registries', async () => {
process.env['INPUT_SCOPE'] = 'myScope';
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 rc = readRcFile(rcFile);
expect(rc['@myscope:registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('false');
});
it('Automatically configures GPR scope', async () => {
await auth.configAuthentication('npm.pkg.github.com', 'false');
expect(fs.existsSync(rcFile)).toBe(true);
expect(fs.readFileSync(rcFile, {encoding: 'utf8'})).toMatchSnapshot();
expect(fs.statSync(rcFile)).toBeDefined();
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 () => {
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
expect(fs.existsSync(rcFile)).toBe(true);
expect(fs.readFileSync(rcFile, {encoding: 'utf8'})).toMatchSnapshot();
expect(fs.statSync(rcFile)).toBeDefined();
let rc = readRcFile(rcFile);
expect(rc['registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('true');
});
});

View 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
}
]

View 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"
}
]
}
]

View File

@ -1,123 +1,336 @@
import io = require('@actions/io');
import fs = require('fs');
import os = require('os');
import path = require('path');
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as tc from '@actions/tool-cache';
import fs from 'fs';
import cp from 'child_process';
import osm = require('os');
import path from 'path';
import * as main from '../src/main';
import * as im from '../src/installer';
import * as auth from '../src/authutil';
const toolDir = path.join(
__dirname,
'runner',
path.join(
Math.random()
.toString(36)
.substring(7)
),
'tools'
);
const tempDir = path.join(
__dirname,
'runner',
path.join(
Math.random()
.toString(36)
.substring(7)
),
'temp'
);
let nodeTestManifest = require('./data/versions-manifest.json');
let nodeTestDist = require('./data/node-dist-index.json');
process.env['RUNNER_TOOL_CACHE'] = toolDir;
process.env['RUNNER_TEMP'] = tempDir;
import * as installer from '../src/installer';
// let matchers = require('../matchers.json');
// let matcherPattern = matchers.problemMatcher[0].pattern[0];
// let matcherRegExp = new RegExp(matcherPattern.regexp);
const IS_WINDOWS = process.platform === 'win32';
describe('setup-node', () => {
let inputs = {} as any;
let os = {} as any;
describe('installer tests', () => {
beforeAll(async () => {
await io.rmRF(toolDir);
await io.rmRF(tempDir);
}, 100000);
let inSpy: jest.SpyInstance;
let findSpy: jest.SpyInstance;
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;
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());
beforeEach(() => {
// @actions/core
inputs = {};
inSpy = jest.spyOn(core, 'getInput');
inSpy.mockImplementation(name => inputs[name]);
expect(fs.existsSync(`${nodeDir}.complete`)).toBe(true);
if (IS_WINDOWS) {
expect(fs.existsSync(path.join(nodeDir, 'node.exe'))).toBe(true);
} else {
expect(fs.existsSync(path.join(nodeDir, 'bin', 'node'))).toBe(true);
}
}, 100000);
// 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');
if (IS_WINDOWS) {
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());
// @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');
expect(fs.existsSync(`${nodeDir}.complete`)).toBe(true);
expect(fs.existsSync(path.join(nodeDir, 'node.exe'))).toBe(true);
}, 100000);
// io
whichSpy = jest.spyOn(io, 'which');
existsSpy = jest.spyOn(fs, 'existsSync');
mkdirpSpy = jest.spyOn(io, 'mkdirP');
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());
// disable authentication portion for installer tests
authSpy = jest.spyOn(auth, 'configAuthentication');
authSpy.mockImplementation(() => {});
expect(fs.existsSync(`${nodeDir}.complete`)).toBe(true);
expect(fs.existsSync(path.join(nodeDir, 'node.exe'))).toBe(true);
}, 100000);
}
// gets
getManifestSpy.mockImplementation(
() => <tc.IToolRelease[]>nodeTestManifest
);
getDistSpy.mockImplementation(() => <im.INodeVersion>nodeTestDist);
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);
// 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');
});
});
it('Acquires version of node with long paths', async () => {
const toolpath = await installer.getNode('8.8.1');
const nodeDir = path.join(toolDir, 'node', '8.8.1', os.arch());
expect(fs.existsSync(`${nodeDir}.complete`)).toBe(true);
if (IS_WINDOWS) {
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;
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
//jest.restoreAllMocks();
});
it('Doesnt use version of node that was only partially installed in cache', async () => {
const nodeDir: string = path.join(toolDir, 'node', '251.0.0', os.arch());
await io.mkdirP(nodeDir);
let thrown = false;
try {
// This will throw if it doesn't find it in the cache (because no such version exists)
await installer.getNode('251.0.0');
} catch {
thrown = true;
}
expect(thrown).toBe(true);
return;
afterAll(async () => {}, 100000);
//--------------------------------------------------
// Manifest find tests
//--------------------------------------------------
it('can mock manifest versions', async () => {
let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo(
'actions',
'node-versions',
'mocktoken'
);
expect(versions).toBeDefined();
expect(versions?.length).toBe(6);
});
it('Resolves semantic versions of node installed in cache', async () => {
const nodeDir: string = path.join(toolDir, 'node', '252.0.0', os.arch());
await io.mkdirP(nodeDir);
fs.writeFileSync(`${nodeDir}.complete`, 'hello');
// These will throw if it doesn't find it in the cache (because no such version exists)
await installer.getNode('252.0.0');
await installer.getNode('252');
await installer.getNode('252.0');
it('can mock dist versions', async () => {
let versions: im.INodeVersion[] = await im.getVersionsFromDist();
expect(versions).toBeDefined();
expect(versions?.length).toBe(23);
});
it('can find 12.16.2 from manifest on osx', async () => {
os.platform = 'darwin';
os.arch = 'x64';
let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo(
'actions',
'node-versions',
'mocktoken'
);
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 12 from manifest on linux', async () => {
os.platform = 'linux';
os.arch = 'x64';
let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo(
'actions',
'node-versions',
'mocktoken'
);
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}`);
});
});

View File

@ -7,13 +7,17 @@ fi
node_version="$(node --version)"
echo "Found node version '$node_version'"
if [ -z "$(echo $node_version | grep v$1)" ]; then
if [ -z "$(echo $node_version | grep --fixed-strings v$1)" ]; then
echo "Unexpected version"
exit 1
fi
echo "Testing npm install"
mkdir -p test-npm-install
cd test-npm-install
npm init -y || exit 1
npm install @actions/core || exit 1
if [ -z "$2" ]; then
echo "Testing npm install"
mkdir -p test-npm-install
cd test-npm-install
npm init -y || exit 1
npm install @actions/core || exit 1
else
echo "Skip testing npm"
fi

View File

@ -1,17 +1,21 @@
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'
inputs:
always-auth:
description: 'Set always-auth in npmrc'
default: 'false'
node-version:
description: 'Version Spec of the version to use. Examples: 10.x, 10.15.1, >=10.15.0'
default: '10.x'
description: 'Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0'
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'
scope:
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
version:
description: 'Deprecated. Use node-version instead. Will not be supported after October 1, 2019'

1442
dist/index.js vendored

File diff suppressed because it is too large Load Diff

3876
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "setup-node",
"version": "1.0.0",
"version": "2.0.0",
"private": true,
"description": "setup node action",
"main": "lib/setup-node.js",
@ -27,7 +27,7 @@
"@actions/github": "^1.1.0",
"@actions/http-client": "^1.0.6",
"@actions/io": "^1.0.2",
"@actions/tool-cache": "^1.3.1",
"@actions/tool-cache": "^1.5.2",
"semver": "^6.1.1"
},
"devDependencies": {
@ -35,10 +35,10 @@
"@types/node": "^12.0.4",
"@types/semver": "^6.0.0",
"@zeit/ncc": "^0.21.0",
"jest": "^24.8.0",
"jest": "^24.9.0",
"jest-circus": "^24.7.1",
"prettier": "^1.17.1",
"ts-jest": "^24.0.2",
"typescript": "^3.5.1"
"prettier": "^1.19.1",
"ts-jest": "^24.3.0",
"typescript": "^3.8.3"
}
}

View File

@ -1,71 +1,89 @@
// Load tempDirectory before it gets wiped by tool-cache
let tempDirectory = process.env['RUNNER_TEMPDIRECTORY'] || '';
import os = require('os');
import * as assert from 'assert';
import * as core from '@actions/core';
import * as hc from '@actions/http-client';
import * as io from '@actions/io';
import * as tc from '@actions/tool-cache';
import * as os from 'os';
import * as path from 'path';
import * as semver from 'semver';
let osPlat: string = os.platform();
let osArch: string = translateArchToDistUrl(os.arch());
if (!tempDirectory) {
let baseLocation;
if (process.platform === 'win32') {
// On windows use the USERPROFILE env variable
baseLocation = process.env['USERPROFILE'] || 'C:\\';
} else {
if (process.platform === 'darwin') {
baseLocation = '/Users';
} else {
baseLocation = '/home';
}
}
tempDirectory = path.join(baseLocation, 'actions', 'temp');
}
import {Url} from 'url';
//
// Node versions interface
// see https://nodejs.org/dist/index.json
//
interface INodeVersion {
export interface INodeVersion {
version: string;
files: string[];
}
export async function getNode(versionSpec: string) {
interface INodeVersionInfo {
downloadUrl: string;
token: string | null;
resolvedVersion: string;
fileName: string;
}
export async function getNode(
versionSpec: string,
stable: boolean,
token: string
) {
let osPlat: string = os.platform();
let osArch: string = translateArchToDistUrl(os.arch());
// check cache
let info: INodeVersionInfo | null = null;
let toolPath: string;
toolPath = tc.find('node', versionSpec);
// If not found in cache, download
if (!toolPath) {
let version: string;
const c = semver.clean(versionSpec) || '';
// If explicit version
if (semver.valid(c) != null) {
// version to download
version = versionSpec;
} else {
// query nodejs.org for a matching version
version = await queryLatestMatch(versionSpec);
if (!version) {
throw new Error(
`Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`
);
if (toolPath) {
console.log(`Found in cache @ ${toolPath}`);
} else {
console.log(`Attempting to download ${versionSpec}...`);
let info = await getInfoFromManifest(versionSpec, stable, token);
if (!info) {
console.log(
'Not found in manifest. Falling back to download directly from Node'
);
info = await getInfoFromDist(versionSpec);
}
if (!info) {
throw new Error(
`Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`
);
}
console.log(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`);
let downloadPath = '';
try {
downloadPath = await tc.downloadTool(info.downloadUrl, undefined, token);
} catch (err) {
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
return await acquireNodeFromFallbackLocation(info.resolvedVersion);
}
// check cache
toolPath = tc.find('node', version);
throw err;
}
if (!toolPath) {
// download, extract, cache
toolPath = await acquireNode(version);
//
// Extract
//
let extPath: string;
if (osPlat == 'win32') {
let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
extPath = await tc.extract7z(downloadPath, undefined, _7zPath);
} else {
extPath = await tc.extractTar(downloadPath);
}
//
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
//
toolPath = await tc.cacheDir(extPath, 'node', info.resolvedVersion);
}
//
@ -82,41 +100,62 @@ export async function getNode(versionSpec: string) {
core.addPath(toolPath);
}
async function queryLatestMatch(versionSpec: string): Promise<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}'`);
async function getInfoFromManifest(
versionSpec: string,
stable: boolean,
token: string
): Promise<INodeVersionInfo | null> {
let info: INodeVersionInfo | null = null;
const releases = await tc.getManifestFromRepo(
'actions',
'node-versions',
token
);
console.log(`matching ${versionSpec}...`);
const rel = await tc.findFromManifest(versionSpec, stable, releases);
if (rel && rel.files.length > 0) {
info = <INodeVersionInfo>{};
info.resolvedVersion = rel.version;
info.downloadUrl = rel.files[0].download_url;
info.fileName = rel.files[0].filename;
info.token = token;
}
let versions: string[] = [];
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);
}
});
return info;
}
// get the latest version that matches the version spec
let version: string = evaluateVersions(versions, versionSpec);
return version;
async function getInfoFromDist(
versionSpec: string
): Promise<INodeVersionInfo | null> {
let osPlat: string = os.platform();
let osArch: string = translateArchToDistUrl(os.arch());
let info: INodeVersionInfo | null = null;
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
@ -147,47 +186,49 @@ function evaluateVersions(versions: string[], versionSpec: string): string {
return version;
}
async function acquireNode(version: string): Promise<string> {
//
// Download - a tool installer intimately knows how to get the tool (and construct urls)
//
version = semver.clean(version) || '';
let fileName: string =
osPlat == 'win32'
? `node-v${version}-win-${osArch}`
: `node-v${version}-${osPlat}-${osArch}`;
let urlFileName: string =
osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`;
let downloadUrl = `https://nodejs.org/dist/v${version}/${urlFileName}`;
async function queryDistForMatch(versionSpec: string): Promise<string> {
let osPlat: string = os.platform();
let osArch: string = translateArchToDistUrl(os.arch());
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 {
downloadPath = await tc.downloadTool(downloadUrl);
} catch (err) {
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
return await acquireNodeFromFallbackLocation(version);
let versions: string[] = [];
let nodeVersions = await module.exports.getVersionsFromDist();
nodeVersions.forEach((nodeVersion: INodeVersion) => {
// 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;
}
//
// Extract
//
let extPath: string;
if (osPlat == 'win32') {
let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
extPath = await tc.extract7z(downloadPath, undefined, _7zPath);
} else {
extPath = await tc.extractTar(downloadPath);
}
//
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
//
let toolRoot = path.join(extPath, fileName);
return await tc.cacheDir(toolRoot, 'node', version);
export async function getVersionsFromDist(): Promise<INodeVersion[]> {
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);
return response.result || [];
}
// For non LTS versions of Node, the files we need (for Windows) are sometimes located
@ -205,10 +246,15 @@ async function acquireNode(version: string): Promise<string> {
async function acquireNodeFromFallbackLocation(
version: string
): Promise<string> {
let osPlat: string = os.platform();
let osArch: string = translateArchToDistUrl(os.arch());
// Create temporary folder to download in to
let tempDownloadFolder: string =
const tempDownloadFolder: string =
'temp_' + Math.floor(Math.random() * 2000000000);
let tempDir: string = path.join(tempDirectory, tempDownloadFolder);
const tempDirectory = process.env['RUNNER_TEMP'] || '';
assert.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined');
const tempDir: string = path.join(tempDirectory, tempDownloadFolder);
await io.mkdirP(tempDir);
let exeUrl: string;
let libUrl: string;

41
src/main.ts Normal file
View File

@ -0,0 +1,41 @@
import * as core from '@actions/core';
import * as installer from './installer';
import * as auth from './authutil';
import * as path from 'path';
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 stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
await installer.getNode(version, stable, token);
}
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);
}
}

View File

@ -1,39 +1,3 @@
import * as core from '@actions/core';
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);
}
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);
}
}
import {run} from './main';
run();

View File

@ -7,6 +7,7 @@
],
"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. */
"sourceMap": true,
"strict": true, /* Enable all strict type-checking options. */
"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'. */

22
validate/test.sh Executable file
View File

@ -0,0 +1,22 @@
#/bin/bash
set -e
rm -rf ./temp
rm -rf ./node
# uncomment to use charles proxy or other debugging proxy
# export NODE_TLS_REJECT_UNAUTHORIZED=0
# export https_proxy=http://127.0.0.1:8888
export RUNNER_TOOL_CACHE=$(pwd)
export RUNNER_TEMP="${RUNNER_TOOL_CACHE}/temp"
export INPUT_STABLE=true
export INPUT_VERSION="12.x"
# export your PAT with repo scope before running
export INPUT_TOKEN=$GITHUB_TOKEN
echo "Getting ${INPUT_VERSION} ($INPUT_STABLE) with ${INPUT_TOKEN}..."
node ../dist/index.js