Compare commits
22 Commits
Author | SHA1 | Date |
---|---|---|
Konrad Pabjan | 60c1140889 | |
Maxim Lobanov | 321b6ccb03 | |
Maxim Lobanov | 1ae8f4b1fd | |
Bryan MacFarlane | 0e2f9cde8b | |
Bryan MacFarlane | e434342e4e | |
Bryan MacFarlane | 7c6182c745 | |
Bryan MacFarlane | a47b2f66c6 | |
Bryan MacFarlane | 89ea387bde | |
Josh Gross | 44c9c18728 | |
Josh Gross | e715d9a456 | |
Josh Gross | b1f2e78536 | |
Josh Gross | 55897e37f3 | |
Josh Gross | 46903d1fb1 | |
Josh Gross | 28505ad4d3 | |
Josh Gross | 2d53d29868 | |
Josh Gross | 1e163ded31 | |
Josh Gross | ffde538781 | |
Charlie Fish | 0cc027b656 | |
Josh Gross | e99a7e62b2 | |
Josh Gross | 0dc69b3a71 | |
Josh Gross | 52eb8a7524 | |
Nick Schonning | 6b7f6c9fa6 |
|
@ -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, macos-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
|
|
@ -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
|
|
@ -0,0 +1,99 @@
|
||||||
|
name: versions
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- releases/*
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
local-cache:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
node-version: [10, 12, 14]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Setup Node
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- name: Verify node and npm
|
||||||
|
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
manifest:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
node-version: [10.15, 12.16.0, 14.2.0]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Setup Node
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- name: Verify node and npm
|
||||||
|
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
check-latest:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
node-version: [10, 11, 12, 14]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Setup Node and check latest
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
check-latest: true
|
||||||
|
- name: Verify node and npm
|
||||||
|
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
node-dist:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
node-version: [11, 13]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Setup Node from dist
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- name: Verify node and npm
|
||||||
|
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
old-versions:
|
||||||
|
runs-on: ${{ matrix.operating-system }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
operating-system: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
# 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
|
||||||
|
run: __tests__/verify-node.sh 0.12.18 SKIP_NPM
|
||||||
|
shell: bash
|
|
@ -1,94 +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: ubuntu-latest
|
|
||||||
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
|
|
42
README.md
42
README.md
|
@ -1,13 +1,30 @@
|
||||||
# setup-node
|
# setup-node
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://github.com/actions/setup-node"><img alt="GitHub Actions status" src="https://github.com/actions/setup-node/workflows/Main%20workflow/badge.svg"></a>
|
<a href="https://github.com/actions/setup-node/actions?query=workflow%3Abuild-test"><img alt="build-test status" src="https://github.com/actions/setup-node/workflows/build-test/badge.svg"></a> <a href="https://github.com/actions/setup-node/actions?query=workflow%3Aversions"><img alt="versions status" src="https://github.com/actions/setup-node/workflows/versions/badge.svg"></a> <a href="https://github.com/actions/setup-node/actions?query=workflow%3Aproxy"><img alt="proxy status" src="https://github.com/actions/setup-node/workflows/proxy/badge.svg"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
This action sets by node environment for use in actions by:
|
This action sets by node environment for use in actions by:
|
||||||
|
|
||||||
- optionally downloading and caching a version of node - npm by version spec and add to PATH
|
- optionally downloading and caching a version of node - npm by version spec and add to PATH
|
||||||
- registering problem matchers for error output
|
- registering problem matchers for error output
|
||||||
|
- configuring authentication for GPR or npm
|
||||||
|
|
||||||
|
# v2-beta
|
||||||
|
|
||||||
|
A beta release which adds reliability for pulling node distributions from a cache of node releases is available by referencing the `v2-beta` tag.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v2-beta
|
||||||
|
with:
|
||||||
|
node-version: '12'
|
||||||
|
```
|
||||||
|
|
||||||
|
The action will first check the local cache for a semver match. The hosted images have been updated with the latest of each LTS from v8, v10, v12, and v14. `self-hosted` machines will benefit from the cache as well only downloading once. The action will pull LTS versions from [node-versions releases](https://github.com/actions/node-versions/releases) and on miss or failure will fall back to the previous behavior of downloading directly from [node dist](https://nodejs.org/dist/).
|
||||||
|
|
||||||
|
The `node-version` input is optional. If not supplied, the node version that is PATH will be used. However, this action will still register problem matchers and support auth features. So setting up the node environment is still a valid scenario without downloading and caching versions.
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
|
@ -19,7 +36,26 @@ steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: '10.x'
|
node-version: '12'
|
||||||
|
- run: npm install
|
||||||
|
- run: npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
Check latest version:
|
||||||
|
|
||||||
|
In the basic example above, the `check-latest` flag defaults to `false`. When set to `false`, the action tries to first resolve a version of node from the local cache. For information regarding locally cached versions of Node on GitHub hosted runners, check out [GitHub Actions Virtual Environments](https://github.com/actions/virtual-environments). The local version of Node in cache gets updated every couple of weeks. If unable to find a specific version in the cache, the action will then attempt to download a version of Node. Use the default or set `check-latest` to `false` if you prefer stability and if you want to ensure a specific version of Node is always used.
|
||||||
|
|
||||||
|
If `check-latest` is set to `true`, the action first checks if the cached version is the latest one. If the locally cached version is not the most up-to-date, a version of Node will then be downloaded. Set `check-latest` to `true` it you want the most up-to-date version of Node to always be used.
|
||||||
|
|
||||||
|
> Setting `check-latest` to `true` has performance implications as downloading versions of Node is slower than using cached versions
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: '12'
|
||||||
|
check-latest: true
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm test
|
- run: npm test
|
||||||
```
|
```
|
||||||
|
@ -31,7 +67,7 @@ jobs:
|
||||||
runs-on: ubuntu-16.04
|
runs-on: ubuntu-16.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [ '10', '8' ]
|
node: [ '10', '12' ]
|
||||||
name: Node ${{ matrix.node }} sample
|
name: Node ${{ matrix.node }} sample
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
|
@ -8,6 +8,7 @@ import path from 'path';
|
||||||
import * as main from '../src/main';
|
import * as main from '../src/main';
|
||||||
import * as im from '../src/installer';
|
import * as im from '../src/installer';
|
||||||
import * as auth from '../src/authutil';
|
import * as auth from '../src/authutil';
|
||||||
|
import {context} from '@actions/github';
|
||||||
|
|
||||||
let nodeTestManifest = require('./data/versions-manifest.json');
|
let nodeTestManifest = require('./data/versions-manifest.json');
|
||||||
let nodeTestDist = require('./data/node-dist-index.json');
|
let nodeTestDist = require('./data/node-dist-index.json');
|
||||||
|
@ -24,6 +25,7 @@ describe('setup-node', () => {
|
||||||
let findSpy: jest.SpyInstance;
|
let findSpy: jest.SpyInstance;
|
||||||
let cnSpy: jest.SpyInstance;
|
let cnSpy: jest.SpyInstance;
|
||||||
let logSpy: jest.SpyInstance;
|
let logSpy: jest.SpyInstance;
|
||||||
|
let warningSpy: jest.SpyInstance;
|
||||||
let getManifestSpy: jest.SpyInstance;
|
let getManifestSpy: jest.SpyInstance;
|
||||||
let getDistSpy: jest.SpyInstance;
|
let getDistSpy: jest.SpyInstance;
|
||||||
let platSpy: jest.SpyInstance;
|
let platSpy: jest.SpyInstance;
|
||||||
|
@ -77,8 +79,9 @@ describe('setup-node', () => {
|
||||||
|
|
||||||
// writes
|
// writes
|
||||||
cnSpy = jest.spyOn(process.stdout, 'write');
|
cnSpy = jest.spyOn(process.stdout, 'write');
|
||||||
logSpy = jest.spyOn(console, 'log');
|
logSpy = jest.spyOn(core, 'info');
|
||||||
dbgSpy = jest.spyOn(core, 'debug');
|
dbgSpy = jest.spyOn(core, 'debug');
|
||||||
|
warningSpy = jest.spyOn(core, 'warning');
|
||||||
cnSpy.mockImplementation(line => {
|
cnSpy.mockImplementation(line => {
|
||||||
// uncomment to debug
|
// uncomment to debug
|
||||||
// process.stderr.write('write:' + line + '\n');
|
// process.stderr.write('write:' + line + '\n');
|
||||||
|
@ -333,4 +336,154 @@ describe('setup-node', () => {
|
||||||
|
|
||||||
expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`);
|
expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('check-latest flag', () => {
|
||||||
|
it('use local version and dont check manifest if check-latest is not specified', async () => {
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
inputs['node-version'] = '12';
|
||||||
|
inputs['check-latest'] = 'false';
|
||||||
|
|
||||||
|
const toolPath = path.normalize('/cache/node/12.16.1/x64');
|
||||||
|
findSpy.mockReturnValue(toolPath);
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
|
||||||
|
expect(logSpy).not.toHaveBeenCalledWith(
|
||||||
|
'Attempt to resolve the latest version from manifest...'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('check latest version and resolve it from local cache', async () => {
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
inputs['node-version'] = '12';
|
||||||
|
inputs['check-latest'] = 'true';
|
||||||
|
|
||||||
|
const toolPath = path.normalize('/cache/node/12.16.2/x64');
|
||||||
|
findSpy.mockReturnValue(toolPath);
|
||||||
|
dlSpy.mockImplementation(async () => '/some/temp/path');
|
||||||
|
exSpy.mockImplementation(async () => '/some/other/temp/path');
|
||||||
|
cacheSpy.mockImplementation(async () => toolPath);
|
||||||
|
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
'Attempt to resolve the latest version from manifest...'
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'");
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('check latest version and install it from manifest', async () => {
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
inputs['node-version'] = '12';
|
||||||
|
inputs['check-latest'] = 'true';
|
||||||
|
|
||||||
|
findSpy.mockImplementation(() => '');
|
||||||
|
dlSpy.mockImplementation(async () => '/some/temp/path');
|
||||||
|
const toolPath = path.normalize('/cache/node/12.16.2/x64');
|
||||||
|
exSpy.mockImplementation(async () => '/some/other/temp/path');
|
||||||
|
cacheSpy.mockImplementation(async () => toolPath);
|
||||||
|
const expectedUrl =
|
||||||
|
'https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-linux-x64.tar.gz';
|
||||||
|
|
||||||
|
await main.run();
|
||||||
|
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
'Attempt to resolve the latest version from manifest...'
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'");
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Acquiring 12.16.2 from ${expectedUrl}`
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith('Extracting ...');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fallback to dist if version if not found in manifest', async () => {
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
// a version which is not in the manifest but is in node dist
|
||||||
|
let versionSpec = '11';
|
||||||
|
|
||||||
|
inputs['node-version'] = versionSpec;
|
||||||
|
inputs['check-latest'] = 'true';
|
||||||
|
inputs['always-auth'] = false;
|
||||||
|
inputs['token'] = 'faketoken';
|
||||||
|
|
||||||
|
// ... 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(
|
||||||
|
'Attempt to resolve the latest version from manifest...'
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Failed to resolve version ${versionSpec} from manifest`
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Attempting to download ${versionSpec}...`
|
||||||
|
);
|
||||||
|
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('fallback to dist if manifest is not available', async () => {
|
||||||
|
os.platform = 'linux';
|
||||||
|
os.arch = 'x64';
|
||||||
|
|
||||||
|
// a version which is not in the manifest but is in node dist
|
||||||
|
let versionSpec = '12';
|
||||||
|
|
||||||
|
inputs['node-version'] = versionSpec;
|
||||||
|
inputs['check-latest'] = 'true';
|
||||||
|
inputs['always-auth'] = false;
|
||||||
|
inputs['token'] = 'faketoken';
|
||||||
|
|
||||||
|
// ... but not in the local cache
|
||||||
|
findSpy.mockImplementation(() => '');
|
||||||
|
getManifestSpy.mockImplementation(() => {
|
||||||
|
throw new Error('Unable to download manifest');
|
||||||
|
});
|
||||||
|
|
||||||
|
dlSpy.mockImplementation(async () => '/some/temp/path');
|
||||||
|
let toolPath = path.normalize('/cache/node/12.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(
|
||||||
|
'Attempt to resolve the latest version from manifest...'
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
'Unable to resolve version from manifest...'
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Failed to resolve version ${versionSpec} from manifest`
|
||||||
|
);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(
|
||||||
|
`Attempting to download ${versionSpec}...`
|
||||||
|
);
|
||||||
|
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,9 @@ inputs:
|
||||||
default: 'false'
|
default: 'false'
|
||||||
node-version:
|
node-version:
|
||||||
description: 'Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0'
|
description: 'Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0'
|
||||||
|
check-latest:
|
||||||
|
description: 'Set this option if you want the action to check for the latest available version that satisfies the version spec'
|
||||||
|
default: false
|
||||||
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:
|
||||||
|
|
|
@ -563,13 +563,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||||
|
result["default"] = mod;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const os = __webpack_require__(87);
|
const os = __importStar(__webpack_require__(87));
|
||||||
const events = __webpack_require__(614);
|
const events = __importStar(__webpack_require__(614));
|
||||||
const child = __webpack_require__(129);
|
const child = __importStar(__webpack_require__(129));
|
||||||
const path = __webpack_require__(622);
|
const path = __importStar(__webpack_require__(622));
|
||||||
const io = __webpack_require__(1);
|
const io = __importStar(__webpack_require__(1));
|
||||||
const ioUtil = __webpack_require__(672);
|
const ioUtil = __importStar(__webpack_require__(672));
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
const IS_WINDOWS = process.platform === 'win32';
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
/*
|
/*
|
||||||
|
@ -1013,6 +1020,12 @@ class ToolRunner extends events.EventEmitter {
|
||||||
resolve(exitCode);
|
resolve(exitCode);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (this.options.input) {
|
||||||
|
if (!cp.stdin) {
|
||||||
|
throw new Error('child process missing stdin');
|
||||||
|
}
|
||||||
|
cp.stdin.end(this.options.input);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1325,7 +1338,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const semver = __importStar(__webpack_require__(280));
|
const semver = __importStar(__webpack_require__(280));
|
||||||
const core_1 = __webpack_require__(470);
|
const core_1 = __webpack_require__(902);
|
||||||
// needs to be require for core node modules to be mocked
|
// needs to be require for core node modules to be mocked
|
||||||
/* eslint @typescript-eslint/no-require-imports: 0 */
|
/* eslint @typescript-eslint/no-require-imports: 0 */
|
||||||
const os = __webpack_require__(87);
|
const os = __webpack_require__(87);
|
||||||
|
@ -4618,6 +4631,7 @@ const core = __importStar(__webpack_require__(470));
|
||||||
const installer = __importStar(__webpack_require__(749));
|
const installer = __importStar(__webpack_require__(749));
|
||||||
const auth = __importStar(__webpack_require__(202));
|
const auth = __importStar(__webpack_require__(202));
|
||||||
const path = __importStar(__webpack_require__(622));
|
const path = __importStar(__webpack_require__(622));
|
||||||
|
const url_1 = __webpack_require__(835);
|
||||||
function run() {
|
function run() {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
try {
|
try {
|
||||||
|
@ -4629,11 +4643,12 @@ function run() {
|
||||||
if (!version) {
|
if (!version) {
|
||||||
version = core.getInput('version');
|
version = core.getInput('version');
|
||||||
}
|
}
|
||||||
console.log(`version: ${version}`);
|
|
||||||
if (version) {
|
if (version) {
|
||||||
let token = core.getInput('token');
|
let token = core.getInput('token');
|
||||||
|
let auth = !token || isGhes() ? undefined : `token ${token}`;
|
||||||
let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
|
let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
|
||||||
yield installer.getNode(version, stable, token);
|
const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE';
|
||||||
|
yield installer.getNode(version, stable, checkLatest, auth);
|
||||||
}
|
}
|
||||||
const registryUrl = core.getInput('registry-url');
|
const registryUrl = core.getInput('registry-url');
|
||||||
const alwaysAuth = core.getInput('always-auth');
|
const alwaysAuth = core.getInput('always-auth');
|
||||||
|
@ -4651,6 +4666,10 @@ function run() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.run = run;
|
exports.run = run;
|
||||||
|
function isGhes() {
|
||||||
|
const ghUrl = new url_1.URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
|
||||||
|
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
|
||||||
|
}
|
||||||
//# sourceMappingURL=main.js.map
|
//# sourceMappingURL=main.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
@ -10870,7 +10889,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(__webpack_require__(470));
|
const core = __importStar(__webpack_require__(902));
|
||||||
const io = __importStar(__webpack_require__(1));
|
const io = __importStar(__webpack_require__(1));
|
||||||
const fs = __importStar(__webpack_require__(747));
|
const fs = __importStar(__webpack_require__(747));
|
||||||
const mm = __importStar(__webpack_require__(31));
|
const mm = __importStar(__webpack_require__(31));
|
||||||
|
@ -10899,9 +10918,10 @@ const userAgent = 'actions/tool-cache';
|
||||||
*
|
*
|
||||||
* @param url url of tool to download
|
* @param url url of tool to download
|
||||||
* @param dest path to download tool
|
* @param dest path to download tool
|
||||||
|
* @param auth authorization header
|
||||||
* @returns path to downloaded tool
|
* @returns path to downloaded tool
|
||||||
*/
|
*/
|
||||||
function downloadTool(url, dest, token) {
|
function downloadTool(url, dest, auth) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
dest = dest || path.join(_getTempDirectory(), v4_1.default());
|
dest = dest || path.join(_getTempDirectory(), v4_1.default());
|
||||||
yield io.mkdirP(path.dirname(dest));
|
yield io.mkdirP(path.dirname(dest));
|
||||||
|
@ -10912,7 +10932,7 @@ function downloadTool(url, dest, token) {
|
||||||
const maxSeconds = _getGlobal('TEST_DOWNLOAD_TOOL_RETRY_MAX_SECONDS', 20);
|
const maxSeconds = _getGlobal('TEST_DOWNLOAD_TOOL_RETRY_MAX_SECONDS', 20);
|
||||||
const retryHelper = new retry_helper_1.RetryHelper(maxAttempts, minSeconds, maxSeconds);
|
const retryHelper = new retry_helper_1.RetryHelper(maxAttempts, minSeconds, maxSeconds);
|
||||||
return yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
return yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () {
|
||||||
return yield downloadToolAttempt(url, dest || '', token);
|
return yield downloadToolAttempt(url, dest || '', auth);
|
||||||
}), (err) => {
|
}), (err) => {
|
||||||
if (err instanceof HTTPError && err.httpStatusCode) {
|
if (err instanceof HTTPError && err.httpStatusCode) {
|
||||||
// Don't retry anything less than 500, except 408 Request Timeout and 429 Too Many Requests
|
// Don't retry anything less than 500, except 408 Request Timeout and 429 Too Many Requests
|
||||||
|
@ -10928,7 +10948,7 @@ function downloadTool(url, dest, token) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.downloadTool = downloadTool;
|
exports.downloadTool = downloadTool;
|
||||||
function downloadToolAttempt(url, dest, token) {
|
function downloadToolAttempt(url, dest, auth) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (fs.existsSync(dest)) {
|
if (fs.existsSync(dest)) {
|
||||||
throw new Error(`Destination file path ${dest} already exists`);
|
throw new Error(`Destination file path ${dest} already exists`);
|
||||||
|
@ -10938,9 +10958,10 @@ function downloadToolAttempt(url, dest, token) {
|
||||||
allowRetries: false
|
allowRetries: false
|
||||||
});
|
});
|
||||||
let headers;
|
let headers;
|
||||||
if (token) {
|
if (auth) {
|
||||||
|
core.debug('set auth');
|
||||||
headers = {
|
headers = {
|
||||||
authorization: `token ${token}`
|
authorization: auth
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const response = yield http.get(url, headers);
|
const response = yield http.get(url, headers);
|
||||||
|
@ -10998,9 +11019,10 @@ function extract7z(file, dest, _7zPath) {
|
||||||
process.chdir(dest);
|
process.chdir(dest);
|
||||||
if (_7zPath) {
|
if (_7zPath) {
|
||||||
try {
|
try {
|
||||||
|
const logLevel = core.isDebug() ? '-bb1' : '-bb0';
|
||||||
const args = [
|
const args = [
|
||||||
'x',
|
'x',
|
||||||
'-bb1',
|
logLevel,
|
||||||
'-bd',
|
'-bd',
|
||||||
'-sccUTF-8',
|
'-sccUTF-8',
|
||||||
file
|
file
|
||||||
|
@ -11076,7 +11098,16 @@ function extractTar(file, dest, flags = 'xz') {
|
||||||
core.debug(versionOutput.trim());
|
core.debug(versionOutput.trim());
|
||||||
const isGnuTar = versionOutput.toUpperCase().includes('GNU TAR');
|
const isGnuTar = versionOutput.toUpperCase().includes('GNU TAR');
|
||||||
// Initialize args
|
// Initialize args
|
||||||
const args = [flags];
|
let args;
|
||||||
|
if (flags instanceof Array) {
|
||||||
|
args = flags;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args = [flags];
|
||||||
|
}
|
||||||
|
if (core.isDebug() && !flags.includes('v')) {
|
||||||
|
args.push('-v');
|
||||||
|
}
|
||||||
let destArg = dest;
|
let destArg = dest;
|
||||||
let fileArg = file;
|
let fileArg = file;
|
||||||
if (IS_WINDOWS && isGnuTar) {
|
if (IS_WINDOWS && isGnuTar) {
|
||||||
|
@ -11126,7 +11157,7 @@ function extractZipWin(file, dest) {
|
||||||
const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, '');
|
const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, '');
|
||||||
const command = `$ErrorActionPreference = 'Stop' ; try { Add-Type -AssemblyName System.IO.Compression.FileSystem } catch { } ; [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}')`;
|
const command = `$ErrorActionPreference = 'Stop' ; try { Add-Type -AssemblyName System.IO.Compression.FileSystem } catch { } ; [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}')`;
|
||||||
// run powershell
|
// run powershell
|
||||||
const powershellPath = yield io.which('powershell');
|
const powershellPath = yield io.which('powershell', true);
|
||||||
const args = [
|
const args = [
|
||||||
'-NoLogo',
|
'-NoLogo',
|
||||||
'-Sta',
|
'-Sta',
|
||||||
|
@ -11142,8 +11173,12 @@ function extractZipWin(file, dest) {
|
||||||
}
|
}
|
||||||
function extractZipNix(file, dest) {
|
function extractZipNix(file, dest) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const unzipPath = yield io.which('unzip');
|
const unzipPath = yield io.which('unzip', true);
|
||||||
yield exec_1.exec(`"${unzipPath}"`, [file], { cwd: dest });
|
const args = [file];
|
||||||
|
if (!core.isDebug()) {
|
||||||
|
args.unshift('-q');
|
||||||
|
}
|
||||||
|
yield exec_1.exec(`"${unzipPath}"`, args, { cwd: dest });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -11271,14 +11306,16 @@ function findAllVersions(toolName, arch) {
|
||||||
return versions;
|
return versions;
|
||||||
}
|
}
|
||||||
exports.findAllVersions = findAllVersions;
|
exports.findAllVersions = findAllVersions;
|
||||||
function getManifestFromRepo(owner, repo, token, branch = 'master') {
|
function getManifestFromRepo(owner, repo, auth, branch = 'master') {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let releases = [];
|
let releases = [];
|
||||||
const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}`;
|
const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}`;
|
||||||
const http = new httpm.HttpClient('tool-cache');
|
const http = new httpm.HttpClient('tool-cache');
|
||||||
const headers = {
|
const headers = {};
|
||||||
authorization: `token ${token}`
|
if (auth) {
|
||||||
};
|
core.debug('set auth');
|
||||||
|
headers.authorization = auth;
|
||||||
|
}
|
||||||
const response = yield http.getJson(treeUrl, headers);
|
const response = yield http.getJson(treeUrl, headers);
|
||||||
if (!response.result) {
|
if (!response.result) {
|
||||||
return releases;
|
return releases;
|
||||||
|
@ -12956,54 +12993,105 @@ const io = __importStar(__webpack_require__(1));
|
||||||
const tc = __importStar(__webpack_require__(533));
|
const tc = __importStar(__webpack_require__(533));
|
||||||
const path = __importStar(__webpack_require__(622));
|
const path = __importStar(__webpack_require__(622));
|
||||||
const semver = __importStar(__webpack_require__(280));
|
const semver = __importStar(__webpack_require__(280));
|
||||||
function getNode(versionSpec, stable, token) {
|
const fs = __webpack_require__(747);
|
||||||
|
function getNode(versionSpec, stable, checkLatest, auth) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let osPlat = os.platform();
|
let osPlat = os.platform();
|
||||||
let osArch = translateArchToDistUrl(os.arch());
|
let osArch = translateArchToDistUrl(os.arch());
|
||||||
|
if (checkLatest) {
|
||||||
|
core.info('Attempt to resolve the latest version from manifest...');
|
||||||
|
const resolvedVersion = yield resolveVersionFromManifest(versionSpec, stable, auth);
|
||||||
|
if (resolvedVersion) {
|
||||||
|
versionSpec = resolvedVersion;
|
||||||
|
core.info(`Resolved as '${versionSpec}'`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.info(`Failed to resolve version ${versionSpec} from manifest`);
|
||||||
|
}
|
||||||
|
}
|
||||||
// check cache
|
// check cache
|
||||||
let info = null;
|
|
||||||
let toolPath;
|
let toolPath;
|
||||||
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) {
|
||||||
console.log(`Found in cache @ ${toolPath}`);
|
core.info(`Found in cache @ ${toolPath}`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log(`Attempting to download ${versionSpec}...`);
|
core.info(`Attempting to download ${versionSpec}...`);
|
||||||
let info = yield getInfoFromManifest(versionSpec, stable, token);
|
|
||||||
if (!info) {
|
|
||||||
console.log('Not found in manifest. Falling back to download directly from Node');
|
|
||||||
info = yield 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 = '';
|
let downloadPath = '';
|
||||||
|
let info = null;
|
||||||
|
//
|
||||||
|
// Try download from internal distribution (popular versions only)
|
||||||
|
//
|
||||||
try {
|
try {
|
||||||
downloadPath = yield tc.downloadTool(info.downloadUrl, undefined, token);
|
info = yield getInfoFromManifest(versionSpec, stable, auth);
|
||||||
|
if (info) {
|
||||||
|
core.info(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`);
|
||||||
|
downloadPath = yield tc.downloadTool(info.downloadUrl, undefined, auth);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.info('Not found in manifest. Falling back to download directly from Node');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
|
// Rate limit?
|
||||||
return yield acquireNodeFromFallbackLocation(info.resolvedVersion);
|
if (err instanceof tc.HTTPError &&
|
||||||
|
(err.httpStatusCode === 403 || err.httpStatusCode === 429)) {
|
||||||
|
core.info(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
core.info(err.message);
|
||||||
|
}
|
||||||
|
core.debug(err.stack);
|
||||||
|
core.info('Falling back to download directly from Node');
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Download from nodejs.org
|
||||||
|
//
|
||||||
|
if (!downloadPath) {
|
||||||
|
info = yield getInfoFromDist(versionSpec);
|
||||||
|
if (!info) {
|
||||||
|
throw new Error(`Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`);
|
||||||
|
}
|
||||||
|
core.info(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`);
|
||||||
|
try {
|
||||||
|
downloadPath = yield tc.downloadTool(info.downloadUrl);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
|
||||||
|
return yield acquireNodeFromFallbackLocation(info.resolvedVersion);
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
}
|
}
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Extract
|
// Extract
|
||||||
//
|
//
|
||||||
|
core.info('Extracting ...');
|
||||||
let extPath;
|
let extPath;
|
||||||
|
info = info || {}; // satisfy compiler, never null when reaches here
|
||||||
if (osPlat == 'win32') {
|
if (osPlat == 'win32') {
|
||||||
let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
|
let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
|
||||||
extPath = yield tc.extract7z(downloadPath, undefined, _7zPath);
|
extPath = yield 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 {
|
else {
|
||||||
extPath = yield tc.extractTar(downloadPath);
|
extPath = yield tc.extractTar(downloadPath, undefined, [
|
||||||
|
'xz',
|
||||||
|
'--strip',
|
||||||
|
'1'
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
|
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
|
||||||
//
|
//
|
||||||
|
core.info('Adding to the cache ...');
|
||||||
toolPath = yield tc.cacheDir(extPath, 'node', info.resolvedVersion);
|
toolPath = yield tc.cacheDir(extPath, 'node', info.resolvedVersion);
|
||||||
|
core.info('Done');
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// a tool installer initimately knows details about the layout of that tool
|
// a tool installer initimately knows details about the layout of that tool
|
||||||
|
@ -13019,18 +13107,16 @@ function getNode(versionSpec, stable, token) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
exports.getNode = getNode;
|
exports.getNode = getNode;
|
||||||
function getInfoFromManifest(versionSpec, stable, token) {
|
function getInfoFromManifest(versionSpec, stable, auth) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let info = null;
|
let info = null;
|
||||||
const releases = yield tc.getManifestFromRepo('actions', 'node-versions', token);
|
const releases = yield tc.getManifestFromRepo('actions', 'node-versions', auth, 'main');
|
||||||
console.log(`matching ${versionSpec}...`);
|
|
||||||
const rel = yield tc.findFromManifest(versionSpec, stable, releases);
|
const rel = yield tc.findFromManifest(versionSpec, stable, releases);
|
||||||
if (rel && rel.files.length > 0) {
|
if (rel && rel.files.length > 0) {
|
||||||
info = {};
|
info = {};
|
||||||
info.resolvedVersion = rel.version;
|
info.resolvedVersion = rel.version;
|
||||||
info.downloadUrl = rel.files[0].download_url;
|
info.downloadUrl = rel.files[0].download_url;
|
||||||
info.fileName = rel.files[0].filename;
|
info.fileName = rel.files[0].filename;
|
||||||
info.token = token;
|
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
});
|
});
|
||||||
|
@ -13039,7 +13125,6 @@ function getInfoFromDist(versionSpec) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
let osPlat = os.platform();
|
let osPlat = os.platform();
|
||||||
let osArch = translateArchToDistUrl(os.arch());
|
let osArch = translateArchToDistUrl(os.arch());
|
||||||
let info = null;
|
|
||||||
let version;
|
let version;
|
||||||
version = yield queryDistForMatch(versionSpec);
|
version = yield queryDistForMatch(versionSpec);
|
||||||
if (!version) {
|
if (!version) {
|
||||||
|
@ -13061,6 +13146,18 @@ function getInfoFromDist(versionSpec) {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function resolveVersionFromManifest(versionSpec, stable, auth) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
try {
|
||||||
|
const info = yield getInfoFromManifest(versionSpec, stable, auth);
|
||||||
|
return info === null || info === void 0 ? void 0 : info.resolvedVersion;
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
core.info('Unable to resolve version from manifest...');
|
||||||
|
core.debug(err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
// 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
|
||||||
function evaluateVersions(versions, versionSpec) {
|
function evaluateVersions(versions, versionSpec) {
|
||||||
let version = '';
|
let version = '';
|
||||||
|
@ -13158,6 +13255,7 @@ function acquireNodeFromFallbackLocation(version) {
|
||||||
try {
|
try {
|
||||||
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`;
|
||||||
|
core.info(`Downloading only node binary from ${exeUrl}`);
|
||||||
const exePath = yield tc.downloadTool(exeUrl);
|
const exePath = yield tc.downloadTool(exeUrl);
|
||||||
yield io.cp(exePath, path.join(tempDir, 'node.exe'));
|
yield io.cp(exePath, path.join(tempDir, 'node.exe'));
|
||||||
const libPath = yield tc.downloadTool(libUrl);
|
const libPath = yield tc.downloadTool(libUrl);
|
||||||
|
@ -13176,7 +13274,9 @@ function acquireNodeFromFallbackLocation(version) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return yield tc.cacheDir(tempDir, 'node', version);
|
let toolPath = yield 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.
|
||||||
|
@ -15920,6 +16020,105 @@ function set(object, path, value) {
|
||||||
module.exports = set;
|
module.exports = set;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 888:
|
||||||
|
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||||
|
result["default"] = mod;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const os = __importStar(__webpack_require__(87));
|
||||||
|
/**
|
||||||
|
* Commands
|
||||||
|
*
|
||||||
|
* Command Format:
|
||||||
|
* ::name key=value,key=value::message
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* ::warning::This is the message
|
||||||
|
* ::set-env name=MY_VAR::some value
|
||||||
|
*/
|
||||||
|
function issueCommand(command, properties, message) {
|
||||||
|
const cmd = new Command(command, properties, message);
|
||||||
|
process.stdout.write(cmd.toString() + os.EOL);
|
||||||
|
}
|
||||||
|
exports.issueCommand = issueCommand;
|
||||||
|
function issue(name, message = '') {
|
||||||
|
issueCommand(name, {}, message);
|
||||||
|
}
|
||||||
|
exports.issue = issue;
|
||||||
|
const CMD_STRING = '::';
|
||||||
|
class Command {
|
||||||
|
constructor(command, properties, message) {
|
||||||
|
if (!command) {
|
||||||
|
command = 'missing.command';
|
||||||
|
}
|
||||||
|
this.command = command;
|
||||||
|
this.properties = properties;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
toString() {
|
||||||
|
let cmdStr = CMD_STRING + this.command;
|
||||||
|
if (this.properties && Object.keys(this.properties).length > 0) {
|
||||||
|
cmdStr += ' ';
|
||||||
|
let first = true;
|
||||||
|
for (const key in this.properties) {
|
||||||
|
if (this.properties.hasOwnProperty(key)) {
|
||||||
|
const val = this.properties[key];
|
||||||
|
if (val) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cmdStr += ',';
|
||||||
|
}
|
||||||
|
cmdStr += `${key}=${escapeProperty(val)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmdStr += `${CMD_STRING}${escapeData(this.message)}`;
|
||||||
|
return cmdStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sanitizes an input into a string so it can be passed into issueCommand safely
|
||||||
|
* @param input input to sanitize into a string
|
||||||
|
*/
|
||||||
|
function toCommandValue(input) {
|
||||||
|
if (input === null || input === undefined) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
else if (typeof input === 'string' || input instanceof String) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
return JSON.stringify(input);
|
||||||
|
}
|
||||||
|
exports.toCommandValue = toCommandValue;
|
||||||
|
function escapeData(s) {
|
||||||
|
return toCommandValue(s)
|
||||||
|
.replace(/%/g, '%25')
|
||||||
|
.replace(/\r/g, '%0D')
|
||||||
|
.replace(/\n/g, '%0A');
|
||||||
|
}
|
||||||
|
function escapeProperty(s) {
|
||||||
|
return toCommandValue(s)
|
||||||
|
.replace(/%/g, '%25')
|
||||||
|
.replace(/\r/g, '%0D')
|
||||||
|
.replace(/\n/g, '%0A')
|
||||||
|
.replace(/:/g, '%3A')
|
||||||
|
.replace(/,/g, '%2C');
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=command.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 899:
|
/***/ 899:
|
||||||
|
@ -16025,6 +16224,235 @@ function patchForDeprecation(octokit, apiOptions, method, methodName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 902:
|
||||||
|
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||||
|
result["default"] = mod;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const command_1 = __webpack_require__(888);
|
||||||
|
const os = __importStar(__webpack_require__(87));
|
||||||
|
const path = __importStar(__webpack_require__(622));
|
||||||
|
/**
|
||||||
|
* The code to exit an action
|
||||||
|
*/
|
||||||
|
var ExitCode;
|
||||||
|
(function (ExitCode) {
|
||||||
|
/**
|
||||||
|
* A code indicating that the action was successful
|
||||||
|
*/
|
||||||
|
ExitCode[ExitCode["Success"] = 0] = "Success";
|
||||||
|
/**
|
||||||
|
* A code indicating that the action was a failure
|
||||||
|
*/
|
||||||
|
ExitCode[ExitCode["Failure"] = 1] = "Failure";
|
||||||
|
})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Variables
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Sets env variable for this action and future actions in the job
|
||||||
|
* @param name the name of the variable to set
|
||||||
|
* @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
function exportVariable(name, val) {
|
||||||
|
const convertedVal = command_1.toCommandValue(val);
|
||||||
|
process.env[name] = convertedVal;
|
||||||
|
command_1.issueCommand('set-env', { name }, convertedVal);
|
||||||
|
}
|
||||||
|
exports.exportVariable = exportVariable;
|
||||||
|
/**
|
||||||
|
* Registers a secret which will get masked from logs
|
||||||
|
* @param secret value of the secret
|
||||||
|
*/
|
||||||
|
function setSecret(secret) {
|
||||||
|
command_1.issueCommand('add-mask', {}, secret);
|
||||||
|
}
|
||||||
|
exports.setSecret = setSecret;
|
||||||
|
/**
|
||||||
|
* Prepends inputPath to the PATH (for this action and future actions)
|
||||||
|
* @param inputPath
|
||||||
|
*/
|
||||||
|
function addPath(inputPath) {
|
||||||
|
command_1.issueCommand('add-path', {}, inputPath);
|
||||||
|
process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
|
||||||
|
}
|
||||||
|
exports.addPath = addPath;
|
||||||
|
/**
|
||||||
|
* Gets the value of an input. The value is also trimmed.
|
||||||
|
*
|
||||||
|
* @param name name of the input to get
|
||||||
|
* @param options optional. See InputOptions.
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
function getInput(name, options) {
|
||||||
|
const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
|
||||||
|
if (options && options.required && !val) {
|
||||||
|
throw new Error(`Input required and not supplied: ${name}`);
|
||||||
|
}
|
||||||
|
return val.trim();
|
||||||
|
}
|
||||||
|
exports.getInput = getInput;
|
||||||
|
/**
|
||||||
|
* Sets the value of an output.
|
||||||
|
*
|
||||||
|
* @param name name of the output to set
|
||||||
|
* @param value value to store. Non-string values will be converted to a string via JSON.stringify
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
function setOutput(name, value) {
|
||||||
|
command_1.issueCommand('set-output', { name }, value);
|
||||||
|
}
|
||||||
|
exports.setOutput = setOutput;
|
||||||
|
/**
|
||||||
|
* Enables or disables the echoing of commands into stdout for the rest of the step.
|
||||||
|
* Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function setCommandEcho(enabled) {
|
||||||
|
command_1.issue('echo', enabled ? 'on' : 'off');
|
||||||
|
}
|
||||||
|
exports.setCommandEcho = setCommandEcho;
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Results
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Sets the action status to failed.
|
||||||
|
* When the action exits it will be with an exit code of 1
|
||||||
|
* @param message add error issue message
|
||||||
|
*/
|
||||||
|
function setFailed(message) {
|
||||||
|
process.exitCode = ExitCode.Failure;
|
||||||
|
error(message);
|
||||||
|
}
|
||||||
|
exports.setFailed = setFailed;
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Logging Commands
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Gets whether Actions Step Debug is on or not
|
||||||
|
*/
|
||||||
|
function isDebug() {
|
||||||
|
return process.env['RUNNER_DEBUG'] === '1';
|
||||||
|
}
|
||||||
|
exports.isDebug = isDebug;
|
||||||
|
/**
|
||||||
|
* Writes debug message to user log
|
||||||
|
* @param message debug message
|
||||||
|
*/
|
||||||
|
function debug(message) {
|
||||||
|
command_1.issueCommand('debug', {}, message);
|
||||||
|
}
|
||||||
|
exports.debug = debug;
|
||||||
|
/**
|
||||||
|
* Adds an error issue
|
||||||
|
* @param message error issue message. Errors will be converted to string via toString()
|
||||||
|
*/
|
||||||
|
function error(message) {
|
||||||
|
command_1.issue('error', message instanceof Error ? message.toString() : message);
|
||||||
|
}
|
||||||
|
exports.error = error;
|
||||||
|
/**
|
||||||
|
* Adds an warning issue
|
||||||
|
* @param message warning issue message. Errors will be converted to string via toString()
|
||||||
|
*/
|
||||||
|
function warning(message) {
|
||||||
|
command_1.issue('warning', message instanceof Error ? message.toString() : message);
|
||||||
|
}
|
||||||
|
exports.warning = warning;
|
||||||
|
/**
|
||||||
|
* Writes info to log with console.log.
|
||||||
|
* @param message info message
|
||||||
|
*/
|
||||||
|
function info(message) {
|
||||||
|
process.stdout.write(message + os.EOL);
|
||||||
|
}
|
||||||
|
exports.info = info;
|
||||||
|
/**
|
||||||
|
* Begin an output group.
|
||||||
|
*
|
||||||
|
* Output until the next `groupEnd` will be foldable in this group
|
||||||
|
*
|
||||||
|
* @param name The name of the output group
|
||||||
|
*/
|
||||||
|
function startGroup(name) {
|
||||||
|
command_1.issue('group', name);
|
||||||
|
}
|
||||||
|
exports.startGroup = startGroup;
|
||||||
|
/**
|
||||||
|
* End an output group.
|
||||||
|
*/
|
||||||
|
function endGroup() {
|
||||||
|
command_1.issue('endgroup');
|
||||||
|
}
|
||||||
|
exports.endGroup = endGroup;
|
||||||
|
/**
|
||||||
|
* Wrap an asynchronous function call in a group.
|
||||||
|
*
|
||||||
|
* Returns the same type as the function itself.
|
||||||
|
*
|
||||||
|
* @param name The name of the group
|
||||||
|
* @param fn The function to wrap in the group
|
||||||
|
*/
|
||||||
|
function group(name, fn) {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
startGroup(name);
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = yield fn();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
endGroup();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.group = group;
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Wrapper action state
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* Saves state for current action, the state can only be retrieved by this action's post job execution.
|
||||||
|
*
|
||||||
|
* @param name name of the state to store
|
||||||
|
* @param value value to store. Non-string values will be converted to a string via JSON.stringify
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
function saveState(name, value) {
|
||||||
|
command_1.issueCommand('save-state', { name }, value);
|
||||||
|
}
|
||||||
|
exports.saveState = saveState;
|
||||||
|
/**
|
||||||
|
* Gets the value of an state set by this action's main execution.
|
||||||
|
*
|
||||||
|
* @param name name of the state to get
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
function getState(name) {
|
||||||
|
return process.env[`STATE_${name}`] || '';
|
||||||
|
}
|
||||||
|
exports.getState = getState;
|
||||||
|
//# sourceMappingURL=core.js.map
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 929:
|
/***/ 929:
|
||||||
|
@ -16666,7 +17094,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(__webpack_require__(470));
|
const core = __importStar(__webpack_require__(902));
|
||||||
/**
|
/**
|
||||||
* Internal class for retries
|
* Internal class for retries
|
||||||
*/
|
*/
|
||||||
|
@ -16735,8 +17163,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
|
if (mod && mod.__esModule) return mod;
|
||||||
|
var result = {};
|
||||||
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||||
|
result["default"] = mod;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const tr = __webpack_require__(9);
|
const tr = __importStar(__webpack_require__(9));
|
||||||
/**
|
/**
|
||||||
* Exec a command.
|
* Exec a command.
|
||||||
* Output will be streamed to the live console.
|
* Output will be streamed to the live console.
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
"integrity": "sha512-IbCx7oefq+Gi6FWbSs2Fnw8VkEI6Y4gvjrYprY3RV//ksq/KPMlClOerJ4jRosyal6zkUIc8R9fS/cpRMlGClg=="
|
"integrity": "sha512-IbCx7oefq+Gi6FWbSs2Fnw8VkEI6Y4gvjrYprY3RV//ksq/KPMlClOerJ4jRosyal6zkUIc8R9fS/cpRMlGClg=="
|
||||||
},
|
},
|
||||||
"@actions/exec": {
|
"@actions/exec": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.4.tgz",
|
||||||
"integrity": "sha512-TogJGnueOmM7ntCi0ASTUj4LapRRtDfj57Ja4IhPmg2fls28uVOPbAn8N+JifaOumN2UG3oEO/Ixek2A4NcYSA==",
|
"integrity": "sha512-4DPChWow9yc9W3WqEbUj8Nr86xkpyE29ZzWjXucHItclLbEW6jr80Zx4nqv18QL6KK65+cifiQZXvnqgTV6oHw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/io": "^1.0.1"
|
"@actions/io": "^1.0.1"
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,11 @@
|
||||||
"integrity": "sha512-J8KuFqVPr3p6U8W93DOXlXW6zFvrQAJANdS+vw0YhusLIq+bszW8zmK2Fh1C2kDPX8FMvwIl1OUcFgvJoXLbAg=="
|
"integrity": "sha512-J8KuFqVPr3p6U8W93DOXlXW6zFvrQAJANdS+vw0YhusLIq+bszW8zmK2Fh1C2kDPX8FMvwIl1OUcFgvJoXLbAg=="
|
||||||
},
|
},
|
||||||
"@actions/tool-cache": {
|
"@actions/tool-cache": {
|
||||||
"version": "1.5.2",
|
"version": "1.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-1.5.4.tgz",
|
||||||
"integrity": "sha512-40A1St0GEo+QvHV1YRjStEoQcKKMaip+zNXPgGHcjYXCdZ7cl1LGlwOpsVVqwk+6ue/shFTS76KC1A02mVVCQA==",
|
"integrity": "sha512-72ijIBM0s/dx2D0eYYxaxaeKWeVatOK8OHPNctJ5cyKjZp1j12egX+nW/N+tnQRNMVxTp9WjudZO5wizUBxC/w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/core": "^1.2.0",
|
"@actions/core": "^1.2.3",
|
||||||
"@actions/exec": "^1.0.0",
|
"@actions/exec": "^1.0.0",
|
||||||
"@actions/http-client": "^1.0.8",
|
"@actions/http-client": "^1.0.8",
|
||||||
"@actions/io": "^1.0.1",
|
"@actions/io": "^1.0.1",
|
||||||
|
@ -52,6 +52,11 @@
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@actions/core": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-YJCEq8BE3CdN8+7HPZ/4DxJjk/OkZV2FFIf+DlZTC/4iBlzYCD5yjRR6eiOS5llO11zbRltIRuKAjMKaWTE6cg=="
|
||||||
|
},
|
||||||
"@actions/http-client": {
|
"@actions/http-client": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz",
|
||||||
|
|
|
@ -24,10 +24,11 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.2",
|
"@actions/core": "^1.2.2",
|
||||||
|
"@actions/exec": "^1.0.3",
|
||||||
"@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.5.2",
|
"@actions/tool-cache": "^1.5.4",
|
||||||
"semver": "^6.1.1"
|
"semver": "^6.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
137
src/installer.ts
137
src/installer.ts
|
@ -6,7 +6,7 @@ import * as io from '@actions/io';
|
||||||
import * as tc from '@actions/tool-cache';
|
import * as tc from '@actions/tool-cache';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as semver from 'semver';
|
import * as semver from 'semver';
|
||||||
import {Url} from 'url';
|
import fs = require('fs');
|
||||||
|
|
||||||
//
|
//
|
||||||
// Node versions interface
|
// Node versions interface
|
||||||
|
@ -19,7 +19,6 @@ export interface INodeVersion {
|
||||||
|
|
||||||
interface INodeVersionInfo {
|
interface INodeVersionInfo {
|
||||||
downloadUrl: string;
|
downloadUrl: string;
|
||||||
token: string | null;
|
|
||||||
resolvedVersion: string;
|
resolvedVersion: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
}
|
}
|
||||||
|
@ -27,63 +26,119 @@ interface INodeVersionInfo {
|
||||||
export async function getNode(
|
export async function getNode(
|
||||||
versionSpec: string,
|
versionSpec: string,
|
||||||
stable: boolean,
|
stable: boolean,
|
||||||
token: string
|
checkLatest: boolean,
|
||||||
|
auth: string | undefined
|
||||||
) {
|
) {
|
||||||
let osPlat: string = os.platform();
|
let osPlat: string = os.platform();
|
||||||
let osArch: string = translateArchToDistUrl(os.arch());
|
let osArch: string = translateArchToDistUrl(os.arch());
|
||||||
|
|
||||||
|
if (checkLatest) {
|
||||||
|
core.info('Attempt to resolve the latest version from manifest...');
|
||||||
|
const resolvedVersion = await resolveVersionFromManifest(
|
||||||
|
versionSpec,
|
||||||
|
stable,
|
||||||
|
auth
|
||||||
|
);
|
||||||
|
if (resolvedVersion) {
|
||||||
|
versionSpec = resolvedVersion;
|
||||||
|
core.info(`Resolved as '${versionSpec}'`);
|
||||||
|
} else {
|
||||||
|
core.info(`Failed to resolve version ${versionSpec} from manifest`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check cache
|
// check cache
|
||||||
let info: INodeVersionInfo | null = null;
|
|
||||||
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) {
|
||||||
console.log(`Found in cache @ ${toolPath}`);
|
core.info(`Found in cache @ ${toolPath}`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`Attempting to download ${versionSpec}...`);
|
core.info(`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 = '';
|
let downloadPath = '';
|
||||||
|
let info: INodeVersionInfo | null = null;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Try download from internal distribution (popular versions only)
|
||||||
|
//
|
||||||
try {
|
try {
|
||||||
downloadPath = await tc.downloadTool(info.downloadUrl, undefined, token);
|
info = await getInfoFromManifest(versionSpec, stable, auth);
|
||||||
|
if (info) {
|
||||||
|
core.info(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`);
|
||||||
|
downloadPath = await tc.downloadTool(info.downloadUrl, undefined, auth);
|
||||||
|
} else {
|
||||||
|
core.info(
|
||||||
|
'Not found in manifest. Falling back to download directly from Node'
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
|
// Rate limit?
|
||||||
return await acquireNodeFromFallbackLocation(info.resolvedVersion);
|
if (
|
||||||
|
err instanceof tc.HTTPError &&
|
||||||
|
(err.httpStatusCode === 403 || err.httpStatusCode === 429)
|
||||||
|
) {
|
||||||
|
core.info(
|
||||||
|
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
core.info(err.message);
|
||||||
|
}
|
||||||
|
core.debug(err.stack);
|
||||||
|
core.info('Falling back to download directly from Node');
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Download from nodejs.org
|
||||||
|
//
|
||||||
|
if (!downloadPath) {
|
||||||
|
info = await getInfoFromDist(versionSpec);
|
||||||
|
if (!info) {
|
||||||
|
throw new Error(
|
||||||
|
`Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw err;
|
core.info(`Acquiring ${info.resolvedVersion} from ${info.downloadUrl}`);
|
||||||
|
try {
|
||||||
|
downloadPath = await tc.downloadTool(info.downloadUrl);
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
|
||||||
|
return await acquireNodeFromFallbackLocation(info.resolvedVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Extract
|
// Extract
|
||||||
//
|
//
|
||||||
|
core.info('Extracting ...');
|
||||||
let extPath: string;
|
let extPath: string;
|
||||||
|
info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here
|
||||||
if (osPlat == 'win32') {
|
if (osPlat == 'win32') {
|
||||||
let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
|
let _7zPath = path.join(__dirname, '..', 'externals', '7zr.exe');
|
||||||
extPath = await tc.extract7z(downloadPath, undefined, _7zPath);
|
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 {
|
} else {
|
||||||
extPath = await tc.extractTar(downloadPath);
|
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
|
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
|
||||||
//
|
//
|
||||||
|
core.info('Adding to the cache ...');
|
||||||
toolPath = await tc.cacheDir(extPath, 'node', info.resolvedVersion);
|
toolPath = await tc.cacheDir(extPath, 'node', info.resolvedVersion);
|
||||||
|
core.info('Done');
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -103,15 +158,15 @@ export async function getNode(
|
||||||
async function getInfoFromManifest(
|
async function getInfoFromManifest(
|
||||||
versionSpec: string,
|
versionSpec: string,
|
||||||
stable: boolean,
|
stable: boolean,
|
||||||
token: string
|
auth: string | undefined
|
||||||
): Promise<INodeVersionInfo | null> {
|
): Promise<INodeVersionInfo | null> {
|
||||||
let info: INodeVersionInfo | null = null;
|
let info: INodeVersionInfo | null = null;
|
||||||
const releases = await tc.getManifestFromRepo(
|
const releases = await tc.getManifestFromRepo(
|
||||||
'actions',
|
'actions',
|
||||||
'node-versions',
|
'node-versions',
|
||||||
token
|
auth,
|
||||||
|
'main'
|
||||||
);
|
);
|
||||||
console.log(`matching ${versionSpec}...`);
|
|
||||||
const rel = await tc.findFromManifest(versionSpec, stable, releases);
|
const rel = await tc.findFromManifest(versionSpec, stable, releases);
|
||||||
|
|
||||||
if (rel && rel.files.length > 0) {
|
if (rel && rel.files.length > 0) {
|
||||||
|
@ -119,7 +174,6 @@ async function getInfoFromManifest(
|
||||||
info.resolvedVersion = rel.version;
|
info.resolvedVersion = rel.version;
|
||||||
info.downloadUrl = rel.files[0].download_url;
|
info.downloadUrl = rel.files[0].download_url;
|
||||||
info.fileName = rel.files[0].filename;
|
info.fileName = rel.files[0].filename;
|
||||||
info.token = token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
@ -131,7 +185,6 @@ async function getInfoFromDist(
|
||||||
let osPlat: string = os.platform();
|
let osPlat: string = os.platform();
|
||||||
let osArch: string = translateArchToDistUrl(os.arch());
|
let osArch: string = translateArchToDistUrl(os.arch());
|
||||||
|
|
||||||
let info: INodeVersionInfo | null = null;
|
|
||||||
let version: string;
|
let version: string;
|
||||||
|
|
||||||
version = await queryDistForMatch(versionSpec);
|
version = await queryDistForMatch(versionSpec);
|
||||||
|
@ -158,6 +211,20 @@ async function getInfoFromDist(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function resolveVersionFromManifest(
|
||||||
|
versionSpec: string,
|
||||||
|
stable: boolean,
|
||||||
|
auth: string | undefined
|
||||||
|
): Promise<string | undefined> {
|
||||||
|
try {
|
||||||
|
const info = await getInfoFromManifest(versionSpec, stable, auth);
|
||||||
|
return info?.resolvedVersion;
|
||||||
|
} catch (err) {
|
||||||
|
core.info('Unable to resolve version from manifest...');
|
||||||
|
core.debug(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
function evaluateVersions(versions: string[], versionSpec: string): string {
|
function evaluateVersions(versions: string[], versionSpec: string): string {
|
||||||
let version = '';
|
let version = '';
|
||||||
|
@ -262,6 +329,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`;
|
||||||
|
|
||||||
|
core.info(`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);
|
||||||
|
@ -279,7 +348,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.
|
||||||
|
|
14
src/main.ts
14
src/main.ts
|
@ -2,6 +2,7 @@ import * as core from '@actions/core';
|
||||||
import * as installer from './installer';
|
import * as installer from './installer';
|
||||||
import * as auth from './authutil';
|
import * as auth from './authutil';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import {URL} from 'url';
|
||||||
|
|
||||||
export async function run() {
|
export async function run() {
|
||||||
try {
|
try {
|
||||||
|
@ -14,11 +15,13 @@ export async function run() {
|
||||||
version = core.getInput('version');
|
version = core.getInput('version');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`version: ${version}`);
|
|
||||||
if (version) {
|
if (version) {
|
||||||
let token = core.getInput('token');
|
let token = core.getInput('token');
|
||||||
|
let auth = !token || isGhes() ? undefined : `token ${token}`;
|
||||||
let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
|
let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
|
||||||
await installer.getNode(version, stable, token);
|
const checkLatest =
|
||||||
|
(core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE';
|
||||||
|
await installer.getNode(version, stable, checkLatest, auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
const registryUrl: string = core.getInput('registry-url');
|
const registryUrl: string = core.getInput('registry-url');
|
||||||
|
@ -39,3 +42,10 @@ export async function run() {
|
||||||
core.setFailed(error.message);
|
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';
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ rm -rf ./node
|
||||||
export RUNNER_TOOL_CACHE=$(pwd)
|
export RUNNER_TOOL_CACHE=$(pwd)
|
||||||
export RUNNER_TEMP="${RUNNER_TOOL_CACHE}/temp"
|
export RUNNER_TEMP="${RUNNER_TOOL_CACHE}/temp"
|
||||||
export INPUT_STABLE=true
|
export INPUT_STABLE=true
|
||||||
export INPUT_VERSION="12.x"
|
export INPUT_VERSION="12" #"0.12.7" #"12" #"11.15.0"
|
||||||
# export your PAT with repo scope before running
|
# export your PAT with repo scope before running
|
||||||
export INPUT_TOKEN=$GITHUB_TOKEN
|
export INPUT_TOKEN=$GITHUB_TOKEN
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue