Compare commits

..

No commits in common. "main" and "v4.0.1" have entirely different histories.
main ... v4.0.1

95 changed files with 13280 additions and 32494 deletions

View File

@ -1,22 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
# Enable version updates for npm
- package-ecosystem: 'npm'
# Look for `package.json` and `lock` files in the `root` directory
directory: '/'
# Check the npm registry for updates every day (weekdays)
schedule:
interval: 'weekly'
# Enable version updates for GitHub Actions
- package-ecosystem: 'github-actions'
# Workflow files stored in the default location of `.github/workflows`
# You don't need to specify `/.github/workflows` for `directory`. You can use `directory: "/"`.
directory: '/'
schedule:
interval: 'weekly'

View File

@ -4,7 +4,7 @@
"owner": "eslint-compact", "owner": "eslint-compact",
"pattern": [ "pattern": [
{ {
"regexp": "^(.+):\\sline\\s(\\d+),\\scol\\s(\\d+),\\s([Ee]rror|[Ww]arning|[Ii]nfo)\\s-\\s(.+)\\s\\((.+)\\)$", "regexp": "^(.+):\\sline\\s(\\d+),\\scol\\s(\\d+),\\s(Error|Warning|Info)\\s-\\s(.+)\\s\\((.+)\\)$",
"file": 1, "file": 1,
"line": 2, "line": 2,
"column": 3, "column": 3,

View File

@ -4,7 +4,7 @@
"owner": "eslint-stylish", "owner": "eslint-stylish",
"pattern": [ "pattern": [
{ {
"regexp": "^\\s*([^\\s].*)$", "regexp": "^([^\\s].*)$",
"file": 1 "file": 1
}, },
{ {

View File

@ -16,4 +16,4 @@ jobs:
name: Basic validation name: Basic validation
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
with: with:
node-version: '24.x' node-version: '20.x'

View File

@ -16,4 +16,4 @@ jobs:
name: Check dist/ name: Check dist/
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
with: with:
node-version: '24.x' node-version: '20.x'

View File

@ -18,10 +18,10 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20, 22, 24] node-version: [12, 14, 16]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Clean global cache - name: Clean global cache
run: npm cache clean --force run: npm cache clean --force
- name: Setup Node - name: Setup Node
@ -41,12 +41,12 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20, 22, 24] node-version: [12, 14, 16]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v2
with: with:
version: 6.10.0 version: 6.10.0
- name: Generate pnpm file - name: Generate pnpm file
@ -74,14 +74,14 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20, 22, 24] node-version: [14, 16]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Yarn version - name: Yarn version
run: yarn --version run: yarn --version
- name: Generate yarn file - name: Generate yarn file
run: yarn install --ignore-engines run: yarn install
- name: Remove dependencies - name: Remove dependencies
shell: pwsh shell: pwsh
run: Remove-Item node_modules -Force -Recurse run: Remove-Item node_modules -Force -Recurse
@ -106,10 +106,10 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20, 22, 24] node-version: [12, 14, 16]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Update yarn - name: Update yarn
run: yarn set version 3.6.4 run: yarn set version 3.6.4
- name: Yarn version - name: Yarn version
@ -139,11 +139,11 @@ jobs:
name: Test yarn subprojects name: Test yarn subprojects
strategy: strategy:
matrix: matrix:
node-version: [20, 22, 24] node-version: [12, 14, 16]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: prepare sub-projects - name: prepare sub-projects
run: __tests__/prepare-yarn-subprojects.sh yarn1 run: __tests__/prepare-yarn-subprojects.sh yarn1
@ -166,11 +166,11 @@ jobs:
name: Test yarn subprojects all locally managed name: Test yarn subprojects all locally managed
strategy: strategy:
matrix: matrix:
node-version: [20, 22, 24] node-version: [12, 14, 16]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: prepare sub-projects - name: prepare sub-projects
run: __tests__/prepare-yarn-subprojects.sh keepcache keepcache run: __tests__/prepare-yarn-subprojects.sh keepcache keepcache
@ -193,11 +193,11 @@ jobs:
name: Test yarn subprojects some locally managed name: Test yarn subprojects some locally managed
strategy: strategy:
matrix: matrix:
node-version: [20, 22, 24] node-version: [12, 14, 16]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: prepare sub-projects - name: prepare sub-projects
run: __tests__/prepare-yarn-subprojects.sh global run: __tests__/prepare-yarn-subprojects.sh global
@ -220,11 +220,11 @@ jobs:
name: Test yarn subprojects managed by git name: Test yarn subprojects managed by git
strategy: strategy:
matrix: matrix:
node-version: [20, 22, 24] node-version: [12, 14, 16]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: prepare sub-projects - name: prepare sub-projects
run: /bin/bash __tests__/prepare-yarn-subprojects.sh keepcache run: /bin/bash __tests__/prepare-yarn-subprojects.sh keepcache
@ -243,62 +243,3 @@ jobs:
cache-dependency-path: | cache-dependency-path: |
sub2/*.lock sub2/*.lock
sub3/*.lock sub3/*.lock
node-npm-packageManager-auto-cache:
name: Test auto cache with top-level packageManager
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large]
node-version: [20, 22, 24]
steps:
- uses: actions/checkout@v6
- name: Create package.json with packageManager field
run: |
echo '{ "name": "test-project", "version": "1.0.0", "packageManager": "npm@8.0.0" }' > package.json
- name: Clean global cache
run: npm cache clean --force
- name: Setup Node with caching enabled
uses: ./
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm install
- name: Verify node and npm
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
shell: bash
node-npm-devEngines-auto-cache:
name: Test auto cache with devEngines.packageManager
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large]
node-version: [20, 22, 24]
steps:
- uses: actions/checkout@v6
- name: Create package.json with devEngines field
run: |
echo '{
"name": "test-project",
"version": "1.0.0",
"devEngines": {
"packageManager": {
"name": "npm",
"onFail": "error"
}
}
}' > package.json
- name: Clean global cache
run: npm cache clean --force
- name: Setup Node with caching enabled
uses: ./
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm install
- name: Verify node and npm
run: __tests__/verify-node.sh "${{ matrix.node-version }}"
shell: bash

View File

@ -25,15 +25,15 @@ jobs:
env: env:
https_proxy: http://squid-proxy:3128 https_proxy: http://squid-proxy:3128
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Clear tool cache - name: Clear tool cache
run: rm -rf $RUNNER_TOOL_CACHE/* run: rm -rf $RUNNER_TOOL_CACHE/*
- name: Setup node 24 - name: Setup node 14
uses: ./ uses: ./
with: with:
node-version: 24.x node-version: 14.x
- name: Verify node and npm - name: Verify node and npm
run: __tests__/verify-node.sh 24 run: __tests__/verify-node.sh 14
test-bypass-proxy: test-bypass-proxy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -41,12 +41,12 @@ jobs:
https_proxy: http://no-such-proxy:3128 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 no_proxy: api.github.com,github.com,nodejs.org,registry.npmjs.org,*.s3.amazonaws.com,s3.amazonaws.com
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Clear tool cache - name: Clear tool cache
run: rm -rf $RUNNER_TOOL_CACHE/* run: rm -rf $RUNNER_TOOL_CACHE/*
- name: Setup node 24 - name: Setup node 11
uses: ./ uses: ./
with: with:
node-version: 24 node-version: 11
- name: Verify node and npm - name: Verify node and npm
run: __tests__/verify-node.sh 24 run: __tests__/verify-node.sh 11

View File

@ -1,20 +0,0 @@
name: 'Publish Immutable Action Version'
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
packages: write
steps:
- name: Checking out
uses: actions/checkout@v6
- name: Publish
id: publish
uses: actions/publish-immutable-action@v0.0.4

View File

@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Update the ${{ env.TAG_NAME }} tag - name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.4.0 uses: actions/publish-action@v0.2.2
with: with:
source-tag: ${{ env.TAG_NAME }} source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }} slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

View File

@ -17,10 +17,10 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20, 22, 24] node-version: [10, 12, 14]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node - name: Setup Node
uses: ./ uses: ./
with: with:
@ -34,16 +34,16 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [lts/dubnium, lts/erbium, lts/fermium, lts/*, lts/-1] node-version: [lts/dubnium, lts/erbium, lts/fermium, lts/*, lts/-1]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node - name: Setup Node
uses: ./ uses: ./
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
check-latest: true check-latest: true
- if: runner.os != 'Windows' && runner.os != 'macOS' - if: runner.os != 'Windows'
name: Verify node and npm name: Verify node and npm
run: | run: |
. "$NVM_DIR/nvm.sh" . "$NVM_DIR/nvm.sh"
@ -56,7 +56,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: node-version:
[ [
'20-v8-canary', '20-v8-canary',
@ -64,7 +64,7 @@ jobs:
'20.0.0-v8-canary20221101e50e45c9f8' '20.0.0-v8-canary20221101e50e45c9f8'
] ]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node - name: Setup Node
uses: ./ uses: ./
with: with:
@ -81,10 +81,11 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20-nightly, 25-nightly, 24.0.0-nightly] node-version:
[16.0.0-nightly20210420a0261d231c, 17-nightly, 18.0.0-nightly]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node - name: Setup Node
uses: ./ uses: ./
with: with:
@ -101,10 +102,10 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20.0.0-rc.1, 22.14.0-rc.1, 24.0.0-rc.4] node-version: [16.0.0-rc.1, 18.0.0-rc.2, 19.0.0-rc.0]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node - name: Setup Node
uses: ./ uses: ./
with: with:
@ -121,10 +122,10 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20.10.0, 22.0.0, 24.9.0] node-version: [10.15, 12.16.0, 14.2.0, 16.3.0]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node - name: Setup Node
uses: ./ uses: ./
with: with:
@ -138,10 +139,10 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20, 22, 24] node-version: [10, 12, 14]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node and check latest - name: Setup Node and check latest
uses: ./ uses: ./
with: with:
@ -156,57 +157,45 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version-file: node-version-file:
[.nvmrc, .tool-versions, .tool-versions-node, package.json] [.nvmrc, .tool-versions, .tool-versions-node, package.json]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Remove volta from package.json
shell: bash
run: cat <<< "$(jq 'del(.volta)' ./__tests__/data/package.json)" > ./__tests__/data/package.json
- name: Setup node from node version file - name: Setup node from node version file
uses: ./ uses: ./
with: with:
node-version-file: '__tests__/data/${{ matrix.node-version-file }}' node-version-file: '__tests__/data/${{ matrix.node-version-file }}'
- name: Verify node - name: Verify node
run: __tests__/verify-node.sh 24 run: __tests__/verify-node.sh 14
version-file-volta: version-file-volta:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup node from node version file - name: Setup node from node version file
uses: ./ uses: ./
with: with:
node-version-file: '__tests__/data/package-volta.json' node-version-file: '__tests__/data/package.json'
- name: Verify node - name: Verify node
run: __tests__/verify-node.sh 24 run: __tests__/verify-node.sh 16
version-file-volta-extends:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large]
steps:
- uses: actions/checkout@v6
- 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 24
node-dist: node-dist:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [17, 19] node-version: [11, 13]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node from dist - name: Setup Node from dist
uses: ./ uses: ./
with: with:
@ -220,9 +209,9 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
# test old versions which didn't have npm and layout different # test old versions which didn't have npm and layout different
- name: Setup node 0.12.18 from dist - name: Setup node 0.12.18 from dist
uses: ./ uses: ./
@ -235,11 +224,11 @@ jobs:
arch: arch:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup node 20 x86 from dist - name: Setup node 14 x86 from dist
uses: ./ uses: ./
with: with:
node-version: '20' node-version: '14'
architecture: 'x86' architecture: 'x86'
- name: Verify node - name: Verify node
run: __tests__/verify-arch.sh "ia32" run: __tests__/verify-arch.sh "ia32"
@ -250,7 +239,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest, macos-latest-large] os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [current, latest, node] node-version: [current, latest, node]
steps: steps:
- name: Get node version - name: Get node version
@ -259,7 +248,7 @@ jobs:
echo "LATEST_NODE_VERSION=$latestNodeVersion" >> $GITHUB_OUTPUT echo "LATEST_NODE_VERSION=$latestNodeVersion" >> $GITHUB_OUTPUT
id: version id: version
shell: bash shell: bash
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Setup Node - name: Setup Node
uses: ./ uses: ./
with: with:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.licenses/npm/lru-cache.dep.yml generated Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.licenses/npm/yallist.dep.yml generated Normal file

Binary file not shown.

View File

@ -12,32 +12,16 @@ This action provides the following functionality for GitHub Actions users:
- Registering problem matchers for error output - Registering problem matchers for error output
- Configuring authentication for GPR or npm - Configuring authentication for GPR or npm
## Breaking changes in V6
- Caching is now automatically enabled for npm projects when either the `devEngines.packageManager` field or the top-level `packageManager` field in `package.json` is set to `npm`. For other package managers, such as Yarn and pnpm, caching is disabled by default and must be configured manually using the `cache` input.
- The `always-auth` input has been removed, as it is deprecated and will no longer be supported in future npm releases. To ensure your workflows continue to run without warnings or errors, please remove any references to `always-auth` from your configuration.
## Breaking changes in V5
- Enabled caching by default with package manager detection if no cache input is provided.
> For workflows with elevated privileges or access to sensitive information, we recommend disabling automatic caching by setting `package-manager-cache: false` when caching is not needed for secure operation.
- Upgraded action from node20 to node24.
> Make sure your runner is on version v2.327.1 or later to ensure compatibility with this release. [See Release Notes](https://github.com/actions/runner/releases/tag/v2.327.1)
For more details, see the full release notes on the [releases page](https://github.com/actions/setup-node/releases/v5.0.0)
## Usage ## Usage
See [action.yml](action.yml) See [action.yml](action.yml)
<!-- start usage --> <!-- start usage -->
```yaml ```yaml
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
# Version Spec of the version to use in SemVer notation. # Version Spec of the version to use in SemVer notation.
# It also admits such aliases as lts/*, latest, nightly and canary builds # 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 # Examples: 12.x, 10.15.1, >=10.15.0, lts/Hydrogen, 16-nightly, latest, node
node-version: '' node-version: ''
@ -73,11 +57,6 @@ See [action.yml](action.yml)
# Default: '' # Default: ''
cache: '' cache: ''
# Controls automatic caching for npm. By default, caching for npm is enabled if either the devEngines.packageManager field or the top-level packageManager field in package.json specifies npm and no explicit cache input is provided.
# To disable automatic caching for npm, set package-manager-cache to false.
# default: true
package-manager-cache: true
# Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. # Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc.
# It will generate hash from the target file for primary key. It works only If cache is specified. # It will generate hash from the target file for primary key. It works only If cache is specified.
# Supports wildcards or a list of file names for caching multiple dependencies. # Supports wildcards or a list of file names for caching multiple dependencies.
@ -94,20 +73,9 @@ See [action.yml](action.yml)
# Default: '' # Default: ''
scope: '' scope: ''
# Optional mirror to download binaries from. # Set always-auth option in npmrc file.
# Artifacts need to match the official Node.js
# Example:
# V8 Canaray Build: <mirror_url>/download/v8-canary
# RC Build: <mirror_url>/download/rc
# Official: Build <mirror_url>/dist
# Nightly build: <mirror_url>/download/nightly
# Default: '' # Default: ''
mirror: '' always-auth: ''
# Optional mirror token.
# The token will be used as a bearer token in the Authorization header
# Default: ''
mirror-token: ''
``` ```
<!-- end usage --> <!-- end usage -->
@ -115,10 +83,10 @@ See [action.yml](action.yml)
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: 24 node-version: 18
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
@ -135,9 +103,9 @@ The `node-version` input supports the Semantic Versioning Specification, for mor
Examples: Examples:
- Major versions: `22`, `24` - Major versions: `16`, `18`, `20`
- More specific versions: `20.19`, `22.17.1` , `24.8.0` - More specific versions: `10.15`, `16.15.1` , `18.4.0`
- NVM LTS syntax: `lts/iron`, `lts/jod`, `lts/*`, `lts/-n` - NVM LTS syntax: `lts/erbium`, `lts/fermium`, `lts/*`, `lts/-n`
- Latest release: `*` or `latest`/`current`/`node` - 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/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. **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.
@ -152,7 +120,7 @@ It's **always** recommended to commit the lockfile of your package manager for s
## Caching global packages data ## Caching global packages data
The action has a built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/cache) under the hood for caching global packages data but requires less configuration settings. Supported package managers are `npm`, `yarn`, `pnpm` (v6.10+). The `cache` input is optional. The action has a built-in functionality for caching and restoring dependencies. It uses [actions/cache](https://github.com/actions/cache) under the hood for caching global packages data but requires less configuration settings. Supported package managers are `npm`, `yarn`, `pnpm` (v6.10+). The `cache` input is optional, and caching is turned off by default.
The action defaults to search for the dependency file (`package-lock.json`, `npm-shrinkwrap.json` or `yarn.lock`) in the repository root, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases when multiple dependency files are used, or they are located in different subdirectories. The action defaults to search for the dependency file (`package-lock.json`, `npm-shrinkwrap.json` or `yarn.lock`) in the repository root, and uses its hash as a part of the cache key. Use `cache-dependency-path` for cases when multiple dependency files are used, or they are located in different subdirectories.
@ -164,10 +132,10 @@ See the examples of using cache for `yarn`/`pnpm` and `cache-dependency-path` in
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: 24 node-version: 16
cache: 'npm' cache: 'npm'
- run: npm ci - run: npm ci
- run: npm test - run: npm test
@ -177,30 +145,16 @@ steps:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: 24 node-version: 16
cache: 'npm' cache: 'npm'
cache-dependency-path: subdir/package-lock.json cache-dependency-path: subdir/package-lock.json
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
Caching for npm dependencies is automatically enabled when your `package.json` contains either `devEngines.packageManager` field or top-level `packageManager` field set to `npm`, and no explicit cache input is provided.
This behavior is controlled by the `package-manager-cache` input, which defaults to `true`. To turn off automatic caching, set `package-manager-cache` to `false`.
```yaml
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v6
with:
package-manager-cache: false
- run: npm ci
```
> If your `package.json` file does not include a `packageManager` field set to `npm`, caching will be disabled unless you explicitly enable it. For workflows with elevated privileges or access to sensitive information, we recommend disabling automatic caching for npm by setting `package-manager-cache: false` when caching is not required for secure operation.
## Matrix Testing ## Matrix Testing
```yaml ```yaml
@ -209,12 +163,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node: [ 20, 22, 24 ] node: [ 14, 16, 18 ]
name: Node ${{ matrix.node }} sample name: Node ${{ matrix.node }} sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- name: Setup node - name: Setup node
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
- run: npm ci - run: npm ci
@ -228,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: 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 ```yaml
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
token: ${{ secrets.GH_DOTCOM_TOKEN }} token: ${{ secrets.GH_DOTCOM_TOKEN }}
node-version: 24 node-version: 16
``` ```
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. 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.
@ -250,15 +204,6 @@ If the runner is not able to access github.com, any Nodejs versions requested du
- [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) - [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn)
- [Using private packages](docs/advanced-usage.md#use-private-packages) - [Using private packages](docs/advanced-usage.md#use-private-packages)
## Recommended permissions
When using the `setup-node` action in your GitHub Actions workflow, it is recommended to set the following permissions to ensure proper functionality:
```yaml
permissions:
contents: read # access to check out code and install dependencies
```
## License ## License
The scripts and documentation in this project are released under the [MIT License](LICENSE) The scripts and documentation in this project are released under the [MIT License](LICENSE)

View File

@ -76,102 +76,115 @@ describe('authutil tests', () => {
} }
it('Sets up npmrc for npmjs', async () => { it('Sets up npmrc for npmjs', async () => {
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'false');
expect(fs.statSync(rcFile)).toBeDefined(); expect(fs.statSync(rcFile)).toBeDefined();
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
const rc = readRcFile(rcFile); const rc = readRcFile(rcFile);
expect(rc['registry']).toBe('https://registry.npmjs.org/'); expect(rc['registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('false');
}); });
it('Appends trailing slash to registry', async () => { it('Appends trailing slash to registry', async () => {
await auth.configAuthentication('https://registry.npmjs.org'); await auth.configAuthentication('https://registry.npmjs.org', 'false');
expect(fs.statSync(rcFile)).toBeDefined(); expect(fs.statSync(rcFile)).toBeDefined();
const rc = readRcFile(rcFile); const rc = readRcFile(rcFile);
expect(rc['registry']).toBe('https://registry.npmjs.org/'); expect(rc['registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('false');
}); });
it('Configures scoped npm registries', async () => { it('Configures scoped npm registries', async () => {
process.env['INPUT_SCOPE'] = 'myScope'; process.env['INPUT_SCOPE'] = 'myScope';
await auth.configAuthentication('https://registry.npmjs.org'); await auth.configAuthentication('https://registry.npmjs.org', 'false');
expect(fs.statSync(rcFile)).toBeDefined(); expect(fs.statSync(rcFile)).toBeDefined();
const rc = readRcFile(rcFile); const rc = readRcFile(rcFile);
expect(rc['@myscope:registry']).toBe('https://registry.npmjs.org/'); expect(rc['@myscope:registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('false');
}); });
it('Automatically configures GPR scope', async () => { it('Automatically configures GPR scope', async () => {
await auth.configAuthentication('npm.pkg.github.com'); await auth.configAuthentication('npm.pkg.github.com', 'false');
expect(fs.statSync(rcFile)).toBeDefined(); expect(fs.statSync(rcFile)).toBeDefined();
const rc = readRcFile(rcFile); const rc = readRcFile(rcFile);
expect(rc['@ownername:registry']).toBe('npm.pkg.github.com/'); expect(rc['@ownername:registry']).toBe('npm.pkg.github.com/');
expect(rc['always-auth']).toBe('false');
});
it('Sets up npmrc for always-auth true', async () => {
await auth.configAuthentication('https://registry.npmjs.org/', 'true');
expect(fs.statSync(rcFile)).toBeDefined();
const rc = readRcFile(rcFile);
expect(rc['registry']).toBe('https://registry.npmjs.org/');
expect(rc['always-auth']).toBe('true');
}); });
it('is already set the NODE_AUTH_TOKEN export it', async () => { it('is already set the NODE_AUTH_TOKEN export it', async () => {
process.env.NODE_AUTH_TOKEN = 'foobar'; process.env.NODE_AUTH_TOKEN = 'foobar';
await auth.configAuthentication('npm.pkg.github.com'); await auth.configAuthentication('npm.pkg.github.com', 'false');
expect(fs.statSync(rcFile)).toBeDefined(); expect(fs.statSync(rcFile)).toBeDefined();
const rc = readRcFile(rcFile); const rc = readRcFile(rcFile);
expect(rc['@ownername:registry']).toBe('npm.pkg.github.com/'); expect(rc['@ownername:registry']).toBe('npm.pkg.github.com/');
expect(rc['always-auth']).toBe('false');
expect(process.env.NODE_AUTH_TOKEN).toEqual('foobar'); expect(process.env.NODE_AUTH_TOKEN).toEqual('foobar');
}); });
it('configAuthentication should overwrite non-scoped with non-scoped', async () => { it('configAuthentication should overwrite non-scoped with non-scoped', async () => {
fs.writeFileSync(rcFile, 'registry=NNN'); fs.writeFileSync(rcFile, 'registry=NNN');
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe( expect(contents).toBe(
`//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/` `//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
); );
}); });
it('configAuthentication should overwrite only non-scoped', async () => { it('configAuthentication should overwrite only non-scoped', async () => {
fs.writeFileSync(rcFile, `registry=NNN${os.EOL}@myscope:registry=MMM`); fs.writeFileSync(rcFile, `registry=NNN${os.EOL}@myscope:registry=MMM`);
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe( expect(contents).toBe(
`@myscope:registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/` `@myscope:registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
); );
}); });
it('configAuthentication should add non-scoped to scoped', async () => { it('configAuthentication should add non-scoped to scoped', async () => {
fs.writeFileSync(rcFile, '@myscope:registry=NNN'); fs.writeFileSync(rcFile, '@myscope:registry=NNN');
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe( expect(contents).toBe(
`@myscope:registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/` `@myscope:registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
); );
}); });
it('configAuthentication should overwrite scoped with scoped', async () => { it('configAuthentication should overwrite scoped with scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope'; process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(rcFile, `@myscope:registry=NNN`); fs.writeFileSync(rcFile, `@myscope:registry=NNN`);
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe( expect(contents).toBe(
`//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/` `//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
); );
}); });
it('configAuthentication should overwrite only scoped', async () => { it('configAuthentication should overwrite only scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope'; process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(rcFile, `registry=NNN${os.EOL}@myscope:registry=MMM`); fs.writeFileSync(rcFile, `registry=NNN${os.EOL}@myscope:registry=MMM`);
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe( expect(contents).toBe(
`registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/` `registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
); );
}); });
it('configAuthentication should add scoped to non-scoped', async () => { it('configAuthentication should add scoped to non-scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope'; process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(rcFile, `registry=MMM`); fs.writeFileSync(rcFile, `registry=MMM`);
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe( expect(contents).toBe(
`registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/` `registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
); );
}); });
@ -181,20 +194,20 @@ describe('authutil tests', () => {
rcFile, rcFile,
`@otherscope:registry=NNN${os.EOL}@myscope:registry=MMM` `@otherscope:registry=NNN${os.EOL}@myscope:registry=MMM`
); );
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe( expect(contents).toBe(
`@otherscope:registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/` `@otherscope:registry=NNN${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
); );
}); });
it('configAuthentication should add scoped to another scoped', async () => { it('configAuthentication should add scoped to another scoped', async () => {
process.env['INPUT_SCOPE'] = 'myscope'; process.env['INPUT_SCOPE'] = 'myscope';
fs.writeFileSync(rcFile, `@otherscope:registry=MMM`); fs.writeFileSync(rcFile, `@otherscope:registry=MMM`);
await auth.configAuthentication('https://registry.npmjs.org/'); await auth.configAuthentication('https://registry.npmjs.org/', 'true');
const contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); const contents = fs.readFileSync(rcFile, {encoding: 'utf8'});
expect(contents).toBe( expect(contents).toBe(
`@otherscope:registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/` `@otherscope:registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
); );
}); });
}); });

View File

@ -2,7 +2,6 @@ import * as core from '@actions/core';
import * as cache from '@actions/cache'; import * as cache from '@actions/cache';
import * as path from 'path'; import * as path from 'path';
import * as glob from '@actions/glob'; import * as glob from '@actions/glob';
import osm from 'os';
import * as utils from '../src/cache-utils'; import * as utils from '../src/cache-utils';
import {restoreCache} from '../src/cache-restore'; import {restoreCache} from '../src/cache-restore';
@ -13,7 +12,6 @@ describe('cache-restore', () => {
process.env.RUNNER_OS = 'Linux'; process.env.RUNNER_OS = 'Linux';
} }
const platform = process.env.RUNNER_OS; const platform = process.env.RUNNER_OS;
const arch = 'arm64';
const commonPath = '/some/random/path'; const commonPath = '/some/random/path';
const npmCachePath = `${commonPath}/npm`; const npmCachePath = `${commonPath}/npm`;
const pnpmCachePath = `${commonPath}/pnpm`; const pnpmCachePath = `${commonPath}/pnpm`;
@ -54,7 +52,6 @@ describe('cache-restore', () => {
let getCommandOutputSpy: jest.SpyInstance; let getCommandOutputSpy: jest.SpyInstance;
let restoreCacheSpy: jest.SpyInstance; let restoreCacheSpy: jest.SpyInstance;
let hashFilesSpy: jest.SpyInstance; let hashFilesSpy: jest.SpyInstance;
let archSpy: jest.SpyInstance;
beforeEach(() => { beforeEach(() => {
// core // core
@ -105,10 +102,6 @@ describe('cache-restore', () => {
// cache-utils // cache-utils
getCommandOutputSpy = jest.spyOn(utils, 'getCommandOutput'); getCommandOutputSpy = jest.spyOn(utils, 'getCommandOutput');
// os
archSpy = jest.spyOn(osm, 'arch');
archSpy.mockImplementation(() => arch);
}); });
describe('Validate provided package manager', () => { describe('Validate provided package manager', () => {
@ -142,7 +135,7 @@ describe('cache-restore', () => {
await restoreCache(packageManager, ''); await restoreCache(packageManager, '');
expect(hashFilesSpy).toHaveBeenCalled(); expect(hashFilesSpy).toHaveBeenCalled();
expect(infoSpy).toHaveBeenCalledWith( expect(infoSpy).toHaveBeenCalledWith(
`Cache restored from key: node-cache-${platform}-${arch}-${packageManager}-${fileHash}` `Cache restored from key: node-cache-${platform}-${packageManager}-${fileHash}`
); );
expect(infoSpy).not.toHaveBeenCalledWith( expect(infoSpy).not.toHaveBeenCalledWith(
`${packageManager} cache is not found` `${packageManager} cache is not found`

View File

@ -6,7 +6,7 @@ import {
PackageManagerInfo, PackageManagerInfo,
isCacheFeatureAvailable, isCacheFeatureAvailable,
supportedPackageManagers, supportedPackageManagers,
isGhes, getCommandOutput,
resetProjectDirectoriesMemoized resetProjectDirectoriesMemoized
} from '../src/cache-utils'; } from '../src/cache-utils';
import fs from 'fs'; import fs from 'fs';
@ -361,41 +361,3 @@ describe('cache-utils', () => {
); );
}); });
}); });
describe('isGhes', () => {
const pristineEnv = process.env;
beforeEach(() => {
jest.resetModules();
process.env = {...pristineEnv};
});
afterAll(() => {
process.env = pristineEnv;
});
it('returns false when the GITHUB_SERVER_URL environment variable is not defined', () => {
delete process.env['GITHUB_SERVER_URL'];
expect(isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable is set to github.com', () => {
process.env['GITHUB_SERVER_URL'] = 'https://github.com';
expect(isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable is set to a GitHub Enterprise Cloud-style URL', () => {
process.env['GITHUB_SERVER_URL'] = 'https://contoso.ghe.com';
expect(isGhes()).toBeFalsy();
});
it('returns false when the GITHUB_SERVER_URL environment variable has a .localhost suffix', () => {
process.env['GITHUB_SERVER_URL'] = 'https://mock-github.localhost';
expect(isGhes()).toBeFalsy();
});
it('returns true when the GITHUB_SERVER_URL environment variable is set to some other URL', () => {
process.env['GITHUB_SERVER_URL'] = 'https://src.onpremise.fabrikam.com';
expect(isGhes()).toBeTruthy();
});
});

View File

@ -227,6 +227,7 @@ describe('setup-node', () => {
const versionSpec = '11.15.0'; const versionSpec = '11.15.0';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -282,6 +283,7 @@ describe('setup-node', () => {
const versionSpec = '19.0.0-v8-canary'; const versionSpec = '19.0.0-v8-canary';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
findSpy.mockImplementation(() => ''); findSpy.mockImplementation(() => '');
@ -322,6 +324,7 @@ describe('setup-node', () => {
inputs['node-version'] = version; inputs['node-version'] = version;
inputs['architecture'] = arch; inputs['architecture'] = arch;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
const expectedUrl = `https://nodejs.org/download/v8-canary/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`; const expectedUrl = `https://nodejs.org/download/v8-canary/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;
@ -495,70 +498,6 @@ describe('setup-node', () => {
); );
} }
); );
it.each([
[
'20.0.0-v8-canary',
'20.0.0-v8-canary20221103f7e2421e91',
'20.0.0-v8-canary20221030fefe1c0879',
'https://my_mirror.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz'
],
[
'20-v8-canary',
'20.0.0-v8-canary20221103f7e2421e91',
'20.0.0-v8-canary20221030fefe1c0879',
'https://my_mirror.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz'
],
[
'19.0.0-v8-canary',
'19.0.0-v8-canary202210187d6960f23f',
'19.0.0-v8-canary202210172ec229fc56',
'https://my_mirror.org/download/v8-canary/v19.0.0-v8-canary202210187d6960f23f/node-v19.0.0-v8-canary202210187d6960f23f-linux-x64.tar.gz'
],
[
'19-v8-canary',
'19.0.0-v8-canary202210187d6960f23f',
'19.0.0-v8-canary202210172ec229fc56',
'https://my_mirror.org/download/v8-canary/v19.0.0-v8-canary202210187d6960f23f/node-v19.0.0-v8-canary202210187d6960f23f-linux-x64.tar.gz'
]
])(
'get %s version from dist if check-latest is true',
async (input, expectedVersion, foundVersion, expectedUrl) => {
const foundToolPath = path.normalize(`/cache/node/${foundVersion}/x64`);
const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
inputs['node-version'] = input;
inputs['check-latest'] = 'true';
os['arch'] = 'x64';
os['platform'] = 'linux';
inputs['mirror'] = 'https://my_mirror.org';
inputs['mirror-token'] = 'faketoken';
findSpy.mockReturnValue(foundToolPath);
findAllVersionsSpy.mockReturnValue([
'20.0.0-v8-canary20221030fefe1c0879',
'19.0.0-v8-canary202210172ec229fc56',
'20.0.0-v8-canary2022102310ff1e5a8d'
]);
dlSpy.mockImplementation(async () => '/some/temp/path');
exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath);
// act
await main.run();
// assert
expect(findAllVersionsSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
`Acquiring ${expectedVersion} - ${os.arch} from ${expectedUrl}`
);
expect(logSpy).toHaveBeenCalledWith('Extracting ...');
expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...');
expect(cnSpy).toHaveBeenCalledWith(
`::add-path::${path.join(toolPath, 'bin')}${osm.EOL}`
);
}
);
}); });
describe('setup-node v8 canary tests', () => { describe('setup-node v8 canary tests', () => {
@ -566,6 +505,7 @@ describe('setup-node', () => {
const versionSpec = 'v20-v8-canary'; const versionSpec = 'v20-v8-canary';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
os.platform = 'linux'; os.platform = 'linux';

View File

@ -1 +1 @@
v24 v14

View File

@ -1 +1 @@
nodejs 24.0.0 nodejs 14.0.0

View File

@ -1 +1 @@
node 24.0.0 node 14.0.0

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +0,0 @@
{
"volta": {
"extends": "./package-volta.json"
}
}

View File

@ -1,8 +0,0 @@
{
"engines": {
"node": "^14.0.0"
},
"volta": {
"node": "24.0.0"
}
}

View File

@ -1,5 +1,8 @@
{ {
"engines": { "engines": {
"node": "^24.0.0" "node": "^14.0.0"
},
"volta": {
"node": "16.0.0"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,111 +2,61 @@
# yarn lockfile v1 # yarn lockfile v1
accepts@^1.3.8: accepts@~1.3.7:
version "1.3.8" version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
dependencies: dependencies:
mime-types "~2.1.34" mime-types "~2.1.24"
negotiator "0.6.3" negotiator "0.6.2"
accepts@^2.0.0: array-flatten@1.1.1:
version "2.0.0" version "1.1.1"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
integrity sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng== integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
body-parser@1.19.0:
version "1.19.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
dependencies: dependencies:
mime-types "^3.0.0" bytes "3.1.0"
negotiator "^1.0.0" content-type "~1.0.4"
array-flatten@3.0.0, array-flatten@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-3.0.0.tgz#6428ca2ee52c7b823192ec600fa3ed2f157cd541"
integrity sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==
body-parser@^1.20.3:
version "1.20.3"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
dependencies:
bytes "3.1.2"
content-type "~1.0.5"
debug "2.6.9" debug "2.6.9"
depd "2.0.0" depd "~1.1.2"
destroy "1.2.0" http-errors "1.7.2"
http-errors "2.0.0"
iconv-lite "0.4.24" iconv-lite "0.4.24"
on-finished "2.4.1" on-finished "~2.3.0"
qs "6.13.0" qs "6.7.0"
raw-body "2.5.2" raw-body "2.4.0"
type-is "~1.6.18" type-is "~1.6.17"
unpipe "1.0.0"
body-parser@^2.0.1: bytes@3.1.0:
version "2.0.1" version "3.1.0"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.0.1.tgz#979de4a43468c5624403457fd6d45f797faffbaf" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-PagxbjvuPH6tv0f/kdVbFGcb79D236SLcDTs6DrQ7GizJ88S1UWP4nMXFEo/I4fdhGRGabvFfFjVGm3M7U8JwA== integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
content-disposition@0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
dependencies: dependencies:
bytes "3.1.2" safe-buffer "5.1.2"
content-type "~1.0.5"
debug "3.1.0"
destroy "1.2.0"
http-errors "2.0.0"
iconv-lite "0.5.2"
on-finished "2.4.1"
qs "6.13.0"
raw-body "^3.0.0"
type-is "~1.6.18"
unpipe "1.0.0"
bytes@3.1.2, bytes@^3.1.2: content-type@~1.0.4:
version "3.1.2" version "1.0.4"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
call-bind@^1.0.7: cookie-signature@1.0.6:
version "1.0.7" version "1.0.6"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
dependencies:
es-define-property "^1.0.0"
es-errors "^1.3.0"
function-bind "^1.1.2"
get-intrinsic "^1.2.4"
set-function-length "^1.2.1"
content-disposition@^0.5.4: cookie@0.4.0:
version "0.5.4" version "0.4.0"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
dependencies:
safe-buffer "5.2.1"
content-disposition@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.0.tgz#844426cb398f934caefcbb172200126bc7ceace2"
integrity sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==
dependencies:
safe-buffer "5.2.1"
content-type@^1.0.5, content-type@~1.0.4, content-type@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
cookie-signature@^1.0.7, cookie-signature@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.1.tgz#790dea2cce64638c7ae04d9fabed193bd7ccf3b4"
integrity sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw==
cookie@0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
cookie@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
debug@2.6.9: debug@2.6.9:
version "2.6.9" version "2.6.9"
@ -115,235 +65,116 @@ debug@2.6.9:
dependencies: dependencies:
ms "2.0.0" ms "2.0.0"
debug@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@4.3.6:
version "4.3.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b"
integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==
dependencies:
ms "2.1.2"
debug@^4.0.0, debug@^4.3.5:
version "4.3.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
dependencies:
ms "^2.1.3"
define-data-property@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
dependencies:
es-define-property "^1.0.0"
es-errors "^1.3.0"
gopd "^1.0.1"
depd@2.0.0, depd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
depd@~1.1.2: depd@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
destroy@1.2.0, destroy@^1.1.0, destroy@^1.2.0: destroy@~1.0.4:
version "1.2.0" version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
ee-first@1.1.1, ee-first@^1.1.1: ee-first@1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
encodeurl@^2.0.0, encodeurl@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
encodeurl@~1.0.2: encodeurl@~1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
es-define-property@^1.0.0: escape-html@~1.0.3:
version "1.0.0"
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
dependencies:
get-intrinsic "^1.2.4"
es-errors@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
escape-html@^1.0.3, escape-html@~1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
etag@^1.8.1, etag@~1.8.1: etag@~1.8.1:
version "1.8.1" version "1.8.1"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
express@^5.0.0: express@^4.17.1:
version "5.0.0" version "4.17.1"
resolved "https://registry.yarnpkg.com/express/-/express-5.0.0.tgz#744f9ec86025a01aeca99e4300aa4fc050d493c7" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
integrity sha512-V4UkHQc+B7ldh1YC84HCXHwf60M4BOMvp9rkvTUWCK5apqDC1Esnbid4wm6nFyVuDy8XMfETsJw5lsIGBWyo0A== integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
dependencies: dependencies:
accepts "^2.0.0" accepts "~1.3.7"
body-parser "^2.0.1" array-flatten "1.1.1"
content-disposition "^1.0.0" body-parser "1.19.0"
content-disposition "0.5.3"
content-type "~1.0.4" content-type "~1.0.4"
cookie "0.6.0" cookie "0.4.0"
cookie-signature "^1.2.1" cookie-signature "1.0.6"
debug "4.3.6" debug "2.6.9"
depd "2.0.0" depd "~1.1.2"
encodeurl "~2.0.0" encodeurl "~1.0.2"
escape-html "~1.0.3" escape-html "~1.0.3"
etag "~1.8.1" etag "~1.8.1"
finalhandler "^2.0.0" finalhandler "~1.1.2"
fresh "2.0.0" fresh "0.5.2"
http-errors "2.0.0" merge-descriptors "1.0.1"
merge-descriptors "^2.0.0"
methods "~1.1.2" methods "~1.1.2"
mime-types "^3.0.0" on-finished "~2.3.0"
on-finished "2.4.1"
once "1.4.0"
parseurl "~1.3.3" parseurl "~1.3.3"
proxy-addr "~2.0.7" path-to-regexp "0.1.7"
qs "6.13.0" proxy-addr "~2.0.5"
qs "6.7.0"
range-parser "~1.2.1" range-parser "~1.2.1"
router "^2.0.0" safe-buffer "5.1.2"
safe-buffer "5.2.1" send "0.17.1"
send "^1.1.0" serve-static "1.14.1"
serve-static "^2.1.0" setprototypeof "1.1.1"
setprototypeof "1.2.0" statuses "~1.5.0"
statuses "2.0.1" type-is "~1.6.18"
type-is "^2.0.0"
utils-merge "1.0.1" utils-merge "1.0.1"
vary "~1.1.2" vary "~1.1.2"
finalhandler@^1.2.0: finalhandler@~1.1.2:
version "1.3.1" version "1.1.2"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
dependencies:
debug "2.6.9"
encodeurl "~2.0.0"
escape-html "~1.0.3"
on-finished "2.4.1"
parseurl "~1.3.3"
statuses "2.0.1"
unpipe "~1.0.0"
finalhandler@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.0.0.tgz#9d3c79156dfa798069db7de7dd53bc37546f564b"
integrity sha512-MX6Zo2adDViYh+GcxxB1dpO43eypOGUOL12rLCOTMQv/DfIbpSJUy4oQIIZhVZkH9e+bZWKMon0XHFEju16tkQ==
dependencies: dependencies:
debug "2.6.9" debug "2.6.9"
encodeurl "~1.0.2" encodeurl "~1.0.2"
escape-html "~1.0.3" escape-html "~1.0.3"
on-finished "2.4.1" on-finished "~2.3.0"
parseurl "~1.3.3" parseurl "~1.3.3"
statuses "2.0.1" statuses "~1.5.0"
unpipe "~1.0.0" unpipe "~1.0.0"
forwarded@0.2.0, forwarded@^0.2.0: forwarded@~0.1.2:
version "0.2.0" version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
fresh@0.5.2, fresh@^0.5.2: fresh@0.5.2:
version "0.5.2" version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
fresh@2.0.0: http-errors@1.7.2:
version "2.0.0" version "1.7.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
dependencies: dependencies:
es-errors "^1.3.0" depd "~1.1.2"
function-bind "^1.1.2" inherits "2.0.3"
has-proto "^1.0.1" setprototypeof "1.1.1"
has-symbols "^1.0.3" statuses ">= 1.5.0 < 2"
hasown "^2.0.0" toidentifier "1.0.0"
gopd@^1.0.1: http-errors@~1.7.2:
version "1.0.1" version "1.7.3"
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
dependencies:
get-intrinsic "^1.1.3"
has-property-descriptors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
dependencies:
es-define-property "^1.0.0"
has-proto@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
has-symbols@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
hasown@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
dependencies:
function-bind "^1.1.2"
http-errors@2.0.0, http-errors@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
dependencies:
depd "2.0.0"
inherits "2.0.4"
setprototypeof "1.2.0"
statuses "2.0.1"
toidentifier "1.0.1"
http-errors@^1.8.0:
version "1.8.1"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==
dependencies: dependencies:
depd "~1.1.2" depd "~1.1.2"
inherits "2.0.4" inherits "2.0.4"
setprototypeof "1.2.0" setprototypeof "1.1.1"
statuses ">= 1.5.0 < 2" statuses ">= 1.5.0 < 2"
toidentifier "1.0.1" toidentifier "1.0.0"
iconv-lite@0.4.24: iconv-lite@0.4.24:
version "0.4.24" version "0.4.24"
@ -352,21 +183,12 @@ iconv-lite@0.4.24:
dependencies: dependencies:
safer-buffer ">= 2.1.2 < 3" safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.5.2: inherits@2.0.3:
version "0.5.2" version "2.0.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.2.tgz#af6d628dccfb463b7364d97f715e4b74b8c8c2b8" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag== integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.6.3, iconv-lite@^0.6.0: inherits@2.0.4:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
dependencies:
safer-buffer ">= 2.1.2 < 3.0.0"
inherits@2.0.4, inherits@^2.0.4:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@ -376,61 +198,34 @@ ipaddr.js@1.9.1:
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
ipaddr.js@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8"
integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==
is-promise@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3"
integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==
media-typer@0.3.0: media-typer@0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
media-typer@^1.1.0: merge-descriptors@1.0.1:
version "1.1.0" version "1.0.1"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
merge-descriptors@^2.0.0: methods@~1.1.2:
version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808"
integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==
methods@^1.1.2, methods@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
mime-db@1.52.0: mime-db@1.47.0:
version "1.52.0" version "1.47.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==
mime-db@^1.51.0, mime-db@^1.53.0: mime-types@~2.1.24:
version "1.53.0" version "2.1.30"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d"
integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==
mime-types@^2.1.35, mime-types@~2.1.24, mime-types@~2.1.34:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies: dependencies:
mime-db "1.52.0" mime-db "1.47.0"
mime-types@^3.0.0: mime@1.6.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.0.tgz#148453a900475522d095a445355c074cca4f5217"
integrity sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==
dependencies:
mime-db "^1.53.0"
mime@1.6.0, mime@^1.6.0:
version "1.6.0" version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
@ -438,220 +233,118 @@ mime@1.6.0, mime@^1.6.0:
ms@2.0.0: ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
ms@2.1.2: ms@2.1.1:
version "2.1.2" version "2.1.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
ms@2.1.3, ms@^2.1.2, ms@^2.1.3: negotiator@0.6.2:
version "2.1.3" version "0.6.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
negotiator@0.6.3, negotiator@^0.6.3: on-finished@~2.3.0:
version "0.6.3" version "2.3.0"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
negotiator@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a"
integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==
object-inspect@^1.13.1:
version "1.13.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff"
integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==
on-finished@2.4.1, on-finished@^2.4.0, on-finished@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
dependencies: dependencies:
ee-first "1.1.1" ee-first "1.1.1"
once@1.4.0: parseurl@~1.3.3:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
dependencies:
wrappy "1"
parseurl@^1.3.3, parseurl@~1.3.3:
version "1.3.3" version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
path-to-regexp@^8.0.0: path-to-regexp@0.1.7:
version "8.1.0" version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.1.0.tgz#4d687606ed0be8ed512ba802eb94d620cb1a86f0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha512-Bqn3vc8CMHty6zuD+tG23s6v2kwxslHEhTj4eYaVKGIEB+YX/2wd0/rgXLFD9G9id9KCtbVy/3ZgmvZjpa0UdQ== integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
proxy-addr@^2.0.7, proxy-addr@~2.0.7: proxy-addr@~2.0.5:
version "2.0.7" version "2.0.6"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==
dependencies: dependencies:
forwarded "0.2.0" forwarded "~0.1.2"
ipaddr.js "1.9.1" ipaddr.js "1.9.1"
qs@6.13.0, qs@^6.8.0: qs@6.7.0:
version "6.13.0" version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
dependencies:
side-channel "^1.0.6"
range-parser@^1.2.1, range-parser@~1.2.1: range-parser@~1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
raw-body@2.5.2, raw-body@^2.4.1: raw-body@2.4.0:
version "2.5.2" version "2.4.0"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
dependencies: dependencies:
bytes "3.1.2" bytes "3.1.0"
http-errors "2.0.0" http-errors "1.7.2"
iconv-lite "0.4.24" iconv-lite "0.4.24"
unpipe "1.0.0" unpipe "1.0.0"
raw-body@^3.0.0: safe-buffer@5.1.2:
version "3.0.0" version "5.1.2"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.0.tgz#25b3476f07a51600619dae3fe82ddc28a36e5e0f" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g== integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
dependencies:
bytes "3.1.2"
http-errors "2.0.0"
iconv-lite "0.6.3"
unpipe "1.0.0"
router@^2.0.0: "safer-buffer@>= 2.1.2 < 3":
version "2.0.0"
resolved "https://registry.yarnpkg.com/router/-/router-2.0.0.tgz#8692720b95de83876870d7bc638dd3c7e1ae8a27"
integrity sha512-dIM5zVoG8xhC6rnSN8uoAgFARwTE7BQs8YwHEvK0VCmfxQXMaOuA1uiR1IPwsW7JyK5iTt7Od/TC9StasS2NPQ==
dependencies:
array-flatten "3.0.0"
is-promise "4.0.0"
methods "~1.1.2"
parseurl "~1.3.3"
path-to-regexp "^8.0.0"
setprototypeof "1.2.0"
utils-merge "1.0.1"
safe-buffer@5.2.1, safe-buffer@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
send@0.19.0, send@^0.19.0: send@0.17.1:
version "0.19.0" version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
dependencies: dependencies:
debug "2.6.9" debug "2.6.9"
depd "2.0.0" depd "~1.1.2"
destroy "1.2.0" destroy "~1.0.4"
encodeurl "~1.0.2" encodeurl "~1.0.2"
escape-html "~1.0.3" escape-html "~1.0.3"
etag "~1.8.1" etag "~1.8.1"
fresh "0.5.2" fresh "0.5.2"
http-errors "2.0.0" http-errors "~1.7.2"
mime "1.6.0" mime "1.6.0"
ms "2.1.3" ms "2.1.1"
on-finished "2.4.1" on-finished "~2.3.0"
range-parser "~1.2.1" range-parser "~1.2.1"
statuses "2.0.1" statuses "~1.5.0"
send@^1.0.0, send@^1.1.0: serve-static@1.14.1:
version "1.1.0" version "1.14.1"
resolved "https://registry.yarnpkg.com/send/-/send-1.1.0.tgz#4efe6ff3bb2139b0e5b2648d8b18d4dec48fc9c5" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
integrity sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA== integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
dependencies: dependencies:
debug "^4.3.5" encodeurl "~1.0.2"
destroy "^1.2.0"
encodeurl "^2.0.0"
escape-html "^1.0.3"
etag "^1.8.1"
fresh "^0.5.2"
http-errors "^2.0.0"
mime-types "^2.1.35"
ms "^2.1.3"
on-finished "^2.4.1"
range-parser "^1.2.1"
statuses "^2.0.1"
serve-static@^1.15.0:
version "1.16.2"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296"
integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==
dependencies:
encodeurl "~2.0.0"
escape-html "~1.0.3" escape-html "~1.0.3"
parseurl "~1.3.3" parseurl "~1.3.3"
send "0.19.0" send "0.17.1"
serve-static@^2.1.0: setprototypeof@1.1.1:
version "2.1.0" version "1.1.1"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.1.0.tgz#1b4eacbe93006b79054faa4d6d0a501d7f0e84e2" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
integrity sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA== integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
dependencies:
encodeurl "^2.0.0"
escape-html "^1.0.3"
parseurl "^1.3.3"
send "^1.0.0"
set-function-length@^1.2.1: "statuses@>= 1.5.0 < 2", statuses@~1.5.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
dependencies:
define-data-property "^1.1.4"
es-errors "^1.3.0"
function-bind "^1.1.2"
get-intrinsic "^1.2.4"
gopd "^1.0.1"
has-property-descriptors "^1.0.2"
setprototypeof@1.2.0, setprototypeof@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
side-channel@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
dependencies:
call-bind "^1.0.7"
es-errors "^1.3.0"
get-intrinsic "^1.2.4"
object-inspect "^1.13.1"
statuses@2.0.1, statuses@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
"statuses@>= 1.5.0 < 2":
version "1.5.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
toidentifier@1.0.1: toidentifier@1.0.0:
version "1.0.1" version "1.0.0"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
type-is@^1.6.18, type-is@~1.6.18: type-is@~1.6.17, type-is@~1.6.18:
version "1.6.18" version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
@ -659,31 +352,17 @@ type-is@^1.6.18, type-is@~1.6.18:
media-typer "0.3.0" media-typer "0.3.0"
mime-types "~2.1.24" mime-types "~2.1.24"
type-is@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.0.tgz#7d249c2e2af716665cc149575dadb8b3858653af"
integrity sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==
dependencies:
content-type "^1.0.5"
media-typer "^1.1.0"
mime-types "^3.0.0"
unpipe@1.0.0, unpipe@~1.0.0: unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
utils-merge@1.0.1, utils-merge@^1.0.1: utils-merge@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
vary@^1.1.2, vary@~1.1.2: vary@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==

View File

@ -2,7 +2,6 @@ import * as core from '@actions/core';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
import * as cache from '@actions/cache'; import * as cache from '@actions/cache';
import * as io from '@actions/io';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
@ -20,19 +19,16 @@ describe('main tests', () => {
let infoSpy: jest.SpyInstance; let infoSpy: jest.SpyInstance;
let warningSpy: jest.SpyInstance; let warningSpy: jest.SpyInstance;
let saveStateSpy: jest.SpyInstance;
let inSpy: jest.SpyInstance; let inSpy: jest.SpyInstance;
let setOutputSpy: jest.SpyInstance; let setOutputSpy: jest.SpyInstance;
let startGroupSpy: jest.SpyInstance; let startGroupSpy: jest.SpyInstance;
let endGroupSpy: jest.SpyInstance; let endGroupSpy: jest.SpyInstance;
let whichSpy: jest.SpyInstance;
let existsSpy: jest.SpyInstance; let existsSpy: jest.SpyInstance;
let getExecOutputSpy: jest.SpyInstance; let getExecOutputSpy: jest.SpyInstance;
let getNodeVersionFromFileSpy: jest.SpyInstance; let parseNodeVersionSpy: jest.SpyInstance;
let cnSpy: jest.SpyInstance; let cnSpy: jest.SpyInstance;
let findSpy: jest.SpyInstance; let findSpy: jest.SpyInstance;
let isCacheActionAvailable: jest.SpyInstance; let isCacheActionAvailable: jest.SpyInstance;
@ -45,7 +41,6 @@ describe('main tests', () => {
// node // node
os = {}; os = {};
console.log('::stop-commands::stoptoken'); 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_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 process.env['GITHUB_OUTPUT'] = ''; // Stub out ENV file functionality so we can verify it writes to standard out
infoSpy = jest.spyOn(core, 'info'); infoSpy = jest.spyOn(core, 'info');
@ -54,8 +49,6 @@ describe('main tests', () => {
setOutputSpy.mockImplementation(() => {}); setOutputSpy.mockImplementation(() => {});
warningSpy = jest.spyOn(core, 'warning'); warningSpy = jest.spyOn(core, 'warning');
warningSpy.mockImplementation(() => {}); warningSpy.mockImplementation(() => {});
saveStateSpy = jest.spyOn(core, 'saveState');
saveStateSpy.mockImplementation(() => {});
startGroupSpy = jest.spyOn(core, 'startGroup'); startGroupSpy = jest.spyOn(core, 'startGroup');
startGroupSpy.mockImplementation(() => {}); startGroupSpy.mockImplementation(() => {});
endGroupSpy = jest.spyOn(core, 'endGroup'); endGroupSpy = jest.spyOn(core, 'endGroup');
@ -63,18 +56,18 @@ describe('main tests', () => {
inSpy = jest.spyOn(core, 'getInput'); inSpy = jest.spyOn(core, 'getInput');
inSpy.mockImplementation(name => inputs[name]); inSpy.mockImplementation(name => inputs[name]);
whichSpy = jest.spyOn(io, 'which');
getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
findSpy = jest.spyOn(tc, 'find'); findSpy = jest.spyOn(tc, 'find');
isCacheActionAvailable = jest.spyOn(cache, 'isFeatureAvailable'); isCacheActionAvailable = jest.spyOn(cache, 'isFeatureAvailable');
existsSpy = jest.spyOn(fs, 'existsSync');
cnSpy = jest.spyOn(process.stdout, 'write'); cnSpy = jest.spyOn(process.stdout, 'write');
cnSpy.mockImplementation(line => { cnSpy.mockImplementation(line => {
// uncomment to debug // uncomment to debug
process.stderr.write('write:' + line + '\n'); // process.stderr.write('write:' + line + '\n');
}); });
setupNodeJsSpy = jest.spyOn(OfficialBuilds.prototype, 'setupNodeJs'); setupNodeJsSpy = jest.spyOn(OfficialBuilds.prototype, 'setupNodeJs');
@ -92,7 +85,7 @@ describe('main tests', () => {
jest.restoreAllMocks(); jest.restoreAllMocks();
}, 100000); }, 100000);
describe('getNodeVersionFromFile', () => { describe('parseNodeVersionFile', () => {
each` each`
contents | expected contents | expected
${'12'} | ${'12'} ${'12'} | ${'12'}
@ -107,27 +100,10 @@ describe('main tests', () => {
${'unknown format'} | ${'unknown format'} ${'unknown format'} | ${'unknown format'}
${' 14.1.0 '} | ${'14.1.0'} ${' 14.1.0 '} | ${'14.1.0'}
${'{"volta": {"node": ">=14.0.0 <=17.0.0"}}'}| ${'>=14.0.0 <=17.0.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'} ${'{"engines": {"node": "17.0.0"}}'} | ${'17.0.0'}
${'{}'} | ${null} ${'{}'} | ${null}
`.it('parses "$contents"', ({contents, expected}) => { `.it('parses "$contents"', ({contents, expected}) => {
const existsSpy = jest.spyOn(fs, 'existsSync'); expect(util.parseNodeVersionFile(contents)).toBe(expected);
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);
}); });
}); });
@ -150,10 +126,6 @@ describe('main tests', () => {
return {stdout: obj[command], stderr: '', exitCode: 0}; return {stdout: obj[command], stderr: '', exitCode: 0};
}); });
whichSpy.mockImplementation(cmd => {
return `some/${cmd}/path`;
});
await util.printEnvDetailsAndSetOutput(); await util.printEnvDetailsAndSetOutput();
expect(setOutputSpy).toHaveBeenCalledWith('node-version', obj['node']); expect(setOutputSpy).toHaveBeenCalledWith('node-version', obj['node']);
@ -170,17 +142,10 @@ describe('main tests', () => {
describe('node-version-file flag', () => { describe('node-version-file flag', () => {
beforeEach(() => { beforeEach(() => {
delete inputs['node-version']; parseNodeVersionSpy = jest.spyOn(util, 'parseNodeVersionFile');
inputs['node-version-file'] = '.nvmrc';
getNodeVersionFromFileSpy = jest.spyOn(util, 'getNodeVersionFromFile');
}); });
afterEach(() => { it('not used if node-version is provided', async () => {
getNodeVersionFromFileSpy.mockRestore();
});
it('does not read node-version-file if node-version is provided', async () => {
// Arrange // Arrange
inputs['node-version'] = '12'; inputs['node-version'] = '12';
@ -188,54 +153,107 @@ describe('main tests', () => {
await main.run(); await main.run();
// Assert // Assert
expect(inputs['node-version']).toBeDefined(); expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0);
expect(inputs['node-version-file']).toBeDefined(); }, 10000);
expect(getNodeVersionFromFileSpy).not.toHaveBeenCalled();
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(warningSpy).toHaveBeenCalledWith( expect(warningSpy).toHaveBeenCalledWith(
'Both node-version and node-version-file inputs are specified, only node-version will be used' 'Both node-version and node-version-file inputs are specified, only node-version will be used'
); );
}); });
it('does not read node-version-file if node-version-file is not provided', async () => { it('should throw an error if node-version-file is not found', async () => {
// Arrange const versionFile = '.nvmrc';
delete inputs['node-version-file']; const versionFilePath = path.join(__dirname, '..', versionFile);
inputs['node-version-file'] = versionFile;
// Act inSpy.mockImplementation(name => inputs[name]);
await main.run(); existsSpy.mockImplementationOnce(
input => input === path.join(__dirname, 'data', versionFile)
// 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 // Act
await main.run(); await main.run();
// Assert // Assert
expect(getNodeVersionFromFileSpy).toHaveBeenCalled(); expect(existsSpy).toHaveBeenCalled();
expect(existsSpy).toHaveReturnedWith(false);
expect(parseNodeVersionSpy).not.toHaveBeenCalled();
expect(cnSpy).toHaveBeenCalledWith( expect(cnSpy).toHaveBeenCalledWith(
`::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}` `::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}`
); );
@ -283,149 +301,4 @@ describe('main tests', () => {
); );
}); });
}); });
describe('cache feature tests', () => {
it('Should enable caching when packageManager is npm and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
packageManager: 'npm@10.8.2'
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should enable caching when devEngines.packageManager.name is "npm" and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: {name: 'npm'}
}
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should enable caching when devEngines.packageManager is array and one entry has name "npm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: [{name: 'pnpm'}, {name: 'npm'}]
}
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should not enable caching if packageManager is "pnpm@8.0.0" and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
packageManager: 'pnpm@8.0.0'
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if devEngines.packageManager.name is "pnpm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: {name: 'pnpm'}
}
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if devEngines.packageManager is array without "npm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: [{name: 'pnpm'}, {name: 'yarn'}]
}
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if packageManager field is missing in package.json and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
// packageManager field is not present
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should skip caching when package-manager-cache is false', async () => {
inputs['package-manager-cache'] = 'false';
inputs['cache'] = '';
inSpy.mockImplementation(name => inputs[name]);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should enable caching with cache input explicitly provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = 'npm';
inSpy.mockImplementation(name => inputs[name]);
isCacheActionAvailable.mockImplementation(() => true);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
});
}); });

View File

@ -255,6 +255,7 @@ describe('setup-node', () => {
const versionSpec = '13.13.1-nightly20200415947ddec091'; const versionSpec = '13.13.1-nightly20200415947ddec091';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -290,6 +291,7 @@ describe('setup-node', () => {
]; ];
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -313,7 +315,7 @@ describe('setup-node', () => {
await main.run(); await main.run();
workingUrls.forEach(url => { workingUrls.forEach(url => {
expect(dlSpy).toHaveBeenCalledWith(url, undefined, undefined); expect(dlSpy).toHaveBeenCalledWith(url);
}); });
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}${osm.EOL}`); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}${osm.EOL}`);
}); });
@ -331,6 +333,7 @@ describe('setup-node', () => {
]; ];
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -386,6 +389,7 @@ describe('setup-node', () => {
const versionSpec = '18.0.0-nightly202204180699150267'; const versionSpec = '18.0.0-nightly202204180699150267';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
findSpy.mockImplementation(() => ''); findSpy.mockImplementation(() => '');
@ -423,6 +427,7 @@ describe('setup-node', () => {
inputs['node-version'] = version; inputs['node-version'] = version;
inputs['architecture'] = arch; inputs['architecture'] = arch;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
const expectedUrl = `https://nodejs.org/download/nightly/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`; const expectedUrl = `https://nodejs.org/download/nightly/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;
@ -444,53 +449,6 @@ describe('setup-node', () => {
} }
}, 100000); }, 100000);
it('acquires specified architecture of node from mirror', async () => {
for (const {arch, version, osSpec} of [
{
arch: 'x86',
version: '18.0.0-nightly202110204cb3e06ed8',
osSpec: 'win32'
},
{
arch: 'x86',
version: '20.0.0-nightly2022101987cdf7d412',
osSpec: 'win32'
}
]) {
os.platform = osSpec;
os.arch = arch;
const fileExtension = os.platform === 'win32' ? '7z' : 'tar.gz';
const platform = {
linux: 'linux',
darwin: 'darwin',
win32: 'win'
}[os.platform];
inputs['node-version'] = version;
inputs['architecture'] = arch;
inputs['token'] = 'faketoken';
inputs['mirror'] = 'https://my-mirror.org';
inputs['mirror-token'] = 'my-mirror-token';
const expectedUrl = `https://my-mirror.org/download/nightly/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;
// ... but not in the local cache
findSpy.mockImplementation(() => '');
findAllVersionsSpy.mockImplementation(() => []);
dlSpy.mockImplementation(async () => '/some/temp/path');
const toolPath = path.normalize(`/cache/node/${version}/${arch}`);
exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath);
await main.run();
expect(dlSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
`Acquiring ${version} - ${arch} from ${expectedUrl}`
);
}
}, 100000);
describe('nightly versions', () => { describe('nightly versions', () => {
it.each([ it.each([
[ [

View File

@ -235,6 +235,7 @@ describe('setup-node', () => {
const resolvedVersion = versionSpec; const resolvedVersion = versionSpec;
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
const expectedUrl = const expectedUrl =
@ -247,9 +248,6 @@ describe('setup-node', () => {
const toolPath = path.normalize('/cache/node/12.16.2/x64'); const toolPath = path.normalize('/cache/node/12.16.2/x64');
exSpy.mockImplementation(async () => '/some/other/temp/path'); exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath); cacheSpy.mockImplementation(async () => toolPath);
whichSpy.mockImplementation(cmd => {
return `some/${cmd}/path`;
});
await main.run(); await main.run();
@ -281,42 +279,6 @@ describe('setup-node', () => {
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
}); });
it('falls back to a version from node dist from mirror', 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';
const mirror = 'https://my_mirror_url';
inputs['node-version'] = versionSpec;
inputs['token'] = 'faketoken';
inputs['mirror'] = mirror;
inputs['mirror-token'] = 'faketoken';
// ... but not in the local cache
findSpy.mockImplementation(() => '');
dlSpy.mockImplementation(async () => '/some/temp/path');
const toolPath = path.normalize('/cache/node/11.15.0/x64');
exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath);
await main.run();
const expPath = path.join(toolPath, 'bin');
expect(getManifestSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
`Attempting to download ${versionSpec}...`
);
expect(logSpy).toHaveBeenCalledWith(
`Not found in manifest. Falling back to download directly from ${mirror}`
);
expect(dlSpy).toHaveBeenCalled();
expect(exSpy).toHaveBeenCalled();
expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`);
});
it('falls back to a version from node dist', async () => { it('falls back to a version from node dist', async () => {
os.platform = 'linux'; os.platform = 'linux';
os.arch = 'x64'; os.arch = 'x64';
@ -325,6 +287,7 @@ describe('setup-node', () => {
const versionSpec = '11.15.0'; const versionSpec = '11.15.0';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -382,6 +345,7 @@ describe('setup-node', () => {
const resolvedVersion = versionSpec; const resolvedVersion = versionSpec;
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
findSpy.mockImplementation(() => ''); findSpy.mockImplementation(() => '');
@ -401,6 +365,7 @@ describe('setup-node', () => {
const versionSpec = '11.15.0'; const versionSpec = '11.15.0';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -443,6 +408,7 @@ describe('setup-node', () => {
inputs['node-version'] = version; inputs['node-version'] = version;
inputs['architecture'] = arch; inputs['architecture'] = arch;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
const expectedUrl = const expectedUrl =
@ -554,6 +520,7 @@ describe('setup-node', () => {
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['check-latest'] = 'true'; inputs['check-latest'] = 'true';
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -595,6 +562,7 @@ describe('setup-node', () => {
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['check-latest'] = 'true'; inputs['check-latest'] = 'true';
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -857,45 +825,4 @@ describe('setup-node', () => {
} }
); );
}); });
it('acquires specified architecture of node from mirror', async () => {
for (const {arch, version, osSpec} of [
{arch: 'x86', version: '12.16.2', osSpec: 'win32'},
{arch: 'x86', version: '14.0.0', osSpec: 'win32'}
]) {
os.platform = osSpec;
os.arch = arch;
const fileExtension = os.platform === 'win32' ? '7z' : 'tar.gz';
const platform = {
linux: 'linux',
darwin: 'darwin',
win32: 'win'
}[os.platform];
inputs['node-version'] = version;
inputs['architecture'] = arch;
inputs['token'] = 'faketoken';
inputs['mirror'] = 'https://my_mirror_url';
inputs['mirror-token'] = 'faketoken';
const expectedUrl =
arch === 'x64'
? `https://github.com/actions/node-versions/releases/download/${version}/node-${version}-${platform}-${arch}.zip`
: `https://my_mirror_url/dist/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;
// ... but not in the local cache
findSpy.mockImplementation(() => '');
dlSpy.mockImplementation(async () => '/some/temp/path');
const toolPath = path.normalize(`/cache/node/${version}/${arch}`);
exSpy.mockImplementation(async () => '/some/other/temp/path');
cacheSpy.mockImplementation(async () => toolPath);
await main.run();
expect(dlSpy).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
`Acquiring ${version} - ${arch} from ${expectedUrl}`
);
}
}, 100000);
}); });

View File

@ -194,6 +194,7 @@ describe('setup-node', () => {
const versionSpec = '13.0.0-rc.0'; const versionSpec = '13.0.0-rc.0';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
// ... but not in the local cache // ... but not in the local cache
@ -238,6 +239,7 @@ describe('setup-node', () => {
const versionSpec = '14.7.0-rc.1'; const versionSpec = '14.7.0-rc.1';
inputs['node-version'] = versionSpec; inputs['node-version'] = versionSpec;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
findSpy.mockImplementation(() => ''); findSpy.mockImplementation(() => '');
@ -266,6 +268,7 @@ describe('setup-node', () => {
inputs['node-version'] = version; inputs['node-version'] = version;
inputs['architecture'] = arch; inputs['architecture'] = arch;
inputs['always-auth'] = false;
inputs['token'] = 'faketoken'; inputs['token'] = 'faketoken';
const expectedUrl = `https://nodejs.org/download/rc/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`; const expectedUrl = `https://nodejs.org/download/rc/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`;

View File

@ -7,13 +7,8 @@ fi
node_version="$(node --version)" node_version="$(node --version)"
echo "Found node version '$node_version'" echo "Found node version '$node_version'"
if [ -z "$(echo $node_version | grep --fixed-strings v$1)" ]; then
# Extract the major version from the node version (remove the 'v' prefix) echo "Unexpected version"
actual_major_version=$(echo $node_version | sed -E 's/^v([0-9]+)\..*/\1/')
expected_major_version=$(echo $1 | sed -E 's/^([0-9]+)\..*/\1/') # Extract major version from argument
if [ "$actual_major_version" != "$expected_major_version" ]; then
echo "Expected Node.js $expected_major_version.x.x but found $node_version"
exit 1 exit 1
fi fi

View File

@ -2,6 +2,9 @@ name: 'Setup Node.js environment'
description: 'Setup a Node.js environment by adding problem matchers and optionally downloading and adding it to the PATH.' description: 'Setup a Node.js environment by adding problem matchers and optionally downloading and adding it to the PATH.'
author: 'GitHub' author: 'GitHub'
inputs: inputs:
always-auth:
description: 'Set always-auth in npmrc.'
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.'
node-version-file: node-version-file:
@ -20,15 +23,8 @@ inputs:
default: ${{ github.server_url == 'https://github.com' && github.token || '' }} default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
cache: cache:
description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.' description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.'
package-manager-cache:
description: 'Set to false to disable automatic caching. By default, caching is enabled when either devEngines.packageManager or the top-level packageManager field in package.json specifies npm as the package manager.'
default: true
cache-dependency-path: cache-dependency-path:
description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.' description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.'
mirror:
description: 'Used to specify an alternative mirror to downlooad Node.js binaries from'
mirror-token:
description: 'The token used as Authorization header when fetching from the mirror'
# TODO: add input to control forcing to pull from cloud or dist. # TODO: add input to control forcing to pull from cloud or dist.
# escape valve for someone having issues or needing the absolute latest which isn't cached yet # escape valve for someone having issues or needing the absolute latest which isn't cached yet
outputs: outputs:
@ -37,7 +33,7 @@ outputs:
node-version: node-version:
description: 'The installed node version.' description: 'The installed node version.'
runs: runs:
using: 'node24' using: 'node20'
main: 'dist/setup/index.js' main: 'dist/setup/index.js'
post: 'dist/cache-save/index.js' post: 'dist/cache-save/index.js'
post-if: success() post-if: success()

15934
dist/cache-save/index.js vendored

File diff suppressed because one or more lines are too long

22963
dist/setup/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -45,10 +45,10 @@ If `check-latest` is set to `true`, the action first checks if the cached versio
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24' node-version: '16'
check-latest: true check-latest: true
- run: npm ci - run: npm ci
- run: npm test - run: npm test
@ -63,8 +63,8 @@ See [supported version syntax](https://github.com/actions/setup-node#supported-v
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
- run: npm ci - run: npm ci
@ -84,8 +84,6 @@ 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 ## 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). 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).
@ -97,10 +95,10 @@ jobs:
runs-on: windows-latest runs-on: windows-latest
name: Node sample name: Node sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24' node-version: '14'
architecture: 'x64' # optional, x64 or x86. If not specified, x64 will be used by default architecture: 'x64' # optional, x64 or x86. If not specified, x64 will be used by default
- run: npm ci - run: npm ci
- run: npm test - run: npm test
@ -118,10 +116,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Node sample name: Node sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24.0.0-v8-canary' # it will install the latest v8 canary release for node 24.0.0 node-version: '20.0.0-v8-canary' # it will install the latest v8 canary release for node 20.0.0
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
@ -133,10 +131,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Node sample name: Node sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24-v8-canary' # it will install the latest v8 canary release for node 24 node-version: '20-v8-canary' # it will install the latest v8 canary release for node 20
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
@ -149,10 +147,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Node sample name: Node sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: 'v24.0.0-v8-canary2025030537242e55ac' node-version: 'v20.1.1-v8-canary20221103f7e2421e91'
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
@ -169,10 +167,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Node sample name: Node sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24-nightly' # it will install the latest nightly release for node 24 node-version: '16-nightly' # it will install the latest nightly release for node 16
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
@ -185,10 +183,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Node sample name: Node sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24.0.0-nightly' # it will install the latest nightly release for node 24.0.0 node-version: '16.0.0-nightly' # it will install the latest nightly release for node 16.0.0
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
@ -201,10 +199,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Node sample name: Node sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24.0.0-nightly202505066102159fa1' node-version: '16.0.0-nightly20210420a0261d231c'
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
@ -219,28 +217,27 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Node sample name: Node sample
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24.0.0-rc.4' node-version: '16.0.0-rc.1'
- run: npm ci - run: npm ci
- run: npm test - run: npm test
``` ```
**Note:** Unlike nightly versions, which support version range specifiers, you must specify the exact version for a release candidate: `24.0.0-rc.4`. **Note:** Unlike nightly versions, which support version range specifiers, you must specify the exact version for a release candidate: `16.0.0-rc.1`.
## Caching packages data ## Caching packages data
The action follows [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) guidelines, and caches global cache on the machine instead of `node_modules`, so cache can be reused between different Node.js versions. The action follows [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) guidelines, and caches global cache on the machine instead of `node_modules`, so cache can be reused between different Node.js versions.
**Caching yarn dependencies:** **Caching yarn dependencies:**
Yarn caching handles both Yarn Classic (v1) and Yarn Berry (v2, v3, v4+). Yarn caching handles both yarn versions: 1 or 2.
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24' node-version: '14'
cache: 'yarn' cache: 'yarn'
- run: yarn install --frozen-lockfile # optional, --immutable - run: yarn install --frozen-lockfile # optional, --immutable
- run: yarn test - run: yarn test
@ -256,13 +253,13 @@ steps:
# NOTE: pnpm caching support requires pnpm version >= 6.10.0 # NOTE: pnpm caching support requires pnpm version >= 6.10.0
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v4 - uses: pnpm/action-setup@v2
with: with:
version: 10 version: 6.32.9
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24' node-version: '14'
cache: 'pnpm' cache: 'pnpm'
- run: pnpm install - run: pnpm install
- run: pnpm test - run: pnpm test
@ -275,10 +272,10 @@ steps:
**Using wildcard patterns to cache dependencies** **Using wildcard patterns to cache dependencies**
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24' node-version: '14'
cache: 'npm' cache: 'npm'
cache-dependency-path: '**/package-lock.json' cache-dependency-path: '**/package-lock.json'
- run: npm ci - run: npm ci
@ -288,10 +285,10 @@ steps:
**Using a list of file paths to cache dependencies** **Using a list of file paths to cache dependencies**
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24' node-version: '14'
cache: 'npm' cache: 'npm'
cache-dependency-path: | cache-dependency-path: |
server/app/package-lock.json server/app/package-lock.json
@ -300,35 +297,6 @@ steps:
- run: npm test - run: npm test
``` ```
**Restore-Only Cache**
```yaml
## In some workflows, you may want to restore a cache without saving it. This can help reduce cache writes and storage usage in workflows that only need to read from cache
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
# Restore Node.js modules cache (restore-only)
- name: Restore Node modules cache
uses: actions/cache@v4
id: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
# Setup Node.js
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: '24'
# Install dependencies
- run: npm install
```
> For more details related to cache scenarios, please refer [Node npm](https://github.com/actions/cache/blob/main/examples.md#node---npm).
## Multiple Operating Systems and Architectures ## Multiple Operating Systems and Architectures
```yaml ```yaml
@ -342,21 +310,21 @@ jobs:
- macos-latest - macos-latest
- windows-latest - windows-latest
node_version: node_version:
- 20 - 12
- 22 - 14
- 24 - 16
architecture: architecture:
- x64 - x64
# an extra windows-x86 run: # an extra windows-x86 run:
include: include:
- os: windows-latest - os: windows-2016
node_version: 24 node_version: 12
architecture: x86 architecture: x86
name: Node ${{ matrix.node_version }} - ${{ matrix.architecture }} on ${{ matrix.os }} name: Node ${{ matrix.node_version }} - ${{ matrix.architecture }} on ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- name: Setup node - name: Setup node
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: ${{ matrix.node_version }} node-version: ${{ matrix.node_version }}
architecture: ${{ matrix.architecture }} architecture: ${{ matrix.architecture }}
@ -367,16 +335,16 @@ jobs:
## Publish to npmjs and GPR with npm ## Publish to npmjs and GPR with npm
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24.x' node-version: '14.x'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
- run: npm ci - run: npm ci
- run: npm publish - run: npm publish
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
registry-url: 'https://npm.pkg.github.com' registry-url: 'https://npm.pkg.github.com'
- run: npm publish - run: npm publish
@ -387,16 +355,16 @@ steps:
## Publish to npmjs and GPR with yarn ## Publish to npmjs and GPR with yarn
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24.x' node-version: '14.x'
registry-url: <registry url> registry-url: <registry url>
- run: yarn install --frozen-lockfile - run: yarn install --frozen-lockfile
- run: yarn publish - run: yarn publish
env: env:
NODE_AUTH_TOKEN: ${{ secrets.YARN_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.YARN_TOKEN }}
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
registry-url: 'https://npm.pkg.github.com' registry-url: 'https://npm.pkg.github.com'
- run: yarn publish - run: yarn publish
@ -407,10 +375,10 @@ steps:
## Use private packages ## Use private packages
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24.x' node-version: '14.x'
registry-url: 'https://registry.npmjs.org' registry-url: 'https://registry.npmjs.org'
# Skip post-install scripts here, as a malicious # Skip post-install scripts here, as a malicious
# script could steal NODE_AUTH_TOKEN. # script could steal NODE_AUTH_TOKEN.
@ -427,10 +395,10 @@ Below you can find a sample "Setup .yarnrc.yml" step, that is going to allow you
```yaml ```yaml
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v4
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version: '24.x' node-version: '14.x'
- name: Setup .yarnrc.yml - name: Setup .yarnrc.yml
run: | run: |
yarn config set npmScopes.my-org.npmRegistryServer "https://npm.pkg.github.com" yarn config set npmScopes.my-org.npmRegistryServer "https://npm.pkg.github.com"
@ -446,17 +414,5 @@ To access private GitHub Packages within the same organization, go to "Manage Ac
Please refer to the [Ensuring workflow access to your package - Configuring a package's access control and visibility](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#ensuring-workflow-access-to-your-package) for more details. Please refer to the [Ensuring workflow access to your package - Configuring a package's access control and visibility](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#ensuring-workflow-access-to-your-package) for more details.
## Use private mirror ### always-auth input
The always-auth input sets `always-auth=true` in .npmrc file. With this option set [npm](https://docs.npmjs.com/cli/v6/using-npm/config#always-auth)/yarn sends the authentication credentials when making a request to the registries.
It is possible to use a private mirror hosting Node.js binaries. This mirror must be a full mirror of the official Node.js distribution.
The mirror URL can be set using the `mirror` input.
It is possible to specify a token to authenticate with the mirror using the `mirror-token` input.
The token will be passed as a bearer token in the `Authorization` header.
```yaml
- uses: actions/setup-node@v6
with:
node-version: '24.x'
mirror: 'https://nodejs.org/dist'
mirror-token: 'your-mirror-token'
```

1103
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,9 @@
{ {
"name": "setup-node", "name": "setup-node",
"version": "6.0.0", "version": "4.0.0",
"private": true, "private": true,
"description": "setup node action", "description": "setup node action",
"main": "lib/setup-node.js", "main": "lib/setup-node.js",
"engines": {
"node": ">=24.0.0"
},
"scripts": { "scripts": {
"build": "ncc build -o dist/setup src/setup-node.ts && ncc build -o dist/cache-save src/cache-save.ts", "build": "ncc build -o dist/setup src/setup-node.ts && ncc build -o dist/cache-save src/cache-save.ts",
"format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write \"**/*.{ts,yml,yaml}\"", "format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write \"**/*.{ts,yml,yaml}\"",
@ -28,33 +25,33 @@
"author": "GitHub", "author": "GitHub",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/cache": "^4.1.0", "@actions/cache": "^3.0.4",
"@actions/core": "^1.11.1", "@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1", "@actions/exec": "^1.1.0",
"@actions/github": "^6.0.1", "@actions/github": "^5.1.1",
"@actions/glob": "^0.5.0", "@actions/glob": "^0.4.0",
"@actions/http-client": "^2.2.1", "@actions/http-client": "^2.1.1",
"@actions/io": "^1.0.2", "@actions/io": "^1.0.2",
"@actions/tool-cache": "^2.0.2", "@actions/tool-cache": "^2.0.1",
"semver": "^7.6.3", "semver": "^7.5.4",
"uuid": "^11.1.0" "uuid": "^9.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.14", "@types/jest": "^29.5.5",
"@types/node": "^24.1.0", "@types/node": "^20.8.2",
"@types/semver": "^7.5.8", "@types/semver": "^7.5.3",
"@typescript-eslint/eslint-plugin": "^5.54.0", "@typescript-eslint/eslint-plugin": "^5.54.0",
"@typescript-eslint/parser": "^5.54.0", "@typescript-eslint/parser": "^5.54.0",
"@vercel/ncc": "^0.38.3", "@vercel/ncc": "^0.38.0",
"eslint": "^8.57.0", "eslint": "^8.35.0",
"eslint-config-prettier": "^8.6.0", "eslint-config-prettier": "^8.6.0",
"eslint-plugin-jest": "^27.9.0", "eslint-plugin-jest": "^27.2.1",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"jest": "^29.7.0", "jest": "^29.7.0",
"jest-circus": "^29.7.0", "jest-circus": "^29.7.0",
"jest-each": "^29.7.0", "jest-each": "^29.7.0",
"prettier": "^3.6.2", "prettier": "^2.8.4",
"ts-jest": "^29.4.1", "ts-jest": "^29.1.1",
"typescript": "^5.4.2" "typescript": "^5.2.2"
} }
} }

View File

@ -4,7 +4,7 @@ import * as path from 'path';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as github from '@actions/github'; import * as github from '@actions/github';
export function configAuthentication(registryUrl: string) { export function configAuthentication(registryUrl: string, alwaysAuth: string) {
const npmrc: string = path.resolve( const npmrc: string = path.resolve(
process.env['RUNNER_TEMP'] || process.cwd(), process.env['RUNNER_TEMP'] || process.cwd(),
'.npmrc' '.npmrc'
@ -13,10 +13,14 @@ export function configAuthentication(registryUrl: string) {
registryUrl += '/'; registryUrl += '/';
} }
writeRegistryToFile(registryUrl, npmrc); writeRegistryToFile(registryUrl, npmrc, alwaysAuth);
} }
function writeRegistryToFile(registryUrl: string, fileLocation: string) { function writeRegistryToFile(
registryUrl: string,
fileLocation: string,
alwaysAuth: string
) {
let scope: string = core.getInput('scope'); let scope: string = core.getInput('scope');
if (!scope && registryUrl.indexOf('npm.pkg.github.com') > -1) { if (!scope && registryUrl.indexOf('npm.pkg.github.com') > -1) {
scope = github.context.repo.owner; scope = github.context.repo.owner;
@ -43,7 +47,8 @@ function writeRegistryToFile(registryUrl: string, fileLocation: string) {
const authString: string = const authString: string =
registryUrl.replace(/(^\w+:|^)/, '') + ':_authToken=${NODE_AUTH_TOKEN}'; registryUrl.replace(/(^\w+:|^)/, '') + ':_authToken=${NODE_AUTH_TOKEN}';
const registryString = `${scope}registry=${registryUrl}`; const registryString = `${scope}registry=${registryUrl}`;
newContents += `${authString}${os.EOL}${registryString}`; const alwaysAuthString = `always-auth=${alwaysAuth}`;
newContents += `${authString}${os.EOL}${registryString}${os.EOL}${alwaysAuthString}`;
fs.writeFileSync(fileLocation, newContents); fs.writeFileSync(fileLocation, newContents);
core.exportVariable('NPM_CONFIG_USERCONFIG', fileLocation); core.exportVariable('NPM_CONFIG_USERCONFIG', fileLocation);
// Export empty node_auth_token if didn't exist so npm doesn't complain about not being able to find it // Export empty node_auth_token if didn't exist so npm doesn't complain about not being able to find it

View File

@ -3,7 +3,6 @@ import * as core from '@actions/core';
import * as glob from '@actions/glob'; import * as glob from '@actions/glob';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
import os from 'os';
import {State} from './constants'; import {State} from './constants';
import { import {
@ -22,7 +21,6 @@ export const restoreCache = async (
throw new Error(`Caching for '${packageManager}' is not supported`); throw new Error(`Caching for '${packageManager}' is not supported`);
} }
const platform = process.env.RUNNER_OS; const platform = process.env.RUNNER_OS;
const arch = os.arch();
const cachePaths = await getCacheDirectories( const cachePaths = await getCacheDirectories(
packageManagerInfo, packageManagerInfo,
@ -40,7 +38,7 @@ export const restoreCache = async (
); );
} }
const keyPrefix = `node-cache-${platform}-${arch}-${packageManager}`; const keyPrefix = `node-cache-${platform}-${packageManager}`;
const primaryKey = `${keyPrefix}-${fileHash}`; const primaryKey = `${keyPrefix}-${fileHash}`;
core.debug(`primary key is ${primaryKey}`); core.debug(`primary key is ${primaryKey}`);

View File

@ -7,7 +7,6 @@ import {getPackageManagerInfo} from './cache-utils';
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in // Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to // @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
// throw an uncaught exception. Instead of failing this action, just warn. // throw an uncaught exception. Instead of failing this action, just warn.
process.on('uncaughtException', e => { process.on('uncaughtException', e => {
const warningPrefix = '[warning]'; const warningPrefix = '[warning]';
core.info(`${warningPrefix}${e.message}`); core.info(`${warningPrefix}${e.message}`);

View File

@ -167,12 +167,14 @@ const getCacheDirectoriesFromCacheDependencyPath = async (
packageManagerInfo: PackageManagerInfo, packageManagerInfo: PackageManagerInfo,
cacheDependencyPath: string cacheDependencyPath: string
): Promise<string[]> => { ): Promise<string[]> => {
const projectDirectories = const projectDirectories = await getProjectDirectoriesFromCacheDependencyPath(
await getProjectDirectoriesFromCacheDependencyPath(cacheDependencyPath); cacheDependencyPath
);
const cacheFoldersPaths = await Promise.all( const cacheFoldersPaths = await Promise.all(
projectDirectories.map(async projectDirectory => { projectDirectories.map(async projectDirectory => {
const cacheFolderPath = const cacheFolderPath = await packageManagerInfo.getCacheFolderPath(
await packageManagerInfo.getCacheFolderPath(projectDirectory); projectDirectory
);
core.debug( core.debug(
`${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the directory "${projectDirectory}"` `${packageManagerInfo.name}'s cache folder "${cacheFolderPath}" configured for the directory "${projectDirectory}"`
); );
@ -293,13 +295,7 @@ export function isGhes(): boolean {
const ghUrl = new URL( const ghUrl = new URL(
process.env['GITHUB_SERVER_URL'] || 'https://github.com' process.env['GITHUB_SERVER_URL'] || 'https://github.com'
); );
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
const hostname = ghUrl.hostname.trimEnd().toUpperCase();
const isGitHubHost = hostname === 'GITHUB.COM';
const isGitHubEnterpriseCloudHost = hostname.endsWith('.GHE.COM');
const isLocalHost = hostname.endsWith('.LOCALHOST');
return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost;
} }
export function isCacheFeatureAvailable(): boolean { export function isCacheFeatureAvailable(): boolean {

View File

@ -24,7 +24,7 @@ export default abstract class BaseDistribution {
}); });
} }
protected abstract getDistributionUrl(mirror: string): string; protected abstract getDistributionUrl(): string;
public async setupNodeJs() { public async setupNodeJs() {
let nodeJsVersions: INodeVersion[] | undefined; let nodeJsVersions: INodeVersion[] | undefined;
@ -97,19 +97,10 @@ export default abstract class BaseDistribution {
} }
protected async getNodeJsVersions(): Promise<INodeVersion[]> { protected async getNodeJsVersions(): Promise<INodeVersion[]> {
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror); const initialUrl = this.getDistributionUrl();
const dataUrl = `${initialUrl}/index.json`; const dataUrl = `${initialUrl}/index.json`;
const headers = {}; const response = await this.httpClient.getJson<INodeVersion[]>(dataUrl);
if (this.nodeInfo.mirrorToken) {
headers['Authorization'] = `Bearer ${this.nodeInfo.mirrorToken}`;
}
const response = await this.httpClient.getJson<INodeVersion[]>(
dataUrl,
headers
);
return response.result || []; return response.result || [];
} }
@ -121,12 +112,8 @@ export default abstract class BaseDistribution {
? `node-v${version}-win-${osArch}` ? `node-v${version}-win-${osArch}`
: `node-v${version}-${this.osPlat}-${osArch}`; : `node-v${version}-${this.osPlat}-${osArch}`;
const urlFileName: string = const urlFileName: string =
this.osPlat == 'win32' this.osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`;
? this.nodeInfo.arch === 'arm64' const initialUrl = this.getDistributionUrl();
? `${fileName}.zip`
: `${fileName}.7z`
: `${fileName}.tar.gz`;
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror);
const url = `${initialUrl}/v${version}/${urlFileName}`; const url = `${initialUrl}/v${version}/${urlFileName}`;
return <INodeVersionInfo>{ return <INodeVersionInfo>{
@ -143,11 +130,7 @@ export default abstract class BaseDistribution {
`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}` `Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`
); );
try { try {
downloadPath = await tc.downloadTool( downloadPath = await tc.downloadTool(info.downloadUrl);
info.downloadUrl,
undefined,
this.nodeInfo.mirrorToken
);
} catch (err) { } catch (err) {
if ( if (
err instanceof tc.HTTPError && err instanceof tc.HTTPError &&
@ -163,7 +146,7 @@ export default abstract class BaseDistribution {
throw err; throw err;
} }
const toolPath = await this.extractArchive(downloadPath, info, true); const toolPath = await this.extractArchive(downloadPath, info);
core.info('Done'); core.info('Done');
return toolPath; return toolPath;
@ -181,7 +164,7 @@ export default abstract class BaseDistribution {
version: string, version: string,
arch: string = os.arch() arch: string = os.arch()
): Promise<string> { ): Promise<string> {
const initialUrl = this.getDistributionUrl(this.nodeInfo.mirror); const initialUrl = this.getDistributionUrl();
const osArch: string = this.translateArchToDistUrl(arch); const osArch: string = this.translateArchToDistUrl(arch);
// Create temporary folder to download to // Create temporary folder to download to
@ -198,34 +181,18 @@ export default abstract class BaseDistribution {
core.info(`Downloading only node binary from ${exeUrl}`); core.info(`Downloading only node binary from ${exeUrl}`);
const exePath = await tc.downloadTool( const exePath = await tc.downloadTool(exeUrl);
exeUrl,
undefined,
this.nodeInfo.mirrorToken
);
await io.cp(exePath, path.join(tempDir, 'node.exe')); await io.cp(exePath, path.join(tempDir, 'node.exe'));
const libPath = await tc.downloadTool( const libPath = await tc.downloadTool(libUrl);
libUrl,
undefined,
this.nodeInfo.mirrorToken
);
await io.cp(libPath, path.join(tempDir, 'node.lib')); await io.cp(libPath, path.join(tempDir, 'node.lib'));
} catch (err) { } catch (err) {
if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { if (err instanceof tc.HTTPError && err.httpStatusCode == 404) {
exeUrl = `${initialUrl}/v${version}/node.exe`; exeUrl = `${initialUrl}/v${version}/node.exe`;
libUrl = `${initialUrl}/v${version}/node.lib`; libUrl = `${initialUrl}/v${version}/node.lib`;
const exePath = await tc.downloadTool( const exePath = await tc.downloadTool(exeUrl);
exeUrl,
undefined,
this.nodeInfo.mirrorToken
);
await io.cp(exePath, path.join(tempDir, 'node.exe')); await io.cp(exePath, path.join(tempDir, 'node.exe'));
const libPath = await tc.downloadTool( const libPath = await tc.downloadTool(libUrl);
libUrl,
undefined,
this.nodeInfo.mirrorToken
);
await io.cp(libPath, path.join(tempDir, 'node.lib')); await io.cp(libPath, path.join(tempDir, 'node.lib'));
} else { } else {
throw err; throw err;
@ -239,8 +206,7 @@ export default abstract class BaseDistribution {
protected async extractArchive( protected async extractArchive(
downloadPath: string, downloadPath: string,
info: INodeVersionInfo | null, info: INodeVersionInfo | null
isOfficialArchive?: boolean
) { ) {
// //
// Extract // Extract
@ -249,24 +215,12 @@ export default abstract class BaseDistribution {
let extPath: string; let extPath: string;
info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here
if (this.osPlat == 'win32') { if (this.osPlat == 'win32') {
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' && isOfficialArchive) {
const renamedArchive = `${downloadPath}.zip`;
fs.renameSync(downloadPath, renamedArchive);
extPath = await tc.extractZip(renamedArchive);
} else {
const _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe'); const _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 // 7z extracts to folder matching file name
const nestedPath = path.join( const nestedPath = path.join(
extPath, extPath,
path.basename(info.fileName, extension) path.basename(info.fileName, '.7z')
); );
if (fs.existsSync(nestedPath)) { if (fs.existsSync(nestedPath)) {
extPath = nestedPath; extPath = nestedPath;
@ -306,11 +260,7 @@ export default abstract class BaseDistribution {
dataFileName = `osx-${osArch}-tar`; dataFileName = `osx-${osArch}-tar`;
break; break;
case 'win32': case 'win32':
if (this.nodeInfo.arch === 'arm64') {
dataFileName = `win-${osArch}-zip`;
} else {
dataFileName = `win-${osArch}-exe`; dataFileName = `win-${osArch}-exe`;
}
break; break;
default: default:
throw new Error(`Unexpected OS '${this.osPlat}'`); throw new Error(`Unexpected OS '${this.osPlat}'`);

View File

@ -4,8 +4,6 @@ export interface NodeInputs {
auth?: string; auth?: string;
checkLatest: boolean; checkLatest: boolean;
stable: boolean; stable: boolean;
mirror: string;
mirrorToken: string;
} }
export interface INodeVersionInfo { export interface INodeVersionInfo {

View File

@ -7,8 +7,7 @@ export default class NightlyNodejs extends BasePrereleaseNodejs {
super(nodeInfo); super(nodeInfo);
} }
protected getDistributionUrl(mirror: string): string { protected getDistributionUrl(): string {
const url = mirror || 'https://nodejs.org'; return 'https://nodejs.org/download/nightly';
return `${url}/download/nightly`;
} }
} }

View File

@ -84,21 +84,15 @@ export default class OfficialBuilds extends BaseDistribution {
downloadPath = await tc.downloadTool( downloadPath = await tc.downloadTool(
versionInfo.downloadUrl, versionInfo.downloadUrl,
undefined, undefined,
this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth this.nodeInfo.auth
); );
if (downloadPath) { if (downloadPath) {
toolPath = await this.extractArchive( toolPath = await this.extractArchive(downloadPath, versionInfo);
downloadPath,
versionInfo,
false
);
} }
} else { } else {
core.info( core.info(
`Not found in manifest. Falling back to download directly from ${ 'Not found in manifest. Falling back to download directly from Node'
this.nodeInfo.mirror || 'Node'
}`
); );
} }
} catch (err) { } catch (err) {
@ -178,9 +172,8 @@ export default class OfficialBuilds extends BaseDistribution {
return version; return version;
} }
protected getDistributionUrl(mirror: string): string { protected getDistributionUrl(): string {
const url = mirror || 'https://nodejs.org'; return `https://nodejs.org/dist`;
return `${url}/dist`;
} }
private getManifest(): Promise<tc.IToolRelease[]> { private getManifest(): Promise<tc.IToolRelease[]> {
@ -188,7 +181,7 @@ export default class OfficialBuilds extends BaseDistribution {
return tc.getManifestFromRepo( return tc.getManifestFromRepo(
'actions', 'actions',
'node-versions', 'node-versions',
this.nodeInfo.mirror ? this.nodeInfo.mirrorToken : this.nodeInfo.auth, this.nodeInfo.auth,
'main' 'main'
); );
} }

View File

@ -6,8 +6,7 @@ export default class RcBuild extends BaseDistribution {
super(nodeInfo); super(nodeInfo);
} }
getDistributionUrl(mirror: string): string { getDistributionUrl(): string {
const url = mirror || 'https://nodejs.org'; return 'https://nodejs.org/download/rc';
return `${url}/download/rc`;
} }
} }

View File

@ -7,8 +7,7 @@ export default class CanaryBuild extends BasePrereleaseNodejs {
super(nodeInfo); super(nodeInfo);
} }
protected getDistributionUrl(mirror: string): string { protected getDistributionUrl(): string {
const url = mirror || 'https://nodejs.org'; return 'https://nodejs.org/download/v8-canary';
return `${url}/download/v8-canary`;
} }
} }

View File

@ -1,14 +1,14 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import os from 'os';
import fs from 'fs'; import fs from 'fs';
import os from 'os';
import * as auth from './authutil'; import * as auth from './authutil';
import * as path from 'path'; import * as path from 'path';
import {restoreCache} from './cache-restore'; import {restoreCache} from './cache-restore';
import {isCacheFeatureAvailable} from './cache-utils'; import {isCacheFeatureAvailable} from './cache-utils';
import {getNodejsDistribution} from './distributions/installer-factory'; import {getNodejsDistribution} from './distributions/installer-factory';
import {getNodeVersionFromFile, printEnvDetailsAndSetOutput} from './util'; import {parseNodeVersionFile, printEnvDetailsAndSetOutput} from './util';
import {State} from './constants'; import {State} from './constants';
export async function run() { export async function run() {
@ -21,9 +21,6 @@ export async function run() {
let arch = core.getInput('architecture'); let arch = core.getInput('architecture');
const cache = core.getInput('cache'); const cache = core.getInput('cache');
const packagemanagercache =
(core.getInput('package-manager-cache') || 'true').toUpperCase() ===
'TRUE';
// if architecture supplied but node-version is not // if architecture supplied but node-version is not
// if we don't throw a warning, the already installed x64 node will be used which is not probably what user meant. // if we don't throw a warning, the already installed x64 node will be used which is not probably what user meant.
@ -40,8 +37,6 @@ export async function run() {
if (version) { if (version) {
const token = core.getInput('token'); const token = core.getInput('token');
const auth = !token ? undefined : `token ${token}`; const auth = !token ? undefined : `token ${token}`;
const mirror = core.getInput('mirror');
const mirrorToken = core.getInput('mirror-token');
const stable = const stable =
(core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; (core.getInput('stable') || 'true').toUpperCase() === 'TRUE';
const checkLatest = const checkLatest =
@ -51,9 +46,7 @@ export async function run() {
checkLatest, checkLatest,
auth, auth,
stable, stable,
arch, arch
mirror,
mirrorToken
}; };
const nodeDistribution = getNodejsDistribution(nodejsInfo); const nodeDistribution = getNodejsDistribution(nodejsInfo);
await nodeDistribution.setupNodeJs(); await nodeDistribution.setupNodeJs();
@ -62,29 +55,15 @@ export async function run() {
await printEnvDetailsAndSetOutput(); await printEnvDetailsAndSetOutput();
const registryUrl: string = core.getInput('registry-url'); const registryUrl: string = core.getInput('registry-url');
const alwaysAuth: string = core.getInput('always-auth');
if (registryUrl) { if (registryUrl) {
auth.configAuthentication(registryUrl); auth.configAuthentication(registryUrl, alwaysAuth);
} }
const cacheDependencyPath = core.getInput('cache-dependency-path'); if (cache && isCacheFeatureAvailable()) {
if (isCacheFeatureAvailable()) {
// if the cache input is provided, use it for caching.
if (cache) {
core.saveState(State.CachePackageManager, cache); core.saveState(State.CachePackageManager, cache);
const cacheDependencyPath = core.getInput('cache-dependency-path');
await restoreCache(cache, cacheDependencyPath); await restoreCache(cache, cacheDependencyPath);
// package manager npm is detected from package.json, enable auto-caching for npm.
} else if (packagemanagercache) {
const resolvedPackageManager = getNameFromPackageManagerField();
if (resolvedPackageManager) {
core.info(
"Detected npm as the package manager from package.json's packageManager field. " +
'Auto caching has been enabled for npm. If you want to disable it, set package-manager-cache input to false'
);
core.saveState(State.CachePackageManager, resolvedPackageManager);
await restoreCache(resolvedPackageManager, cacheDependencyPath);
}
}
} }
const matchersPath = path.join(__dirname, '../..', '.github'); const matchersPath = path.join(__dirname, '../..', '.github');
@ -120,7 +99,15 @@ function resolveVersionInput(): string {
versionFileInput versionFileInput
); );
const parsedVersion = getNodeVersionFromFile(versionFilePath); if (!fs.existsSync(versionFilePath)) {
throw new Error(
`The specified node version file at: ${versionFilePath} does not exist`
);
}
const parsedVersion = parseNodeVersionFile(
fs.readFileSync(versionFilePath, 'utf8')
);
if (parsedVersion) { if (parsedVersion) {
version = parsedVersion; version = parsedVersion;
@ -135,34 +122,3 @@ function resolveVersionInput(): string {
return version; return version;
} }
export function getNameFromPackageManagerField(): string | undefined {
const npmRegex = /^(\^)?npm(@.*)?$/; // matches "npm", "npm@...", "^npm@..."
try {
const packageJson = JSON.parse(
fs.readFileSync(
path.join(process.env.GITHUB_WORKSPACE!, 'package.json'),
'utf-8'
)
);
// Check devEngines.packageManager first (object or array)
const devPM = packageJson?.devEngines?.packageManager;
const devPMArray = devPM ? (Array.isArray(devPM) ? devPM : [devPM]) : [];
for (const obj of devPMArray) {
if (typeof obj?.name === 'string' && npmRegex.test(obj.name)) {
return 'npm';
}
}
// Check top-level packageManager
const topLevelPM = packageJson?.packageManager;
if (typeof topLevelPM === 'string' && npmRegex.test(topLevelPM)) {
return 'npm';
}
return undefined;
} catch {
return undefined;
}
}

View File

@ -1,70 +1,52 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
import * as io from '@actions/io';
import fs from 'fs'; export function parseNodeVersionFile(contents: string): string | null {
import path from 'path'; let nodeVersion: string | undefined;
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 parsing the file as an NPM `package.json` file.
try { try {
const manifest = JSON.parse(contents); const manifest = JSON.parse(contents);
// Presume package.json file. // JSON can parse numbers, but that's handled later
if (typeof manifest === 'object' && !!manifest) { if (typeof manifest === 'object') {
// Support Volta. nodeVersion = manifest.volta?.node;
// See https://docs.volta.sh/guide/understanding#managing-your-project if (!nodeVersion) nodeVersion = manifest.engines?.node;
if (manifest.volta?.node) {
return manifest.volta.node;
}
if (manifest.engines?.node) { // if contents are an object, we parsed JSON
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 // this can happen if node-version-file is a package.json
// yet contains no volta.node or engines.node // yet contains no volta.node or engines.node
// //
// If node-version file is _not_ JSON, control flow // if node-version file is _not_ json, control flow
// will not have reached these lines. // will not have reached these lines.
// //
// And because we've reached here, we know the contents // And because we've reached here, we know the contents
// *are* JSON, so no further string parsing makes sense. // *are* JSON, so no further string parsing makes sense.
if (!nodeVersion) {
return null; return null;
} }
}
} catch { } catch {
core.info('Node version file is not JSON file'); core.info('Node version file is not JSON file');
} }
if (!nodeVersion) {
const found = contents.match(/^(?:node(js)?\s+)?v?(?<version>[^\s]+)$/m); const found = contents.match(/^(?:node(js)?\s+)?v?(?<version>[^\s]+)$/m);
return found?.groups?.version ?? contents.trim(); 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;
} }
export async function printEnvDetailsAndSetOutput() { export async function printEnvDetailsAndSetOutput() {
core.startGroup('Environment details'); core.startGroup('Environment details');
const promises = ['node', 'npm', 'yarn'].map(async tool => { const promises = ['node', 'npm', 'yarn'].map(async tool => {
const pathTool = await io.which(tool, false); const output = await getToolVersion(tool, ['--version']);
const output = pathTool ? await getToolVersion(tool, ['--version']) : '';
return {tool, output}; return {tool, output};
}); });