diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index 0472e64..88a1b0f 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -51,6 +51,46 @@ jobs: __tests__/verify-node.sh "${BASH_REMATCH[1]}" shell: bash + nightly-syntax: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + node-version: [16.0.0-nightly20210420a0261d231c, 17-nightly, 18.0.0-nightly] + steps: + - uses: actions/checkout@v3 + - name: Setup Node + uses: ./ + with: + node-version: ${{ matrix.node-version }} + - name: Verify node and npm + run: | + nightlyVersion="${{ matrix.node-version }}" + majorVersion=$(echo $nightlyVersion | cut -d- -f1) + __tests__/verify-node.sh "$majorVersion" + shell: bash + + rc-syntax: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + node-version: [16.0.0-rc.1, 18.0.0-rc.2, 19.0.0-rc.0] + steps: + - uses: actions/checkout@v3 + - name: Setup Node + uses: ./ + with: + node-version: ${{ matrix.node-version }} + - name: Verify node and npm + run: | + rcVersion="${{ matrix.node-version }}" + majorVersion=$(echo $rcVersion | cut -d- -f1) + __tests__/verify-node.sh "$majorVersion" + shell: bash + manifest: runs-on: ${{ matrix.os }} strategy: diff --git a/README.md b/README.md index 3d9d7ee..f2fbd3d 100644 --- a/README.md +++ b/README.md @@ -131,11 +131,13 @@ If the runner is not able to access github.com, any Nodejs versions requested du 1. [Check latest version](docs/advanced-usage.md#check-latest-version) 2. [Using a node version file](docs/advanced-usage.md#node-version-file) 3. [Using different architectures](docs/advanced-usage.md#architecture) -4. [Caching packages data](docs/advanced-usage.md#caching-packages-data) -5. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures) -6. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) -7. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) -8. [Using private packages](docs/advanced-usage.md#use-private-packages) +4. [Using nigthly versions](docs/advanced-usage.md#nightly-versions) +5. [Using rc versions](docs/advanced-usage.md#rc-versions) +6. [Caching packages data](docs/advanced-usage.md#caching-packages-data) +7. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures) +8. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) +9. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) +10. [Using private packages](docs/advanced-usage.md#use-private-packages) ## License diff --git a/__tests__/README.md b/__tests__/README.md new file mode 100644 index 0000000..c148984 --- /dev/null +++ b/__tests__/README.md @@ -0,0 +1,10 @@ +Files located in data directory are used only for testing purposes. + + +## Here the list of files in the data directory + - `.nvmrc`, `.tools-versions` and `package.json` are used to test node-version-file logic + - `package-lock.json`, `pnpm-lock.yaml` and `yarn.lock` are used to test cache logic + - `versions-manifest.json` is used for unit testing to check downloading Node.js versions from the node-versions repository. + - `node-dist-index.json` is used for unit testing to check downloading Node.js versions from the official site. The file was constructed from https://nodejs.org/dist/index.json + - `node-rc-index.json` is used for unit testing to check downloading Node.js rc versions from the official site. The file was constructed from https://nodejs.org/download/rc/index.json + - `node-nightly-index.json` is used for unit testing to check downloading Node.js nightly builds from the official site. The file was constructed from https://nodejs.org/download/nightly/index.json \ No newline at end of file diff --git a/__tests__/authutil.test.ts b/__tests__/authutil.test.ts index 1ec4e1e..594c6a1 100644 --- a/__tests__/authutil.test.ts +++ b/__tests__/authutil.test.ts @@ -1,4 +1,4 @@ -import os = require('os'); +import os from 'os'; import * as fs from 'fs'; import * as path from 'path'; import * as core from '@actions/core'; diff --git a/__tests__/data/node-nightly-index.json b/__tests__/data/node-nightly-index.json new file mode 100644 index 0000000..dd0e7fc --- /dev/null +++ b/__tests__/data/node-nightly-index.json @@ -0,0 +1,35 @@ +[ + {"version":"v20.0.0-nightly2022101987cdf7d412","date":"2022-10-19","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"8.19.2","v8":"10.7.193.16","uv":"1.43.0","zlib":"1.2.11","openssl":"3.0.5+quic","modules":"111","lts":false,"security":false}, + {"version":"v19.0.0-nightly202210182672219b78","date":"2022-10-18","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"8.19.2","v8":"10.7.193.13","uv":"1.43.0","zlib":"1.2.11","openssl":"3.0.5+quic","modules":"111","lts":false,"security":false}, + + + {"version":"v19.0.0-nightly202204201fe5d56403","date":"2022-04-20","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip"],"npm":"8.7.0","v8":"10.1.124.8","uv":"1.43.0","zlib":"1.2.11","openssl":"3.0.2+quic","modules":"108","lts":false,"security":false}, + {"version":"v18.0.0-nightly20220419bde889bd4e","date":"2022-04-19","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip"],"npm":"8.7.0","v8":"10.1.124.8","uv":"1.43.0","zlib":"1.2.11","openssl":"3.0.2+quic","modules":"108","lts":false,"security":false}, + {"version":"v18.0.0-nightly202204180699150267","date":"2022-04-18","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip"],"npm":"8.7.0","v8":"10.1.124.8","uv":"1.43.0","zlib":"1.2.11","openssl":"3.0.2+quic","modules":"108","lts":false,"security":false}, + + {"version":"v18.0.0-nightly202110204cb3e06ed8","date":"2021-10-20","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"8.1.0","v8":"9.5.172.21","uv":"1.42.0","zlib":"1.2.11","openssl":"3.0.0+quic","modules":"102","lts":false,"security":false}, + {"version":"v17.5.0-nightly20220209e43808936a","date":"2022-02-09","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"8.4.1","v8":"9.6.180.15","uv":"1.43.0","zlib":"1.2.11","openssl":"3.0.1+quic","modules":"102","lts":false,"security":false}, + {"version":"v17.0.0-nightly202110193f11666dc7","date":"2021-10-19","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"8.1.0","v8":"9.5.172.21","uv":"1.42.0","zlib":"1.2.11","openssl":"3.0.0+quic","modules":"102","lts":false,"security":false}, + {"version":"v17.0.0-nightly20211018c0a70203de","date":"2021-10-18","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"8.0.0","v8":"9.5.172.21","uv":"1.42.0","zlib":"1.2.11","openssl":"3.0.0+quic","modules":"102","lts":false,"security":false}, + + {"version":"v16.0.0-nightly20210420a0261d231c","date":"2021-04-20","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"7.10.0","v8":"9.0.257.17","uv":"1.41.0","zlib":"1.2.11","openssl":"1.1.1k+quic","modules":"93","lts":false,"security":false}, + {"version":"v16.0.0-nightly20210417bc31dc0e0f","date":"2021-04-17","files":["aix-ppc64","headers","linux-arm64","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"7.10.0","v8":"9.0.257.17","uv":"1.41.0","zlib":"1.2.11","openssl":"1.1.1k+quic","modules":"93","lts":false,"security":false}, + {"version":"v16.0.0-nightly20210416d3162da8dd","date":"2021-04-16","files":["aix-ppc64","headers","linux-arm64","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"7.9.0","v8":"9.0.257.17","uv":"1.41.0","zlib":"1.2.11","openssl":"1.1.1k+quic","modules":"93","lts":false,"security":false}, + {"version":"v16.0.0-nightly20210415c3a5e15ebe","date":"2021-04-15","files":["aix-ppc64","headers","linux-arm64","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"7.9.0","v8":"9.0.257.17","uv":"1.41.0","zlib":"1.2.11","openssl":"1.1.1k+quic","modules":"93","lts":false,"security":false}, + + + {"version":"v15.0.0-nightly2020102011f1ad939f","date":"2020-10-20","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"7.0.2","v8":"8.6.395.16","uv":"1.40.0","zlib":"1.2.11","openssl":"1.1.1g","modules":"88","lts":false,"security":false}, + {"version":"v15.0.0-nightly20201019c55f661551","date":"2020-10-19","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"7.0.2","v8":"8.6.395.16","uv":"1.40.0","zlib":"1.2.11","openssl":"1.1.1g","modules":"88","lts":false,"security":false}, + {"version":"v14.0.0-nightly20200421c3554307c6","date":"2020-04-21","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.14.4","v8":"8.1.307.30","uv":"1.37.0","zlib":"1.2.11","openssl":"1.1.1f","modules":"83","lts":false,"security":false}, + {"version":"v14.0.0-nightly202004204af0598134","date":"2020-04-20","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.14.4","v8":"8.1.307.26","uv":"1.37.0","zlib":"1.2.11","openssl":"1.1.1f","modules":"83","lts":false,"security":false}, + + {"version":"v13.13.1-nightly20200415947ddec091","date":"2020-04-15","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.14.4","v8":"7.9.317.25","uv":"1.35.0","zlib":"1.2.11","openssl":"1.1.1f","modules":"79","lts":false,"security":false}, + {"version":"v13.11.1-nightly2020032628e298f219","date":"2020-03-26","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.14.3","v8":"7.9.317.25","uv":"1.35.0","zlib":"1.2.11","openssl":"1.1.1e","modules":"79","lts":false,"security":false}, + + {"version":"v13.10.2-nightly202003056122620832","date":"2020-03-05","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.13.7","v8":"7.9.317.25","uv":"1.34.2","zlib":"1.2.11","openssl":"1.1.1d","modules":"79","lts":false,"security":false}, + {"version":"v13.9.1-nightly202003041bca7b6c70","date":"2020-03-04","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.13.7","v8":"7.9.317.25","uv":"1.34.2","zlib":"1.2.11","openssl":"1.1.1d","modules":"79","lts":false,"security":false}, + {"version":"v13.0.0-nightly201908175e3b4d6ed9","date":"2019-08-17","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.10.2","v8":"7.6.303.28","uv":"1.31.0","zlib":"1.2.11","openssl":"1.1.1c","modules":"77","lts":false,"security":true}, + {"version":"v13.0.0-nightly2019081671b5ce5885","date":"2019-08-16","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.10.2","v8":"7.6.303.28","uv":"1.31.0","zlib":"1.2.11","openssl":"1.1.1c","modules":"77","lts":false,"security":true}, + {"version":"v13.0.0-nightly2019072962a809fa54","date":"2019-07-29","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"npm":"6.10.0","v8":"7.5.288.22","uv":"1.30.1","zlib":"1.2.11","openssl":"1.1.1c","modules":"74","lts":false,"security":false} + + ] \ No newline at end of file diff --git a/__tests__/data/node-rc-index.json b/__tests__/data/node-rc-index.json new file mode 100644 index 0000000..ba8ff9f --- /dev/null +++ b/__tests__/data/node-rc-index.json @@ -0,0 +1,28 @@ +[ + {"version":"v19.0.0-rc.2","date":"2022-10-14","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v19.0.0-rc.1","date":"2022-10-04","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v17.0.0-rc.1","date":"2021-10-05","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v17.0.0-rc.0","date":"2021-09-21","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v16.17.0-rc.1","date":"2022-08-06","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-arm64-tar","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v16.0.0-rc.2","date":"2021-04-07","files":["headers","linux-arm64","linux-ppc64le","linux-x64","osx-x64-pkg","osx-x64-tar","src"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v16.0.0-rc.1","date":"2021-03-30","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v16.0.0-rc.0","date":"2021-03-19","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.19.0-rc.0","date":"2022-01-25","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.18.0-rc.0","date":"2021-09-08","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.17.4-rc.0","date":"2021-07-20","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.17.1-rc.0","date":"2021-06-11","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.16.0-rc.0","date":"2021-02-22","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.15.5-rc.1","date":"2021-02-08","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.15.5-rc.0","date":"2021-01-27","files":["headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.15.2-rc.0","date":"2020-12-14","files":["headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v14.7.0-rc.1","date":"2020-07-29","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.11.0-rc.1","date":"2020-03-11","files":["headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.11.0-rc.0","date":"2020-03-10","files":["headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-x64","osx-x64-pkg","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.10.1-rc.0","date":"2020-03-04","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.4.0-rc.0","date":"2019-12-13","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.0.1-rc.0","date":"2019-10-23","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.0.0-rc.3","date":"2019-10-21","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.0.0-rc.2","date":"2019-10-15","files":["headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.0.0-rc.1","date":"2019-10-01","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false}, + {"version":"v13.0.0-rc.0","date":"2019-09-25","files":["aix-ppc64","headers","linux-arm64","linux-armv7l","linux-ppc64le","linux-s390x","linux-x64","osx-x64-pkg","osx-x64-tar","src","sunos-x64","win-x64-7z","win-x64-exe","win-x64-msi","win-x64-zip","win-x86-7z","win-x86-exe","win-x86-msi","win-x86-zip"],"v8":"","uv":"","zlib":null,"openssl":null,"modules":null,"lts":false,"security":false} + ] \ No newline at end of file diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 28d77e7..3c3105e 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -4,16 +4,19 @@ import * as tc from '@actions/tool-cache'; import * as exec from '@actions/exec'; import * as im from '../src/installer'; import * as cache from '@actions/cache'; +import * as httpm from '@actions/http-client'; import fs from 'fs'; import cp from 'child_process'; -import osm = require('os'); +import osm from 'os'; import path from 'path'; import each from 'jest-each'; import * as main from '../src/main'; import * as auth from '../src/authutil'; -let nodeTestManifest = require('./data/versions-manifest.json'); -let nodeTestDist = require('./data/node-dist-index.json'); +const nodeTestManifest = require('./data/versions-manifest.json'); +const nodeTestDist = require('./data/node-dist-index.json'); +const nodeTestDistNightly = require('./data/node-nightly-index.json'); +const nodeTestDistRc = require('./data/node-rc-index.json'); describe('setup-node', () => { let inputs = {} as any; @@ -21,6 +24,7 @@ describe('setup-node', () => { let inSpy: jest.SpyInstance; let findSpy: jest.SpyInstance; + let findAllVersionsSpy: jest.SpyInstance; let cnSpy: jest.SpyInstance; let logSpy: jest.SpyInstance; let warningSpy: jest.SpyInstance; @@ -41,6 +45,7 @@ describe('setup-node', () => { let parseNodeVersionSpy: jest.SpyInstance; let isCacheActionAvailable: jest.SpyInstance; let getExecOutputSpy: jest.SpyInstance; + let getJsonSpy: jest.SpyInstance; beforeEach(() => { // @actions/core @@ -61,6 +66,7 @@ describe('setup-node', () => { // @actions/tool-cache findSpy = jest.spyOn(tc, 'find'); + findAllVersionsSpy = jest.spyOn(tc, 'findAllVersions'); dlSpy = jest.spyOn(tc, 'downloadTool'); exSpy = jest.spyOn(tc, 'extractTar'); cacheSpy = jest.spyOn(tc, 'cacheDir'); @@ -68,6 +74,9 @@ describe('setup-node', () => { getDistSpy = jest.spyOn(im, 'getVersionsFromDist'); parseNodeVersionSpy = jest.spyOn(im, 'parseNodeVersionFile'); + // http-client + getJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); + // io whichSpy = jest.spyOn(io, 'which'); existsSpy = jest.spyOn(fs, 'existsSync'); @@ -84,7 +93,30 @@ describe('setup-node', () => { getManifestSpy.mockImplementation( () => nodeTestManifest ); - getDistSpy.mockImplementation(() => nodeTestDist); + + getDistSpy.mockImplementation(version => { + const initialUrl = im.getNodejsDistUrl(version); + if (initialUrl.endsWith('/rc')) { + return nodeTestDistRc; + } else if (initialUrl.endsWith('/nightly')) { + return nodeTestDistNightly; + } else { + return nodeTestDist; + } + }); + + getJsonSpy.mockImplementation(url => { + let res: any; + if (url.includes('/rc')) { + res = nodeTestDistRc; + } else if (url.includes('/nightly')) { + res = nodeTestDistNightly; + } else { + res = nodeTestDist; + } + + return {result: res}; + }); // writes cnSpy = jest.spyOn(process.stdout, 'write'); @@ -138,7 +170,8 @@ describe('setup-node', () => { }); it('can mock dist versions', async () => { - let versions: im.INodeVersion[] = await im.getVersionsFromDist(); + const versionSpec = '1.2.3'; + let versions: im.INodeVersion[] = await im.getVersionsFromDist(versionSpec); expect(versions).toBeDefined(); expect(versions?.length).toBe(23); }); @@ -896,6 +929,277 @@ describe('setup-node', () => { }); }); + describe('rc versions', () => { + it.each([ + [ + '13.10.1-rc.0', + '13.10.1-rc.0', + 'https://nodejs.org/download/rc/v13.10.1-rc.0/node-v13.10.1-rc.0-linux-x64.tar.gz' + ], + [ + '14.15.5-rc.1', + '14.15.5-rc.1', + 'https://nodejs.org/download/rc/v14.15.5-rc.1/node-v14.15.5-rc.1-linux-x64.tar.gz' + ], + [ + '16.17.0-rc.1', + '16.17.0-rc.1', + 'https://nodejs.org/download/rc/v16.17.0-rc.1/node-v16.17.0-rc.1-linux-x64.tar.gz' + ], + [ + '17.0.0-rc.1', + '17.0.0-rc.1', + 'https://nodejs.org/download/rc/v17.0.0-rc.1/node-v17.0.0-rc.1-linux-x64.tar.gz' + ], + [ + '19.0.0-rc.2', + '19.0.0-rc.2', + 'https://nodejs.org/download/rc/v19.0.0-rc.2/node-v19.0.0-rc.2-linux-x64.tar.gz' + ] + ])( + 'finds the versions in the index.json and installs it', + async (input, expectedVersion, expectedUrl) => { + const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); + + findSpy.mockImplementation(() => ''); + findAllVersionsSpy.mockImplementation(() => []); + dlSpy.mockImplementation(async () => '/some/temp/path'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + + inputs['node-version'] = input; + os['arch'] = 'x64'; + os['platform'] = 'linux'; + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith( + `Attempting to download ${input}...` + ); + + 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}` + ); + } + ); + + it.each([ + ['13.10.1-rc.0', '13.10.1-rc.0'], + ['14.15.5-rc.1', '14.15.5-rc.1'], + ['16.17.0-rc.1', '16.17.0-rc.1'], + ['17.0.0-rc.1', '17.0.0-rc.1'] + ])( + 'finds the %s version in the hostedToolcache', + async (input, expectedVersion) => { + const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); + findSpy.mockReturnValue(toolPath); + + inputs['node-version'] = input; + os['arch'] = 'x64'; + os['platform'] = 'linux'; + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + expect(cnSpy).toHaveBeenCalledWith( + `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` + ); + } + ); + + it('throws an error if version is not found', async () => { + const versionSpec = '19.0.0-rc.3'; + + findSpy.mockImplementation(() => ''); + findAllVersionsSpy.mockImplementation(() => []); + dlSpy.mockImplementation(async () => '/some/temp/path'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + + inputs['node-version'] = versionSpec; + os['arch'] = 'x64'; + os['platform'] = 'linux'; + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith( + `Attempting to download ${versionSpec}...` + ); + expect(cnSpy).toHaveBeenCalledWith( + `::error::Unable to find Node version '${versionSpec}' for platform ${os.platform} and architecture ${os.arch}.${osm.EOL}` + ); + }); + }); + + describe('nightly versions', () => { + it.each([ + [ + '17.5.0-nightly', + '17.5.0-nightly20220209e43808936a', + 'https://nodejs.org/download/nightly/v17.5.0-nightly20220209e43808936a/node-v17.5.0-nightly20220209e43808936a-linux-x64.tar.gz' + ], + [ + '17-nightly', + '17.5.0-nightly20220209e43808936a', + 'https://nodejs.org/download/nightly/v17.5.0-nightly20220209e43808936a/node-v17.5.0-nightly20220209e43808936a-linux-x64.tar.gz' + ], + [ + '18.0.0-nightly', + '18.0.0-nightly20220419bde889bd4e', + 'https://nodejs.org/download/nightly/v18.0.0-nightly20220419bde889bd4e/node-v18.0.0-nightly20220419bde889bd4e-linux-x64.tar.gz' + ], + [ + '18-nightly', + '18.0.0-nightly20220419bde889bd4e', + 'https://nodejs.org/download/nightly/v18.0.0-nightly20220419bde889bd4e/node-v18.0.0-nightly20220419bde889bd4e-linux-x64.tar.gz' + ], + [ + '20.0.0-nightly', + '20.0.0-nightly2022101987cdf7d412', + 'https://nodejs.org/download/nightly/v20.0.0-nightly2022101987cdf7d412/node-v20.0.0-nightly2022101987cdf7d412-linux-x64.tar.gz' + ] + ])( + 'finds the versions in the index.json and installs it', + async (input, expectedVersion, expectedUrl) => { + const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); + + findSpy.mockImplementation(() => ''); + findAllVersionsSpy.mockImplementation(() => []); + dlSpy.mockImplementation(async () => '/some/temp/path'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + + inputs['node-version'] = input; + os['arch'] = 'x64'; + os['platform'] = 'linux'; + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith( + `Attempting to download ${input}...` + ); + + 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}` + ); + } + ); + + it.each([ + ['17.5.0-nightly', '17.5.0-nightly20220209e43808936a'], + ['17-nightly', '17.5.0-nightly20220209e43808936a'], + ['20.0.0-nightly', '20.0.0-nightly2022101987cdf7d412'] + ])( + 'finds the %s version in the hostedToolcache', + async (input, expectedVersion) => { + const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); + findSpy.mockReturnValue(toolPath); + findAllVersionsSpy.mockReturnValue([ + '17.5.0-nightly20220209e43808936a', + '17.5.0-nightly20220209e43808935a', + '20.0.0-nightly2022101987cdf7d412', + '20.0.0-nightly2022101987cdf7d411' + ]); + + inputs['node-version'] = input; + os['arch'] = 'x64'; + os['platform'] = 'linux'; + + // act + await main.run(); + + // assert + expect(findAllVersionsSpy).toHaveBeenCalled(); + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + expect(cnSpy).toHaveBeenCalledWith( + `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` + ); + } + ); + + it.each([ + [ + '17.5.0-nightly', + '17.5.0-nightly20220209e43808936a', + '17.0.0-nightly202110193f11666dc7', + 'https://nodejs.org/download/nightly/v17.5.0-nightly20220209e43808936a/node-v17.5.0-nightly20220209e43808936a-linux-x64.tar.gz' + ], + [ + '17-nightly', + '17.5.0-nightly20220209e43808936a', + '17.0.0-nightly202110193f11666dc7', + 'https://nodejs.org/download/nightly/v17.5.0-nightly20220209e43808936a/node-v17.5.0-nightly20220209e43808936a-linux-x64.tar.gz' + ], + [ + '18.0.0-nightly', + '18.0.0-nightly20220419bde889bd4e', + '18.0.0-nightly202204180699150267', + 'https://nodejs.org/download/nightly/v18.0.0-nightly20220419bde889bd4e/node-v18.0.0-nightly20220419bde889bd4e-linux-x64.tar.gz' + ], + [ + '18-nightly', + '18.0.0-nightly20220419bde889bd4e', + '18.0.0-nightly202204180699150267', + 'https://nodejs.org/download/nightly/v18.0.0-nightly20220419bde889bd4e/node-v18.0.0-nightly20220419bde889bd4e-linux-x64.tar.gz' + ], + [ + '20.0.0-nightly', + '20.0.0-nightly2022101987cdf7d412', + '20.0.0-nightly2022101987cdf7d411', + 'https://nodejs.org/download/nightly/v20.0.0-nightly2022101987cdf7d412/node-v20.0.0-nightly2022101987cdf7d412-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'; + + findSpy.mockReturnValue(foundToolPath); + findAllVersionsSpy.mockReturnValue([ + '17.0.0-nightly202110193f11666dc7', + '18.0.0-nightly202204180699150267', + '20.0.0-nightly2022101987cdf7d411' + ]); + 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('latest alias syntax', () => { it.each(['latest', 'current', 'node'])( 'download the %s version if alias is provided', diff --git a/dist/setup/index.js b/dist/setup/index.js index e147887..0cfca70 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73196,6 +73196,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; @@ -73204,7 +73207,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const os = __nccwpck_require__(2037); +const os_1 = __importDefault(__nccwpck_require__(2037)); const assert = __importStar(__nccwpck_require__(9491)); const core = __importStar(__nccwpck_require__(2186)); const hc = __importStar(__nccwpck_require__(9925)); @@ -73212,13 +73215,14 @@ const io = __importStar(__nccwpck_require__(7436)); const tc = __importStar(__nccwpck_require__(7784)); const path = __importStar(__nccwpck_require__(1017)); const semver = __importStar(__nccwpck_require__(5911)); -const fs = __nccwpck_require__(7147); -function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { +const fs_1 = __importDefault(__nccwpck_require__(7147)); +function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arch()) { return __awaiter(this, void 0, void 0, function* () { // Store manifest data to avoid multiple calls let manifest; let nodeVersions; - let osPlat = os.platform(); + let isNightly = versionSpec.includes('nightly'); + let osPlat = os_1.default.platform(); let osArch = translateArchToDistUrl(arch); if (isLtsAlias(versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); @@ -73227,11 +73231,15 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } if (isLatestSyntax(versionSpec)) { - nodeVersions = yield getVersionsFromDist(); + nodeVersions = yield getVersionsFromDist(versionSpec); versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); core.info(`getting latest node version...`); } - if (checkLatest) { + if (isNightly && checkLatest) { + nodeVersions = yield getVersionsFromDist(versionSpec); + versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); + } + if (checkLatest && !isNightly) { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = yield resolveVersionFromManifest(versionSpec, stable, auth, osArch, manifest); if (resolvedVersion) { @@ -73244,7 +73252,13 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { } // check cache let toolPath; - toolPath = tc.find('node', versionSpec, osArch); + if (isNightly) { + const nightlyVersion = findNightlyVersionInHostedToolcache(versionSpec, osArch); + toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch); + } + else { + toolPath = tc.find('node', versionSpec, osArch); + } // If not found in cache, download if (toolPath) { core.info(`Found in cache @ ${toolPath}`); @@ -73308,7 +73322,7 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { extPath = yield tc.extract7z(downloadPath, undefined, _7zPath); // 7z extracts to folder matching file name let nestedPath = path.join(extPath, path.basename(info.fileName, '.7z')); - if (fs.existsSync(nestedPath)) { + if (fs_1.default.existsSync(nestedPath)) { extPath = nestedPath; } } @@ -73340,6 +73354,11 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { }); } exports.getNode = getNode; +function findNightlyVersionInHostedToolcache(versionsSpec, osArch) { + const foundAllVersions = tc.findAllVersions('node', osArch); + const version = evaluateVersions(foundAllVersions, versionsSpec); + return version; +} function isLtsAlias(versionSpec) { return versionSpec.startsWith('lts/'); } @@ -73372,7 +73391,7 @@ function resolveLtsAliasFromManifest(versionSpec, stable, manifest) { core.debug(`Found LTS release '${release.version}' for Node version '${versionSpec}'`); return release.version.split('.')[0]; } -function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os.arch()), manifest) { +function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os_1.default.arch()), manifest) { return __awaiter(this, void 0, void 0, function* () { let info = null; if (!manifest) { @@ -73390,9 +73409,9 @@ function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchTo return info; }); } -function getInfoFromDist(versionSpec, arch = os.arch(), nodeVersions) { +function getInfoFromDist(versionSpec, arch = os_1.default.arch(), nodeVersions) { return __awaiter(this, void 0, void 0, function* () { - let osPlat = os.platform(); + let osPlat = os_1.default.platform(); let osArch = translateArchToDistUrl(arch); let version = yield queryDistForMatch(versionSpec, arch, nodeVersions); if (!version) { @@ -73406,7 +73425,8 @@ function getInfoFromDist(versionSpec, arch = os.arch(), nodeVersions) { ? `node-v${version}-win-${osArch}` : `node-v${version}-${osPlat}-${osArch}`; let urlFileName = osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; - let url = `https://nodejs.org/dist/v${version}/${urlFileName}`; + const initialUrl = getNodejsDistUrl(versionSpec); + const url = `${initialUrl}/v${version}/${urlFileName}`; return { downloadUrl: url, resolvedVersion: version, @@ -73415,7 +73435,7 @@ function getInfoFromDist(versionSpec, arch = os.arch(), nodeVersions) { }; }); } -function resolveVersionFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os.arch()), manifest) { +function resolveVersionFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os_1.default.arch()), manifest) { return __awaiter(this, void 0, void 0, function* () { try { const info = yield getInfoFromManifest(versionSpec, stable, auth, osArch, manifest); @@ -73427,16 +73447,46 @@ function resolveVersionFromManifest(versionSpec, stable, auth, osArch = translat } }); } +function evaluateNightlyVersions(versions, versionSpec) { + let version = ''; + let range; + const [raw, prerelease] = versionSpec.split('-'); + const isValidVersion = semver.valid(raw); + const rawVersion = isValidVersion ? raw : semver.coerce(raw); + if (rawVersion) { + if (prerelease !== 'nightly') { + range = `${rawVersion}-${prerelease.replace('nightly', 'nightly.')}`; + } + else { + range = `${semver.validRange(`^${rawVersion}-0`)}-0`; + } + } + if (range) { + versions.sort(semver.rcompare); + for (const currentVersion of versions) { + const satisfied = semver.satisfies(currentVersion.replace('-nightly', '-nightly.'), range, { includePrerelease: true }) && currentVersion.includes('nightly'); + if (satisfied) { + version = currentVersion; + break; + } + } + } + if (version) { + core.debug(`matched: ${version}`); + } + else { + core.debug('match not found'); + } + return version; +} // TODO - should we just export this from @actions/tool-cache? Lifted directly from there function evaluateVersions(versions, versionSpec) { let version = ''; core.debug(`evaluating ${versions.length} versions`); - versions = versions.sort((a, b) => { - if (semver.gt(a, b)) { - return 1; - } - return -1; - }); + if (versionSpec.includes('nightly')) { + return evaluateNightlyVersions(versions, versionSpec); + } + versions = versions.sort(semver.rcompare); for (let i = versions.length - 1; i >= 0; i--) { const potential = versions[i]; const satisfied = semver.satisfies(potential, versionSpec); @@ -73453,9 +73503,20 @@ function evaluateVersions(versions, versionSpec) { } return version; } -function queryDistForMatch(versionSpec, arch = os.arch(), nodeVersions) { +function getNodejsDistUrl(version) { + const prerelease = semver.prerelease(version); + if (version.includes('nightly')) { + return 'https://nodejs.org/download/nightly'; + } + else if (prerelease) { + return 'https://nodejs.org/download/rc'; + } + return 'https://nodejs.org/dist'; +} +exports.getNodejsDistUrl = getNodejsDistUrl; +function queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions) { return __awaiter(this, void 0, void 0, function* () { - let osPlat = os.platform(); + let osPlat = os_1.default.platform(); let osArch = translateArchToDistUrl(arch); // node offers a json list of versions let dataFileName; @@ -73474,7 +73535,7 @@ function queryDistForMatch(versionSpec, arch = os.arch(), nodeVersions) { } if (!nodeVersions) { core.debug('No dist manifest cached'); - nodeVersions = yield getVersionsFromDist(); + nodeVersions = yield getVersionsFromDist(versionSpec); } let versions = []; if (isLatestSyntax(versionSpec)) { @@ -73492,9 +73553,10 @@ function queryDistForMatch(versionSpec, arch = os.arch(), nodeVersions) { return version; }); } -function getVersionsFromDist() { +function getVersionsFromDist(versionSpec) { return __awaiter(this, void 0, void 0, function* () { - let dataUrl = 'https://nodejs.org/dist/index.json'; + const initialUrl = getNodejsDistUrl(versionSpec); + const dataUrl = `${initialUrl}/index.json`; let httpClient = new hc.HttpClient('setup-node', [], { allowRetries: true, maxRetries: 3 @@ -73516,9 +73578,10 @@ exports.getVersionsFromDist = getVersionsFromDist; // This method attempts to download and cache the resources from these alternative locations. // Note also that the files are normally zipped but in this case they are just an exe // and lib file in a folder, not zipped. -function acquireNodeFromFallbackLocation(version, arch = os.arch()) { +function acquireNodeFromFallbackLocation(version, arch = os_1.default.arch()) { return __awaiter(this, void 0, void 0, function* () { - let osPlat = os.platform(); + const initialUrl = getNodejsDistUrl(version); + let osPlat = os_1.default.platform(); let osArch = translateArchToDistUrl(arch); // Create temporary folder to download in to const tempDownloadFolder = 'temp_' + Math.floor(Math.random() * 2000000000); @@ -73529,8 +73592,8 @@ function acquireNodeFromFallbackLocation(version, arch = os.arch()) { let exeUrl; let libUrl; try { - exeUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.exe`; - libUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.lib`; + exeUrl = `${initialUrl}/v${version}/win-${osArch}/node.exe`; + libUrl = `${initialUrl}/v${version}/win-${osArch}/node.lib`; core.info(`Downloading only node binary from ${exeUrl}`); const exePath = yield tc.downloadTool(exeUrl); yield io.cp(exePath, path.join(tempDir, 'node.exe')); @@ -73539,8 +73602,8 @@ function acquireNodeFromFallbackLocation(version, arch = os.arch()) { } catch (err) { if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { - exeUrl = `https://nodejs.org/dist/v${version}/node.exe`; - libUrl = `https://nodejs.org/dist/v${version}/node.lib`; + exeUrl = `${initialUrl}/v${version}/node.exe`; + libUrl = `${initialUrl}/v${version}/node.lib`; const exePath = yield tc.downloadTool(exeUrl); yield io.cp(exePath, path.join(tempDir, 'node.exe')); const libPath = yield tc.downloadTool(libUrl); @@ -73631,7 +73694,7 @@ const auth = __importStar(__nccwpck_require__(7573)); const path = __importStar(__nccwpck_require__(1017)); const cache_restore_1 = __nccwpck_require__(9517); const cache_utils_1 = __nccwpck_require__(1678); -const os = __nccwpck_require__(2037); +const os_1 = __importDefault(__nccwpck_require__(2037)); function run() { return __awaiter(this, void 0, void 0, function* () { try { @@ -73639,7 +73702,7 @@ function run() { // Version is optional. If supplied, install / use from the tool cache // If not supplied then task is still used to setup proxy, auth, etc... // - let version = resolveVersionInput(); + const version = resolveVersionInput(); let arch = core.getInput('architecture'); const cache = core.getInput('cache'); // if architecture supplied but node-version is not @@ -73648,12 +73711,12 @@ function run() { core.warning('`architecture` is provided but `node-version` is missing. In this configuration, the version/architecture of Node will not be changed. To fix this, provide `architecture` in combination with `node-version`'); } if (!arch) { - arch = os.arch(); + arch = os_1.default.arch(); } if (version) { - let token = core.getInput('token'); - let auth = !token ? undefined : `token ${token}`; - let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; + const token = core.getInput('token'); + const auth = !token ? undefined : `token ${token}`; + const stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; yield installer.getNode(version, stable, checkLatest, auth, arch); } diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 4b620cb..4789f2e 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -104,6 +104,78 @@ jobs: - run: npm test ``` +## Nightly versions + +You can specify a nightly version to download it from https://nodejs.org/download/nightly. + +### Install the nightly build for a major version + +```yaml +jobs: + build: + runs-on: ubuntu-latest + name: Node sample + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '16-nightly' # it will install the latest nightly release for node 16 + - run: npm ci + - run: npm test +``` + +### Install the nightly build for a specific version + +```yaml +jobs: + build: + runs-on: ubuntu-latest + name: Node sample + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '16.0.0-nightly' # it will install the latest nightly release for node 16.0.0 + - run: npm ci + - run: npm test +``` + +### Install an exact nightly version + +```yaml +jobs: + build: + runs-on: ubuntu-latest + name: Node sample + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '16.0.0-nightly20210420a0261d231c' + - run: npm ci + - run: npm test +``` + +## RC versions + +You can use specify a rc version to download it from https://nodejs.org/download/rc. + +```yaml +jobs: + build: + runs-on: ubuntu-latest + name: Node sample + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '16.0.0-rc.1' + - run: npm ci + - run: npm test +``` + +**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 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. diff --git a/src/cache-restore.ts b/src/cache-restore.ts index d49b27f..7f761da 100644 --- a/src/cache-restore.ts +++ b/src/cache-restore.ts @@ -4,7 +4,7 @@ import * as glob from '@actions/glob'; import path from 'path'; import fs from 'fs'; -import {State, Outputs} from './constants'; +import {State} from './constants'; import { getCacheDirectoryPath, getPackageManagerInfo, diff --git a/src/installer.ts b/src/installer.ts index 83a43d8..1b5659b 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -1,4 +1,4 @@ -import os = require('os'); +import os from 'os'; import * as assert from 'assert'; import * as core from '@actions/core'; import * as hc from '@actions/http-client'; @@ -6,11 +6,13 @@ import * as io from '@actions/io'; import * as tc from '@actions/tool-cache'; import * as path from 'path'; import * as semver from 'semver'; -import fs = require('fs'); +import fs from 'fs'; // // Node versions interface // see https://nodejs.org/dist/index.json +// for nightly https://nodejs.org/download/nightly/index.json +// for rc https://nodejs.org/download/rc/index.json // export interface INodeVersion { version: string; @@ -38,6 +40,7 @@ export async function getNode( // Store manifest data to avoid multiple calls let manifest: INodeRelease[] | undefined; let nodeVersions: INodeVersion[] | undefined; + let isNightly = versionSpec.includes('nightly'); let osPlat: string = os.platform(); let osArch: string = translateArchToDistUrl(arch); @@ -51,12 +54,17 @@ export async function getNode( } if (isLatestSyntax(versionSpec)) { - nodeVersions = await getVersionsFromDist(); + nodeVersions = await getVersionsFromDist(versionSpec); versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); core.info(`getting latest node version...`); } - if (checkLatest) { + if (isNightly && checkLatest) { + nodeVersions = await getVersionsFromDist(versionSpec); + versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); + } + + if (checkLatest && !isNightly) { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = await resolveVersionFromManifest( versionSpec, @@ -75,7 +83,15 @@ export async function getNode( // check cache let toolPath: string; - toolPath = tc.find('node', versionSpec, osArch); + if (isNightly) { + const nightlyVersion = findNightlyVersionInHostedToolcache( + versionSpec, + osArch + ); + toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch); + } else { + toolPath = tc.find('node', versionSpec, osArch); + } // If not found in cache, download if (toolPath) { @@ -199,6 +215,16 @@ export async function getNode( core.addPath(toolPath); } +function findNightlyVersionInHostedToolcache( + versionsSpec: string, + osArch: string +) { + const foundAllVersions = tc.findAllVersions('node', osArch); + const version = evaluateVersions(foundAllVersions, versionsSpec); + + return version; +} + function isLtsAlias(versionSpec: string): boolean { return versionSpec.startsWith('lts/'); } @@ -306,7 +332,8 @@ async function getInfoFromDist( : `node-v${version}-${osPlat}-${osArch}`; let urlFileName: string = osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; - let url = `https://nodejs.org/dist/v${version}/${urlFileName}`; + const initialUrl = getNodejsDistUrl(versionSpec); + const url = `${initialUrl}/v${version}/${urlFileName}`; return { downloadUrl: url, @@ -338,16 +365,58 @@ async function resolveVersionFromManifest( } } +function evaluateNightlyVersions( + versions: string[], + versionSpec: string +): string { + let version = ''; + let range: string | undefined; + const [raw, prerelease] = versionSpec.split('-'); + const isValidVersion = semver.valid(raw); + const rawVersion = isValidVersion ? raw : semver.coerce(raw); + if (rawVersion) { + if (prerelease !== 'nightly') { + range = `${rawVersion}-${prerelease.replace('nightly', 'nightly.')}`; + } else { + range = `${semver.validRange(`^${rawVersion}-0`)}-0`; + } + } + + if (range) { + versions.sort(semver.rcompare); + for (const currentVersion of versions) { + const satisfied: boolean = + semver.satisfies( + currentVersion.replace('-nightly', '-nightly.'), + range, + {includePrerelease: true} + ) && currentVersion.includes('nightly'); + if (satisfied) { + version = currentVersion; + break; + } + } + } + + if (version) { + core.debug(`matched: ${version}`); + } else { + core.debug('match not found'); + } + + return version; +} + // TODO - should we just export this from @actions/tool-cache? Lifted directly from there function evaluateVersions(versions: string[], versionSpec: string): string { let version = ''; core.debug(`evaluating ${versions.length} versions`); - versions = versions.sort((a, b) => { - if (semver.gt(a, b)) { - return 1; - } - return -1; - }); + + if (versionSpec.includes('nightly')) { + return evaluateNightlyVersions(versions, versionSpec); + } + + versions = versions.sort(semver.rcompare); for (let i = versions.length - 1; i >= 0; i--) { const potential: string = versions[i]; const satisfied: boolean = semver.satisfies(potential, versionSpec); @@ -366,6 +435,17 @@ function evaluateVersions(versions: string[], versionSpec: string): string { return version; } +export function getNodejsDistUrl(version: string) { + const prerelease = semver.prerelease(version); + if (version.includes('nightly')) { + return 'https://nodejs.org/download/nightly'; + } else if (prerelease) { + return 'https://nodejs.org/download/rc'; + } + + return 'https://nodejs.org/dist'; +} + async function queryDistForMatch( versionSpec: string, arch: string = os.arch(), @@ -392,7 +472,7 @@ async function queryDistForMatch( if (!nodeVersions) { core.debug('No dist manifest cached'); - nodeVersions = await getVersionsFromDist(); + nodeVersions = await getVersionsFromDist(versionSpec); } let versions: string[] = []; @@ -410,12 +490,15 @@ async function queryDistForMatch( }); // get the latest version that matches the version spec - let version: string = evaluateVersions(versions, versionSpec); + let version = evaluateVersions(versions, versionSpec); return version; } -export async function getVersionsFromDist(): Promise { - let dataUrl = 'https://nodejs.org/dist/index.json'; +export async function getVersionsFromDist( + versionSpec: string +): Promise { + const initialUrl = getNodejsDistUrl(versionSpec); + const dataUrl = `${initialUrl}/index.json`; let httpClient = new hc.HttpClient('setup-node', [], { allowRetries: true, maxRetries: 3 @@ -440,6 +523,7 @@ async function acquireNodeFromFallbackLocation( version: string, arch: string = os.arch() ): Promise { + const initialUrl = getNodejsDistUrl(version); let osPlat: string = os.platform(); let osArch: string = translateArchToDistUrl(arch); @@ -453,8 +537,8 @@ async function acquireNodeFromFallbackLocation( let exeUrl: string; let libUrl: string; try { - exeUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.exe`; - libUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.lib`; + exeUrl = `${initialUrl}/v${version}/win-${osArch}/node.exe`; + libUrl = `${initialUrl}/v${version}/win-${osArch}/node.lib`; core.info(`Downloading only node binary from ${exeUrl}`); @@ -464,8 +548,8 @@ async function acquireNodeFromFallbackLocation( await io.cp(libPath, path.join(tempDir, 'node.lib')); } catch (err) { if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { - exeUrl = `https://nodejs.org/dist/v${version}/node.exe`; - libUrl = `https://nodejs.org/dist/v${version}/node.lib`; + exeUrl = `${initialUrl}/v${version}/node.exe`; + libUrl = `${initialUrl}/v${version}/node.lib`; const exePath = await tc.downloadTool(exeUrl); await io.cp(exePath, path.join(tempDir, 'node.exe')); diff --git a/src/main.ts b/src/main.ts index 2107c95..91cad42 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,7 +6,7 @@ import * as auth from './authutil'; import * as path from 'path'; import {restoreCache} from './cache-restore'; import {isGhes, isCacheFeatureAvailable} from './cache-utils'; -import os = require('os'); +import os from 'os'; export async function run() { try { @@ -14,7 +14,7 @@ export async function run() { // Version is optional. If supplied, install / use from the tool cache // If not supplied then task is still used to setup proxy, auth, etc... // - let version = resolveVersionInput(); + const version = resolveVersionInput(); let arch = core.getInput('architecture'); const cache = core.getInput('cache'); @@ -32,9 +32,10 @@ export async function run() { } if (version) { - let token = core.getInput('token'); - let auth = !token ? undefined : `token ${token}`; - let stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; + const token = core.getInput('token'); + const auth = !token ? undefined : `token ${token}`; + const stable = + (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; await installer.getNode(version, stable, checkLatest, auth, arch);