mirror of
https://github.com/actions/setup-node.git
synced 2026-05-07 07:37:31 +08:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eff380dfbc | |||
| c2ac33f2c6 | |||
| 25b062c917 | |||
| 60edb5dd54 | |||
| d86ebcd40b | |||
| b39b52d121 | |||
| 7247617371 | |||
| f3ec4ca66f | |||
| ec97f37504 | |||
| 5ef044f9d0 | |||
| c45882a6ea | |||
| ee36e8b5c0 | |||
| 8f152de45c | |||
| 23755b521f | |||
| 54534a2a9b | |||
| 1a4442cacd | |||
| 6e9e44895f | |||
| e52912ef25 | |||
| ac16ae42d7 | |||
| 5a8d9111e3 | |||
| 9e956a555c | |||
| 7da2a7eb0c | |||
| 2a017f350d | |||
| 72c43c2d8f | |||
| d3ace34546 | |||
| acbf0586b1 | |||
| f1744b62b7 | |||
| 2651591c72 | |||
| 5e21ff4d9b |
@@ -15,3 +15,5 @@ jobs:
|
||||
call-basic-validation:
|
||||
name: Basic validation
|
||||
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
@@ -15,3 +15,5 @@ jobs:
|
||||
call-check-dist:
|
||||
name: Check dist/
|
||||
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
@@ -19,9 +19,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [12, 14, 16]
|
||||
node-version: [18, 20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clean global cache
|
||||
run: npm cache clean --force
|
||||
- name: Setup Node
|
||||
@@ -42,9 +42,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [12, 14, 16]
|
||||
node-version: [18, 20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
@@ -75,9 +75,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [14, 16]
|
||||
node-version: [18, 20]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Yarn version
|
||||
run: yarn --version
|
||||
- name: Generate yarn file
|
||||
@@ -93,13 +93,13 @@ jobs:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'yarn'
|
||||
- name: Install dependencies
|
||||
run: yarn install
|
||||
run: yarn install --ignore-engines
|
||||
- name: Verify node and yarn
|
||||
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
|
||||
shell: bash
|
||||
|
||||
node-yarn2-depencies-caching:
|
||||
name: Test yarn 2 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
|
||||
node-yarn3-depencies-caching:
|
||||
name: Test yarn 3 (Node ${{ matrix.node-version}}, ${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
YARN_ENABLE_IMMUTABLE_INSTALLS: false
|
||||
@@ -107,11 +107,11 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [12, 14, 16]
|
||||
node-version: [18, 20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Update yarn
|
||||
run: yarn set version berry
|
||||
run: yarn set version 3.6.4
|
||||
- name: Yarn version
|
||||
run: yarn --version
|
||||
- name: Generate simple .yarnrc.yml
|
||||
@@ -139,11 +139,11 @@ jobs:
|
||||
name: Test yarn subprojects
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12, 14, 16]
|
||||
node-version: [18, 20, 22]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: prepare sub-projects
|
||||
run: __tests__/prepare-yarn-subprojects.sh yarn1
|
||||
@@ -166,11 +166,11 @@ jobs:
|
||||
name: Test yarn subprojects all locally managed
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12, 14, 16]
|
||||
node-version: [18, 20, 22]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: prepare sub-projects
|
||||
run: __tests__/prepare-yarn-subprojects.sh keepcache keepcache
|
||||
@@ -193,11 +193,11 @@ jobs:
|
||||
name: Test yarn subprojects some locally managed
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12, 14, 16]
|
||||
node-version: [18, 20, 22]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: prepare sub-projects
|
||||
run: __tests__/prepare-yarn-subprojects.sh global
|
||||
@@ -220,11 +220,11 @@ jobs:
|
||||
name: Test yarn subprojects managed by git
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12, 14, 16]
|
||||
node-version: [18, 20, 22]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: prepare sub-projects
|
||||
run: /bin/bash __tests__/prepare-yarn-subprojects.sh keepcache
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
env:
|
||||
https_proxy: http://squid-proxy:3128
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clear tool cache
|
||||
run: rm -rf $RUNNER_TOOL_CACHE/*
|
||||
- name: Setup node 14
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
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@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Clear tool cache
|
||||
run: rm -rf $RUNNER_TOOL_CACHE/*
|
||||
- name: Setup node 11
|
||||
|
||||
@@ -18,9 +18,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [10, 12, 14]
|
||||
node-version: [18, 20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
@@ -34,16 +34,16 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-13]
|
||||
node-version: [lts/dubnium, lts/erbium, lts/fermium, lts/*, lts/-1]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
check-latest: true
|
||||
- if: runner.os != 'Windows'
|
||||
- if: runner.os != 'Windows' && runner.os != 'macOS'
|
||||
name: Verify node and npm
|
||||
run: |
|
||||
. "$NVM_DIR/nvm.sh"
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
'20.0.0-v8-canary20221101e50e45c9f8'
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
@@ -83,9 +83,9 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version:
|
||||
[16.0.0-nightly20210420a0261d231c, 17-nightly, 18.0.0-nightly]
|
||||
[20.11.0-nightly202312211a0be537da, 21-nightly, 18.0.0-nightly]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
@@ -103,9 +103,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [16.0.0-rc.1, 18.0.0-rc.2, 19.0.0-rc.0]
|
||||
node-version: [20.0.0-rc.1, 18.0.0-rc.2, 19.0.0-rc.0]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
@@ -123,9 +123,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [10.15, 12.16.0, 14.2.0, 16.3.0]
|
||||
node-version: [18.20.0, 20.10.0, 22.0.0]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
@@ -140,9 +140,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [10, 12, 14]
|
||||
node-version: [18, 20, 22]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node and check latest
|
||||
uses: ./
|
||||
with:
|
||||
@@ -161,16 +161,13 @@ jobs:
|
||||
node-version-file:
|
||||
[.nvmrc, .tool-versions, .tool-versions-node, package.json]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Remove volta from package.json
|
||||
shell: bash
|
||||
run: cat <<< "$(jq 'del(.volta)' ./__tests__/data/package.json)" > ./__tests__/data/package.json
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup node from node version file
|
||||
uses: ./
|
||||
with:
|
||||
node-version-file: '__tests__/data/${{ matrix.node-version-file }}'
|
||||
- name: Verify node
|
||||
run: __tests__/verify-node.sh 14
|
||||
run: __tests__/verify-node.sh 20
|
||||
|
||||
version-file-volta:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -179,13 +176,28 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup node from node version file
|
||||
uses: ./
|
||||
with:
|
||||
node-version-file: '__tests__/data/package.json'
|
||||
node-version-file: '__tests__/data/package-volta.json'
|
||||
- name: Verify node
|
||||
run: __tests__/verify-node.sh 16
|
||||
run: __tests__/verify-node.sh 20
|
||||
|
||||
version-file-volta-extends:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup node from node version file
|
||||
uses: ./
|
||||
with:
|
||||
node-version-file: '__tests__/data/package-volta-extends.json'
|
||||
- name: Verify node
|
||||
run: __tests__/verify-node.sh 20
|
||||
|
||||
node-dist:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@@ -193,9 +205,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
node-version: [11, 13]
|
||||
node-version: [17, 19]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node from dist
|
||||
uses: ./
|
||||
with:
|
||||
@@ -209,9 +221,9 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-13]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
# test old versions which didn't have npm and layout different
|
||||
- name: Setup node 0.12.18 from dist
|
||||
uses: ./
|
||||
@@ -224,11 +236,11 @@ jobs:
|
||||
arch:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup node 14 x86 from dist
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup node 20 x86 from dist
|
||||
uses: ./
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '20'
|
||||
architecture: 'x86'
|
||||
- name: Verify node
|
||||
run: __tests__/verify-arch.sh "ia32"
|
||||
@@ -248,7 +260,7 @@ jobs:
|
||||
echo "LATEST_NODE_VERSION=$latestNodeVersion" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Node
|
||||
uses: ./
|
||||
with:
|
||||
|
||||
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Binary file not shown.
Generated
BIN
Binary file not shown.
Binary file not shown.
@@ -18,14 +18,14 @@ See [action.yml](action.yml)
|
||||
|
||||
<!-- start usage -->
|
||||
```yaml
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
# Version Spec of the version to use in SemVer notation.
|
||||
# It also emits such aliases as lts, latest, nightly and canary builds
|
||||
# Examples: 12.x, 10.15.1, >=10.15.0, lts/Hydrogen, 16-nightly, latest, node
|
||||
node-version: ''
|
||||
|
||||
# File containing the version Spec of the version to use. Examples: .nvmrc, .node-version, .tool-versions.
|
||||
# File containing the version Spec of the version to use. Examples: package.json, .nvmrc, .node-version, .tool-versions.
|
||||
# If node-version and node-version-file are both provided the action will use version from node-version.
|
||||
node-version-file: ''
|
||||
|
||||
@@ -83,8 +83,8 @@ See [action.yml](action.yml)
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- run: npm ci
|
||||
@@ -103,12 +103,12 @@ The `node-version` input supports the Semantic Versioning Specification, for mor
|
||||
|
||||
Examples:
|
||||
|
||||
- Major versions: `14`, `16`, `18`
|
||||
- Major versions: `18`, `20`
|
||||
- More specific versions: `10.15`, `16.15.1` , `18.4.0`
|
||||
- NVM LTS syntax: `lts/erbium`, `lts/fermium`, `lts/*`, `lts/-n`
|
||||
- Latest release: `*` or `latest`/`current`/`node`
|
||||
|
||||
**Note:** Like the other values, `*` will get the latest [locally-cached Node.js version](https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md#nodejs), or the latest version from [actions/node-versions](https://github.com/actions/node-versions/blob/main/versions-manifest.json), depending on the [`check-latest`](docs/advanced-usage.md#check-latest-version) input.
|
||||
**Note:** Like the other values, `*` will get the latest [locally-cached Node.js version](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md#nodejs), or the latest version from [actions/node-versions](https://github.com/actions/node-versions/blob/main/versions-manifest.json), depending on the [`check-latest`](docs/advanced-usage.md#check-latest-version) input.
|
||||
|
||||
`current`/`latest`/`node` always resolve to the latest [dist version](https://nodejs.org/dist/index.json).
|
||||
That version is then downloaded from actions/node-versions if possible, or directly from Node.js if not.
|
||||
@@ -132,10 +132,10 @@ See the examples of using cache for `yarn`/`pnpm` and `cache-dependency-path` in
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 20
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
@@ -145,10 +145,10 @@ steps:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 20
|
||||
cache: 'npm'
|
||||
cache-dependency-path: subdir/package-lock.json
|
||||
- run: npm ci
|
||||
@@ -166,9 +166,9 @@ jobs:
|
||||
node: [ 14, 16, 18 ]
|
||||
name: Node ${{ matrix.node }} sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- run: npm ci
|
||||
@@ -182,10 +182,10 @@ jobs:
|
||||
To get a higher rate limit, you can [generate a personal access token on github.com](https://github.com/settings/tokens/new) and pass it as the `token` input for the action:
|
||||
|
||||
```yaml
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
token: ${{ secrets.GH_DOTCOM_TOKEN }}
|
||||
node-version: 16
|
||||
node-version: 20
|
||||
```
|
||||
|
||||
If the runner is not able to access github.com, any Nodejs versions requested during a workflow run must come from the runner's tool cache. See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server@3.2/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)" for more information.
|
||||
|
||||
@@ -1 +1 @@
|
||||
v14
|
||||
v20
|
||||
|
||||
@@ -1 +1 @@
|
||||
nodejs 14.0.0
|
||||
nodejs 20.0.0
|
||||
|
||||
@@ -1 +1 @@
|
||||
node 14.0.0
|
||||
node 20.0.0
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"volta": {
|
||||
"extends": "./package-volta.json"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"engines": {
|
||||
"node": "^14.0.0"
|
||||
},
|
||||
"volta": {
|
||||
"node": "20.0.0"
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"engines": {
|
||||
"node": "^14.0.0"
|
||||
},
|
||||
"volta": {
|
||||
"node": "16.0.0"
|
||||
"node": "^20.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
+77
-97
@@ -2,6 +2,7 @@ import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as cache from '@actions/cache';
|
||||
import * as io from '@actions/io';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
@@ -24,11 +25,13 @@ describe('main tests', () => {
|
||||
let startGroupSpy: jest.SpyInstance;
|
||||
let endGroupSpy: jest.SpyInstance;
|
||||
|
||||
let whichSpy: jest.SpyInstance;
|
||||
|
||||
let existsSpy: jest.SpyInstance;
|
||||
|
||||
let getExecOutputSpy: jest.SpyInstance;
|
||||
|
||||
let parseNodeVersionSpy: jest.SpyInstance;
|
||||
let getNodeVersionFromFileSpy: jest.SpyInstance;
|
||||
let cnSpy: jest.SpyInstance;
|
||||
let findSpy: jest.SpyInstance;
|
||||
let isCacheActionAvailable: jest.SpyInstance;
|
||||
@@ -41,6 +44,7 @@ describe('main tests', () => {
|
||||
// node
|
||||
os = {};
|
||||
console.log('::stop-commands::stoptoken');
|
||||
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
|
||||
process.env['GITHUB_PATH'] = ''; // Stub out ENV file functionality so we can verify it writes to standard out
|
||||
process.env['GITHUB_OUTPUT'] = ''; // Stub out ENV file functionality so we can verify it writes to standard out
|
||||
infoSpy = jest.spyOn(core, 'info');
|
||||
@@ -56,18 +60,18 @@ describe('main tests', () => {
|
||||
inSpy = jest.spyOn(core, 'getInput');
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
|
||||
whichSpy = jest.spyOn(io, 'which');
|
||||
|
||||
getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
|
||||
|
||||
findSpy = jest.spyOn(tc, 'find');
|
||||
|
||||
isCacheActionAvailable = jest.spyOn(cache, 'isFeatureAvailable');
|
||||
|
||||
existsSpy = jest.spyOn(fs, 'existsSync');
|
||||
|
||||
cnSpy = jest.spyOn(process.stdout, 'write');
|
||||
cnSpy.mockImplementation(line => {
|
||||
// uncomment to debug
|
||||
// process.stderr.write('write:' + line + '\n');
|
||||
process.stderr.write('write:' + line + '\n');
|
||||
});
|
||||
|
||||
setupNodeJsSpy = jest.spyOn(OfficialBuilds.prototype, 'setupNodeJs');
|
||||
@@ -85,7 +89,7 @@ describe('main tests', () => {
|
||||
jest.restoreAllMocks();
|
||||
}, 100000);
|
||||
|
||||
describe('parseNodeVersionFile', () => {
|
||||
describe('getNodeVersionFromFile', () => {
|
||||
each`
|
||||
contents | expected
|
||||
${'12'} | ${'12'}
|
||||
@@ -100,9 +104,27 @@ describe('main tests', () => {
|
||||
${'unknown format'} | ${'unknown format'}
|
||||
${' 14.1.0 '} | ${'14.1.0'}
|
||||
${'{"volta": {"node": ">=14.0.0 <=17.0.0"}}'}| ${'>=14.0.0 <=17.0.0'}
|
||||
${'{"volta": {"extends": "./package.json"}}'}| ${'18.0.0'}
|
||||
${'{"engines": {"node": "17.0.0"}}'} | ${'17.0.0'}
|
||||
${'{}'} | ${null}
|
||||
`.it('parses "$contents"', ({contents, expected}) => {
|
||||
expect(util.parseNodeVersionFile(contents)).toBe(expected);
|
||||
const existsSpy = jest.spyOn(fs, 'existsSync');
|
||||
existsSpy.mockImplementation(() => true);
|
||||
|
||||
const readFileSpy = jest.spyOn(fs, 'readFileSync');
|
||||
readFileSpy.mockImplementation(filePath => {
|
||||
if (
|
||||
typeof filePath === 'string' &&
|
||||
path.basename(filePath) === 'package.json'
|
||||
) {
|
||||
// Special case for volta.extends
|
||||
return '{"volta": {"node": "18.0.0"}}';
|
||||
}
|
||||
|
||||
return contents;
|
||||
});
|
||||
|
||||
expect(util.getNodeVersionFromFile('file')).toBe(expected);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,6 +147,10 @@ describe('main tests', () => {
|
||||
return {stdout: obj[command], stderr: '', exitCode: 0};
|
||||
});
|
||||
|
||||
whichSpy.mockImplementation(cmd => {
|
||||
return `some/${cmd}/path`;
|
||||
});
|
||||
|
||||
await util.printEnvDetailsAndSetOutput();
|
||||
|
||||
expect(setOutputSpy).toHaveBeenCalledWith('node-version', obj['node']);
|
||||
@@ -141,10 +167,17 @@ describe('main tests', () => {
|
||||
|
||||
describe('node-version-file flag', () => {
|
||||
beforeEach(() => {
|
||||
parseNodeVersionSpy = jest.spyOn(util, 'parseNodeVersionFile');
|
||||
delete inputs['node-version'];
|
||||
inputs['node-version-file'] = '.nvmrc';
|
||||
|
||||
getNodeVersionFromFileSpy = jest.spyOn(util, 'getNodeVersionFromFile');
|
||||
});
|
||||
|
||||
it('not used if node-version is provided', async () => {
|
||||
afterEach(() => {
|
||||
getNodeVersionFromFileSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('does not read node-version-file if node-version is provided', async () => {
|
||||
// Arrange
|
||||
inputs['node-version'] = '12';
|
||||
|
||||
@@ -152,107 +185,54 @@ describe('main tests', () => {
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0);
|
||||
}, 10000);
|
||||
|
||||
it('not used if node-version-file not provided', async () => {
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('reads node-version-file if provided', async () => {
|
||||
// Arrange
|
||||
const versionSpec = 'v14';
|
||||
const versionFile = '.nvmrc';
|
||||
const expectedVersionSpec = '14';
|
||||
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
|
||||
inputs['node-version-file'] = versionFile;
|
||||
|
||||
parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec);
|
||||
existsSpy.mockImplementationOnce(
|
||||
input => input === path.join(__dirname, 'data', versionFile)
|
||||
);
|
||||
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(existsSpy).toHaveBeenCalledTimes(1);
|
||||
expect(existsSpy).toHaveReturnedWith(true);
|
||||
expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec);
|
||||
expect(infoSpy).toHaveBeenCalledWith(
|
||||
`Resolved ${versionFile} as ${expectedVersionSpec}`
|
||||
);
|
||||
}, 10000);
|
||||
|
||||
it('reads package.json as node-version-file if provided', async () => {
|
||||
// Arrange
|
||||
const versionSpec = fs.readFileSync(
|
||||
path.join(__dirname, 'data/package.json'),
|
||||
'utf-8'
|
||||
);
|
||||
const versionFile = 'package.json';
|
||||
const expectedVersionSpec = '14';
|
||||
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
|
||||
inputs['node-version-file'] = versionFile;
|
||||
|
||||
parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec);
|
||||
existsSpy.mockImplementationOnce(
|
||||
input => input === path.join(__dirname, 'data', versionFile)
|
||||
);
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(existsSpy).toHaveBeenCalledTimes(1);
|
||||
expect(existsSpy).toHaveReturnedWith(true);
|
||||
expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec);
|
||||
expect(infoSpy).toHaveBeenCalledWith(
|
||||
`Resolved ${versionFile} as ${expectedVersionSpec}`
|
||||
);
|
||||
}, 10000);
|
||||
|
||||
it('both node-version-file and node-version are provided', async () => {
|
||||
inputs['node-version'] = '12';
|
||||
const versionSpec = 'v14';
|
||||
const versionFile = '.nvmrc';
|
||||
const expectedVersionSpec = '14';
|
||||
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, '..');
|
||||
inputs['node-version-file'] = versionFile;
|
||||
|
||||
parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec);
|
||||
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(existsSpy).toHaveBeenCalledTimes(0);
|
||||
expect(parseNodeVersionSpy).not.toHaveBeenCalled();
|
||||
expect(inputs['node-version']).toBeDefined();
|
||||
expect(inputs['node-version-file']).toBeDefined();
|
||||
expect(getNodeVersionFromFileSpy).not.toHaveBeenCalled();
|
||||
expect(warningSpy).toHaveBeenCalledWith(
|
||||
'Both node-version and node-version-file inputs are specified, only node-version will be used'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw an error if node-version-file is not found', async () => {
|
||||
const versionFile = '.nvmrc';
|
||||
const versionFilePath = path.join(__dirname, '..', versionFile);
|
||||
inputs['node-version-file'] = versionFile;
|
||||
it('does not read node-version-file if node-version-file is not provided', async () => {
|
||||
// Arrange
|
||||
delete inputs['node-version-file'];
|
||||
|
||||
inSpy.mockImplementation(name => inputs[name]);
|
||||
existsSpy.mockImplementationOnce(
|
||||
input => input === path.join(__dirname, 'data', versionFile)
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(getNodeVersionFromFileSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('reads node-version-file', async () => {
|
||||
// Arrange
|
||||
const expectedVersionSpec = '14';
|
||||
getNodeVersionFromFileSpy.mockImplementation(() => expectedVersionSpec);
|
||||
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(getNodeVersionFromFileSpy).toHaveBeenCalled();
|
||||
expect(infoSpy).toHaveBeenCalledWith(
|
||||
`Resolved ${inputs['node-version-file']} as ${expectedVersionSpec}`
|
||||
);
|
||||
}, 10000);
|
||||
|
||||
it('should throw an error if node-version-file is not accessible', async () => {
|
||||
// Arrange
|
||||
inputs['node-version-file'] = 'non-existing-file';
|
||||
const versionFilePath = path.join(
|
||||
__dirname,
|
||||
'data',
|
||||
inputs['node-version-file']
|
||||
);
|
||||
|
||||
// Act
|
||||
await main.run();
|
||||
|
||||
// Assert
|
||||
expect(existsSpy).toHaveBeenCalled();
|
||||
expect(existsSpy).toHaveReturnedWith(false);
|
||||
expect(parseNodeVersionSpy).not.toHaveBeenCalled();
|
||||
expect(getNodeVersionFromFileSpy).toHaveBeenCalled();
|
||||
expect(cnSpy).toHaveBeenCalledWith(
|
||||
`::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}`
|
||||
);
|
||||
|
||||
@@ -248,6 +248,9 @@ describe('setup-node', () => {
|
||||
const toolPath = path.normalize('/cache/node/12.16.2/x64');
|
||||
exSpy.mockImplementation(async () => '/some/other/temp/path');
|
||||
cacheSpy.mockImplementation(async () => toolPath);
|
||||
whichSpy.mockImplementation(cmd => {
|
||||
return `some/${cmd}/path`;
|
||||
});
|
||||
|
||||
await main.run();
|
||||
|
||||
@@ -357,6 +360,41 @@ describe('setup-node', () => {
|
||||
expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`);
|
||||
});
|
||||
|
||||
it('reports when download failed but version exists', async () => {
|
||||
os.platform = 'linux';
|
||||
os.arch = 'x64';
|
||||
|
||||
// a version which is not in the manifest but is in node dist
|
||||
const versionSpec = '11.15.0';
|
||||
|
||||
inputs['node-version'] = versionSpec;
|
||||
inputs['always-auth'] = false;
|
||||
inputs['token'] = 'faketoken';
|
||||
|
||||
// ... but not in the local cache
|
||||
findSpy.mockImplementation(() => '');
|
||||
|
||||
dlSpy.mockImplementationOnce(async () => {
|
||||
throw new tc.HTTPError(404);
|
||||
});
|
||||
|
||||
await main.run();
|
||||
|
||||
expect(getManifestSpy).toHaveBeenCalled();
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
`Attempting to download ${versionSpec}...`
|
||||
);
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
'Not found in manifest. Falling back to download directly from Node'
|
||||
);
|
||||
expect(dlSpy).toHaveBeenCalled();
|
||||
expect(warningSpy).toHaveBeenCalledWith(
|
||||
`Node version ${versionSpec} for platform ${os.platform} and architecture ${os.arch} was found but failed to download. ` +
|
||||
'This usually happens when downloadable binaries are not fully updated at https://nodejs.org/. ' +
|
||||
'To resolve this issue you may either fall back to the older version or try again later.'
|
||||
);
|
||||
});
|
||||
|
||||
it('acquires specified architecture of node', async () => {
|
||||
for (const {arch, version, osSpec} of [
|
||||
{arch: 'x86', version: '12.16.2', osSpec: 'win32'},
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ inputs:
|
||||
node-version:
|
||||
description: 'Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0.'
|
||||
node-version-file:
|
||||
description: 'File containing the version Spec of the version to use. Examples: .nvmrc, .node-version, .tool-versions.'
|
||||
description: 'File containing the version Spec of the version to use. Examples: package.json, .nvmrc, .node-version, .tool-versions.'
|
||||
architecture:
|
||||
description: 'Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default.'
|
||||
check-latest:
|
||||
@@ -33,7 +33,7 @@ outputs:
|
||||
node-version:
|
||||
description: 'The installed node version.'
|
||||
runs:
|
||||
using: 'node16'
|
||||
using: 'node20'
|
||||
main: 'dist/setup/index.js'
|
||||
post: 'dist/cache-save/index.js'
|
||||
post-if: success()
|
||||
|
||||
Vendored
+31006
-7774
File diff suppressed because one or more lines are too long
Vendored
+38210
-16104
File diff suppressed because one or more lines are too long
+42
-40
@@ -45,8 +45,8 @@ If `check-latest` is set to `true`, the action first checks if the cached versio
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
check-latest: true
|
||||
@@ -63,8 +63,8 @@ See [supported version syntax](https://github.com/actions/setup-node#supported-v
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
- run: npm ci
|
||||
@@ -84,6 +84,8 @@ When using the `package.json` input, the action will look for `volta.node` first
|
||||
}
|
||||
```
|
||||
|
||||
Otherwise, when [`volta.extends`](https://docs.volta.sh/advanced/workspaces) is defined, then it will resolve the corresponding file and look for `volta.node` or `engines.node` recursively.
|
||||
|
||||
## Architecture
|
||||
|
||||
You can use any of the [supported operating systems](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners), and the compatible `architecture` can be selected using `architecture`. Values are `x86`, `x64`, `arm64`, `armv6l`, `armv7l`, `ppc64le`, `s390x` (not all of the architectures are available on all platforms).
|
||||
@@ -95,8 +97,8 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
name: Node sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14'
|
||||
architecture: 'x64' # optional, x64 or x86. If not specified, x64 will be used by default
|
||||
@@ -116,8 +118,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Node sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.0.0-v8-canary' # it will install the latest v8 canary release for node 20.0.0
|
||||
- run: npm ci
|
||||
@@ -131,8 +133,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Node sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20-v8-canary' # it will install the latest v8 canary release for node 20
|
||||
- run: npm ci
|
||||
@@ -147,8 +149,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Node sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'v20.1.1-v8-canary20221103f7e2421e91'
|
||||
- run: npm ci
|
||||
@@ -167,8 +169,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Node sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16-nightly' # it will install the latest nightly release for node 16
|
||||
- run: npm ci
|
||||
@@ -183,8 +185,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Node sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16.0.0-nightly' # it will install the latest nightly release for node 16.0.0
|
||||
- run: npm ci
|
||||
@@ -199,8 +201,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Node sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16.0.0-nightly20210420a0261d231c'
|
||||
- run: npm ci
|
||||
@@ -217,8 +219,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Node sample
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16.0.0-rc.1'
|
||||
- run: npm ci
|
||||
@@ -234,8 +236,8 @@ The action follows [actions/cache](https://github.com/actions/cache/blob/main/ex
|
||||
Yarn caching handles both yarn versions: 1 or 2.
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'yarn'
|
||||
@@ -253,11 +255,11 @@ steps:
|
||||
# NOTE: pnpm caching support requires pnpm version >= 6.10.0
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 6.32.9
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'pnpm'
|
||||
@@ -272,8 +274,8 @@ steps:
|
||||
**Using wildcard patterns to cache dependencies**
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'npm'
|
||||
@@ -285,8 +287,8 @@ steps:
|
||||
**Using a list of file paths to cache dependencies**
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'npm'
|
||||
@@ -322,9 +324,9 @@ jobs:
|
||||
architecture: x86
|
||||
name: Node ${{ matrix.node_version }} - ${{ matrix.architecture }} on ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node_version }}
|
||||
architecture: ${{ matrix.architecture }}
|
||||
@@ -335,8 +337,8 @@ jobs:
|
||||
## Publish to npmjs and GPR with npm
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
@@ -344,7 +346,7 @@ steps:
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
registry-url: 'https://npm.pkg.github.com'
|
||||
- run: npm publish
|
||||
@@ -355,8 +357,8 @@ steps:
|
||||
## Publish to npmjs and GPR with yarn
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14.x'
|
||||
registry-url: <registry url>
|
||||
@@ -364,7 +366,7 @@ steps:
|
||||
- run: yarn publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.YARN_TOKEN }}
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
registry-url: 'https://npm.pkg.github.com'
|
||||
- run: yarn publish
|
||||
@@ -375,8 +377,8 @@ steps:
|
||||
## Use private packages
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
@@ -395,8 +397,8 @@ Below you can find a sample "Setup .yarnrc.yml" step, that is going to allow you
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '14.x'
|
||||
- name: Setup .yarnrc.yml
|
||||
|
||||
Generated
+2147
-7802
File diff suppressed because it is too large
Load Diff
+19
-18
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "setup-node",
|
||||
"version": "3.4.1",
|
||||
"version": "4.0.0",
|
||||
"private": true,
|
||||
"description": "setup node action",
|
||||
"main": "lib/setup-node.js",
|
||||
@@ -25,32 +25,33 @@
|
||||
"author": "GitHub",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^3.0.4",
|
||||
"@actions/cache": "^3.2.4",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.0",
|
||||
"@actions/github": "^1.1.0",
|
||||
"@actions/glob": "^0.2.0",
|
||||
"@actions/http-client": "^1.0.11",
|
||||
"@actions/github": "^5.1.1",
|
||||
"@actions/glob": "^0.4.0",
|
||||
"@actions/http-client": "^2.2.1",
|
||||
"@actions/io": "^1.0.2",
|
||||
"@actions/tool-cache": "^1.5.4",
|
||||
"semver": "^6.3.1"
|
||||
"@actions/tool-cache": "^2.0.1",
|
||||
"semver": "^7.6.0",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/node": "^16.11.25",
|
||||
"@types/semver": "^6.0.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.11.25",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||
"@typescript-eslint/parser": "^5.54.0",
|
||||
"@vercel/ncc": "^0.33.4",
|
||||
"eslint": "^8.35.0",
|
||||
"@vercel/ncc": "^0.38.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"eslint-plugin-jest": "^27.9.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"jest": "^27.2.5",
|
||||
"jest-circus": "^27.2.5",
|
||||
"jest-each": "^27.2.5",
|
||||
"jest": "^29.7.0",
|
||||
"jest-circus": "^29.7.0",
|
||||
"jest-each": "^29.7.0",
|
||||
"prettier": "^2.8.4",
|
||||
"ts-jest": "^27.0.5",
|
||||
"typescript": "^4.2.3"
|
||||
"ts-jest": "^29.1.2",
|
||||
"typescript": "^5.4.2"
|
||||
}
|
||||
}
|
||||
|
||||
+15
-8
@@ -1,8 +1,6 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as cache from '@actions/cache';
|
||||
|
||||
import fs from 'fs';
|
||||
|
||||
import {State} from './constants';
|
||||
import {getPackageManagerInfo} from './cache-utils';
|
||||
|
||||
@@ -14,22 +12,31 @@ process.on('uncaughtException', e => {
|
||||
core.info(`${warningPrefix}${e.message}`);
|
||||
});
|
||||
|
||||
export async function run() {
|
||||
// Added early exit to resolve issue with slow post action step:
|
||||
export async function run(earlyExit?: boolean) {
|
||||
try {
|
||||
const cacheLock = core.getState(State.CachePackageManager);
|
||||
await cachePackages(cacheLock);
|
||||
|
||||
if (cacheLock) {
|
||||
await cachePackages(cacheLock);
|
||||
|
||||
if (earlyExit) {
|
||||
process.exit(0);
|
||||
}
|
||||
} else {
|
||||
core.debug(`Caching for '${cacheLock}' is not supported`);
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
core.setFailed((error as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
const cachePackages = async (packageManager: string) => {
|
||||
const state = core.getState(State.CacheMatchedKey);
|
||||
const primaryKey = core.getState(State.CachePrimaryKey);
|
||||
let cachePaths = JSON.parse(
|
||||
const cachePaths = JSON.parse(
|
||||
core.getState(State.CachePaths) || '[]'
|
||||
) as string[];
|
||||
cachePaths = cachePaths.filter(fs.existsSync);
|
||||
|
||||
const packageManagerInfo = await getPackageManagerInfo(packageManager);
|
||||
if (!packageManagerInfo) {
|
||||
@@ -61,4 +68,4 @@ const cachePackages = async (packageManager: string) => {
|
||||
core.info(`Cache saved with the key: ${primaryKey}`);
|
||||
};
|
||||
|
||||
run();
|
||||
run(true);
|
||||
|
||||
@@ -16,12 +16,12 @@ export default abstract class BasePrereleaseNodejs extends BaseDistribution {
|
||||
const localVersionPaths = tc
|
||||
.findAllVersions('node', this.nodeInfo.arch)
|
||||
.filter(i => {
|
||||
const prerelease = semver.prerelease(i);
|
||||
const prerelease = semver.prerelease(i, {});
|
||||
if (!prerelease) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return prerelease[0].includes(this.distribution);
|
||||
return prerelease[0].toString().includes(this.distribution);
|
||||
});
|
||||
localVersionPaths.sort(semver.rcompare);
|
||||
const localVersion = this.evaluateVersions(localVersionPaths);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import * as hc from '@actions/http-client';
|
||||
import * as core from '@actions/core';
|
||||
@@ -111,7 +112,11 @@ export default abstract class BaseDistribution {
|
||||
? `node-v${version}-win-${osArch}`
|
||||
: `node-v${version}-${this.osPlat}-${osArch}`;
|
||||
const urlFileName: string =
|
||||
this.osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`;
|
||||
this.osPlat == 'win32'
|
||||
? this.nodeInfo.arch === 'arm64'
|
||||
? `${fileName}.zip`
|
||||
: `${fileName}.7z`
|
||||
: `${fileName}.tar.gz`;
|
||||
const initialUrl = this.getDistributionUrl();
|
||||
const url = `${initialUrl}/v${version}/${urlFileName}`;
|
||||
|
||||
@@ -152,7 +157,7 @@ export default abstract class BaseDistribution {
|
||||
}
|
||||
|
||||
protected validRange(versionSpec: string) {
|
||||
let options: semver.Options | undefined;
|
||||
let options: semver.RangeOptions | undefined;
|
||||
const c = semver.clean(versionSpec) || '';
|
||||
const valid = semver.valid(c) ?? versionSpec;
|
||||
|
||||
@@ -166,9 +171,8 @@ export default abstract class BaseDistribution {
|
||||
const initialUrl = this.getDistributionUrl();
|
||||
const osArch: string = this.translateArchToDistUrl(arch);
|
||||
|
||||
// Create temporary folder to download in to
|
||||
const tempDownloadFolder: string =
|
||||
'temp_' + Math.floor(Math.random() * 2000000000);
|
||||
// Create temporary folder to download to
|
||||
const tempDownloadFolder = `temp_${uuidv4()}`;
|
||||
const tempDirectory = process.env['RUNNER_TEMP'] || '';
|
||||
assert.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined');
|
||||
const tempDir: string = path.join(tempDirectory, tempDownloadFolder);
|
||||
@@ -215,12 +219,24 @@ export default abstract class BaseDistribution {
|
||||
let extPath: string;
|
||||
info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here
|
||||
if (this.osPlat == 'win32') {
|
||||
const _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe');
|
||||
extPath = await tc.extract7z(downloadPath, undefined, _7zPath);
|
||||
const extension = this.nodeInfo.arch === 'arm64' ? '.zip' : '.7z';
|
||||
// Rename archive to add extension because after downloading
|
||||
// archive does not contain extension type and it leads to some issues
|
||||
// on Windows runners without PowerShell Core.
|
||||
//
|
||||
// For default PowerShell Windows it should contain extension type to unpack it.
|
||||
if (extension === '.zip') {
|
||||
const renamedArchive = `${downloadPath}.zip`;
|
||||
fs.renameSync(downloadPath, renamedArchive);
|
||||
extPath = await tc.extractZip(renamedArchive);
|
||||
} else {
|
||||
const _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe');
|
||||
extPath = await tc.extract7z(downloadPath, undefined, _7zPath);
|
||||
}
|
||||
// 7z extracts to folder matching file name
|
||||
const nestedPath = path.join(
|
||||
extPath,
|
||||
path.basename(info.fileName, '.7z')
|
||||
path.basename(info.fileName, extension)
|
||||
);
|
||||
if (fs.existsSync(nestedPath)) {
|
||||
extPath = nestedPath;
|
||||
@@ -260,7 +276,11 @@ export default abstract class BaseDistribution {
|
||||
dataFileName = `osx-${osArch}-tar`;
|
||||
break;
|
||||
case 'win32':
|
||||
dataFileName = `win-${osArch}-exe`;
|
||||
if (this.nodeInfo.arch === 'arm64') {
|
||||
dataFileName = `win-${osArch}-zip`;
|
||||
} else {
|
||||
dataFileName = `win-${osArch}-exe`;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unexpected OS '${this.osPlat}'`);
|
||||
|
||||
@@ -18,6 +18,7 @@ export default class OfficialBuilds extends BaseDistribution {
|
||||
let manifest: tc.IToolRelease[] | undefined;
|
||||
let nodeJsVersions: INodeVersion[] | undefined;
|
||||
const osArch = this.translateArchToDistUrl(this.nodeInfo.arch);
|
||||
|
||||
if (this.isLtsAlias(this.nodeInfo.versionSpec)) {
|
||||
core.info('Attempt to resolve LTS alias from manifest...');
|
||||
|
||||
@@ -61,63 +62,57 @@ export default class OfficialBuilds extends BaseDistribution {
|
||||
|
||||
if (toolPath) {
|
||||
core.info(`Found in cache @ ${toolPath}`);
|
||||
} else {
|
||||
let downloadPath = '';
|
||||
try {
|
||||
core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`);
|
||||
this.addToolPath(toolPath);
|
||||
return;
|
||||
}
|
||||
|
||||
const versionInfo = await this.getInfoFromManifest(
|
||||
this.nodeInfo.versionSpec,
|
||||
this.nodeInfo.stable,
|
||||
osArch,
|
||||
manifest
|
||||
let downloadPath = '';
|
||||
try {
|
||||
core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`);
|
||||
|
||||
const versionInfo = await this.getInfoFromManifest(
|
||||
this.nodeInfo.versionSpec,
|
||||
this.nodeInfo.stable,
|
||||
osArch,
|
||||
manifest
|
||||
);
|
||||
|
||||
if (versionInfo) {
|
||||
core.info(
|
||||
`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`
|
||||
);
|
||||
downloadPath = await tc.downloadTool(
|
||||
versionInfo.downloadUrl,
|
||||
undefined,
|
||||
this.nodeInfo.auth
|
||||
);
|
||||
if (versionInfo) {
|
||||
core.info(
|
||||
`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`
|
||||
);
|
||||
downloadPath = await tc.downloadTool(
|
||||
versionInfo.downloadUrl,
|
||||
undefined,
|
||||
this.nodeInfo.auth
|
||||
);
|
||||
|
||||
if (downloadPath) {
|
||||
toolPath = await this.extractArchive(downloadPath, versionInfo);
|
||||
}
|
||||
} else {
|
||||
core.info(
|
||||
'Not found in manifest. Falling back to download directly from Node'
|
||||
);
|
||||
if (downloadPath) {
|
||||
toolPath = await this.extractArchive(downloadPath, versionInfo);
|
||||
}
|
||||
} catch (err) {
|
||||
// Rate limit?
|
||||
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');
|
||||
} else {
|
||||
core.info(
|
||||
'Not found in manifest. Falling back to download directly from Node'
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
// Rate limit?
|
||||
if (
|
||||
err instanceof tc.HTTPError &&
|
||||
(err.httpStatusCode === 403 || err.httpStatusCode === 429)
|
||||
) {
|
||||
core.info(
|
||||
`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`
|
||||
);
|
||||
} else {
|
||||
core.info((err as Error).message);
|
||||
}
|
||||
core.debug((err as Error).stack ?? 'empty stack');
|
||||
core.info('Falling back to download directly from Node');
|
||||
}
|
||||
|
||||
if (!toolPath) {
|
||||
const nodeJsVersions = await this.getNodeJsVersions();
|
||||
const versions = this.filterVersions(nodeJsVersions);
|
||||
const evaluatedVersion = this.evaluateVersions(versions);
|
||||
if (!evaluatedVersion) {
|
||||
throw new Error(
|
||||
`Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.`
|
||||
);
|
||||
}
|
||||
const toolName = this.getNodejsDistInfo(evaluatedVersion);
|
||||
toolPath = await this.downloadNodejs(toolName);
|
||||
}
|
||||
if (!toolPath) {
|
||||
toolPath = await this.downloadDirectlyFromNode();
|
||||
}
|
||||
|
||||
if (this.osPlat != 'win32') {
|
||||
@@ -127,6 +122,43 @@ export default class OfficialBuilds extends BaseDistribution {
|
||||
core.addPath(toolPath);
|
||||
}
|
||||
|
||||
protected addToolPath(toolPath: string) {
|
||||
if (this.osPlat != 'win32') {
|
||||
toolPath = path.join(toolPath, 'bin');
|
||||
}
|
||||
|
||||
core.addPath(toolPath);
|
||||
}
|
||||
|
||||
protected async downloadDirectlyFromNode() {
|
||||
const nodeJsVersions = await this.getNodeJsVersions();
|
||||
const versions = this.filterVersions(nodeJsVersions);
|
||||
const evaluatedVersion = this.evaluateVersions(versions);
|
||||
|
||||
if (!evaluatedVersion) {
|
||||
throw new Error(
|
||||
`Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.`
|
||||
);
|
||||
}
|
||||
|
||||
const toolName = this.getNodejsDistInfo(evaluatedVersion);
|
||||
|
||||
try {
|
||||
const toolPath = await this.downloadNodejs(toolName);
|
||||
return toolPath;
|
||||
} catch (error) {
|
||||
if (error instanceof tc.HTTPError && error.httpStatusCode === 404) {
|
||||
core.warning(
|
||||
`Node version ${this.nodeInfo.versionSpec} for platform ${this.osPlat} and architecture ${this.nodeInfo.arch} was found but failed to download. ` +
|
||||
'This usually happens when downloadable binaries are not fully updated at https://nodejs.org/. ' +
|
||||
'To resolve this issue you may either fall back to the older version or try again later.'
|
||||
);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
protected evaluateVersions(versions: string[]): string {
|
||||
let version = '';
|
||||
|
||||
@@ -214,7 +246,7 @@ export default class OfficialBuilds extends BaseDistribution {
|
||||
return info?.resolvedVersion;
|
||||
} catch (err) {
|
||||
core.info('Unable to resolve version from manifest...');
|
||||
core.debug(err.message);
|
||||
core.debug((err as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-8
@@ -1,6 +1,5 @@
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
|
||||
import * as auth from './authutil';
|
||||
@@ -8,7 +7,7 @@ import * as path from 'path';
|
||||
import {restoreCache} from './cache-restore';
|
||||
import {isCacheFeatureAvailable} from './cache-utils';
|
||||
import {getNodejsDistribution} from './distributions/installer-factory';
|
||||
import {parseNodeVersionFile, printEnvDetailsAndSetOutput} from './util';
|
||||
import {getNodeVersionFromFile, printEnvDetailsAndSetOutput} from './util';
|
||||
import {State} from './constants';
|
||||
|
||||
export async function run() {
|
||||
@@ -75,7 +74,7 @@ export async function run() {
|
||||
`##[add-matcher]${path.join(matchersPath, 'eslint-compact.json')}`
|
||||
);
|
||||
} catch (err) {
|
||||
core.setFailed(err.message);
|
||||
core.setFailed((err as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,14 +98,16 @@ function resolveVersionInput(): string {
|
||||
versionFileInput
|
||||
);
|
||||
|
||||
if (!fs.existsSync(versionFilePath)) {
|
||||
throw new Error(
|
||||
`The specified node version file at: ${versionFilePath} does not exist`
|
||||
const parsedVersion = getNodeVersionFromFile(versionFilePath);
|
||||
|
||||
if (parsedVersion) {
|
||||
version = parsedVersion;
|
||||
} else {
|
||||
core.warning(
|
||||
`Could not determine node version from ${versionFilePath}. Falling back`
|
||||
);
|
||||
}
|
||||
|
||||
version = parseNodeVersionFile(fs.readFileSync(versionFilePath, 'utf8'));
|
||||
|
||||
core.info(`Resolved ${versionFileInput} as ${version}`);
|
||||
}
|
||||
|
||||
|
||||
+52
-16
@@ -1,34 +1,70 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as io from '@actions/io';
|
||||
|
||||
export function parseNodeVersionFile(contents: string): string {
|
||||
let nodeVersion: string | undefined;
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
export function getNodeVersionFromFile(versionFilePath: string): string | null {
|
||||
if (!fs.existsSync(versionFilePath)) {
|
||||
throw new Error(
|
||||
`The specified node version file at: ${versionFilePath} does not exist`
|
||||
);
|
||||
}
|
||||
|
||||
const contents = fs.readFileSync(versionFilePath, 'utf8');
|
||||
|
||||
// Try parsing the file as an NPM `package.json` file.
|
||||
try {
|
||||
nodeVersion = JSON.parse(contents).volta?.node;
|
||||
if (!nodeVersion) nodeVersion = JSON.parse(contents).engines?.node;
|
||||
const manifest = JSON.parse(contents);
|
||||
|
||||
// Presume package.json file.
|
||||
if (typeof manifest === 'object' && !!manifest) {
|
||||
// Support Volta.
|
||||
// See https://docs.volta.sh/guide/understanding#managing-your-project
|
||||
if (manifest.volta?.node) {
|
||||
return manifest.volta.node;
|
||||
}
|
||||
|
||||
if (manifest.engines?.node) {
|
||||
return manifest.engines.node;
|
||||
}
|
||||
|
||||
// Support Volta workspaces.
|
||||
// See https://docs.volta.sh/advanced/workspaces
|
||||
if (manifest.volta?.extends) {
|
||||
const extendedFilePath = path.resolve(
|
||||
path.dirname(versionFilePath),
|
||||
manifest.volta.extends
|
||||
);
|
||||
core.info('Resolving node version from ' + extendedFilePath);
|
||||
return getNodeVersionFromFile(extendedFilePath);
|
||||
}
|
||||
|
||||
// If contents are an object, we parsed JSON
|
||||
// this can happen if node-version-file is a package.json
|
||||
// yet contains no volta.node or engines.node
|
||||
//
|
||||
// If node-version file is _not_ JSON, control flow
|
||||
// will not have reached these lines.
|
||||
//
|
||||
// And because we've reached here, we know the contents
|
||||
// *are* JSON, so no further string parsing makes sense.
|
||||
return null;
|
||||
}
|
||||
} catch {
|
||||
core.info('Node version file is not JSON file');
|
||||
}
|
||||
|
||||
if (!nodeVersion) {
|
||||
const found = contents.match(/^(?:node(js)?\s+)?v?(?<version>[^\s]+)$/m);
|
||||
nodeVersion = found?.groups?.version;
|
||||
}
|
||||
|
||||
// In the case of an unknown format,
|
||||
// return as is and evaluate the version separately.
|
||||
if (!nodeVersion) nodeVersion = contents.trim();
|
||||
|
||||
return nodeVersion as string;
|
||||
const found = contents.match(/^(?:node(js)?\s+)?v?(?<version>[^\s]+)$/m);
|
||||
return found?.groups?.version ?? contents.trim();
|
||||
}
|
||||
|
||||
export async function printEnvDetailsAndSetOutput() {
|
||||
core.startGroup('Environment details');
|
||||
|
||||
const promises = ['node', 'npm', 'yarn'].map(async tool => {
|
||||
const output = await getToolVersion(tool, ['--version']);
|
||||
const pathTool = await io.which(tool, false);
|
||||
const output = pathTool ? await getToolVersion(tool, ['--version']) : '';
|
||||
|
||||
return {tool, output};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user