mirror of
				https://kkgithub.com/actions/setup-node.git
				synced 2025-10-31 18:51:54 +08:00 
			
		
		
		
	Compare commits
	
		
			32 Commits
		
	
	
		
			kotewar/up
			...
			v3.6.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 64ed1c7eab | |||
| 92a57f4a93 | |||
| 99e61d697a | |||
| 3e8819f8f2 | |||
| 8cd2fb28b8 | |||
| c406543918 | |||
| 92a07fe466 | |||
| 217387cf3e | |||
| 2db3663870 | |||
| bbe2ac79a1 | |||
| f5ab623822 | |||
| ca97bf7f80 | |||
| fe4d514f1a | |||
| 8151ea11a4 | |||
| 772ffdda26 | |||
| da188081b1 | |||
| 377c6dae40 | |||
| b28830cbe2 | |||
| 676975d9aa | |||
| d1b197b965 | |||
| 069a4f8926 | |||
| e77eaaccd3 | |||
| a69d45adcd | |||
| 3ae886ede4 | |||
| 41acaa2e85 | |||
| 2349c84f5c | |||
| 6bc15ab23c | |||
| 9b8fcdc725 | |||
| 00e1b6691b | |||
| 16352bb09b | |||
| 788c6ccbd0 | |||
| 8c91899e58 | 
							
								
								
									
										17
									
								
								.github/workflows/basic-validation.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.github/workflows/basic-validation.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| name: Basic validation | ||||
|  | ||||
| on: | ||||
|   pull_request: | ||||
|     paths-ignore: | ||||
|       - '**.md' | ||||
|   push: | ||||
|     branches: | ||||
|       - main | ||||
|       - releases/* | ||||
|     paths-ignore: | ||||
|       - '**.md' | ||||
|  | ||||
| jobs: | ||||
|   call-basic-validation: | ||||
|     name: Basic validation | ||||
|     uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main | ||||
							
								
								
									
										30
									
								
								.github/workflows/build-test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								.github/workflows/build-test.yml
									
									
									
									
										vendored
									
									
								
							| @ -1,30 +0,0 @@ | ||||
| name: build-test | ||||
|  | ||||
| on: | ||||
|   pull_request: | ||||
|     paths-ignore: | ||||
|       - '**.md' | ||||
|   push: | ||||
|     branches: | ||||
|       - main | ||||
|       - releases/* | ||||
|     paths-ignore: | ||||
|       - '**.md' | ||||
|  | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       matrix: | ||||
|         os: [ubuntu-latest, windows-latest, macos-latest] | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - name: Setup Node 16.x | ||||
|         uses: actions/setup-node@v3 | ||||
|         with: | ||||
|           node-version: 16.x | ||||
|           cache: npm | ||||
|       - run: npm ci | ||||
|       - run: npm run build | ||||
|       - run: npm run format-check | ||||
|       - run: npm test | ||||
							
								
								
									
										41
									
								
								.github/workflows/check-dist.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								.github/workflows/check-dist.yml
									
									
									
									
										vendored
									
									
								
							| @ -1,8 +1,3 @@ | ||||
| # `dist/index.js` is a special file in Actions. | ||||
| # When you reference an action with `uses:` in a workflow, | ||||
| # `index.js` is the code that will run. | ||||
| # For our project, we generate this file through a build process from other source files. | ||||
| # We need to make sure the checked-in `index.js` actually matches what we expect it to be. | ||||
| name: Check dist/ | ||||
|  | ||||
| on: | ||||
| @ -17,36 +12,6 @@ on: | ||||
|   workflow_dispatch: | ||||
|  | ||||
| jobs: | ||||
|   check-dist: | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|  | ||||
|       - name: Setup Node 16.x | ||||
|         uses: actions/setup-node@v3 | ||||
|         with: | ||||
|           node-version: 16.x | ||||
|           cache: npm | ||||
|  | ||||
|       - name: Install dependencies | ||||
|         run: npm ci | ||||
|  | ||||
|       - name: Rebuild the dist/ directory | ||||
|         run: npm run build | ||||
|  | ||||
|       - name: Compare the expected and actual dist/ directories | ||||
|         run: | | ||||
|           if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then | ||||
|             echo "Detected uncommitted changes after build.  See status below:" | ||||
|             git diff | ||||
|             exit 1 | ||||
|           fi | ||||
|         id: diff | ||||
|  | ||||
|       # If index.js was different than expected, upload the expected version as an artifact | ||||
|       - uses: actions/upload-artifact@v3 | ||||
|         if: ${{ failure() && steps.diff.conclusion == 'failure' }} | ||||
|         with: | ||||
|           name: dist | ||||
|           path: dist/ | ||||
|   call-check-dist: | ||||
|     name: Check dist/ | ||||
|     uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main | ||||
							
								
								
									
										14
									
								
								.github/workflows/codeql-analysis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.github/workflows/codeql-analysis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| name: CodeQL analysis | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: [ main ] | ||||
|   pull_request: | ||||
|     branches: [ main ] | ||||
|   schedule: | ||||
|     - cron: '0 3 * * 0' | ||||
|  | ||||
| jobs: | ||||
|   call-codeQL-analysis: | ||||
|     name: CodeQL analysis  | ||||
|     uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main | ||||
							
								
								
									
										2
									
								
								.github/workflows/e2e-cache.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/e2e-cache.yml
									
									
									
									
										vendored
									
									
								
							| @ -75,7 +75,7 @@ jobs: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: [ubuntu-latest, windows-latest, macos-latest] | ||||
|         node-version: [12, 14, 16] | ||||
|         node-version: [14, 16] | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - name: Yarn version | ||||
|  | ||||
							
								
								
									
										17
									
								
								.github/workflows/licensed.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								.github/workflows/licensed.yml
									
									
									
									
										vendored
									
									
								
							| @ -7,18 +7,9 @@ on: | ||||
|   pull_request: | ||||
|     branches: | ||||
|       - main | ||||
|   workflow_dispatch: | ||||
|  | ||||
| jobs: | ||||
|   test: | ||||
|     runs-on: ubuntu-latest | ||||
|     name: Check licenses | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - run: npm ci | ||||
|       - name: Install licensed | ||||
|         run: | | ||||
|           cd $RUNNER_TEMP | ||||
|           curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.4.4/licensed-3.4.4-linux-x64.tar.gz | ||||
|           sudo tar -xzf licensed.tar.gz | ||||
|           sudo mv licensed /usr/local/bin/licensed | ||||
|       - run: licensed status | ||||
|   call-licensed: | ||||
|     name: Licensed | ||||
|     uses: actions/reusable-workflows/.github/workflows/licensed.yml@main | ||||
|  | ||||
							
								
								
									
										2
									
								
								.github/workflows/proxy.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/proxy.yml
									
									
									
									
										vendored
									
									
								
							| @ -19,7 +19,7 @@ jobs: | ||||
|       options: --dns 127.0.0.1 | ||||
|     services: | ||||
|       squid-proxy: | ||||
|         image: datadog/squid:latest | ||||
|         image: ubuntu/squid:latest | ||||
|         ports: | ||||
|           - 3128:3128 | ||||
|     env: | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| name: Release new action version | ||||
|  | ||||
| on: | ||||
|   release: | ||||
|     types: [released] | ||||
| @ -21,7 +22,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|     - name: Update the ${{ env.TAG_NAME }} tag | ||||
|       uses: actions/publish-action@v0.1.0 | ||||
|       uses: actions/publish-action@v0.2.1 | ||||
|       with: | ||||
|         source-tag: ${{ env.TAG_NAME }} | ||||
|         slack-webhook: ${{ secrets.SLACK_WEBHOOK }} | ||||
|  | ||||
							
								
								
									
										64
									
								
								.github/workflows/versions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								.github/workflows/versions.yml
									
									
									
									
										vendored
									
									
								
							| @ -51,6 +51,66 @@ jobs: | ||||
|           __tests__/verify-node.sh "${BASH_REMATCH[1]}" | ||||
|         shell: bash | ||||
|  | ||||
|   v8-canary-syntax: | ||||
|     runs-on: ${{ matrix.os }} | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         os: [ubuntu-latest, windows-latest, macos-latest] | ||||
|         node-version: ['20-v8-canary', '20.0.0-v8-canary','20.0.0-v8-canary20221103f7e2421e91'] | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - name: Setup Node | ||||
|         uses: ./ | ||||
|         with: | ||||
|           node-version: ${{ matrix.node-version }} | ||||
|       - name: Verify node and npm | ||||
|         run: | | ||||
|           canaryVersion="${{ matrix.node-version }}" | ||||
|           majorVersion=$(echo $canaryVersion | cut -d- -f1) | ||||
|           __tests__/verify-node.sh "$majorVersion" | ||||
|         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: | ||||
| @ -178,7 +238,7 @@ jobs: | ||||
|       - name: Get node version | ||||
|         run: | | ||||
|           latestNodeVersion=$(curl https://nodejs.org/dist/index.json | jq -r '. [0].version') | ||||
|           echo "::set-output name=LATEST_NODE_VERSION::$latestNodeVersion" | ||||
|           echo "LATEST_NODE_VERSION=$latestNodeVersion" >> $GITHUB_OUTPUT | ||||
|         id: version | ||||
|         shell: bash | ||||
|       - uses: actions/checkout@v3 | ||||
| @ -189,7 +249,7 @@ jobs: | ||||
|       - name: Retrieve version after install | ||||
|         run: | | ||||
|           updatedVersion=$(echo $(node --version)) | ||||
|           echo "::set-output name=NODE_VERSION_UPDATED::$updatedVersion" | ||||
|           echo "NODE_VERSION_UPDATED=$updatedVersion" >> $GITHUB_OUTPUT | ||||
|         id: updatedVersion | ||||
|         shell: bash | ||||
|       - name: Compare versions | ||||
|  | ||||
							
								
								
									
										2
									
								
								.licenses/npm/@actions/core.dep.yml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.licenses/npm/@actions/core.dep.yml
									
									
									
										generated
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| --- | ||||
| name: "@actions/core" | ||||
| version: 1.9.1 | ||||
| version: 1.10.0 | ||||
| type: npm | ||||
| summary: Actions core lib | ||||
| homepage: https://github.com/actions/toolkit/tree/main/packages/core | ||||
|  | ||||
							
								
								
									
										2
									
								
								.licenses/npm/minimatch.dep.yml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.licenses/npm/minimatch.dep.yml
									
									
									
										generated
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| --- | ||||
| name: minimatch | ||||
| version: 3.0.4 | ||||
| version: 3.1.2 | ||||
| type: npm | ||||
| summary: a glob matcher in javascript | ||||
| homepage: https://github.com/isaacs/minimatch#readme | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| * @actions/actions-service | ||||
| * @actions/setup-actions-team | ||||
|  | ||||
							
								
								
									
										34
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								README.md
									
									
									
									
									
								
							| @ -111,16 +111,34 @@ jobs: | ||||
|       - run: npm test | ||||
| ``` | ||||
|  | ||||
| ## Using `setup-node` on GHES | ||||
|  | ||||
| `setup-node` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Nodejs distributions, `setup-node` downloads distributions from [`actions/node-versions`](https://github.com/actions/node-versions) on github.com (outside of the appliance). These calls to `actions/node-versions` are made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If more requests are made within the time frame, then you will start to see rate-limit errors during downloading that looks like: `##[error]API rate limit exceeded for...`. After that error the action will try to download versions directly from the official site, but it also can have rate limit so it's better to put token. | ||||
|  | ||||
| To get a higher rate limit, you can [generate a personal access token on github.com](https://github.com/settings/tokens/new) and pass it as the `token` input for the action: | ||||
|  | ||||
| ```yaml | ||||
| uses: actions/setup-node@v3 | ||||
| with: | ||||
|   token: ${{ secrets.GH_DOTCOM_TOKEN }} | ||||
|   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. | ||||
|  | ||||
| ## Advanced usage | ||||
|  | ||||
| 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) | ||||
|  - [Check latest version](docs/advanced-usage.md#check-latest-version) | ||||
|  - [Using a node version file](docs/advanced-usage.md#node-version-file) | ||||
|  - [Using different architectures](docs/advanced-usage.md#architecture) | ||||
|  - [Using v8 canary versions](docs/advanced-usage.md#v8-canary-versions) | ||||
|  - [Using nigthly versions](docs/advanced-usage.md#nightly-versions) | ||||
|  - [Using rc versions](docs/advanced-usage.md#rc-versions) | ||||
|  - [Caching packages data](docs/advanced-usage.md#caching-packages-data) | ||||
|  - [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures) | ||||
|  - [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) | ||||
|  - [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) | ||||
|  | ||||
| ## License | ||||
|  | ||||
|  | ||||
							
								
								
									
										10
									
								
								__tests__/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								__tests__/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
| @ -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'; | ||||
| @ -123,6 +123,7 @@ describe('authutil tests', () => { | ||||
|     expect(rc['registry']).toBe('https://registry.npmjs.org/'); | ||||
|     expect(rc['always-auth']).toBe('true'); | ||||
|   }); | ||||
|  | ||||
|   it('It is already set the NODE_AUTH_TOKEN export it ', async () => { | ||||
|     process.env.NODE_AUTH_TOKEN = 'foobar'; | ||||
|     await auth.configAuthentication('npm.pkg.github.com', 'false'); | ||||
| @ -132,4 +133,84 @@ describe('authutil tests', () => { | ||||
|     expect(rc['always-auth']).toBe('false'); | ||||
|     expect(process.env.NODE_AUTH_TOKEN).toEqual('foobar'); | ||||
|   }); | ||||
|  | ||||
|   it('configAuthentication should overwrite non-scoped with non-scoped', async () => { | ||||
|     fs.writeFileSync(rcFile, 'registry=NNN'); | ||||
|     await auth.configAuthentication('https://registry.npmjs.org/', 'true'); | ||||
|     let contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); | ||||
|     expect(contents).toBe( | ||||
|       `//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 () => { | ||||
|     fs.writeFileSync(rcFile, `registry=NNN${os.EOL}@myscope:registry=MMM`); | ||||
|     await auth.configAuthentication('https://registry.npmjs.org/', 'true'); | ||||
|     let contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); | ||||
|     expect(contents).toBe( | ||||
|       `@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 () => { | ||||
|     fs.writeFileSync(rcFile, '@myscope:registry=NNN'); | ||||
|     await auth.configAuthentication('https://registry.npmjs.org/', 'true'); | ||||
|     let contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); | ||||
|     expect(contents).toBe( | ||||
|       `@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 () => { | ||||
|     process.env['INPUT_SCOPE'] = 'myscope'; | ||||
|     fs.writeFileSync(rcFile, `@myscope:registry=NNN`); | ||||
|     await auth.configAuthentication('https://registry.npmjs.org/', 'true'); | ||||
|     let contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); | ||||
|     expect(contents).toBe( | ||||
|       `//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 () => { | ||||
|     process.env['INPUT_SCOPE'] = 'myscope'; | ||||
|     fs.writeFileSync(rcFile, `registry=NNN${os.EOL}@myscope:registry=MMM`); | ||||
|     await auth.configAuthentication('https://registry.npmjs.org/', 'true'); | ||||
|     let contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); | ||||
|     expect(contents).toBe( | ||||
|       `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 () => { | ||||
|     process.env['INPUT_SCOPE'] = 'myscope'; | ||||
|     fs.writeFileSync(rcFile, `registry=MMM`); | ||||
|     await auth.configAuthentication('https://registry.npmjs.org/', 'true'); | ||||
|     let contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); | ||||
|     expect(contents).toBe( | ||||
|       `registry=MMM${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 overwrite only one scoped', async () => { | ||||
|     process.env['INPUT_SCOPE'] = 'myscope'; | ||||
|     fs.writeFileSync( | ||||
|       rcFile, | ||||
|       `@otherscope:registry=NNN${os.EOL}@myscope:registry=MMM` | ||||
|     ); | ||||
|     await auth.configAuthentication('https://registry.npmjs.org/', 'true'); | ||||
|     let contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); | ||||
|     expect(contents).toBe( | ||||
|       `@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 () => { | ||||
|     process.env['INPUT_SCOPE'] = 'myscope'; | ||||
|     fs.writeFileSync(rcFile, `@otherscope:registry=MMM`); | ||||
|     await auth.configAuthentication('https://registry.npmjs.org/', 'true'); | ||||
|     let contents = fs.readFileSync(rcFile, {encoding: 'utf8'}); | ||||
|     expect(contents).toBe( | ||||
|       `@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` | ||||
|     ); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| @ -46,7 +46,8 @@ describe('cache-utils', () => { | ||||
|     isFeatureAvailable.mockImplementation(() => false); | ||||
|     process.env['GITHUB_SERVER_URL'] = 'https://www.test.com'; | ||||
|  | ||||
|     expect(() => isCacheFeatureAvailable()).toThrowError( | ||||
|     expect(isCacheFeatureAvailable()).toBeFalsy(); | ||||
|     expect(warningSpy).toHaveBeenCalledWith( | ||||
|       'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.' | ||||
|     ); | ||||
|   }); | ||||
|  | ||||
							
								
								
									
										531
									
								
								__tests__/canary-installer.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										531
									
								
								__tests__/canary-installer.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,531 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as io from '@actions/io'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as httpm from '@actions/http-client'; | ||||
| import * as exec from '@actions/exec'; | ||||
| import * as cache from '@actions/cache'; | ||||
| import fs from 'fs'; | ||||
| import cp from 'child_process'; | ||||
| import osm from 'os'; | ||||
| import path from 'path'; | ||||
| import * as main from '../src/main'; | ||||
| import * as auth from '../src/authutil'; | ||||
| import {INodeVersion} from '../src/distributions/base-models'; | ||||
|  | ||||
| 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'); | ||||
| const nodeV8CanaryTestDist = require('./data/v8-canary-dist-index.json'); | ||||
|  | ||||
| describe('setup-node', () => { | ||||
|   let inputs = {} as any; | ||||
|   let os = {} as any; | ||||
|  | ||||
|   let inSpy: jest.SpyInstance; | ||||
|   let findSpy: jest.SpyInstance; | ||||
|   let findAllVersionsSpy: jest.SpyInstance; | ||||
|   let cnSpy: jest.SpyInstance; | ||||
|   let logSpy: jest.SpyInstance; | ||||
|   let warningSpy: jest.SpyInstance; | ||||
|   let getManifestSpy: jest.SpyInstance; | ||||
|   let getDistSpy: jest.SpyInstance; | ||||
|   let platSpy: jest.SpyInstance; | ||||
|   let archSpy: jest.SpyInstance; | ||||
|   let dlSpy: jest.SpyInstance; | ||||
|   let exSpy: jest.SpyInstance; | ||||
|   let cacheSpy: jest.SpyInstance; | ||||
|   let dbgSpy: jest.SpyInstance; | ||||
|   let whichSpy: jest.SpyInstance; | ||||
|   let existsSpy: jest.SpyInstance; | ||||
|   let readFileSyncSpy: jest.SpyInstance; | ||||
|   let mkdirpSpy: jest.SpyInstance; | ||||
|   let execSpy: jest.SpyInstance; | ||||
|   let authSpy: jest.SpyInstance; | ||||
|   let parseNodeVersionSpy: jest.SpyInstance; | ||||
|   let isCacheActionAvailable: jest.SpyInstance; | ||||
|   let getExecOutputSpy: jest.SpyInstance; | ||||
|   let getJsonSpy: jest.SpyInstance; | ||||
|  | ||||
|   beforeEach(() => { | ||||
|     // @actions/core | ||||
|     console.log('::stop-commands::stoptoken'); // Disable executing of runner commands when running tests in actions | ||||
|     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 | ||||
|     inputs = {}; | ||||
|     inSpy = jest.spyOn(core, 'getInput'); | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|     // node | ||||
|     os = {}; | ||||
|     platSpy = jest.spyOn(osm, 'platform'); | ||||
|     platSpy.mockImplementation(() => os['platform']); | ||||
|     archSpy = jest.spyOn(osm, 'arch'); | ||||
|     archSpy.mockImplementation(() => os['arch']); | ||||
|     execSpy = jest.spyOn(cp, 'execSync'); | ||||
|  | ||||
|     // @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'); | ||||
|     getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo'); | ||||
|  | ||||
|     // http-client | ||||
|     getJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); | ||||
|  | ||||
|     // io | ||||
|     whichSpy = jest.spyOn(io, 'which'); | ||||
|     existsSpy = jest.spyOn(fs, 'existsSync'); | ||||
|     mkdirpSpy = jest.spyOn(io, 'mkdirP'); | ||||
|  | ||||
|     // @actions/tool-cache | ||||
|     isCacheActionAvailable = jest.spyOn(cache, 'isFeatureAvailable'); | ||||
|  | ||||
|     // disable authentication portion for installer tests | ||||
|     authSpy = jest.spyOn(auth, 'configAuthentication'); | ||||
|     authSpy.mockImplementation(() => {}); | ||||
|  | ||||
|     // gets | ||||
|     getManifestSpy.mockImplementation( | ||||
|       () => <tc.IToolRelease[]>nodeTestManifest | ||||
|     ); | ||||
|  | ||||
|     getJsonSpy.mockImplementation(url => { | ||||
|       let res: any; | ||||
|       if (url.includes('/rc')) { | ||||
|         res = <INodeVersion>nodeTestDistRc; | ||||
|       } else if (url.includes('/nightly')) { | ||||
|         res = <INodeVersion>nodeTestDistNightly; | ||||
|       } else if (url.includes('/v8-canary')) { | ||||
|         res = <INodeVersion>nodeV8CanaryTestDist; | ||||
|       } else { | ||||
|         res = <INodeVersion>nodeTestDist; | ||||
|       } | ||||
|  | ||||
|       return {result: res}; | ||||
|     }); | ||||
|  | ||||
|     // writes | ||||
|     cnSpy = jest.spyOn(process.stdout, 'write'); | ||||
|     logSpy = jest.spyOn(core, 'info'); | ||||
|     dbgSpy = jest.spyOn(core, 'debug'); | ||||
|     warningSpy = jest.spyOn(core, 'warning'); | ||||
|     cnSpy.mockImplementation(line => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('write:' + line + '\n'); | ||||
|     }); | ||||
|     logSpy.mockImplementation(line => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('log:' + line + '\n'); | ||||
|     }); | ||||
|     dbgSpy.mockImplementation(msg => { | ||||
|       // uncomment to see debug output | ||||
|       // process.stderr.write(msg + '\n'); | ||||
|     }); | ||||
|     warningSpy.mockImplementation(msg => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('log:' + msg + '\n'); | ||||
|     }); | ||||
|  | ||||
|     // @actions/exec | ||||
|     getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); | ||||
|     getExecOutputSpy.mockImplementation(() => 'v16.15.0'); | ||||
|   }); | ||||
|  | ||||
|   afterEach(() => { | ||||
|     jest.resetAllMocks(); | ||||
|     jest.clearAllMocks(); | ||||
|     //jest.restoreAllMocks(); | ||||
|   }); | ||||
|  | ||||
|   afterAll(async () => { | ||||
|     console.log('::stoptoken::'); // Re-enable executing of runner commands when running tests in actions | ||||
|     jest.restoreAllMocks(); | ||||
|   }, 100000); | ||||
|  | ||||
|   //-------------------------------------------------- | ||||
|   // Found in cache tests | ||||
|   //-------------------------------------------------- | ||||
|  | ||||
|   it('finds version in cache with stable true', async () => { | ||||
|     inputs['node-version'] = '20-v8-canary'; | ||||
|     os['arch'] = 'x64'; | ||||
|     inputs.stable = 'true'; | ||||
|  | ||||
|     let toolPath = path.normalize( | ||||
|       '/cache/node/20.0.0-v8-canary20221103f7e2421e91/x64' | ||||
|     ); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '20.0.0-v8-canary20221103f7e2421e91', | ||||
|       '20.0.0-v8-canary20221030fefe1c0879', | ||||
|       '19.0.0-v8-canary202210172ec229fc56', | ||||
|       '20.0.0-v8-canary2022102310ff1e5a8d' | ||||
|     ]); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(findSpy).toHaveBeenCalledWith( | ||||
|       'node', | ||||
|       '20.0.0-v8-canary20221103f7e2421e91', | ||||
|       'x64' | ||||
|     ); | ||||
|     expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|   }); | ||||
|  | ||||
|   it('finds version in cache and adds it to the path', async () => { | ||||
|     inputs['node-version'] = '20-v8-canary'; | ||||
|     os['arch'] = 'x64'; | ||||
|  | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|     let toolPath = path.normalize( | ||||
|       '/cache/node/20.0.0-v8-canary20221103f7e2421e91/x64' | ||||
|     ); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '20.0.0-v8-canary20221103f7e2421e91', | ||||
|       '20.0.0-v8-canary20221030fefe1c0879', | ||||
|       '19.0.0-v8-canary202210172ec229fc56', | ||||
|       '20.0.0-v8-canary2022102310ff1e5a8d' | ||||
|     ]); | ||||
|     await main.run(); | ||||
|  | ||||
|     let expPath = path.join(toolPath, 'bin'); | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('handles unhandled find error and reports error', async () => { | ||||
|     os.platform = 'linux'; | ||||
|     let errMsg = 'unhandled error message'; | ||||
|     inputs['node-version'] = '20.0.0-v8-canary20221103f7e2421e91'; | ||||
|  | ||||
|     findSpy.mockImplementation(() => { | ||||
|       throw new Error(errMsg); | ||||
|     }); | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '20.0.0-v8-canary20221103f7e2421e91', | ||||
|       '20.0.0-v8-canary20221030fefe1c0879', | ||||
|       '19.0.0-v8-canary202210172ec229fc56', | ||||
|       '20.0.0-v8-canary2022102310ff1e5a8d' | ||||
|     ]); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith('::error::' + errMsg + osm.EOL); | ||||
|   }); | ||||
|  | ||||
|   //-------------------------------------------------- | ||||
|   // Manifest tests | ||||
|   //-------------------------------------------------- | ||||
|   it('falls back to a version from node dist', async () => { | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     // a version which is not in the manifest but is in node dist | ||||
|     let versionSpec = '11.15.0'; | ||||
|  | ||||
|     inputs['node-version'] = versionSpec; | ||||
|     inputs['always-auth'] = false; | ||||
|     inputs['token'] = 'faketoken'; | ||||
|  | ||||
|     // ... but not in the local cache | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|  | ||||
|     dlSpy.mockImplementation(async () => '/some/temp/path'); | ||||
|     let toolPath = path.normalize('/cache/node/11.11.0/x64'); | ||||
|     exSpy.mockImplementation(async () => '/some/other/temp/path'); | ||||
|     cacheSpy.mockImplementation(async () => toolPath); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     let expPath = path.join(toolPath, 'bin'); | ||||
|  | ||||
|     expect(dlSpy).toHaveBeenCalled(); | ||||
|     expect(exSpy).toHaveBeenCalled(); | ||||
|     expect(logSpy).toHaveBeenCalledWith( | ||||
|       'Not found in manifest. Falling back to download directly from Node' | ||||
|     ); | ||||
|     expect(logSpy).toHaveBeenCalledWith( | ||||
|       `Attempting to download ${versionSpec}...` | ||||
|     ); | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('does not find a version that does not exist', async () => { | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     let versionSpec = '23.0.0-v8-canary20221103f7e2421e91'; | ||||
|     inputs['node-version'] = versionSpec; | ||||
|  | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '20.0.0-v8-canary20221103f7e2421e91', | ||||
|       '20.0.0-v8-canary20221030fefe1c0879', | ||||
|       '19.0.0-v8-canary202210172ec229fc56', | ||||
|       '20.0.0-v8-canary2022102310ff1e5a8d' | ||||
|     ]); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith( | ||||
|       `::error::Unable to find Node version '${versionSpec}' for platform ${os.platform} and architecture ${os.arch}.${osm.EOL}` | ||||
|     ); | ||||
|   }); | ||||
|  | ||||
|   it('reports a failed download', async () => { | ||||
|     let errMsg = 'unhandled download message'; | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     // a version which is in the manifest | ||||
|     let versionSpec = '19.0.0-v8-canary'; | ||||
|  | ||||
|     inputs['node-version'] = versionSpec; | ||||
|     inputs['always-auth'] = false; | ||||
|     inputs['token'] = 'faketoken'; | ||||
|  | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '20.0.0-v8-canary20221103f7e2421e91', | ||||
|       '20.0.0-v8-canary20221030fefe1c0879', | ||||
|       '20.0.0-v8-canary2022102310ff1e5a8d' | ||||
|     ]); | ||||
|     dlSpy.mockImplementation(() => { | ||||
|       throw new Error(errMsg); | ||||
|     }); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('acquires specified architecture of node', async () => { | ||||
|     for (const {arch, version, osSpec} of [ | ||||
|       { | ||||
|         arch: 'x86', | ||||
|         version: '20.0.0-v8-canary20221022e83bcb6c41', | ||||
|         osSpec: 'win32' | ||||
|       }, | ||||
|       { | ||||
|         arch: 'x86', | ||||
|         version: '20.0.0-v8-canary20221103f7e2421e91', | ||||
|         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['always-auth'] = false; | ||||
|       inputs['token'] = 'faketoken'; | ||||
|  | ||||
|       let expectedUrl = `https://nodejs.org/download/v8-canary/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`; | ||||
|  | ||||
|       // ... but not in the local cache | ||||
|       findSpy.mockImplementation(() => ''); | ||||
|       findAllVersionsSpy.mockImplementation(() => []); | ||||
|  | ||||
|       dlSpy.mockImplementation(async () => '/some/temp/path'); | ||||
|       let 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', () => { | ||||
|     it.each([ | ||||
|       [ | ||||
|         '20.0.0-v8-canary', | ||||
|         '20.0.0-v8-canary20221103f7e2421e91', | ||||
|         'https://nodejs.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', | ||||
|         'https://nodejs.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', | ||||
|         'https://nodejs.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', | ||||
|         'https://nodejs.org/download/v8-canary/v19.0.0-v8-canary202210187d6960f23f/node-v19.0.0-v8-canary202210187d6960f23f-linux-x64.tar.gz' | ||||
|       ], | ||||
|       [ | ||||
|         '19.0.0-v8-canary202210187d6960f23f', | ||||
|         '19.0.0-v8-canary202210187d6960f23f', | ||||
|         'https://nodejs.org/download/v8-canary/v19.0.0-v8-canary202210187d6960f23f/node-v19.0.0-v8-canary202210187d6960f23f-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( | ||||
|           `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([ | ||||
|       [ | ||||
|         '20.0.0-v8-canary20221103f7e2421e91', | ||||
|         '20.0.0-v8-canary20221103f7e2421e91' | ||||
|       ], | ||||
|       ['20.0.0-v8-canary', '20.0.0-v8-canary20221103f7e2421e91'], | ||||
|       ['20-v8-canary', '20.0.0-v8-canary20221103f7e2421e91'] | ||||
|     ])( | ||||
|       'finds the %s version in the hostedToolcache', | ||||
|       async (input, expectedVersion) => { | ||||
|         const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); | ||||
|         findSpy.mockReturnValue(toolPath); | ||||
|         findAllVersionsSpy.mockReturnValue([ | ||||
|           '20.0.0-v8-canary20221103f7e2421e91', | ||||
|           '20.0.0-v8-canary20221030fefe1c0879', | ||||
|           '19.0.0-v8-canary202210172ec229fc56', | ||||
|           '20.0.0-v8-canary2022102310ff1e5a8d' | ||||
|         ]); | ||||
|  | ||||
|         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([ | ||||
|       [ | ||||
|         '20.0.0-v8-canary', | ||||
|         '20.0.0-v8-canary20221103f7e2421e91', | ||||
|         '20.0.0-v8-canary20221030fefe1c0879', | ||||
|         'https://nodejs.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://nodejs.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://nodejs.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://nodejs.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'; | ||||
|  | ||||
|         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', () => { | ||||
|     it('v8 canary setup node flow with cached', async () => { | ||||
|       let versionSpec = 'v20-v8-canary'; | ||||
|  | ||||
|       inputs['node-version'] = versionSpec; | ||||
|       inputs['always-auth'] = false; | ||||
|       inputs['token'] = 'faketoken'; | ||||
|  | ||||
|       os.platform = 'linux'; | ||||
|       os.arch = 'x64'; | ||||
|  | ||||
|       const versionExpected = 'v20.0.0-v8-canary20221103f7e2421e91'; | ||||
|       findAllVersionsSpy.mockImplementation(() => [versionExpected]); | ||||
|  | ||||
|       const toolPath = path.normalize(`/cache/node/${versionExpected}/x64`); | ||||
|       findSpy.mockImplementation(version => toolPath); | ||||
|  | ||||
|       await main.run(); | ||||
|  | ||||
|       expect(cnSpy).toHaveBeenCalledWith( | ||||
|         `::add-path::${toolPath}${path.sep}bin${osm.EOL}` | ||||
|       ); | ||||
|  | ||||
|       expect(dlSpy).not.toHaveBeenCalled(); | ||||
|       expect(exSpy).not.toHaveBeenCalled(); | ||||
|       expect(cacheSpy).not.toHaveBeenCalled(); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										35
									
								
								__tests__/data/node-nightly-index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								__tests__/data/node-nightly-index.json
									
									
									
									
									
										Normal file
									
								
							| @ -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} | ||||
|  | ||||
|     ] | ||||
							
								
								
									
										28
									
								
								__tests__/data/node-rc-index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								__tests__/data/node-rc-index.json
									
									
									
									
									
										Normal file
									
								
							| @ -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} | ||||
|     ] | ||||
							
								
								
									
										537
									
								
								__tests__/data/v8-canary-dist-index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										537
									
								
								__tests__/data/v8-canary-dist-index.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,537 @@ | ||||
| [ | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221103f7e2421e91", | ||||
|     "date": "2022-11-03", | ||||
|     "files": [ | ||||
|       "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.9.138.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary202211026bf85d0fb4", | ||||
|     "date": "2022-11-02", | ||||
|     "files": [ | ||||
|       "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.9.130.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221101e50e45c9f8", | ||||
|     "date": "2022-11-01", | ||||
|     "files": [ | ||||
|       "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", | ||||
|       "win-x86-7z", | ||||
|       "win-x86-exe", | ||||
|       "win-x86-msi", | ||||
|       "win-x86-zip" | ||||
|     ], | ||||
|     "npm": "8.19.2", | ||||
|     "v8": "10.9.129.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary202210311b1e675ad0", | ||||
|     "date": "2022-10-31", | ||||
|     "files": [ | ||||
|       "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", | ||||
|       "win-x86-7z", | ||||
|       "win-x86-exe", | ||||
|       "win-x86-msi", | ||||
|       "win-x86-zip" | ||||
|     ], | ||||
|     "npm": "8.19.2", | ||||
|     "v8": "10.9.125.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221030fefe1c0879", | ||||
|     "date": "2022-10-30", | ||||
|     "files": [ | ||||
|       "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.9.125.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary202210293881e51ba2", | ||||
|     "date": "2022-10-29", | ||||
|     "files": [ | ||||
|       "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.9.122.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary202210286fe49d2a49", | ||||
|     "date": "2022-10-28", | ||||
|     "files": [ | ||||
|       "osx-arm64-tar", | ||||
|       "osx-x64-pkg", | ||||
|       "osx-x64-tar", | ||||
|       "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.9.112.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221027c470b3108c", | ||||
|     "date": "2022-10-27", | ||||
|     "files": [ | ||||
|       "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.9.101.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221026c24f7d1e4a", | ||||
|     "date": "2022-10-26", | ||||
|     "files": [ | ||||
|       "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.9.88.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221025b063237e20", | ||||
|     "date": "2022-10-25", | ||||
|     "files": [ | ||||
|       "headers", | ||||
|       "linux-arm64", | ||||
|       "linux-armv7l", | ||||
|       "linux-ppc64le", | ||||
|       "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.9.73.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary2022102454996f930f", | ||||
|     "date": "2022-10-24", | ||||
|     "files": [ | ||||
|       "headers", | ||||
|       "linux-arm64", | ||||
|       "linux-armv7l", | ||||
|       "linux-ppc64le", | ||||
|       "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.9.61.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary2022102310ff1e5a8d", | ||||
|     "date": "2022-10-23", | ||||
|     "files": [ | ||||
|       "headers", | ||||
|       "linux-arm64", | ||||
|       "linux-armv7l", | ||||
|       "linux-ppc64le", | ||||
|       "linux-x64", | ||||
|       "osx-arm64-tar", | ||||
|       "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.9.61.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221022e83bcb6c41", | ||||
|     "date": "2022-10-22", | ||||
|     "files": [ | ||||
|       "headers", | ||||
|       "linux-arm64", | ||||
|       "linux-armv7l", | ||||
|       "linux-x64", | ||||
|       "osx-arm64-tar", | ||||
|       "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.9.60.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221021f6d5f347fa", | ||||
|     "date": "2022-10-21", | ||||
|     "files": [ | ||||
|       "headers", | ||||
|       "linux-arm64", | ||||
|       "linux-armv7l", | ||||
|       "linux-x64", | ||||
|       "osx-arm64-tar", | ||||
|       "osx-x64-tar", | ||||
|       "src", | ||||
|       "win-x64-7z", | ||||
|       "win-x64-exe", | ||||
|       "win-x64-msi", | ||||
|       "win-x64-zip" | ||||
|     ], | ||||
|     "npm": "8.19.2", | ||||
|     "v8": "10.9.48.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221020f78c149307", | ||||
|     "date": "2022-10-20", | ||||
|     "files": [ | ||||
|       "headers", | ||||
|       "linux-arm64", | ||||
|       "linux-armv7l", | ||||
|       "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.19.2", | ||||
|     "v8": "10.9.38.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v20.0.0-v8-canary20221019d52c76f76e", | ||||
|     "date": "2022-10-19", | ||||
|     "files": [ | ||||
|       "aix-ppc64", | ||||
|       "headers", | ||||
|       "linux-arm64", | ||||
|       "linux-armv7l", | ||||
|       "linux-ppc64le", | ||||
|       "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.19.2", | ||||
|     "v8": "10.9.27.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v19.0.0-v8-canary202210187d6960f23f", | ||||
|     "date": "2022-10-18", | ||||
|     "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.19.2", | ||||
|     "v8": "10.9.12.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   }, | ||||
|   { | ||||
|     "version": "v19.0.0-v8-canary202210172ec229fc56", | ||||
|     "date": "2022-10-17", | ||||
|     "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.19.2", | ||||
|     "v8": "10.9.6.0", | ||||
|     "uv": "1.43.0", | ||||
|     "zlib": "1.2.11", | ||||
|     "openssl": "3.0.5+quic", | ||||
|     "modules": "112", | ||||
|     "lts": false, | ||||
|     "security": false | ||||
|   } | ||||
| ] | ||||
							
								
								
									
										303
									
								
								__tests__/main.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								__tests__/main.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,303 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as exec from '@actions/exec'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as cache from '@actions/cache'; | ||||
|  | ||||
| import fs from 'fs'; | ||||
| import path from 'path'; | ||||
| import osm from 'os'; | ||||
|  | ||||
| import each from 'jest-each'; | ||||
|  | ||||
| import * as main from '../src/main'; | ||||
| import * as util from '../src/util'; | ||||
| import OfficialBuilds from '../src/distributions/official_builds/official_builds'; | ||||
|  | ||||
| describe('main tests', () => { | ||||
|   let inputs = {} as any; | ||||
|   let os = {} as any; | ||||
|  | ||||
|   let infoSpy: jest.SpyInstance; | ||||
|   let warningSpy: jest.SpyInstance; | ||||
|   let inSpy: jest.SpyInstance; | ||||
|   let setOutputSpy: jest.SpyInstance; | ||||
|   let startGroupSpy: jest.SpyInstance; | ||||
|   let endGroupSpy: jest.SpyInstance; | ||||
|  | ||||
|   let existsSpy: jest.SpyInstance; | ||||
|  | ||||
|   let getExecOutputSpy: jest.SpyInstance; | ||||
|  | ||||
|   let parseNodeVersionSpy: jest.SpyInstance; | ||||
|   let cnSpy: jest.SpyInstance; | ||||
|   let findSpy: jest.SpyInstance; | ||||
|   let isCacheActionAvailable: jest.SpyInstance; | ||||
|  | ||||
|   let setupNodeJsSpy: jest.SpyInstance; | ||||
|  | ||||
|   beforeEach(() => { | ||||
|     inputs = {}; | ||||
|  | ||||
|     // node | ||||
|     os = {}; | ||||
|     console.log('::stop-commands::stoptoken'); | ||||
|     process.env['GITHUB_PATH'] = ''; // Stub out ENV file functionality so we can verify it writes to standard out | ||||
|     process.env['GITHUB_OUTPUT'] = ''; // Stub out ENV file functionality so we can verify it writes to standard out | ||||
|     infoSpy = jest.spyOn(core, 'info'); | ||||
|     infoSpy.mockImplementation(() => {}); | ||||
|     setOutputSpy = jest.spyOn(core, 'setOutput'); | ||||
|     setOutputSpy.mockImplementation(() => {}); | ||||
|     warningSpy = jest.spyOn(core, 'warning'); | ||||
|     warningSpy.mockImplementation(() => {}); | ||||
|     startGroupSpy = jest.spyOn(core, 'startGroup'); | ||||
|     startGroupSpy.mockImplementation(() => {}); | ||||
|     endGroupSpy = jest.spyOn(core, 'endGroup'); | ||||
|     endGroupSpy.mockImplementation(() => {}); | ||||
|     inSpy = jest.spyOn(core, 'getInput'); | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|     getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); | ||||
|  | ||||
|     findSpy = jest.spyOn(tc, 'find'); | ||||
|  | ||||
|     isCacheActionAvailable = jest.spyOn(cache, 'isFeatureAvailable'); | ||||
|  | ||||
|     existsSpy = jest.spyOn(fs, 'existsSync'); | ||||
|  | ||||
|     cnSpy = jest.spyOn(process.stdout, 'write'); | ||||
|     cnSpy.mockImplementation(line => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('write:' + line + '\n'); | ||||
|     }); | ||||
|  | ||||
|     setupNodeJsSpy = jest.spyOn(OfficialBuilds.prototype, 'setupNodeJs'); | ||||
|     setupNodeJsSpy.mockImplementation(() => {}); | ||||
|   }); | ||||
|  | ||||
|   afterEach(() => { | ||||
|     jest.resetAllMocks(); | ||||
|     jest.clearAllMocks(); | ||||
|     //jest.restoreAllMocks(); | ||||
|   }); | ||||
|  | ||||
|   afterAll(async () => { | ||||
|     console.log('::stoptoken::'); | ||||
|     jest.restoreAllMocks(); | ||||
|   }, 100000); | ||||
|  | ||||
|   describe('parseNodeVersionFile', () => { | ||||
|     each` | ||||
|       contents                                     | expected | ||||
|       ${'12'}                                      | ${'12'} | ||||
|       ${'12.3'}                                    | ${'12.3'} | ||||
|       ${'12.3.4'}                                  | ${'12.3.4'} | ||||
|       ${'v12.3.4'}                                 | ${'12.3.4'} | ||||
|       ${'lts/erbium'}                              | ${'lts/erbium'} | ||||
|       ${'lts/*'}                                   | ${'lts/*'} | ||||
|       ${'nodejs 12.3.4'}                           | ${'12.3.4'} | ||||
|       ${'ruby 2.3.4\nnodejs 12.3.4\npython 3.4.5'} | ${'12.3.4'} | ||||
|       ${''}                                        | ${''} | ||||
|       ${'unknown format'}                          | ${'unknown format'} | ||||
|       ${'  14.1.0  '}                              | ${'14.1.0'} | ||||
|       ${'{"volta": {"node": ">=14.0.0 <=17.0.0"}}'}| ${'>=14.0.0 <=17.0.0'} | ||||
|       ${'{"engines": {"node": "17.0.0"}}'}         | ${'17.0.0'} | ||||
|     `.it('parses "$contents"', ({contents, expected}) => { | ||||
|       expect(util.parseNodeVersionFile(contents)).toBe(expected); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   describe('printEnvDetailsAndSetOutput', () => { | ||||
|     it.each([ | ||||
|       [{node: '12.0.2', npm: '6.3.3', yarn: '1.22.11'}], | ||||
|       [{node: '16.0.2', npm: '7.3.3', yarn: '2.22.11'}], | ||||
|       [{node: '14.0.1', npm: '8.1.0', yarn: '3.2.1'}], | ||||
|       [{node: '17.0.2', npm: '6.3.3', yarn: ''}] | ||||
|     ])('Tools versions %p', async obj => { | ||||
|       getExecOutputSpy.mockImplementation(async command => { | ||||
|         if (Reflect.has(obj, command) && !obj[command]) { | ||||
|           return { | ||||
|             stdout: '', | ||||
|             stderr: `${command} does not exist`, | ||||
|             exitCode: 1 | ||||
|           }; | ||||
|         } | ||||
|  | ||||
|         return {stdout: obj[command], stderr: '', exitCode: 0}; | ||||
|       }); | ||||
|  | ||||
|       await util.printEnvDetailsAndSetOutput(); | ||||
|  | ||||
|       expect(setOutputSpy).toHaveBeenCalledWith('node-version', obj['node']); | ||||
|       Object.getOwnPropertyNames(obj).forEach(name => { | ||||
|         if (!obj[name]) { | ||||
|           expect(infoSpy).toHaveBeenCalledWith( | ||||
|             `[warning]${name} does not exist` | ||||
|           ); | ||||
|         } | ||||
|         expect(infoSpy).toHaveBeenCalledWith(`${name}: ${obj[name]}`); | ||||
|       }); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   describe('node-version-file flag', () => { | ||||
|     beforeEach(() => { | ||||
|       parseNodeVersionSpy = jest.spyOn(util, 'parseNodeVersionFile'); | ||||
|     }); | ||||
|  | ||||
|     it('not used if node-version is provided', async () => { | ||||
|       // Arrange | ||||
|       inputs['node-version'] = '12'; | ||||
|  | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); | ||||
|     }, 10000); | ||||
|  | ||||
|     it('not used if node-version-file not provided', async () => { | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); | ||||
|     }); | ||||
|  | ||||
|     it('reads node-version-file if provided', async () => { | ||||
|       // Arrange | ||||
|       const versionSpec = 'v14'; | ||||
|       const versionFile = '.nvmrc'; | ||||
|       const expectedVersionSpec = '14'; | ||||
|       process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data'); | ||||
|       inputs['node-version-file'] = versionFile; | ||||
|  | ||||
|       parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); | ||||
|       existsSpy.mockImplementationOnce( | ||||
|         input => input === path.join(__dirname, 'data', versionFile) | ||||
|       ); | ||||
|  | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(existsSpy).toHaveBeenCalledTimes(1); | ||||
|       expect(existsSpy).toHaveReturnedWith(true); | ||||
|       expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec); | ||||
|       expect(infoSpy).toHaveBeenCalledWith( | ||||
|         `Resolved ${versionFile} as ${expectedVersionSpec}` | ||||
|       ); | ||||
|     }, 10000); | ||||
|  | ||||
|     it('reads package.json as node-version-file if provided', async () => { | ||||
|       // Arrange | ||||
|       const versionSpec = fs.readFileSync( | ||||
|         path.join(__dirname, 'data/package.json'), | ||||
|         'utf-8' | ||||
|       ); | ||||
|       const versionFile = 'package.json'; | ||||
|       const expectedVersionSpec = '14'; | ||||
|       process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data'); | ||||
|       inputs['node-version-file'] = versionFile; | ||||
|  | ||||
|       parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); | ||||
|       existsSpy.mockImplementationOnce( | ||||
|         input => input === path.join(__dirname, 'data', versionFile) | ||||
|       ); | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(existsSpy).toHaveBeenCalledTimes(1); | ||||
|       expect(existsSpy).toHaveReturnedWith(true); | ||||
|       expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec); | ||||
|       expect(infoSpy).toHaveBeenCalledWith( | ||||
|         `Resolved ${versionFile} as ${expectedVersionSpec}` | ||||
|       ); | ||||
|     }, 10000); | ||||
|  | ||||
|     it('both node-version-file and node-version are provided', async () => { | ||||
|       inputs['node-version'] = '12'; | ||||
|       const versionSpec = 'v14'; | ||||
|       const versionFile = '.nvmrc'; | ||||
|       const expectedVersionSpec = '14'; | ||||
|       process.env['GITHUB_WORKSPACE'] = path.join(__dirname, '..'); | ||||
|       inputs['node-version-file'] = versionFile; | ||||
|  | ||||
|       parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); | ||||
|  | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(existsSpy).toHaveBeenCalledTimes(0); | ||||
|       expect(parseNodeVersionSpy).not.toHaveBeenCalled(); | ||||
|       expect(warningSpy).toHaveBeenCalledWith( | ||||
|         'Both node-version and node-version-file inputs are specified, only node-version will be used' | ||||
|       ); | ||||
|     }); | ||||
|  | ||||
|     it('should throw an error if node-version-file is not found', async () => { | ||||
|       const versionFile = '.nvmrc'; | ||||
|       const versionFilePath = path.join(__dirname, '..', versionFile); | ||||
|       inputs['node-version-file'] = versionFile; | ||||
|  | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       existsSpy.mockImplementationOnce( | ||||
|         input => input === path.join(__dirname, 'data', versionFile) | ||||
|       ); | ||||
|  | ||||
|       // Act | ||||
|       await main.run(); | ||||
|  | ||||
|       // Assert | ||||
|       expect(existsSpy).toHaveBeenCalled(); | ||||
|       expect(existsSpy).toHaveReturnedWith(false); | ||||
|       expect(parseNodeVersionSpy).not.toHaveBeenCalled(); | ||||
|       expect(cnSpy).toHaveBeenCalledWith( | ||||
|         `::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}` | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   describe('cache on GHES', () => { | ||||
|     it('Should throw an error, because cache is not supported', async () => { | ||||
|       inputs['node-version'] = '12'; | ||||
|       inputs['cache'] = 'npm'; | ||||
|  | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|       let toolPath = path.normalize('/cache/node/12.16.1/x64'); | ||||
|       findSpy.mockImplementation(() => toolPath); | ||||
|  | ||||
|       // expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|       process.env['GITHUB_SERVER_URL'] = 'https://www.test.com'; | ||||
|       isCacheActionAvailable.mockImplementation(() => false); | ||||
|  | ||||
|       await main.run(); | ||||
|  | ||||
|       expect(warningSpy).toHaveBeenCalledWith( | ||||
|         `Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.` | ||||
|       ); | ||||
|     }); | ||||
|  | ||||
|     it('Should throw an internal error', async () => { | ||||
|       inputs['node-version'] = '12'; | ||||
|       inputs['cache'] = 'npm'; | ||||
|  | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|       let toolPath = path.normalize('/cache/node/12.16.1/x64'); | ||||
|       findSpy.mockImplementation(() => toolPath); | ||||
|  | ||||
|       // expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|       process.env['GITHUB_SERVER_URL'] = ''; | ||||
|       isCacheActionAvailable.mockImplementation(() => false); | ||||
|  | ||||
|       await main.run(); | ||||
|  | ||||
|       expect(warningSpy).toHaveBeenCalledWith( | ||||
|         'The runner was not able to contact the cache service. Caching will be skipped' | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										517
									
								
								__tests__/nightly-installer.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										517
									
								
								__tests__/nightly-installer.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,517 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as io from '@actions/io'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as httpm from '@actions/http-client'; | ||||
| import * as exec from '@actions/exec'; | ||||
| import * as cache from '@actions/cache'; | ||||
| import fs from 'fs'; | ||||
| import cp from 'child_process'; | ||||
| import osm from 'os'; | ||||
| import path from 'path'; | ||||
| import * as main from '../src/main'; | ||||
| import * as auth from '../src/authutil'; | ||||
| import {INodeVersion} from '../src/distributions/base-models'; | ||||
|  | ||||
| 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'); | ||||
| const nodeV8CanaryTestDist = require('./data/v8-canary-dist-index.json'); | ||||
|  | ||||
| describe('setup-node', () => { | ||||
|   let inputs = {} as any; | ||||
|   let os = {} as any; | ||||
|  | ||||
|   let inSpy: jest.SpyInstance; | ||||
|   let findSpy: jest.SpyInstance; | ||||
|   let findAllVersionsSpy: jest.SpyInstance; | ||||
|   let cnSpy: jest.SpyInstance; | ||||
|   let logSpy: jest.SpyInstance; | ||||
|   let warningSpy: jest.SpyInstance; | ||||
|   let getManifestSpy: jest.SpyInstance; | ||||
|   let getDistSpy: jest.SpyInstance; | ||||
|   let platSpy: jest.SpyInstance; | ||||
|   let archSpy: jest.SpyInstance; | ||||
|   let dlSpy: jest.SpyInstance; | ||||
|   let exSpy: jest.SpyInstance; | ||||
|   let cacheSpy: jest.SpyInstance; | ||||
|   let dbgSpy: jest.SpyInstance; | ||||
|   let whichSpy: jest.SpyInstance; | ||||
|   let existsSpy: jest.SpyInstance; | ||||
|   let mkdirpSpy: jest.SpyInstance; | ||||
|   let execSpy: jest.SpyInstance; | ||||
|   let authSpy: jest.SpyInstance; | ||||
|   let parseNodeVersionSpy: jest.SpyInstance; | ||||
|   let isCacheActionAvailable: jest.SpyInstance; | ||||
|   let getExecOutputSpy: jest.SpyInstance; | ||||
|   let getJsonSpy: jest.SpyInstance; | ||||
|  | ||||
|   beforeEach(() => { | ||||
|     // @actions/core | ||||
|     console.log('::stop-commands::stoptoken'); // Disable executing of runner commands when running tests in actions | ||||
|     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 | ||||
|     inputs = {}; | ||||
|     inSpy = jest.spyOn(core, 'getInput'); | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|     // node | ||||
|     os = {}; | ||||
|     platSpy = jest.spyOn(osm, 'platform'); | ||||
|     platSpy.mockImplementation(() => os['platform']); | ||||
|     archSpy = jest.spyOn(osm, 'arch'); | ||||
|     archSpy.mockImplementation(() => os['arch']); | ||||
|     execSpy = jest.spyOn(cp, 'execSync'); | ||||
|  | ||||
|     // @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'); | ||||
|     getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo'); | ||||
|  | ||||
|     // http-client | ||||
|     getJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); | ||||
|  | ||||
|     // io | ||||
|     whichSpy = jest.spyOn(io, 'which'); | ||||
|     existsSpy = jest.spyOn(fs, 'existsSync'); | ||||
|     mkdirpSpy = jest.spyOn(io, 'mkdirP'); | ||||
|  | ||||
|     // @actions/tool-cache | ||||
|     isCacheActionAvailable = jest.spyOn(cache, 'isFeatureAvailable'); | ||||
|  | ||||
|     // disable authentication portion for installer tests | ||||
|     authSpy = jest.spyOn(auth, 'configAuthentication'); | ||||
|     authSpy.mockImplementation(() => {}); | ||||
|  | ||||
|     getJsonSpy.mockImplementation(url => { | ||||
|       let res: any; | ||||
|       if (url.includes('/rc')) { | ||||
|         res = <INodeVersion>nodeTestDistRc; | ||||
|       } else if (url.includes('/nightly')) { | ||||
|         res = <INodeVersion>nodeTestDistNightly; | ||||
|       } else { | ||||
|         res = <INodeVersion>nodeTestDist; | ||||
|       } | ||||
|  | ||||
|       return {result: res}; | ||||
|     }); | ||||
|  | ||||
|     // writes | ||||
|     cnSpy = jest.spyOn(process.stdout, 'write'); | ||||
|     logSpy = jest.spyOn(core, 'info'); | ||||
|     dbgSpy = jest.spyOn(core, 'debug'); | ||||
|     warningSpy = jest.spyOn(core, 'warning'); | ||||
|     cnSpy.mockImplementation(line => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('write:' + line + '\n'); | ||||
|     }); | ||||
|     logSpy.mockImplementation(line => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('log:' + line + '\n'); | ||||
|     }); | ||||
|     dbgSpy.mockImplementation(msg => { | ||||
|       // uncomment to see debug output | ||||
|       // process.stderr.write(msg + '\n'); | ||||
|     }); | ||||
|     warningSpy.mockImplementation(msg => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('log:' + msg + '\n'); | ||||
|     }); | ||||
|  | ||||
|     // @actions/exec | ||||
|     getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); | ||||
|     getExecOutputSpy.mockImplementation(() => 'v16.15.0'); | ||||
|   }); | ||||
|  | ||||
|   afterEach(() => { | ||||
|     jest.resetAllMocks(); | ||||
|     jest.clearAllMocks(); | ||||
|     //jest.restoreAllMocks(); | ||||
|   }); | ||||
|  | ||||
|   afterAll(async () => { | ||||
|     console.log('::stoptoken::'); // Re-enable executing of runner commands when running tests in actions | ||||
|     jest.restoreAllMocks(); | ||||
|   }, 100000); | ||||
|  | ||||
|   //-------------------------------------------------- | ||||
|   // Found in cache tests | ||||
|   //-------------------------------------------------- | ||||
|  | ||||
|   it('finds version in cache with stable true', async () => { | ||||
|     inputs['node-version'] = '16-nightly'; | ||||
|     os['arch'] = 'x64'; | ||||
|     inputs.stable = 'true'; | ||||
|  | ||||
|     let toolPath = path.normalize( | ||||
|       '/cache/node/16.0.0-nightly20210417bc31dc0e0f/x64' | ||||
|     ); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '12.0.1', | ||||
|       '16.0.0-nightly20210415c3a5e15ebe', | ||||
|       '16.0.0-nightly20210417bc31dc0e0f', | ||||
|       '16.1.3' | ||||
|     ]); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(findSpy).toHaveBeenCalledWith( | ||||
|       'node', | ||||
|       '16.0.0-nightly20210417bc31dc0e0f', | ||||
|       'x64' | ||||
|     ); | ||||
|     expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|   }); | ||||
|  | ||||
|   it('finds version in cache with stable false', async () => { | ||||
|     inputs['node-version'] = '16.0.0-nightly20210415c3a5e15ebe'; | ||||
|     os['arch'] = 'x64'; | ||||
|     inputs.stable = 'false'; | ||||
|  | ||||
|     let toolPath = path.normalize( | ||||
|       '/cache/node/16.0.0-nightly20210415c3a5e15ebe/x64' | ||||
|     ); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '12.0.1', | ||||
|       '16.0.0-nightly20210415c3a5e15ebe', | ||||
|       '16.0.0-nightly20210417bc31dc0e0f', | ||||
|       '16.1.3' | ||||
|     ]); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(findSpy).toHaveBeenCalledWith( | ||||
|       'node', | ||||
|       '16.0.0-nightly20210415c3a5e15ebe', | ||||
|       'x64' | ||||
|     ); | ||||
|     expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|   }); | ||||
|  | ||||
|   it('finds version in cache and adds it to the path', async () => { | ||||
|     inputs['node-version'] = '16-nightly'; | ||||
|     os['arch'] = 'x64'; | ||||
|  | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|     let toolPath = path.normalize( | ||||
|       '/cache/node/16.0.0-nightly20210417bc31dc0e0f/x64' | ||||
|     ); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '12.0.1', | ||||
|       '16.0.0-nightly20210415c3a5e15ebe', | ||||
|       '16.0.0-nightly20210417bc31dc0e0f', | ||||
|       '16.1.3' | ||||
|     ]); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(findSpy).toHaveBeenCalledWith( | ||||
|       'node', | ||||
|       '16.0.0-nightly20210417bc31dc0e0f', | ||||
|       'x64' | ||||
|     ); | ||||
|  | ||||
|     let expPath = path.join(toolPath, 'bin'); | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('handles unhandled find error and reports error', async () => { | ||||
|     let errMsg = 'unhandled error message'; | ||||
|     inputs['node-version'] = '16.0.0-nightly20210417bc31dc0e0f'; | ||||
|  | ||||
|     findAllVersionsSpy.mockImplementation(() => [ | ||||
|       '12.0.1', | ||||
|       '16.0.0-nightly20210415c3a5e15ebe', | ||||
|       '16.0.0-nightly20210417bc31dc0e0f', | ||||
|       '16.1.3' | ||||
|     ]); | ||||
|  | ||||
|     findSpy.mockImplementation(() => { | ||||
|       throw new Error(errMsg); | ||||
|     }); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith('::error::' + errMsg + osm.EOL); | ||||
|   }); | ||||
|  | ||||
|   it('falls back to a version from node dist', async () => { | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     // a version which is not in the manifest but is in node dist | ||||
|     let versionSpec = '13.13.1-nightly20200415947ddec091'; | ||||
|  | ||||
|     inputs['node-version'] = versionSpec; | ||||
|     inputs['always-auth'] = false; | ||||
|     inputs['token'] = 'faketoken'; | ||||
|  | ||||
|     // ... but not in the local cache | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|     findAllVersionsSpy.mockImplementation(() => []); | ||||
|  | ||||
|     dlSpy.mockImplementation(async () => '/some/temp/path'); | ||||
|     let toolPath = path.normalize( | ||||
|       '/cache/node/13.13.1-nightly20200415947ddec091/x64' | ||||
|     ); | ||||
|     exSpy.mockImplementation(async () => '/some/other/temp/path'); | ||||
|     cacheSpy.mockImplementation(async () => toolPath); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     let expPath = path.join(toolPath, 'bin'); | ||||
|  | ||||
|     expect(dlSpy).toHaveBeenCalled(); | ||||
|     expect(exSpy).toHaveBeenCalled(); | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('does not find a version that does not exist', async () => { | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     let versionSpec = '10.13.1-nightly20200415947ddec091'; | ||||
|     inputs['node-version'] = versionSpec; | ||||
|  | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|     findAllVersionsSpy.mockImplementation(() => []); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith( | ||||
|       `::error::Unable to find Node version '${versionSpec}' for platform ${os.platform} and architecture ${os.arch}.${osm.EOL}` | ||||
|     ); | ||||
|   }); | ||||
|  | ||||
|   it('reports a failed download', async () => { | ||||
|     let errMsg = 'unhandled download message'; | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     // a version which is in the manifest | ||||
|     let versionSpec = '18.0.0-nightly202204180699150267'; | ||||
|  | ||||
|     inputs['node-version'] = versionSpec; | ||||
|     inputs['always-auth'] = false; | ||||
|     inputs['token'] = 'faketoken'; | ||||
|  | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|     findAllVersionsSpy.mockImplementation(() => []); | ||||
|  | ||||
|     dlSpy.mockImplementation(() => { | ||||
|       throw new Error(errMsg); | ||||
|     }); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('acquires specified architecture of node', 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['always-auth'] = false; | ||||
|       inputs['token'] = 'faketoken'; | ||||
|  | ||||
|       let expectedUrl = `https://nodejs.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'); | ||||
|       let 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', () => { | ||||
|     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( | ||||
|           `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}` | ||||
|         ); | ||||
|       } | ||||
|     ); | ||||
|   }); | ||||
| }); | ||||
| @ -1,31 +1,36 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as io from '@actions/io'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as httpm from '@actions/http-client'; | ||||
| import * as exec from '@actions/exec'; | ||||
| import * as im from '../src/installer'; | ||||
| import * as cache from '@actions/cache'; | ||||
| 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'; | ||||
| import OfficialBuilds from '../src/distributions/official_builds/official_builds'; | ||||
| import {INodeVersion} from '../src/distributions/base-models'; | ||||
| 
 | ||||
| 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'); | ||||
| const nodeV8CanaryTestDist = require('./data/v8-canary-dist-index.json'); | ||||
| 
 | ||||
| describe('setup-node', () => { | ||||
|   let build: OfficialBuilds; | ||||
|   let inputs = {} as any; | ||||
|   let os = {} as any; | ||||
| 
 | ||||
|   let inSpy: jest.SpyInstance; | ||||
|   let findSpy: jest.SpyInstance; | ||||
|   let findAllVersionsSpy: jest.SpyInstance; | ||||
|   let cnSpy: jest.SpyInstance; | ||||
|   let logSpy: jest.SpyInstance; | ||||
|   let warningSpy: jest.SpyInstance; | ||||
|   let getManifestSpy: jest.SpyInstance; | ||||
|   let getDistSpy: jest.SpyInstance; | ||||
|   let platSpy: jest.SpyInstance; | ||||
|   let archSpy: jest.SpyInstance; | ||||
|   let dlSpy: jest.SpyInstance; | ||||
| @ -38,14 +43,15 @@ describe('setup-node', () => { | ||||
|   let mkdirpSpy: jest.SpyInstance; | ||||
|   let execSpy: jest.SpyInstance; | ||||
|   let authSpy: jest.SpyInstance; | ||||
|   let parseNodeVersionSpy: jest.SpyInstance; | ||||
|   let isCacheActionAvailable: jest.SpyInstance; | ||||
|   let getExecOutputSpy: jest.SpyInstance; | ||||
|   let getJsonSpy: jest.SpyInstance; | ||||
| 
 | ||||
|   beforeEach(() => { | ||||
|     // @actions/core
 | ||||
|     console.log('::stop-commands::stoptoken'); // Disable executing of runner commands when running tests in actions
 | ||||
|     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
 | ||||
|     inputs = {}; | ||||
|     inSpy = jest.spyOn(core, 'getInput'); | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
| @ -60,12 +66,14 @@ 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'); | ||||
|     getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo'); | ||||
|     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'); | ||||
| @ -83,7 +91,19 @@ describe('setup-node', () => { | ||||
|     getManifestSpy.mockImplementation( | ||||
|       () => <tc.IToolRelease[]>nodeTestManifest | ||||
|     ); | ||||
|     getDistSpy.mockImplementation(() => <im.INodeVersion>nodeTestDist); | ||||
| 
 | ||||
|     getJsonSpy.mockImplementation(url => { | ||||
|       let res: any; | ||||
|       if (url.includes('/rc')) { | ||||
|         res = <INodeVersion>nodeTestDistRc; | ||||
|       } else if (url.includes('/nightly')) { | ||||
|         res = <INodeVersion>nodeTestDistNightly; | ||||
|       } else { | ||||
|         res = <INodeVersion>nodeTestDist; | ||||
|       } | ||||
| 
 | ||||
|       return {result: res}; | ||||
|     }); | ||||
| 
 | ||||
|     // writes
 | ||||
|     cnSpy = jest.spyOn(process.stdout, 'write'); | ||||
| @ -92,11 +112,11 @@ describe('setup-node', () => { | ||||
|     warningSpy = jest.spyOn(core, 'warning'); | ||||
|     cnSpy.mockImplementation(line => { | ||||
|       // uncomment to debug
 | ||||
|       // process.stderr.write('write:' + line + '\n');
 | ||||
|       process.stderr.write('write:' + line + '\n'); | ||||
|     }); | ||||
|     logSpy.mockImplementation(line => { | ||||
|       //   uncomment to debug
 | ||||
|       // process.stderr.write('log:' + line + '\n');
 | ||||
|       process.stderr.write('log:' + line + '\n'); | ||||
|     }); | ||||
|     dbgSpy.mockImplementation(msg => { | ||||
|       // uncomment to see debug output
 | ||||
| @ -104,7 +124,7 @@ describe('setup-node', () => { | ||||
|     }); | ||||
|     warningSpy.mockImplementation(msg => { | ||||
|       // uncomment to debug
 | ||||
|       // process.stderr.write('log:' + line + '\n');
 | ||||
|       // process.stderr.write('log:' + msg + '\n');
 | ||||
|     }); | ||||
| 
 | ||||
|     // @actions/exec
 | ||||
| @ -126,22 +146,6 @@ describe('setup-node', () => { | ||||
|   //--------------------------------------------------
 | ||||
|   // Manifest find tests
 | ||||
|   //--------------------------------------------------
 | ||||
|   it('can mock manifest versions', async () => { | ||||
|     let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo( | ||||
|       'actions', | ||||
|       'node-versions', | ||||
|       'mocktoken' | ||||
|     ); | ||||
|     expect(versions).toBeDefined(); | ||||
|     expect(versions?.length).toBe(7); | ||||
|   }); | ||||
| 
 | ||||
|   it('can mock dist versions', async () => { | ||||
|     let versions: im.INodeVersion[] = await im.getVersionsFromDist(); | ||||
|     expect(versions).toBeDefined(); | ||||
|     expect(versions?.length).toBe(23); | ||||
|   }); | ||||
| 
 | ||||
|   it.each([ | ||||
|     ['12.16.2', 'darwin', '12.16.2', 'Erbium'], | ||||
|     ['12', 'linux', '12.16.2', 'Erbium'], | ||||
| @ -281,35 +285,32 @@ describe('setup-node', () => { | ||||
| 
 | ||||
|     // a version which is not in the manifest but is in node dist
 | ||||
|     let versionSpec = '11.15.0'; | ||||
|     let resolvedVersion = versionSpec; | ||||
| 
 | ||||
|     inputs['node-version'] = versionSpec; | ||||
|     inputs['always-auth'] = false; | ||||
|     inputs['token'] = 'faketoken'; | ||||
| 
 | ||||
|     let expectedUrl = | ||||
|       'https://github.com/actions/node-versions/releases/download/12.16.2-20200507.95/node-12.16.2-linux-x64.tar.gz'; | ||||
| 
 | ||||
|     // ... but not in the local cache
 | ||||
|     findSpy.mockImplementation(() => ''); | ||||
| 
 | ||||
|     dlSpy.mockImplementation(async () => '/some/temp/path'); | ||||
|     let toolPath = path.normalize('/cache/node/11.11.0/x64'); | ||||
|     const toolPath = path.normalize('/cache/node/11.15.0/x64'); | ||||
|     exSpy.mockImplementation(async () => '/some/other/temp/path'); | ||||
|     cacheSpy.mockImplementation(async () => toolPath); | ||||
| 
 | ||||
|     await main.run(); | ||||
| 
 | ||||
|     let expPath = path.join(toolPath, 'bin'); | ||||
|     const expPath = path.join(toolPath, 'bin'); | ||||
| 
 | ||||
|     expect(dlSpy).toHaveBeenCalled(); | ||||
|     expect(exSpy).toHaveBeenCalled(); | ||||
|     expect(logSpy).toHaveBeenCalledWith( | ||||
|       'Not found in manifest.  Falling back to download directly from Node' | ||||
|     ); | ||||
|     expect(getManifestSpy).toHaveBeenCalled(); | ||||
|     expect(logSpy).toHaveBeenCalledWith( | ||||
|       `Attempting to download ${versionSpec}...` | ||||
|     ); | ||||
|     expect(logSpy).toHaveBeenCalledWith( | ||||
|       'Not found in manifest. Falling back to download directly from Node' | ||||
|     ); | ||||
|     expect(dlSpy).toHaveBeenCalled(); | ||||
|     expect(exSpy).toHaveBeenCalled(); | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); | ||||
|   }); | ||||
| 
 | ||||
| @ -562,164 +563,6 @@ describe('setup-node', () => { | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('node-version-file flag', () => { | ||||
|     it('not used if node-version is provided', async () => { | ||||
|       // Arrange
 | ||||
|       inputs['node-version'] = '12'; | ||||
| 
 | ||||
|       // Act
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       // Assert
 | ||||
|       expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); | ||||
|     }); | ||||
| 
 | ||||
|     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(logSpy).toHaveBeenCalledWith( | ||||
|         `Resolved ${versionFile} as ${expectedVersionSpec}` | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     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(logSpy).toHaveBeenCalledWith( | ||||
|         `Resolved ${versionFile} as ${expectedVersionSpec}` | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     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( | ||||
|         'Both node-version and node-version-file inputs are specified, only node-version will be used' | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     it('should throw an error if node-version-file is not found', async () => { | ||||
|       const versionFile = '.nvmrc'; | ||||
|       const versionFilePath = path.join(__dirname, '..', versionFile); | ||||
|       inputs['node-version-file'] = versionFile; | ||||
| 
 | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       existsSpy.mockImplementationOnce( | ||||
|         input => input === path.join(__dirname, 'data', versionFile) | ||||
|       ); | ||||
| 
 | ||||
|       // Act
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       // Assert
 | ||||
|       expect(existsSpy).toHaveBeenCalled(); | ||||
|       expect(existsSpy).toHaveReturnedWith(false); | ||||
|       expect(parseNodeVersionSpy).not.toHaveBeenCalled(); | ||||
|       expect(cnSpy).toHaveBeenCalledWith( | ||||
|         `::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}` | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('cache on GHES', () => { | ||||
|     it('Should throw an error, because cache is not supported', async () => { | ||||
|       inputs['node-version'] = '12'; | ||||
|       inputs['cache'] = 'npm'; | ||||
| 
 | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
| 
 | ||||
|       let toolPath = path.normalize('/cache/node/12.16.1/x64'); | ||||
|       findSpy.mockImplementation(() => toolPath); | ||||
| 
 | ||||
|       // expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
 | ||||
|       process.env['GITHUB_SERVER_URL'] = 'https://www.test.com'; | ||||
|       isCacheActionAvailable.mockImplementation(() => false); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(cnSpy).toHaveBeenCalledWith( | ||||
|         `::error::Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.${osm.EOL}` | ||||
|       ); | ||||
|     }); | ||||
| 
 | ||||
|     it('Should throw an internal error', async () => { | ||||
|       inputs['node-version'] = '12'; | ||||
|       inputs['cache'] = 'npm'; | ||||
| 
 | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
| 
 | ||||
|       let toolPath = path.normalize('/cache/node/12.16.1/x64'); | ||||
|       findSpy.mockImplementation(() => toolPath); | ||||
| 
 | ||||
|       // expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
 | ||||
|       process.env['GITHUB_SERVER_URL'] = ''; | ||||
|       isCacheActionAvailable.mockImplementation(() => false); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(warningSpy).toHaveBeenCalledWith( | ||||
|         'The runner was not able to contact the cache service. Caching will be skipped' | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('LTS version', () => { | ||||
|     beforeEach(() => { | ||||
|       os.platform = 'linux'; | ||||
| @ -935,36 +778,16 @@ describe('setup-node', () => { | ||||
|         const toolPath = path.normalize( | ||||
|           `/cache/node/${expectedVersion.version}/x64` | ||||
|         ); | ||||
|         findSpy.mockReturnValue(toolPath); | ||||
|         findSpy.mockImplementation(() => toolPath); | ||||
| 
 | ||||
|         // Act
 | ||||
|         await main.run(); | ||||
| 
 | ||||
|         // assert
 | ||||
|         expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
| 
 | ||||
|         expect(logSpy).toHaveBeenCalledWith('getting latest node version...'); | ||||
|         expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|       } | ||||
|     ); | ||||
|   }); | ||||
| }); | ||||
| 
 | ||||
| describe('helper methods', () => { | ||||
|   describe('parseNodeVersionFile', () => { | ||||
|     each` | ||||
|       contents                                     | expected | ||||
|       ${'12'}                                      | ${'12'} | ||||
|       ${'12.3'}                                    | ${'12.3'} | ||||
|       ${'12.3.4'}                                  | ${'12.3.4'} | ||||
|       ${'v12.3.4'}                                 | ${'12.3.4'} | ||||
|       ${'lts/erbium'}                              | ${'lts/erbium'} | ||||
|       ${'lts/*'}                                   | ${'lts/*'} | ||||
|       ${'nodejs 12.3.4'}                           | ${'12.3.4'} | ||||
|       ${'ruby 2.3.4\nnodejs 12.3.4\npython 3.4.5'} | ${'12.3.4'} | ||||
|       ${''}                                        | ${''} | ||||
|       ${'unknown format'}                          | ${'unknown format'} | ||||
|     `.it('parses "$contents"', ({contents, expected}) => {
 | ||||
|       expect(im.parseNodeVersionFile(contents)).toBe(expected); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										402
									
								
								__tests__/rc-installer.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										402
									
								
								__tests__/rc-installer.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,402 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as io from '@actions/io'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as httpm from '@actions/http-client'; | ||||
| import * as exec from '@actions/exec'; | ||||
| import * as cache from '@actions/cache'; | ||||
| import fs from 'fs'; | ||||
| import cp from 'child_process'; | ||||
| import osm from 'os'; | ||||
| import path from 'path'; | ||||
| import * as main from '../src/main'; | ||||
| import * as auth from '../src/authutil'; | ||||
| import {INodeVersion} from '../src/distributions/base-models'; | ||||
|  | ||||
| const nodeTestDist = require('./data/node-dist-index.json'); | ||||
| const nodeTestDistNightly = require('./data/node-nightly-index.json'); | ||||
| const nodeTestDistRc = require('./data/node-rc-index.json'); | ||||
| const nodeV8CanaryTestDist = require('./data/v8-canary-dist-index.json'); | ||||
|  | ||||
| describe('setup-node', () => { | ||||
|   let inputs = {} as any; | ||||
|   let os = {} as any; | ||||
|  | ||||
|   let inSpy: jest.SpyInstance; | ||||
|   let findSpy: jest.SpyInstance; | ||||
|   let findAllVersionsSpy: jest.SpyInstance; | ||||
|   let cnSpy: jest.SpyInstance; | ||||
|   let logSpy: jest.SpyInstance; | ||||
|   let warningSpy: jest.SpyInstance; | ||||
|   let platSpy: jest.SpyInstance; | ||||
|   let archSpy: jest.SpyInstance; | ||||
|   let dlSpy: jest.SpyInstance; | ||||
|   let exSpy: jest.SpyInstance; | ||||
|   let cacheSpy: jest.SpyInstance; | ||||
|   let dbgSpy: jest.SpyInstance; | ||||
|   let whichSpy: jest.SpyInstance; | ||||
|   let existsSpy: jest.SpyInstance; | ||||
|   let mkdirpSpy: jest.SpyInstance; | ||||
|   let execSpy: jest.SpyInstance; | ||||
|   let authSpy: jest.SpyInstance; | ||||
|   let isCacheActionAvailable: jest.SpyInstance; | ||||
|   let getExecOutputSpy: jest.SpyInstance; | ||||
|   let getJsonSpy: jest.SpyInstance; | ||||
|  | ||||
|   beforeEach(() => { | ||||
|     // @actions/core | ||||
|     console.log('::stop-commands::stoptoken'); // Disable executing of runner commands when running tests in actions | ||||
|     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 | ||||
|     inputs = {}; | ||||
|     inSpy = jest.spyOn(core, 'getInput'); | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|     // node | ||||
|     os = {}; | ||||
|     platSpy = jest.spyOn(osm, 'platform'); | ||||
|     platSpy.mockImplementation(() => os['platform']); | ||||
|     archSpy = jest.spyOn(osm, 'arch'); | ||||
|     archSpy.mockImplementation(() => os['arch']); | ||||
|     execSpy = jest.spyOn(cp, 'execSync'); | ||||
|  | ||||
|     // @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'); | ||||
|     // getDistSpy = jest.spyOn(im, 'getVersionsFromDist'); | ||||
|  | ||||
|     // http-client | ||||
|     getJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); | ||||
|  | ||||
|     // io | ||||
|     whichSpy = jest.spyOn(io, 'which'); | ||||
|     existsSpy = jest.spyOn(fs, 'existsSync'); | ||||
|     mkdirpSpy = jest.spyOn(io, 'mkdirP'); | ||||
|  | ||||
|     // @actions/tool-cache | ||||
|     isCacheActionAvailable = jest.spyOn(cache, 'isFeatureAvailable'); | ||||
|     isCacheActionAvailable.mockImplementation(() => false); | ||||
|  | ||||
|     // disable authentication portion for installer tests | ||||
|     authSpy = jest.spyOn(auth, 'configAuthentication'); | ||||
|     authSpy.mockImplementation(() => {}); | ||||
|  | ||||
|     getJsonSpy.mockImplementation(url => { | ||||
|       let res: any; | ||||
|       if (url.includes('/rc')) { | ||||
|         res = <INodeVersion>nodeTestDistRc; | ||||
|       } else if (url.includes('/nightly')) { | ||||
|         res = <INodeVersion>nodeTestDistNightly; | ||||
|       } else { | ||||
|         res = <INodeVersion>nodeTestDist; | ||||
|       } | ||||
|  | ||||
|       return {result: res}; | ||||
|     }); | ||||
|  | ||||
|     // writes | ||||
|     cnSpy = jest.spyOn(process.stdout, 'write'); | ||||
|     logSpy = jest.spyOn(core, 'info'); | ||||
|     dbgSpy = jest.spyOn(core, 'debug'); | ||||
|     warningSpy = jest.spyOn(core, 'warning'); | ||||
|     cnSpy.mockImplementation(line => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('write:' + line + '\n'); | ||||
|     }); | ||||
|     logSpy.mockImplementation(line => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('log:' + line + '\n'); | ||||
|     }); | ||||
|     dbgSpy.mockImplementation(msg => { | ||||
|       // uncomment to see debug output | ||||
|       // process.stderr.write(msg + '\n'); | ||||
|     }); | ||||
|     warningSpy.mockImplementation(msg => { | ||||
|       // uncomment to debug | ||||
|       // process.stderr.write('log:' + msg + '\n'); | ||||
|     }); | ||||
|  | ||||
|     // @actions/exec | ||||
|     getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); | ||||
|     getExecOutputSpy.mockImplementation(() => 'v16.15.0-rc.1'); | ||||
|   }); | ||||
|  | ||||
|   afterEach(() => { | ||||
|     jest.resetAllMocks(); | ||||
|     jest.clearAllMocks(); | ||||
|     //jest.restoreAllMocks(); | ||||
|   }); | ||||
|  | ||||
|   afterAll(async () => { | ||||
|     console.log('::stoptoken::'); // Re-enable executing of runner commands when running tests in actions | ||||
|     jest.restoreAllMocks(); | ||||
|   }, 100000); | ||||
|  | ||||
|   //-------------------------------------------------- | ||||
|   // Found in cache tests | ||||
|   //-------------------------------------------------- | ||||
|  | ||||
|   it('finds version in cache with stable true', async () => { | ||||
|     inputs['node-version'] = '12.0.0-rc.1'; | ||||
|     inputs.stable = 'true'; | ||||
|  | ||||
|     let toolPath = path.normalize('/cache/node/12.0.0-rc.1/x64'); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|   }); | ||||
|  | ||||
|   it('finds version in cache with stable not supplied', async () => { | ||||
|     inputs['node-version'] = '12.0.0-rc.1'; | ||||
|  | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|     let toolPath = path.normalize('/cache/node/12.0.0-rc.1/x64'); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|   }); | ||||
|  | ||||
|   it('finds version in cache and adds it to the path', async () => { | ||||
|     inputs['node-version'] = '12.0.0-rc.1'; | ||||
|  | ||||
|     inSpy.mockImplementation(name => inputs[name]); | ||||
|  | ||||
|     let toolPath = path.normalize('/cache/node/12.0.0-rc.1/x64'); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|     await main.run(); | ||||
|  | ||||
|     let expPath = path.join(toolPath, 'bin'); | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('handles unhandled find error and reports error', async () => { | ||||
|     let errMsg = 'unhandled error message'; | ||||
|     inputs['node-version'] = '12.0.0-rc.1'; | ||||
|  | ||||
|     findSpy.mockImplementation(() => { | ||||
|       throw new Error(errMsg); | ||||
|     }); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith('::error::' + errMsg + osm.EOL); | ||||
|   }); | ||||
|  | ||||
|   it('falls back to a version from node dist', async () => { | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     let versionSpec = '13.0.0-rc.0'; | ||||
|  | ||||
|     inputs['node-version'] = versionSpec; | ||||
|     inputs['always-auth'] = false; | ||||
|     inputs['token'] = 'faketoken'; | ||||
|  | ||||
|     // ... but not in the local cache | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|  | ||||
|     dlSpy.mockImplementation(async () => '/some/temp/path'); | ||||
|     let toolPath = path.normalize('/cache/node/13.0.0-rc.0/x64'); | ||||
|     exSpy.mockImplementation(async () => '/some/other/temp/path'); | ||||
|     cacheSpy.mockImplementation(async () => toolPath); | ||||
|  | ||||
|     await main.run(); | ||||
|  | ||||
|     let expPath = path.join(toolPath, 'bin'); | ||||
|  | ||||
|     expect(dlSpy).toHaveBeenCalled(); | ||||
|     expect(exSpy).toHaveBeenCalled(); | ||||
|     expect(logSpy).toHaveBeenCalledWith('Extracting ...'); | ||||
|     expect(logSpy).toHaveBeenCalledWith('Done'); | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('does not find a version that does not exist', async () => { | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     let versionSpec = '9.99.9-rc.1'; | ||||
|     inputs['node-version'] = versionSpec; | ||||
|  | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith( | ||||
|       `::error::Unable to find Node version '${versionSpec}' for platform ${os.platform} and architecture ${os.arch}.${osm.EOL}` | ||||
|     ); | ||||
|   }); | ||||
|  | ||||
|   it('reports a failed download', async () => { | ||||
|     let errMsg = 'unhandled download message'; | ||||
|     os.platform = 'linux'; | ||||
|     os.arch = 'x64'; | ||||
|  | ||||
|     let versionSpec = '14.7.0-rc.1'; | ||||
|  | ||||
|     inputs['node-version'] = versionSpec; | ||||
|     inputs['always-auth'] = false; | ||||
|     inputs['token'] = 'faketoken'; | ||||
|  | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|     findAllVersionsSpy.mockImplementation(() => []); | ||||
|     dlSpy.mockImplementation(() => { | ||||
|       throw new Error(errMsg); | ||||
|     }); | ||||
|     await main.run(); | ||||
|  | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`); | ||||
|   }); | ||||
|  | ||||
|   it('acquires specified architecture of node', async () => { | ||||
|     for (const {arch, version, osSpec} of [ | ||||
|       {arch: 'x86', version: '13.4.0-rc.0', osSpec: 'win32'}, | ||||
|       {arch: 'x86', version: '14.15.5-rc.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['always-auth'] = false; | ||||
|       inputs['token'] = 'faketoken'; | ||||
|  | ||||
|       let expectedUrl = `https://nodejs.org/download/rc/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`; | ||||
|  | ||||
|       // ... but not in the local cache | ||||
|       findSpy.mockImplementation(() => ''); | ||||
|       findAllVersionsSpy.mockImplementation(() => []); | ||||
|  | ||||
|       dlSpy.mockImplementation(async () => '/some/temp/path'); | ||||
|       let 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('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('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.mockImplementation((_, version) => | ||||
|           path.normalize(`/cache/node/${version}/x64`) | ||||
|         ); | ||||
|         findAllVersionsSpy.mockReturnValue([ | ||||
|           '2.2.2-rc.2', | ||||
|           '1.1.1-rc.1', | ||||
|           '99.1.1', | ||||
|           expectedVersion, | ||||
|           '88.1.1', | ||||
|           '3.3.3-rc.3' | ||||
|         ]); | ||||
|  | ||||
|         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(cnSpy).toHaveBeenCalledWith( | ||||
|         `::error::Unable to find Node version '${versionSpec}' for platform ${os.platform} and architecture ${os.arch}.${osm.EOL}` | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
| @ -19,8 +19,8 @@ inputs: | ||||
|   scope: | ||||
|     description: 'Optional scope for authenticating against scoped registries. Will fall back to the repository owner when using the GitHub Packages registry (https://npm.pkg.github.com/).' | ||||
|   token: | ||||
|     description: Used to pull node distributions from node-versions.  Since there's a default, this is typically not supplied by the user. | ||||
|     default: ${{ github.token }} | ||||
|     description: Used to pull node distributions from node-versions. Since there's a default, this is typically not supplied by the user. When running this action on github.com, the default value is sufficient. When running on GHES, you can pass a personal access token for github.com if you are experiencing rate limiting. | ||||
|     default: ${{ github.server_url == 'https://github.com' && github.token || '' }} | ||||
|   cache: | ||||
|     description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.' | ||||
|   cache-dependency-path: | ||||
|  | ||||
							
								
								
									
										255
									
								
								dist/cache-save/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										255
									
								
								dist/cache-save/index.js
									
									
									
									
										vendored
									
									
								
							| @ -3477,7 +3477,6 @@ const file_command_1 = __nccwpck_require__(717); | ||||
| const utils_1 = __nccwpck_require__(5278); | ||||
| const os = __importStar(__nccwpck_require__(2037)); | ||||
| const path = __importStar(__nccwpck_require__(1017)); | ||||
| const uuid_1 = __nccwpck_require__(8974); | ||||
| const oidc_utils_1 = __nccwpck_require__(8041); | ||||
| /** | ||||
|  * The code to exit an action | ||||
| @ -3507,21 +3506,10 @@ function exportVariable(name, val) { | ||||
|     process.env[name] = convertedVal; | ||||
|     const filePath = process.env['GITHUB_ENV'] || ''; | ||||
|     if (filePath) { | ||||
|         const delimiter = `ghadelimiter_${uuid_1.v4()}`; | ||||
|         // These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter.
 | ||||
|         if (name.includes(delimiter)) { | ||||
|             throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); | ||||
|         return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); | ||||
|     } | ||||
|         if (convertedVal.includes(delimiter)) { | ||||
|             throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); | ||||
|         } | ||||
|         const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; | ||||
|         file_command_1.issueCommand('ENV', commandValue); | ||||
|     } | ||||
|     else { | ||||
|     command_1.issueCommand('set-env', { name }, convertedVal); | ||||
| } | ||||
| } | ||||
| exports.exportVariable = exportVariable; | ||||
| /** | ||||
|  * Registers a secret which will get masked from logs | ||||
| @ -3538,7 +3526,7 @@ exports.setSecret = setSecret; | ||||
| function addPath(inputPath) { | ||||
|     const filePath = process.env['GITHUB_PATH'] || ''; | ||||
|     if (filePath) { | ||||
|         file_command_1.issueCommand('PATH', inputPath); | ||||
|         file_command_1.issueFileCommand('PATH', inputPath); | ||||
|     } | ||||
|     else { | ||||
|         command_1.issueCommand('add-path', {}, inputPath); | ||||
| @ -3578,8 +3566,11 @@ function getMultilineInput(name, options) { | ||||
|     const inputs = getInput(name, options) | ||||
|         .split('\n') | ||||
|         .filter(x => x !== ''); | ||||
|     if (options && options.trimWhitespace === false) { | ||||
|         return inputs; | ||||
|     } | ||||
|     return inputs.map(input => input.trim()); | ||||
| } | ||||
| exports.getMultilineInput = getMultilineInput; | ||||
| /** | ||||
|  * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. | ||||
| @ -3611,8 +3602,12 @@ exports.getBooleanInput = getBooleanInput; | ||||
|  */ | ||||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||
| function setOutput(name, value) { | ||||
|     const filePath = process.env['GITHUB_OUTPUT'] || ''; | ||||
|     if (filePath) { | ||||
|         return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); | ||||
|     } | ||||
|     process.stdout.write(os.EOL); | ||||
|     command_1.issueCommand('set-output', { name }, value); | ||||
|     command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); | ||||
| } | ||||
| exports.setOutput = setOutput; | ||||
| /** | ||||
| @ -3741,7 +3736,11 @@ exports.group = group; | ||||
|  */ | ||||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||
| function saveState(name, value) { | ||||
|     command_1.issueCommand('save-state', { name }, value); | ||||
|     const filePath = process.env['GITHUB_STATE'] || ''; | ||||
|     if (filePath) { | ||||
|         return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); | ||||
|     } | ||||
|     command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); | ||||
| } | ||||
| exports.saveState = saveState; | ||||
| /** | ||||
| @ -3807,13 +3806,14 @@ var __importStar = (this && this.__importStar) || function (mod) { | ||||
|     return result; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", ({ value: true })); | ||||
| exports.issueCommand = void 0; | ||||
| exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; | ||||
| // We use any as a valid input type
 | ||||
| /* eslint-disable @typescript-eslint/no-explicit-any */ | ||||
| const fs = __importStar(__nccwpck_require__(7147)); | ||||
| const os = __importStar(__nccwpck_require__(2037)); | ||||
| const uuid_1 = __nccwpck_require__(8974); | ||||
| const utils_1 = __nccwpck_require__(5278); | ||||
| function issueCommand(command, message) { | ||||
| function issueFileCommand(command, message) { | ||||
|     const filePath = process.env[`GITHUB_${command}`]; | ||||
|     if (!filePath) { | ||||
|         throw new Error(`Unable to find environment variable for file command ${command}`); | ||||
| @ -3825,7 +3825,22 @@ function issueCommand(command, message) { | ||||
|         encoding: 'utf8' | ||||
|     }); | ||||
| } | ||||
| exports.issueCommand = issueCommand; | ||||
| exports.issueFileCommand = issueFileCommand; | ||||
| function prepareKeyValueMessage(key, value) { | ||||
|     const delimiter = `ghadelimiter_${uuid_1.v4()}`; | ||||
|     const convertedValue = utils_1.toCommandValue(value); | ||||
|     // These should realistically never happen, but just in case someone finds a
 | ||||
|     // way to exploit uuid generation let's not allow keys or values that contain
 | ||||
|     // the delimiter.
 | ||||
|     if (key.includes(delimiter)) { | ||||
|         throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); | ||||
|     } | ||||
|     if (convertedValue.includes(delimiter)) { | ||||
|         throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); | ||||
|     } | ||||
|     return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; | ||||
| } | ||||
| exports.prepareKeyValueMessage = prepareKeyValueMessage; | ||||
| //# sourceMappingURL=file-command.js.map
 | ||||
| 
 | ||||
| /***/ }), | ||||
| @ -45297,10 +45312,10 @@ function populateMaps (extensions, types) { | ||||
| module.exports = minimatch | ||||
| minimatch.Minimatch = Minimatch | ||||
| 
 | ||||
| var path = { sep: '/' } | ||||
| try { | ||||
|   path = __nccwpck_require__(1017) | ||||
| } catch (er) {} | ||||
| var path = (function () { try { return __nccwpck_require__(1017) } catch (e) {}}()) || { | ||||
|   sep: '/' | ||||
| } | ||||
| minimatch.sep = path.sep | ||||
| 
 | ||||
| var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} | ||||
| var expand = __nccwpck_require__(3717) | ||||
| @ -45352,43 +45367,64 @@ function filter (pattern, options) { | ||||
| } | ||||
| 
 | ||||
| function ext (a, b) { | ||||
|   a = a || {} | ||||
|   b = b || {} | ||||
|   var t = {} | ||||
|   Object.keys(b).forEach(function (k) { | ||||
|     t[k] = b[k] | ||||
|   }) | ||||
|   Object.keys(a).forEach(function (k) { | ||||
|     t[k] = a[k] | ||||
|   }) | ||||
|   Object.keys(b).forEach(function (k) { | ||||
|     t[k] = b[k] | ||||
|   }) | ||||
|   return t | ||||
| } | ||||
| 
 | ||||
| minimatch.defaults = function (def) { | ||||
|   if (!def || !Object.keys(def).length) return minimatch | ||||
|   if (!def || typeof def !== 'object' || !Object.keys(def).length) { | ||||
|     return minimatch | ||||
|   } | ||||
| 
 | ||||
|   var orig = minimatch | ||||
| 
 | ||||
|   var m = function minimatch (p, pattern, options) { | ||||
|     return orig.minimatch(p, pattern, ext(def, options)) | ||||
|     return orig(p, pattern, ext(def, options)) | ||||
|   } | ||||
| 
 | ||||
|   m.Minimatch = function Minimatch (pattern, options) { | ||||
|     return new orig.Minimatch(pattern, ext(def, options)) | ||||
|   } | ||||
|   m.Minimatch.defaults = function defaults (options) { | ||||
|     return orig.defaults(ext(def, options)).Minimatch | ||||
|   } | ||||
| 
 | ||||
|   m.filter = function filter (pattern, options) { | ||||
|     return orig.filter(pattern, ext(def, options)) | ||||
|   } | ||||
| 
 | ||||
|   m.defaults = function defaults (options) { | ||||
|     return orig.defaults(ext(def, options)) | ||||
|   } | ||||
| 
 | ||||
|   m.makeRe = function makeRe (pattern, options) { | ||||
|     return orig.makeRe(pattern, ext(def, options)) | ||||
|   } | ||||
| 
 | ||||
|   m.braceExpand = function braceExpand (pattern, options) { | ||||
|     return orig.braceExpand(pattern, ext(def, options)) | ||||
|   } | ||||
| 
 | ||||
|   m.match = function (list, pattern, options) { | ||||
|     return orig.match(list, pattern, ext(def, options)) | ||||
|   } | ||||
| 
 | ||||
|   return m | ||||
| } | ||||
| 
 | ||||
| Minimatch.defaults = function (def) { | ||||
|   if (!def || !Object.keys(def).length) return Minimatch | ||||
|   return minimatch.defaults(def).Minimatch | ||||
| } | ||||
| 
 | ||||
| function minimatch (p, pattern, options) { | ||||
|   if (typeof pattern !== 'string') { | ||||
|     throw new TypeError('glob pattern string required') | ||||
|   } | ||||
|   assertValidPattern(pattern) | ||||
| 
 | ||||
|   if (!options) options = {} | ||||
| 
 | ||||
| @ -45397,9 +45433,6 @@ function minimatch (p, pattern, options) { | ||||
|     return false | ||||
|   } | ||||
| 
 | ||||
|   // "" only matches ""
 | ||||
|   if (pattern.trim() === '') return p === '' | ||||
| 
 | ||||
|   return new Minimatch(pattern, options).match(p) | ||||
| } | ||||
| 
 | ||||
| @ -45408,15 +45441,14 @@ function Minimatch (pattern, options) { | ||||
|     return new Minimatch(pattern, options) | ||||
|   } | ||||
| 
 | ||||
|   if (typeof pattern !== 'string') { | ||||
|     throw new TypeError('glob pattern string required') | ||||
|   } | ||||
|   assertValidPattern(pattern) | ||||
| 
 | ||||
|   if (!options) options = {} | ||||
| 
 | ||||
|   pattern = pattern.trim() | ||||
| 
 | ||||
|   // windows support: need to use /, not \
 | ||||
|   if (path.sep !== '/') { | ||||
|   if (!options.allowWindowsEscape && path.sep !== '/') { | ||||
|     pattern = pattern.split(path.sep).join('/') | ||||
|   } | ||||
| 
 | ||||
| @ -45427,6 +45459,7 @@ function Minimatch (pattern, options) { | ||||
|   this.negate = false | ||||
|   this.comment = false | ||||
|   this.empty = false | ||||
|   this.partial = !!options.partial | ||||
| 
 | ||||
|   // make the set of regexps etc.
 | ||||
|   this.make() | ||||
| @ -45436,9 +45469,6 @@ Minimatch.prototype.debug = function () {} | ||||
| 
 | ||||
| Minimatch.prototype.make = make | ||||
| function make () { | ||||
|   // don't do it more than once.
 | ||||
|   if (this._made) return | ||||
| 
 | ||||
|   var pattern = this.pattern | ||||
|   var options = this.options | ||||
| 
 | ||||
| @ -45458,7 +45488,7 @@ function make () { | ||||
|   // step 2: expand braces
 | ||||
|   var set = this.globSet = this.braceExpand() | ||||
| 
 | ||||
|   if (options.debug) this.debug = console.error | ||||
|   if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) } | ||||
| 
 | ||||
|   this.debug(this.pattern, set) | ||||
| 
 | ||||
| @ -45538,12 +45568,11 @@ function braceExpand (pattern, options) { | ||||
|   pattern = typeof pattern === 'undefined' | ||||
|     ? this.pattern : pattern | ||||
| 
 | ||||
|   if (typeof pattern === 'undefined') { | ||||
|     throw new TypeError('undefined pattern') | ||||
|   } | ||||
|   assertValidPattern(pattern) | ||||
| 
 | ||||
|   if (options.nobrace || | ||||
|     !pattern.match(/\{.*\}/)) { | ||||
|   // Thanks to Yeting Li <https://github.com/yetingli> for
 | ||||
|   // improving this regexp to avoid a ReDOS vulnerability.
 | ||||
|   if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) { | ||||
|     // shortcut. no need to expand.
 | ||||
|     return [pattern] | ||||
|   } | ||||
| @ -45551,6 +45580,17 @@ function braceExpand (pattern, options) { | ||||
|   return expand(pattern) | ||||
| } | ||||
| 
 | ||||
| var MAX_PATTERN_LENGTH = 1024 * 64 | ||||
| var assertValidPattern = function (pattern) { | ||||
|   if (typeof pattern !== 'string') { | ||||
|     throw new TypeError('invalid pattern') | ||||
|   } | ||||
| 
 | ||||
|   if (pattern.length > MAX_PATTERN_LENGTH) { | ||||
|     throw new TypeError('pattern is too long') | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // parse a component of the expanded set.
 | ||||
| // At this point, no pattern may contain "/" in it
 | ||||
| // so we're going to return a 2d array, where each entry is the full
 | ||||
| @ -45565,14 +45605,17 @@ function braceExpand (pattern, options) { | ||||
| Minimatch.prototype.parse = parse | ||||
| var SUBPARSE = {} | ||||
| function parse (pattern, isSub) { | ||||
|   if (pattern.length > 1024 * 64) { | ||||
|     throw new TypeError('pattern is too long') | ||||
|   } | ||||
|   assertValidPattern(pattern) | ||||
| 
 | ||||
|   var options = this.options | ||||
| 
 | ||||
|   // shortcuts
 | ||||
|   if (!options.noglobstar && pattern === '**') return GLOBSTAR | ||||
|   if (pattern === '**') { | ||||
|     if (!options.noglobstar) | ||||
|       return GLOBSTAR | ||||
|     else | ||||
|       pattern = '*' | ||||
|   } | ||||
|   if (pattern === '') return '' | ||||
| 
 | ||||
|   var re = '' | ||||
| @ -45628,10 +45671,12 @@ function parse (pattern, isSub) { | ||||
|     } | ||||
| 
 | ||||
|     switch (c) { | ||||
|       case '/': | ||||
|       /* istanbul ignore next */ | ||||
|       case '/': { | ||||
|         // completely not allowed, even escaped.
 | ||||
|         // Should already be path-split by now.
 | ||||
|         return false | ||||
|       } | ||||
| 
 | ||||
|       case '\\': | ||||
|         clearStateChar() | ||||
| @ -45750,7 +45795,6 @@ function parse (pattern, isSub) { | ||||
| 
 | ||||
|         // handle the case where we left a class open.
 | ||||
|         // "[z-a]" is valid, equivalent to "\[z-a\]"
 | ||||
|         if (inClass) { | ||||
|         // split where the last [ was, make sure we don't have
 | ||||
|         // an invalid re. if so, re-walk the contents of the
 | ||||
|         // would-be class to re-translate any characters that
 | ||||
| @ -45769,7 +45813,6 @@ function parse (pattern, isSub) { | ||||
|           inClass = false | ||||
|           continue | ||||
|         } | ||||
|         } | ||||
| 
 | ||||
|         // finish up the class.
 | ||||
|         hasMagic = true | ||||
| @ -45852,9 +45895,7 @@ function parse (pattern, isSub) { | ||||
|   // something that could conceivably capture a dot
 | ||||
|   var addPatternStart = false | ||||
|   switch (re.charAt(0)) { | ||||
|     case '.': | ||||
|     case '[': | ||||
|     case '(': addPatternStart = true | ||||
|     case '[': case '.': case '(': addPatternStart = true | ||||
|   } | ||||
| 
 | ||||
|   // Hack to work around lack of negative lookbehind in JS
 | ||||
| @ -45916,7 +45957,7 @@ function parse (pattern, isSub) { | ||||
|   var flags = options.nocase ? 'i' : '' | ||||
|   try { | ||||
|     var regExp = new RegExp('^' + re + '$', flags) | ||||
|   } catch (er) { | ||||
|   } catch (er) /* istanbul ignore next - should be impossible */ { | ||||
|     // If it was an invalid regular expression, then it can't match
 | ||||
|     // anything.  This trick looks for a character after the end of
 | ||||
|     // the string, which is of course impossible, except in multi-line
 | ||||
| @ -45974,7 +46015,7 @@ function makeRe () { | ||||
| 
 | ||||
|   try { | ||||
|     this.regexp = new RegExp(re, flags) | ||||
|   } catch (ex) { | ||||
|   } catch (ex) /* istanbul ignore next - should be impossible */ { | ||||
|     this.regexp = false | ||||
|   } | ||||
|   return this.regexp | ||||
| @ -45992,8 +46033,8 @@ minimatch.match = function (list, pattern, options) { | ||||
|   return list | ||||
| } | ||||
| 
 | ||||
| Minimatch.prototype.match = match | ||||
| function match (f, partial) { | ||||
| Minimatch.prototype.match = function match (f, partial) { | ||||
|   if (typeof partial === 'undefined') partial = this.partial | ||||
|   this.debug('match', f, this.pattern) | ||||
|   // short-circuit in the case of busted things.
 | ||||
|   // comments, etc.
 | ||||
| @ -46075,6 +46116,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { | ||||
| 
 | ||||
|     // should be impossible.
 | ||||
|     // some invalid regexp stuff in the set.
 | ||||
|     /* istanbul ignore if */ | ||||
|     if (p === false) return false | ||||
| 
 | ||||
|     if (p === GLOBSTAR) { | ||||
| @ -46148,6 +46190,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { | ||||
|       // no match was found.
 | ||||
|       // However, in partial mode, we can't say this is necessarily over.
 | ||||
|       // If there's more *pattern* left, then
 | ||||
|       /* istanbul ignore if */ | ||||
|       if (partial) { | ||||
|         // ran out of file
 | ||||
|         this.debug('\n>>> no match, partial?', file, fr, pattern, pr) | ||||
| @ -46161,11 +46204,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { | ||||
|     // patterns with magic have been turned into regexps.
 | ||||
|     var hit | ||||
|     if (typeof p === 'string') { | ||||
|       if (options.nocase) { | ||||
|         hit = f.toLowerCase() === p.toLowerCase() | ||||
|       } else { | ||||
|       hit = f === p | ||||
|       } | ||||
|       this.debug('string match', p, f, hit) | ||||
|     } else { | ||||
|       hit = f.match(p) | ||||
| @ -46196,16 +46235,16 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { | ||||
|     // this is ok if we're doing the match as part of
 | ||||
|     // a glob fs traversal.
 | ||||
|     return partial | ||||
|   } else if (pi === pl) { | ||||
|   } else /* istanbul ignore else */ if (pi === pl) { | ||||
|     // ran out of pattern, still have file left.
 | ||||
|     // this is only acceptable if we're on the very last
 | ||||
|     // empty segment of a file with a trailing slash.
 | ||||
|     // a/* should match a/b/
 | ||||
|     var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') | ||||
|     return emptyFileEnd | ||||
|     return (fi === fl - 1) && (file[fi] === '') | ||||
|   } | ||||
| 
 | ||||
|   // should be unreachable.
 | ||||
|   /* istanbul ignore next */ | ||||
|   throw new Error('wtf?') | ||||
| } | ||||
| 
 | ||||
| @ -60980,6 +61019,25 @@ exports.fromPromise = function (fn) { | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||||
|     if (k2 === undefined) k2 = k; | ||||
|     Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||||
| }) : (function(o, m, k, k2) { | ||||
|     if (k2 === undefined) k2 = k; | ||||
|     o[k2] = m[k]; | ||||
| })); | ||||
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||||
|     Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||||
| }) : function(o, v) { | ||||
|     o["default"] = v; | ||||
| }); | ||||
| var __importStar = (this && this.__importStar) || function (mod) { | ||||
|     if (mod && mod.__esModule) return mod; | ||||
|     var result = {}; | ||||
|     if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||||
|     __setModuleDefault(result, mod); | ||||
|     return result; | ||||
| }; | ||||
| var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||||
|     function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||||
|     return new (P || (P = Promise))(function (resolve, reject) { | ||||
| @ -60989,17 +61047,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge | ||||
|         step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||||
|     }); | ||||
| }; | ||||
| var __importStar = (this && this.__importStar) || function (mod) { | ||||
|     if (mod && mod.__esModule) return mod; | ||||
|     var result = {}; | ||||
|     if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||||
|     result["default"] = mod; | ||||
|     return result; | ||||
| }; | ||||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
|     return (mod && mod.__esModule) ? mod : { "default": mod }; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", ({ value: true })); | ||||
| exports.run = void 0; | ||||
| const core = __importStar(__nccwpck_require__(2186)); | ||||
| const cache = __importStar(__nccwpck_require__(7799)); | ||||
| const fs_1 = __importDefault(__nccwpck_require__(7147)); | ||||
| @ -61056,6 +61108,25 @@ run(); | ||||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||||
|     if (k2 === undefined) k2 = k; | ||||
|     Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||||
| }) : (function(o, m, k, k2) { | ||||
|     if (k2 === undefined) k2 = k; | ||||
|     o[k2] = m[k]; | ||||
| })); | ||||
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||||
|     Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||||
| }) : function(o, v) { | ||||
|     o["default"] = v; | ||||
| }); | ||||
| var __importStar = (this && this.__importStar) || function (mod) { | ||||
|     if (mod && mod.__esModule) return mod; | ||||
|     var result = {}; | ||||
|     if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||||
|     __setModuleDefault(result, mod); | ||||
|     return result; | ||||
| }; | ||||
| var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||||
|     function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||||
|     return new (P || (P = Promise))(function (resolve, reject) { | ||||
| @ -61065,14 +61136,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge | ||||
|         step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||||
|     }); | ||||
| }; | ||||
| var __importStar = (this && this.__importStar) || function (mod) { | ||||
|     if (mod && mod.__esModule) return mod; | ||||
|     var result = {}; | ||||
|     if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||||
|     result["default"] = mod; | ||||
|     return result; | ||||
| }; | ||||
| Object.defineProperty(exports, "__esModule", ({ value: true })); | ||||
| exports.isCacheFeatureAvailable = exports.isGhes = exports.getCacheDirectoryPath = exports.getPackageManagerInfo = exports.getCommandOutput = exports.supportedPackageManagers = void 0; | ||||
| const core = __importStar(__nccwpck_require__(2186)); | ||||
| const exec = __importStar(__nccwpck_require__(1514)); | ||||
| const cache = __importStar(__nccwpck_require__(7799)); | ||||
| @ -61094,7 +61159,7 @@ exports.supportedPackageManagers = { | ||||
|         getCacheFolderCommand: 'yarn config get cacheFolder' | ||||
|     } | ||||
| }; | ||||
| exports.getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () { | ||||
| const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () { | ||||
|     let { stdout, stderr, exitCode } = yield exec.getExecOutput(toolCommand, undefined, { ignoreReturnCode: true }); | ||||
|     if (exitCode) { | ||||
|         stderr = !stderr.trim() | ||||
| @ -61104,6 +61169,7 @@ exports.getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, fu | ||||
|     } | ||||
|     return stdout.trim(); | ||||
| }); | ||||
| exports.getCommandOutput = getCommandOutput; | ||||
| const getPackageManagerVersion = (packageManager, command) => __awaiter(void 0, void 0, void 0, function* () { | ||||
|     const stdOut = yield exports.getCommandOutput(`${packageManager} ${command}`); | ||||
|     if (!stdOut) { | ||||
| @ -61111,7 +61177,7 @@ const getPackageManagerVersion = (packageManager, command) => __awaiter(void 0, | ||||
|     } | ||||
|     return stdOut; | ||||
| }); | ||||
| exports.getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () { | ||||
| const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () { | ||||
|     if (packageManager === 'npm') { | ||||
|         return exports.supportedPackageManagers.npm; | ||||
|     } | ||||
| @ -61132,7 +61198,8 @@ exports.getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, vo | ||||
|         return null; | ||||
|     } | ||||
| }); | ||||
| exports.getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaiter(void 0, void 0, void 0, function* () { | ||||
| exports.getPackageManagerInfo = getPackageManagerInfo; | ||||
| const getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaiter(void 0, void 0, void 0, function* () { | ||||
|     const stdOut = yield exports.getCommandOutput(packageManagerInfo.getCacheFolderCommand); | ||||
|     if (!stdOut) { | ||||
|         throw new Error(`Could not get cache folder path for ${packageManager}`); | ||||
| @ -61140,22 +61207,21 @@ exports.getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaite | ||||
|     core.debug(`${packageManager} path is ${stdOut}`); | ||||
|     return stdOut.trim(); | ||||
| }); | ||||
| exports.getCacheDirectoryPath = getCacheDirectoryPath; | ||||
| function isGhes() { | ||||
|     const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com'); | ||||
|     return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'; | ||||
| } | ||||
| exports.isGhes = isGhes; | ||||
| function isCacheFeatureAvailable() { | ||||
|     if (!cache.isFeatureAvailable()) { | ||||
|     if (cache.isFeatureAvailable()) | ||||
|         return true; | ||||
|     if (isGhes()) { | ||||
|             throw new Error('Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.'); | ||||
|         } | ||||
|         else { | ||||
|             core.warning('The runner was not able to contact the cache service. Caching will be skipped'); | ||||
|         } | ||||
|         core.warning('Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.'); | ||||
|         return false; | ||||
|     } | ||||
|     return true; | ||||
|     core.warning('The runner was not able to contact the cache service. Caching will be skipped'); | ||||
|     return false; | ||||
| } | ||||
| exports.isCacheFeatureAvailable = isCacheFeatureAvailable; | ||||
| 
 | ||||
| @ -61168,6 +61234,7 @@ exports.isCacheFeatureAvailable = isCacheFeatureAvailable; | ||||
| "use strict"; | ||||
| 
 | ||||
| Object.defineProperty(exports, "__esModule", ({ value: true })); | ||||
| exports.Outputs = exports.State = exports.LockType = void 0; | ||||
| var LockType; | ||||
| (function (LockType) { | ||||
|     LockType["Npm"] = "npm"; | ||||
|  | ||||
							
								
								
									
										1302
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1302
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -104,6 +104,129 @@ jobs: | ||||
|       - run: npm test | ||||
| ``` | ||||
|  | ||||
| ## V8 Canary versions | ||||
|  | ||||
| You can specify a nightly version to download it from https://nodejs.org/download/v8-canary. | ||||
|  | ||||
| ### Install v8 canary build for specific node version | ||||
|  | ||||
| ```yaml | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     name: Node sample | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - uses: actions/setup-node@v3 | ||||
|         with: | ||||
|           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 test | ||||
| ``` | ||||
| ### Install v8 canary build for major node version | ||||
|  | ||||
| ```yaml | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     name: Node sample | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - uses: actions/setup-node@v3 | ||||
|         with: | ||||
|           node-version: '20-v8-canary' # it will install the latest v8 canary release for node 20 | ||||
|       - run: npm ci | ||||
|       - run: npm test | ||||
| ``` | ||||
|  | ||||
| ### Install the exact v8 canary version | ||||
|  | ||||
| ```yaml | ||||
| jobs: | ||||
|   build: | ||||
|     runs-on: ubuntu-latest | ||||
|     name: Node sample | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - uses: actions/setup-node@v3 | ||||
|         with: | ||||
|           node-version: 'v20.1.1-v8-canary20221103f7e2421e91' | ||||
|       - run: npm ci | ||||
|       - 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. | ||||
|  | ||||
|  | ||||
							
								
								
									
										72
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										72
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -10,7 +10,7 @@ | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "@actions/cache": "^3.0.4", | ||||
|         "@actions/core": "^1.6.0", | ||||
|         "@actions/core": "^1.10.0", | ||||
|         "@actions/exec": "^1.1.0", | ||||
|         "@actions/github": "^1.1.0", | ||||
|         "@actions/glob": "^0.2.0", | ||||
| @ -28,7 +28,7 @@ | ||||
|         "jest-circus": "^27.2.5", | ||||
|         "prettier": "^1.19.1", | ||||
|         "ts-jest": "^27.0.5", | ||||
|         "typescript": "^3.8.3" | ||||
|         "typescript": "^4.2.3" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@actions/cache": { | ||||
| @ -74,9 +74,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@actions/core": { | ||||
|       "version": "1.9.1", | ||||
|       "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", | ||||
|       "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", | ||||
|       "version": "1.10.0", | ||||
|       "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz", | ||||
|       "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==", | ||||
|       "dependencies": { | ||||
|         "@actions/http-client": "^2.0.1", | ||||
|         "uuid": "^8.3.2" | ||||
| @ -3779,13 +3779,10 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/json5": { | ||||
|       "version": "2.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", | ||||
|       "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", | ||||
|       "version": "2.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz", | ||||
|       "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==", | ||||
|       "dev": true, | ||||
|       "dependencies": { | ||||
|         "minimist": "^1.2.5" | ||||
|       }, | ||||
|       "bin": { | ||||
|         "json5": "lib/cli.js" | ||||
|       }, | ||||
| @ -3955,9 +3952,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/minimatch": { | ||||
|       "version": "3.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", | ||||
|       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", | ||||
|       "version": "3.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", | ||||
|       "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", | ||||
|       "dependencies": { | ||||
|         "brace-expansion": "^1.1.7" | ||||
|       }, | ||||
| @ -3965,12 +3962,6 @@ | ||||
|         "node": "*" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/minimist": { | ||||
|       "version": "1.2.6", | ||||
|       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", | ||||
|       "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "node_modules/ms": { | ||||
|       "version": "2.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", | ||||
| @ -4813,9 +4804,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/typescript": { | ||||
|       "version": "3.8.3", | ||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", | ||||
|       "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", | ||||
|       "version": "4.2.3", | ||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", | ||||
|       "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", | ||||
|       "dev": true, | ||||
|       "bin": { | ||||
|         "tsc": "bin/tsc", | ||||
| @ -5144,9 +5135,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "@actions/core": { | ||||
|       "version": "1.9.1", | ||||
|       "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", | ||||
|       "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", | ||||
|       "version": "1.10.0", | ||||
|       "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz", | ||||
|       "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==", | ||||
|       "requires": { | ||||
|         "@actions/http-client": "^2.0.1", | ||||
|         "uuid": "^8.3.2" | ||||
| @ -8088,13 +8079,10 @@ | ||||
|       "dev": true | ||||
|     }, | ||||
|     "json5": { | ||||
|       "version": "2.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", | ||||
|       "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "minimist": "^1.2.5" | ||||
|       } | ||||
|       "version": "2.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz", | ||||
|       "integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "kleur": { | ||||
|       "version": "3.0.3", | ||||
| @ -8222,19 +8210,13 @@ | ||||
|       "dev": true | ||||
|     }, | ||||
|     "minimatch": { | ||||
|       "version": "3.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", | ||||
|       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", | ||||
|       "version": "3.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", | ||||
|       "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", | ||||
|       "requires": { | ||||
|         "brace-expansion": "^1.1.7" | ||||
|       } | ||||
|     }, | ||||
|     "minimist": { | ||||
|       "version": "1.2.6", | ||||
|       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", | ||||
|       "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "ms": { | ||||
|       "version": "2.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", | ||||
| @ -8861,9 +8843,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "typescript": { | ||||
|       "version": "3.8.3", | ||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", | ||||
|       "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", | ||||
|       "version": "4.2.3", | ||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", | ||||
|       "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "universal-user-agent": { | ||||
|  | ||||
| @ -8,6 +8,7 @@ | ||||
|     "build": "ncc build -o dist/setup src/setup-node.ts && ncc build -o dist/cache-save src/cache-save.ts", | ||||
|     "format": "prettier --write **/*.ts", | ||||
|     "format-check": "prettier --check **/*.ts", | ||||
|     "lint": "echo \"Fake command that does nothing. It is used in reusable workflows\"", | ||||
|     "test": "jest --coverage", | ||||
|     "pre-checkin": "npm run format && npm run build && npm test" | ||||
|   }, | ||||
| @ -24,7 +25,7 @@ | ||||
|   "license": "MIT", | ||||
|   "dependencies": { | ||||
|     "@actions/cache": "^3.0.4", | ||||
|     "@actions/core": "^1.6.0", | ||||
|     "@actions/core": "^1.10.0", | ||||
|     "@actions/exec": "^1.1.0", | ||||
|     "@actions/github": "^1.1.0", | ||||
|     "@actions/glob": "^0.2.0", | ||||
| @ -42,6 +43,6 @@ | ||||
|     "jest-circus": "^27.2.5", | ||||
|     "prettier": "^1.19.1", | ||||
|     "ts-jest": "^27.0.5", | ||||
|     "typescript": "^3.8.3" | ||||
|     "typescript": "^4.2.3" | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -29,7 +29,7 @@ function writeRegistryToFile( | ||||
|     scope = '@' + scope; | ||||
|   } | ||||
|   if (scope) { | ||||
|     scope = scope.toLowerCase(); | ||||
|     scope = scope.toLowerCase() + ':'; | ||||
|   } | ||||
|  | ||||
|   core.debug(`Setting auth in ${fileLocation}`); | ||||
| @ -38,7 +38,7 @@ function writeRegistryToFile( | ||||
|     const curContents: string = fs.readFileSync(fileLocation, 'utf8'); | ||||
|     curContents.split(os.EOL).forEach((line: string) => { | ||||
|       // Add current contents unless they are setting the registry | ||||
|       if (!line.toLowerCase().startsWith('registry')) { | ||||
|       if (!line.toLowerCase().startsWith(`${scope}registry`)) { | ||||
|         newContents += line + os.EOL; | ||||
|       } | ||||
|     }); | ||||
| @ -46,9 +46,7 @@ function writeRegistryToFile( | ||||
|   // Remove http: or https: from front of registry. | ||||
|   const authString: string = | ||||
|     registryUrl.replace(/(^\w+:|^)/, '') + ':_authToken=${NODE_AUTH_TOKEN}'; | ||||
|   const registryString: string = scope | ||||
|     ? `${scope}:registry=${registryUrl}` | ||||
|     : `registry=${registryUrl}`; | ||||
|   const registryString: string = `${scope}registry=${registryUrl}`; | ||||
|   const alwaysAuthString: string = `always-auth=${alwaysAuth}`; | ||||
|   newContents += `${authString}${os.EOL}${registryString}${os.EOL}${alwaysAuthString}`; | ||||
|   fs.writeFileSync(fileLocation, newContents); | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -105,19 +105,18 @@ export function isGhes(): boolean { | ||||
| } | ||||
|  | ||||
| export function isCacheFeatureAvailable(): boolean { | ||||
|   if (!cache.isFeatureAvailable()) { | ||||
|   if (cache.isFeatureAvailable()) return true; | ||||
|  | ||||
|   if (isGhes()) { | ||||
|       throw new Error( | ||||
|     core.warning( | ||||
|       'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.' | ||||
|     ); | ||||
|     } else { | ||||
|       core.warning( | ||||
|         'The runner was not able to contact the cache service. Caching will be skipped' | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   return true; | ||||
|   core.warning( | ||||
|     'The runner was not able to contact the cache service. Caching will be skipped' | ||||
|   ); | ||||
|  | ||||
|   return false; | ||||
| } | ||||
|  | ||||
							
								
								
									
										53
									
								
								src/distributions/base-distribution-prerelease.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/distributions/base-distribution-prerelease.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| import * as tc from '@actions/tool-cache'; | ||||
|  | ||||
| import semver from 'semver'; | ||||
|  | ||||
| import BaseDistribution from './base-distribution'; | ||||
| import {NodeInputs} from './base-models'; | ||||
|  | ||||
| export default abstract class BasePrereleaseNodejs extends BaseDistribution { | ||||
|   protected abstract distribution: string; | ||||
|   constructor(nodeInfo: NodeInputs) { | ||||
|     super(nodeInfo); | ||||
|   } | ||||
|  | ||||
|   protected findVersionInHostedToolCacheDirectory(): string { | ||||
|     let toolPath = ''; | ||||
|     const localVersionPaths = tc | ||||
|       .findAllVersions('node', this.nodeInfo.arch) | ||||
|       .filter(i => { | ||||
|         const prerelease = semver.prerelease(i); | ||||
|         if (!prerelease) { | ||||
|           return false; | ||||
|         } | ||||
|  | ||||
|         return prerelease[0].includes(this.distribution); | ||||
|       }); | ||||
|     localVersionPaths.sort(semver.rcompare); | ||||
|     const localVersion = this.evaluateVersions(localVersionPaths); | ||||
|     if (localVersion) { | ||||
|       toolPath = tc.find('node', localVersion, this.nodeInfo.arch); | ||||
|     } | ||||
|  | ||||
|     return toolPath; | ||||
|   } | ||||
|  | ||||
|   protected validRange(versionSpec: string) { | ||||
|     let range: string; | ||||
|     const [raw, prerelease] = this.splitVersionSpec(versionSpec); | ||||
|     const isValidVersion = semver.valid(raw); | ||||
|     const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; | ||||
|  | ||||
|     if (prerelease !== this.distribution) { | ||||
|       range = versionSpec; | ||||
|     } else { | ||||
|       range = `${semver.validRange(`^${rawVersion}-${this.distribution}`)}-0`; | ||||
|     } | ||||
|  | ||||
|     return {range, options: {includePrerelease: !isValidVersion}}; | ||||
|   } | ||||
|  | ||||
|   protected splitVersionSpec(versionSpec: string) { | ||||
|     return versionSpec.split(/-(.*)/s); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										287
									
								
								src/distributions/base-distribution.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								src/distributions/base-distribution.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,287 @@ | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as hc from '@actions/http-client'; | ||||
| import * as core from '@actions/core'; | ||||
| import * as io from '@actions/io'; | ||||
|  | ||||
| import semver from 'semver'; | ||||
| import * as assert from 'assert'; | ||||
|  | ||||
| import * as path from 'path'; | ||||
| import os from 'os'; | ||||
| import fs from 'fs'; | ||||
|  | ||||
| import {NodeInputs, INodeVersion, INodeVersionInfo} from './base-models'; | ||||
|  | ||||
| export default abstract class BaseDistribution { | ||||
|   protected httpClient: hc.HttpClient; | ||||
|   protected osPlat = os.platform(); | ||||
|  | ||||
|   constructor(protected nodeInfo: NodeInputs) { | ||||
|     this.httpClient = new hc.HttpClient('setup-node', [], { | ||||
|       allowRetries: true, | ||||
|       maxRetries: 3 | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   protected abstract getDistributionUrl(): string; | ||||
|  | ||||
|   public async setupNodeJs() { | ||||
|     let nodeJsVersions: INodeVersion[] | undefined; | ||||
|     if (this.nodeInfo.checkLatest) { | ||||
|       const evaluatedVersion = await this.findVersionInDist(nodeJsVersions); | ||||
|       this.nodeInfo.versionSpec = evaluatedVersion; | ||||
|     } | ||||
|  | ||||
|     let toolPath = this.findVersionInHostedToolCacheDirectory(); | ||||
|     if (toolPath) { | ||||
|       core.info(`Found in cache @ ${toolPath}`); | ||||
|     } else { | ||||
|       const evaluatedVersion = await this.findVersionInDist(nodeJsVersions); | ||||
|       const toolName = this.getNodejsDistInfo(evaluatedVersion); | ||||
|       toolPath = await this.downloadNodejs(toolName); | ||||
|     } | ||||
|  | ||||
|     if (this.osPlat != 'win32') { | ||||
|       toolPath = path.join(toolPath, 'bin'); | ||||
|     } | ||||
|  | ||||
|     core.addPath(toolPath); | ||||
|   } | ||||
|  | ||||
|   protected async findVersionInDist(nodeJsVersions?: INodeVersion[]) { | ||||
|     if (!nodeJsVersions) { | ||||
|       nodeJsVersions = await this.getNodeJsVersions(); | ||||
|     } | ||||
|     const versions = this.filterVersions(nodeJsVersions); | ||||
|     const evaluatedVersion = this.evaluateVersions(versions); | ||||
|     if (!evaluatedVersion) { | ||||
|       throw new Error( | ||||
|         `Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.` | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     return evaluatedVersion; | ||||
|   } | ||||
|  | ||||
|   protected evaluateVersions(versions: string[]): string { | ||||
|     let version = ''; | ||||
|  | ||||
|     const {range, options} = this.validRange(this.nodeInfo.versionSpec); | ||||
|  | ||||
|     core.debug(`evaluating ${versions.length} versions`); | ||||
|  | ||||
|     for (let potential of versions) { | ||||
|       const satisfied: boolean = semver.satisfies(potential, range, options); | ||||
|       if (satisfied) { | ||||
|         version = potential; | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (version) { | ||||
|       core.debug(`matched: ${version}`); | ||||
|     } else { | ||||
|       core.debug('match not found'); | ||||
|     } | ||||
|  | ||||
|     return version; | ||||
|   } | ||||
|  | ||||
|   protected findVersionInHostedToolCacheDirectory() { | ||||
|     return tc.find('node', this.nodeInfo.versionSpec, this.nodeInfo.arch); | ||||
|   } | ||||
|  | ||||
|   protected async getNodeJsVersions(): Promise<INodeVersion[]> { | ||||
|     const initialUrl = this.getDistributionUrl(); | ||||
|     const dataUrl = `${initialUrl}/index.json`; | ||||
|  | ||||
|     let response = await this.httpClient.getJson<INodeVersion[]>(dataUrl); | ||||
|     return response.result || []; | ||||
|   } | ||||
|  | ||||
|   protected getNodejsDistInfo(version: string) { | ||||
|     let osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|     version = semver.clean(version) || ''; | ||||
|     let fileName: string = | ||||
|       this.osPlat == 'win32' | ||||
|         ? `node-v${version}-win-${osArch}` | ||||
|         : `node-v${version}-${this.osPlat}-${osArch}`; | ||||
|     let urlFileName: string = | ||||
|       this.osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; | ||||
|     const initialUrl = this.getDistributionUrl(); | ||||
|     const url = `${initialUrl}/v${version}/${urlFileName}`; | ||||
|  | ||||
|     return <INodeVersionInfo>{ | ||||
|       downloadUrl: url, | ||||
|       resolvedVersion: version, | ||||
|       arch: osArch, | ||||
|       fileName: fileName | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   protected async downloadNodejs(info: INodeVersionInfo) { | ||||
|     let downloadPath = ''; | ||||
|     core.info( | ||||
|       `Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}` | ||||
|     ); | ||||
|     try { | ||||
|       downloadPath = await tc.downloadTool(info.downloadUrl); | ||||
|     } catch (err) { | ||||
|       if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { | ||||
|         return await this.acquireNodeFromFallbackLocation( | ||||
|           info.resolvedVersion, | ||||
|           info.arch | ||||
|         ); | ||||
|       } | ||||
|  | ||||
|       throw err; | ||||
|     } | ||||
|  | ||||
|     let toolPath = await this.extractArchive(downloadPath, info); | ||||
|     core.info('Done'); | ||||
|  | ||||
|     return toolPath; | ||||
|   } | ||||
|  | ||||
|   protected validRange(versionSpec: string) { | ||||
|     let options: semver.Options | undefined; | ||||
|     const c = semver.clean(versionSpec) || ''; | ||||
|     const valid = semver.valid(c) ?? versionSpec; | ||||
|  | ||||
|     return {range: valid, options}; | ||||
|   } | ||||
|  | ||||
|   protected async acquireNodeFromFallbackLocation( | ||||
|     version: string, | ||||
|     arch: string = os.arch() | ||||
|   ): Promise<string> { | ||||
|     const initialUrl = this.getDistributionUrl(); | ||||
|     let osArch: string = this.translateArchToDistUrl(arch); | ||||
|  | ||||
|     // Create temporary folder to download in to | ||||
|     const tempDownloadFolder: string = | ||||
|       'temp_' + Math.floor(Math.random() * 2000000000); | ||||
|     const tempDirectory = process.env['RUNNER_TEMP'] || ''; | ||||
|     assert.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined'); | ||||
|     const tempDir: string = path.join(tempDirectory, tempDownloadFolder); | ||||
|     await io.mkdirP(tempDir); | ||||
|     let exeUrl: string; | ||||
|     let libUrl: string; | ||||
|     try { | ||||
|       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 = await tc.downloadTool(exeUrl); | ||||
|       await io.cp(exePath, path.join(tempDir, 'node.exe')); | ||||
|       const libPath = await tc.downloadTool(libUrl); | ||||
|       await io.cp(libPath, path.join(tempDir, 'node.lib')); | ||||
|     } catch (err) { | ||||
|       if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { | ||||
|         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')); | ||||
|         const libPath = await tc.downloadTool(libUrl); | ||||
|         await io.cp(libPath, path.join(tempDir, 'node.lib')); | ||||
|       } else { | ||||
|         throw err; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     const toolPath = await tc.cacheDir(tempDir, 'node', version, arch); | ||||
|  | ||||
|     return toolPath; | ||||
|   } | ||||
|  | ||||
|   protected async extractArchive( | ||||
|     downloadPath: string, | ||||
|     info: INodeVersionInfo | null | ||||
|   ) { | ||||
|     // | ||||
|     // Extract | ||||
|     // | ||||
|     core.info('Extracting ...'); | ||||
|     let extPath: string; | ||||
|     info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here | ||||
|     if (this.osPlat == 'win32') { | ||||
|       const _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe'); | ||||
|       extPath = await tc.extract7z(downloadPath, undefined, _7zPath); | ||||
|       // 7z extracts to folder matching file name | ||||
|       const nestedPath = path.join( | ||||
|         extPath, | ||||
|         path.basename(info.fileName, '.7z') | ||||
|       ); | ||||
|       if (fs.existsSync(nestedPath)) { | ||||
|         extPath = nestedPath; | ||||
|       } | ||||
|     } else { | ||||
|       extPath = await tc.extractTar(downloadPath, undefined, [ | ||||
|         'xz', | ||||
|         '--strip', | ||||
|         '1' | ||||
|       ]); | ||||
|     } | ||||
|  | ||||
|     // | ||||
|     // Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded | ||||
|     // | ||||
|     core.info('Adding to the cache ...'); | ||||
|     const toolPath = await tc.cacheDir( | ||||
|       extPath, | ||||
|       'node', | ||||
|       info.resolvedVersion, | ||||
|       info.arch | ||||
|     ); | ||||
|  | ||||
|     return toolPath; | ||||
|   } | ||||
|  | ||||
|   protected getDistFileName(): string { | ||||
|     let osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|  | ||||
|     // node offers a json list of versions | ||||
|     let dataFileName: string; | ||||
|     switch (this.osPlat) { | ||||
|       case 'linux': | ||||
|         dataFileName = `linux-${osArch}`; | ||||
|         break; | ||||
|       case 'darwin': | ||||
|         dataFileName = `osx-${osArch}-tar`; | ||||
|         break; | ||||
|       case 'win32': | ||||
|         dataFileName = `win-${osArch}-exe`; | ||||
|         break; | ||||
|       default: | ||||
|         throw new Error(`Unexpected OS '${this.osPlat}'`); | ||||
|     } | ||||
|  | ||||
|     return dataFileName; | ||||
|   } | ||||
|  | ||||
|   protected filterVersions(nodeJsVersions: INodeVersion[]) { | ||||
|     const versions: string[] = []; | ||||
|  | ||||
|     const dataFileName = this.getDistFileName(); | ||||
|  | ||||
|     nodeJsVersions.forEach((nodeVersion: INodeVersion) => { | ||||
|       // ensure this version supports your os and platform | ||||
|       if (nodeVersion.files.indexOf(dataFileName) >= 0) { | ||||
|         versions.push(nodeVersion.version); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     return versions.sort(semver.rcompare); | ||||
|   } | ||||
|  | ||||
|   protected translateArchToDistUrl(arch: string): string { | ||||
|     switch (arch) { | ||||
|       case 'arm': | ||||
|         return 'armv7l'; | ||||
|       default: | ||||
|         return arch; | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/distributions/base-models.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/distributions/base-models.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| export interface NodeInputs { | ||||
|   versionSpec: string; | ||||
|   arch: string; | ||||
|   auth?: string; | ||||
|   checkLatest: boolean; | ||||
|   stable: boolean; | ||||
| } | ||||
|  | ||||
| export interface INodeVersionInfo { | ||||
|   downloadUrl: string; | ||||
|   resolvedVersion: string; | ||||
|   arch: string; | ||||
|   fileName: string; | ||||
| } | ||||
|  | ||||
| export interface INodeVersion { | ||||
|   version: string; | ||||
|   files: string[]; | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/distributions/installer-factory.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/distributions/installer-factory.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| import BaseDistribution from './base-distribution'; | ||||
| import {NodeInputs} from './base-models'; | ||||
| import NightlyNodejs from './nightly/nightly_builds'; | ||||
| import OfficialBuilds from './official_builds/official_builds'; | ||||
| import RcBuild from './rc/rc_builds'; | ||||
| import CanaryBuild from './v8-canary/canary_builds'; | ||||
|  | ||||
| enum Distributions { | ||||
|   DEFAULT = '', | ||||
|   CANARY = 'v8-canary', | ||||
|   NIGHTLY = 'nightly', | ||||
|   RC = 'rc' | ||||
| } | ||||
|  | ||||
| export function getNodejsDistribution( | ||||
|   installerOptions: NodeInputs | ||||
| ): BaseDistribution { | ||||
|   const versionSpec = installerOptions.versionSpec; | ||||
|   let distribution: BaseDistribution; | ||||
|   if (versionSpec.includes(Distributions.NIGHTLY)) { | ||||
|     distribution = new NightlyNodejs(installerOptions); | ||||
|   } else if (versionSpec.includes(Distributions.CANARY)) { | ||||
|     distribution = new CanaryBuild(installerOptions); | ||||
|   } else if (versionSpec.includes(Distributions.RC)) { | ||||
|     distribution = new RcBuild(installerOptions); | ||||
|   } else { | ||||
|     distribution = new OfficialBuilds(installerOptions); | ||||
|   } | ||||
|  | ||||
|   return distribution; | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/distributions/nightly/nightly_builds.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/distributions/nightly/nightly_builds.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| import BasePrereleaseNodejs from '../base-distribution-prerelease'; | ||||
| import {NodeInputs} from '../base-models'; | ||||
|  | ||||
| export default class NightlyNodejs extends BasePrereleaseNodejs { | ||||
|   protected distribution = 'nightly'; | ||||
|   constructor(nodeInfo: NodeInputs) { | ||||
|     super(nodeInfo); | ||||
|   } | ||||
|  | ||||
|   protected getDistributionUrl(): string { | ||||
|     return 'https://nodejs.org/download/nightly'; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										258
									
								
								src/distributions/official_builds/official_builds.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								src/distributions/official_builds/official_builds.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,258 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import path from 'path'; | ||||
|  | ||||
| import BaseDistribution from '../base-distribution'; | ||||
| import {NodeInputs, INodeVersion, INodeVersionInfo} from '../base-models'; | ||||
|  | ||||
| interface INodeRelease extends tc.IToolRelease { | ||||
|   lts?: string; | ||||
| } | ||||
|  | ||||
| export default class OfficialBuilds extends BaseDistribution { | ||||
|   constructor(nodeInfo: NodeInputs) { | ||||
|     super(nodeInfo); | ||||
|   } | ||||
|  | ||||
|   public async setupNodeJs() { | ||||
|     let manifest: tc.IToolRelease[] | undefined; | ||||
|     let nodeJsVersions: INodeVersion[] | undefined; | ||||
|     const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|     if (this.isLtsAlias(this.nodeInfo.versionSpec)) { | ||||
|       core.info('Attempt to resolve LTS alias from manifest...'); | ||||
|  | ||||
|       // No try-catch since it's not possible to resolve LTS alias without manifest | ||||
|       manifest = await this.getManifest(); | ||||
|  | ||||
|       this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest( | ||||
|         this.nodeInfo.versionSpec, | ||||
|         this.nodeInfo.stable, | ||||
|         manifest | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { | ||||
|       nodeJsVersions = await this.getNodeJsVersions(); | ||||
|       const versions = this.filterVersions(nodeJsVersions); | ||||
|       this.nodeInfo.versionSpec = this.evaluateVersions(versions); | ||||
|  | ||||
|       core.info('getting latest node version...'); | ||||
|     } | ||||
|  | ||||
|     if (this.nodeInfo.checkLatest) { | ||||
|       core.info('Attempt to resolve the latest version from manifest...'); | ||||
|       const resolvedVersion = await this.resolveVersionFromManifest( | ||||
|         this.nodeInfo.versionSpec, | ||||
|         this.nodeInfo.stable, | ||||
|         osArch, | ||||
|         manifest | ||||
|       ); | ||||
|       if (resolvedVersion) { | ||||
|         this.nodeInfo.versionSpec = resolvedVersion; | ||||
|         core.info(`Resolved as '${resolvedVersion}'`); | ||||
|       } else { | ||||
|         core.info( | ||||
|           `Failed to resolve version ${this.nodeInfo.versionSpec} from manifest` | ||||
|         ); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     let toolPath = this.findVersionInHostedToolCacheDirectory(); | ||||
|  | ||||
|     if (toolPath) { | ||||
|       core.info(`Found in cache @ ${toolPath}`); | ||||
|     } else { | ||||
|       let downloadPath = ''; | ||||
|       try { | ||||
|         core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); | ||||
|  | ||||
|         const versionInfo = await this.getInfoFromManifest( | ||||
|           this.nodeInfo.versionSpec, | ||||
|           this.nodeInfo.stable, | ||||
|           osArch, | ||||
|           manifest | ||||
|         ); | ||||
|         if (versionInfo) { | ||||
|           core.info( | ||||
|             `Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}` | ||||
|           ); | ||||
|           downloadPath = await tc.downloadTool( | ||||
|             versionInfo.downloadUrl, | ||||
|             undefined, | ||||
|             this.nodeInfo.auth | ||||
|           ); | ||||
|  | ||||
|           if (downloadPath) { | ||||
|             toolPath = await this.extractArchive(downloadPath, versionInfo); | ||||
|           } | ||||
|         } else { | ||||
|           core.info( | ||||
|             'Not found in manifest. Falling back to download directly from Node' | ||||
|           ); | ||||
|         } | ||||
|       } catch (err) { | ||||
|         // Rate limit? | ||||
|         if ( | ||||
|           err instanceof tc.HTTPError && | ||||
|           (err.httpStatusCode === 403 || err.httpStatusCode === 429) | ||||
|         ) { | ||||
|           core.info( | ||||
|             `Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded` | ||||
|           ); | ||||
|         } else { | ||||
|           core.info(err.message); | ||||
|         } | ||||
|         core.debug(err.stack); | ||||
|         core.info('Falling back to download directly from Node'); | ||||
|       } | ||||
|  | ||||
|       if (!toolPath) { | ||||
|         const nodeJsVersions = await this.getNodeJsVersions(); | ||||
|         const versions = this.filterVersions(nodeJsVersions); | ||||
|         const evaluatedVersion = this.evaluateVersions(versions); | ||||
|         if (!evaluatedVersion) { | ||||
|           throw new Error( | ||||
|             `Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.` | ||||
|           ); | ||||
|         } | ||||
|         const toolName = this.getNodejsDistInfo(evaluatedVersion); | ||||
|         toolPath = await this.downloadNodejs(toolName); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (this.osPlat != 'win32') { | ||||
|       toolPath = path.join(toolPath, 'bin'); | ||||
|     } | ||||
|  | ||||
|     core.addPath(toolPath); | ||||
|   } | ||||
|  | ||||
|   protected evaluateVersions(versions: string[]): string { | ||||
|     let version = ''; | ||||
|  | ||||
|     if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { | ||||
|       core.info(`getting latest node version...`); | ||||
|       return versions[0]; | ||||
|     } | ||||
|  | ||||
|     version = super.evaluateVersions(versions); | ||||
|  | ||||
|     return version; | ||||
|   } | ||||
|  | ||||
|   protected getDistributionUrl(): string { | ||||
|     return `https://nodejs.org/dist`; | ||||
|   } | ||||
|  | ||||
|   private getManifest(): Promise<tc.IToolRelease[]> { | ||||
|     core.debug('Getting manifest from actions/node-versions@main'); | ||||
|     return tc.getManifestFromRepo( | ||||
|       'actions', | ||||
|       'node-versions', | ||||
|       this.nodeInfo.auth, | ||||
|       'main' | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   private resolveLtsAliasFromManifest( | ||||
|     versionSpec: string, | ||||
|     stable: boolean, | ||||
|     manifest: INodeRelease[] | ||||
|   ): string { | ||||
|     const alias = versionSpec.split('lts/')[1]?.toLowerCase(); | ||||
|  | ||||
|     if (!alias) { | ||||
|       throw new Error( | ||||
|         `Unable to parse LTS alias for Node version '${versionSpec}'` | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     core.debug(`LTS alias '${alias}' for Node version '${versionSpec}'`); | ||||
|  | ||||
|     // Supported formats are `lts/<alias>`, `lts/*`, and `lts/-n`. Where asterisk means highest possible LTS and -n means the nth-highest. | ||||
|     const n = Number(alias); | ||||
|     const aliases = Object.fromEntries( | ||||
|       manifest | ||||
|         .filter(x => x.lts && x.stable === stable) | ||||
|         .map(x => [x.lts!.toLowerCase(), x]) | ||||
|         .reverse() | ||||
|     ); | ||||
|     const numbered = Object.values(aliases); | ||||
|     const release = | ||||
|       alias === '*' | ||||
|         ? numbered[numbered.length - 1] | ||||
|         : n < 0 | ||||
|         ? numbered[numbered.length - 1 + n] | ||||
|         : aliases[alias]; | ||||
|  | ||||
|     if (!release) { | ||||
|       throw new Error( | ||||
|         `Unable to find LTS release '${alias}' for Node version '${versionSpec}'.` | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     core.debug( | ||||
|       `Found LTS release '${release.version}' for Node version '${versionSpec}'` | ||||
|     ); | ||||
|  | ||||
|     return release.version.split('.')[0]; | ||||
|   } | ||||
|  | ||||
|   private async resolveVersionFromManifest( | ||||
|     versionSpec: string, | ||||
|     stable: boolean, | ||||
|     osArch: string, | ||||
|     manifest: tc.IToolRelease[] | undefined | ||||
|   ): Promise<string | undefined> { | ||||
|     try { | ||||
|       const info = await this.getInfoFromManifest( | ||||
|         versionSpec, | ||||
|         stable, | ||||
|         osArch, | ||||
|         manifest | ||||
|       ); | ||||
|       return info?.resolvedVersion; | ||||
|     } catch (err) { | ||||
|       core.info('Unable to resolve version from manifest...'); | ||||
|       core.debug(err.message); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private async getInfoFromManifest( | ||||
|     versionSpec: string, | ||||
|     stable: boolean, | ||||
|     osArch: string, | ||||
|     manifest: tc.IToolRelease[] | undefined | ||||
|   ): Promise<INodeVersionInfo | null> { | ||||
|     let info: INodeVersionInfo | null = null; | ||||
|     if (!manifest) { | ||||
|       core.debug('No manifest cached'); | ||||
|       manifest = await this.getManifest(); | ||||
|     } | ||||
|  | ||||
|     const rel = await tc.findFromManifest( | ||||
|       versionSpec, | ||||
|       stable, | ||||
|       manifest, | ||||
|       osArch | ||||
|     ); | ||||
|  | ||||
|     if (rel && rel.files.length > 0) { | ||||
|       info = <INodeVersionInfo>{}; | ||||
|       info.resolvedVersion = rel.version; | ||||
|       info.arch = rel.files[0].arch; | ||||
|       info.downloadUrl = rel.files[0].download_url; | ||||
|       info.fileName = rel.files[0].filename; | ||||
|     } | ||||
|  | ||||
|     return info; | ||||
|   } | ||||
|  | ||||
|   private isLtsAlias(versionSpec: string): boolean { | ||||
|     return versionSpec.startsWith('lts/'); | ||||
|   } | ||||
|  | ||||
|   private isLatestSyntax(versionSpec): boolean { | ||||
|     return ['current', 'latest', 'node'].includes(versionSpec); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										12
									
								
								src/distributions/rc/rc_builds.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/distributions/rc/rc_builds.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| import BaseDistribution from '../base-distribution'; | ||||
| import {NodeInputs} from '../base-models'; | ||||
|  | ||||
| export default class RcBuild extends BaseDistribution { | ||||
|   constructor(nodeInfo: NodeInputs) { | ||||
|     super(nodeInfo); | ||||
|   } | ||||
|  | ||||
|   getDistributionUrl(): string { | ||||
|     return 'https://nodejs.org/download/rc'; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/distributions/v8-canary/canary_builds.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/distributions/v8-canary/canary_builds.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| import BasePrereleaseNodejs from '../base-distribution-prerelease'; | ||||
| import {NodeInputs} from '../base-models'; | ||||
|  | ||||
| export default class CanaryBuild extends BasePrereleaseNodejs { | ||||
|   protected distribution = 'v8-canary'; | ||||
|   constructor(nodeInfo: NodeInputs) { | ||||
|     super(nodeInfo); | ||||
|   } | ||||
|  | ||||
|   protected getDistributionUrl(): string { | ||||
|     return 'https://nodejs.org/download/v8-canary'; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										522
									
								
								src/installer.ts
									
									
									
									
									
								
							
							
						
						
									
										522
									
								
								src/installer.ts
									
									
									
									
									
								
							| @ -1,522 +0,0 @@ | ||||
| import os = require('os'); | ||||
| import * as assert from 'assert'; | ||||
| import * as core from '@actions/core'; | ||||
| import * as hc from '@actions/http-client'; | ||||
| import * as io from '@actions/io'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as path from 'path'; | ||||
| import * as semver from 'semver'; | ||||
| import fs = require('fs'); | ||||
|  | ||||
| // | ||||
| // Node versions interface | ||||
| // see https://nodejs.org/dist/index.json | ||||
| // | ||||
| export interface INodeVersion { | ||||
|   version: string; | ||||
|   files: string[]; | ||||
| } | ||||
|  | ||||
| interface INodeVersionInfo { | ||||
|   downloadUrl: string; | ||||
|   resolvedVersion: string; | ||||
|   arch: string; | ||||
|   fileName: string; | ||||
| } | ||||
|  | ||||
| interface INodeRelease extends tc.IToolRelease { | ||||
|   lts?: string; | ||||
| } | ||||
|  | ||||
| export async function getNode( | ||||
|   versionSpec: string, | ||||
|   stable: boolean, | ||||
|   checkLatest: boolean, | ||||
|   auth: string | undefined, | ||||
|   arch: string = os.arch() | ||||
| ) { | ||||
|   // Store manifest data to avoid multiple calls | ||||
|   let manifest: INodeRelease[] | undefined; | ||||
|   let nodeVersions: INodeVersion[] | undefined; | ||||
|   let osPlat: string = os.platform(); | ||||
|   let osArch: string = translateArchToDistUrl(arch); | ||||
|  | ||||
|   if (isLtsAlias(versionSpec)) { | ||||
|     core.info('Attempt to resolve LTS alias from manifest...'); | ||||
|  | ||||
|     // No try-catch since it's not possible to resolve LTS alias without manifest | ||||
|     manifest = await getManifest(auth); | ||||
|  | ||||
|     versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); | ||||
|   } | ||||
|  | ||||
|   if (isLatestSyntax(versionSpec)) { | ||||
|     nodeVersions = await getVersionsFromDist(); | ||||
|     versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); | ||||
|     core.info(`getting latest node version...`); | ||||
|   } | ||||
|  | ||||
|   if (checkLatest) { | ||||
|     core.info('Attempt to resolve the latest version from manifest...'); | ||||
|     const resolvedVersion = await resolveVersionFromManifest( | ||||
|       versionSpec, | ||||
|       stable, | ||||
|       auth, | ||||
|       osArch, | ||||
|       manifest | ||||
|     ); | ||||
|     if (resolvedVersion) { | ||||
|       versionSpec = resolvedVersion; | ||||
|       core.info(`Resolved as '${versionSpec}'`); | ||||
|     } else { | ||||
|       core.info(`Failed to resolve version ${versionSpec} from manifest`); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // check cache | ||||
|   let toolPath: string; | ||||
|   toolPath = tc.find('node', versionSpec, osArch); | ||||
|  | ||||
|   // If not found in cache, download | ||||
|   if (toolPath) { | ||||
|     core.info(`Found in cache @ ${toolPath}`); | ||||
|   } else { | ||||
|     core.info(`Attempting to download ${versionSpec}...`); | ||||
|     let downloadPath = ''; | ||||
|     let info: INodeVersionInfo | null = null; | ||||
|  | ||||
|     // | ||||
|     // Try download from internal distribution (popular versions only) | ||||
|     // | ||||
|     try { | ||||
|       info = await getInfoFromManifest( | ||||
|         versionSpec, | ||||
|         stable, | ||||
|         auth, | ||||
|         osArch, | ||||
|         manifest | ||||
|       ); | ||||
|       if (info) { | ||||
|         core.info( | ||||
|           `Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}` | ||||
|         ); | ||||
|         downloadPath = await tc.downloadTool(info.downloadUrl, undefined, auth); | ||||
|       } else { | ||||
|         core.info( | ||||
|           'Not found in manifest.  Falling back to download directly from Node' | ||||
|         ); | ||||
|       } | ||||
|     } catch (err) { | ||||
|       // Rate limit? | ||||
|       if ( | ||||
|         err instanceof tc.HTTPError && | ||||
|         (err.httpStatusCode === 403 || err.httpStatusCode === 429) | ||||
|       ) { | ||||
|         core.info( | ||||
|           `Received HTTP status code ${err.httpStatusCode}.  This usually indicates the rate limit has been exceeded` | ||||
|         ); | ||||
|       } else { | ||||
|         core.info(err.message); | ||||
|       } | ||||
|       core.debug(err.stack); | ||||
|       core.info('Falling back to download directly from Node'); | ||||
|     } | ||||
|  | ||||
|     // | ||||
|     // Download from nodejs.org | ||||
|     // | ||||
|     if (!downloadPath) { | ||||
|       info = await getInfoFromDist(versionSpec, arch, nodeVersions); | ||||
|       if (!info) { | ||||
|         throw new Error( | ||||
|           `Unable to find Node version '${versionSpec}' for platform ${osPlat} and architecture ${osArch}.` | ||||
|         ); | ||||
|       } | ||||
|  | ||||
|       core.info( | ||||
|         `Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}` | ||||
|       ); | ||||
|       try { | ||||
|         downloadPath = await tc.downloadTool(info.downloadUrl); | ||||
|       } catch (err) { | ||||
|         if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { | ||||
|           return await acquireNodeFromFallbackLocation( | ||||
|             info.resolvedVersion, | ||||
|             info.arch | ||||
|           ); | ||||
|         } | ||||
|  | ||||
|         throw err; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // | ||||
|     // Extract | ||||
|     // | ||||
|     core.info('Extracting ...'); | ||||
|     let extPath: string; | ||||
|     info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here | ||||
|     if (osPlat == 'win32') { | ||||
|       let _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe'); | ||||
|       extPath = await tc.extract7z(downloadPath, undefined, _7zPath); | ||||
|       // 7z extracts to folder matching file name | ||||
|       let nestedPath = path.join(extPath, path.basename(info.fileName, '.7z')); | ||||
|       if (fs.existsSync(nestedPath)) { | ||||
|         extPath = nestedPath; | ||||
|       } | ||||
|     } else { | ||||
|       extPath = await tc.extractTar(downloadPath, undefined, [ | ||||
|         'xz', | ||||
|         '--strip', | ||||
|         '1' | ||||
|       ]); | ||||
|     } | ||||
|  | ||||
|     // | ||||
|     // Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded | ||||
|     // | ||||
|     core.info('Adding to the cache ...'); | ||||
|     toolPath = await tc.cacheDir( | ||||
|       extPath, | ||||
|       'node', | ||||
|       info.resolvedVersion, | ||||
|       info.arch | ||||
|     ); | ||||
|     core.info('Done'); | ||||
|   } | ||||
|  | ||||
|   // | ||||
|   // a tool installer initimately knows details about the layout of that tool | ||||
|   // for example, node binary is in the bin folder after the extract on Mac/Linux. | ||||
|   // layouts could change by version, by platform etc... but that's the tool installers job | ||||
|   // | ||||
|   if (osPlat != 'win32') { | ||||
|     toolPath = path.join(toolPath, 'bin'); | ||||
|   } | ||||
|  | ||||
|   // | ||||
|   // prepend the tools path. instructs the agent to prepend for future tasks | ||||
|   core.addPath(toolPath); | ||||
| } | ||||
|  | ||||
| function isLtsAlias(versionSpec: string): boolean { | ||||
|   return versionSpec.startsWith('lts/'); | ||||
| } | ||||
|  | ||||
| function getManifest(auth: string | undefined): Promise<tc.IToolRelease[]> { | ||||
|   core.debug('Getting manifest from actions/node-versions@main'); | ||||
|   return tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); | ||||
| } | ||||
|  | ||||
| function resolveLtsAliasFromManifest( | ||||
|   versionSpec: string, | ||||
|   stable: boolean, | ||||
|   manifest: INodeRelease[] | ||||
| ): string { | ||||
|   const alias = versionSpec.split('lts/')[1]?.toLowerCase(); | ||||
|  | ||||
|   if (!alias) { | ||||
|     throw new Error( | ||||
|       `Unable to parse LTS alias for Node version '${versionSpec}'` | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   core.debug(`LTS alias '${alias}' for Node version '${versionSpec}'`); | ||||
|  | ||||
|   // Supported formats are `lts/<alias>`, `lts/*`, and `lts/-n`. Where asterisk means highest possible LTS and -n means the nth-highest. | ||||
|   const n = Number(alias); | ||||
|   const aliases = Object.fromEntries( | ||||
|     manifest | ||||
|       .filter(x => x.lts && x.stable === stable) | ||||
|       .map(x => [x.lts!.toLowerCase(), x]) | ||||
|       .reverse() | ||||
|   ); | ||||
|   const numbered = Object.values(aliases); | ||||
|   const release = | ||||
|     alias === '*' | ||||
|       ? numbered[numbered.length - 1] | ||||
|       : n < 0 | ||||
|       ? numbered[numbered.length - 1 + n] | ||||
|       : aliases[alias]; | ||||
|  | ||||
|   if (!release) { | ||||
|     throw new Error( | ||||
|       `Unable to find LTS release '${alias}' for Node version '${versionSpec}'.` | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   core.debug( | ||||
|     `Found LTS release '${release.version}' for Node version '${versionSpec}'` | ||||
|   ); | ||||
|  | ||||
|   return release.version.split('.')[0]; | ||||
| } | ||||
|  | ||||
| async function getInfoFromManifest( | ||||
|   versionSpec: string, | ||||
|   stable: boolean, | ||||
|   auth: string | undefined, | ||||
|   osArch: string = translateArchToDistUrl(os.arch()), | ||||
|   manifest: tc.IToolRelease[] | undefined | ||||
| ): Promise<INodeVersionInfo | null> { | ||||
|   let info: INodeVersionInfo | null = null; | ||||
|   if (!manifest) { | ||||
|     core.debug('No manifest cached'); | ||||
|     manifest = await getManifest(auth); | ||||
|   } | ||||
|  | ||||
|   const rel = await tc.findFromManifest(versionSpec, stable, manifest, osArch); | ||||
|  | ||||
|   if (rel && rel.files.length > 0) { | ||||
|     info = <INodeVersionInfo>{}; | ||||
|     info.resolvedVersion = rel.version; | ||||
|     info.arch = rel.files[0].arch; | ||||
|     info.downloadUrl = rel.files[0].download_url; | ||||
|     info.fileName = rel.files[0].filename; | ||||
|   } | ||||
|  | ||||
|   return info; | ||||
| } | ||||
|  | ||||
| async function getInfoFromDist( | ||||
|   versionSpec: string, | ||||
|   arch: string = os.arch(), | ||||
|   nodeVersions?: INodeVersion[] | ||||
| ): Promise<INodeVersionInfo | null> { | ||||
|   let osPlat: string = os.platform(); | ||||
|   let osArch: string = translateArchToDistUrl(arch); | ||||
|  | ||||
|   let version: string = await queryDistForMatch( | ||||
|     versionSpec, | ||||
|     arch, | ||||
|     nodeVersions | ||||
|   ); | ||||
|  | ||||
|   if (!version) { | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   // | ||||
|   // Download - a tool installer intimately knows how to get the tool (and construct urls) | ||||
|   // | ||||
|   version = semver.clean(version) || ''; | ||||
|   let fileName: string = | ||||
|     osPlat == 'win32' | ||||
|       ? `node-v${version}-win-${osArch}` | ||||
|       : `node-v${version}-${osPlat}-${osArch}`; | ||||
|   let urlFileName: string = | ||||
|     osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; | ||||
|   let url = `https://nodejs.org/dist/v${version}/${urlFileName}`; | ||||
|  | ||||
|   return <INodeVersionInfo>{ | ||||
|     downloadUrl: url, | ||||
|     resolvedVersion: version, | ||||
|     arch: arch, | ||||
|     fileName: fileName | ||||
|   }; | ||||
| } | ||||
|  | ||||
| async function resolveVersionFromManifest( | ||||
|   versionSpec: string, | ||||
|   stable: boolean, | ||||
|   auth: string | undefined, | ||||
|   osArch: string = translateArchToDistUrl(os.arch()), | ||||
|   manifest: tc.IToolRelease[] | undefined | ||||
| ): Promise<string | undefined> { | ||||
|   try { | ||||
|     const info = await getInfoFromManifest( | ||||
|       versionSpec, | ||||
|       stable, | ||||
|       auth, | ||||
|       osArch, | ||||
|       manifest | ||||
|     ); | ||||
|     return info?.resolvedVersion; | ||||
|   } catch (err) { | ||||
|     core.info('Unable to resolve version from manifest...'); | ||||
|     core.debug(err.message); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // TODO - should we just export this from @actions/tool-cache? Lifted directly from there | ||||
| 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; | ||||
|   }); | ||||
|   for (let i = versions.length - 1; i >= 0; i--) { | ||||
|     const potential: string = versions[i]; | ||||
|     const satisfied: boolean = semver.satisfies(potential, versionSpec); | ||||
|     if (satisfied) { | ||||
|       version = potential; | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (version) { | ||||
|     core.debug(`matched: ${version}`); | ||||
|   } else { | ||||
|     core.debug('match not found'); | ||||
|   } | ||||
|  | ||||
|   return version; | ||||
| } | ||||
|  | ||||
| async function queryDistForMatch( | ||||
|   versionSpec: string, | ||||
|   arch: string = os.arch(), | ||||
|   nodeVersions?: INodeVersion[] | ||||
| ): Promise<string> { | ||||
|   let osPlat: string = os.platform(); | ||||
|   let osArch: string = translateArchToDistUrl(arch); | ||||
|  | ||||
|   // node offers a json list of versions | ||||
|   let dataFileName: string; | ||||
|   switch (osPlat) { | ||||
|     case 'linux': | ||||
|       dataFileName = `linux-${osArch}`; | ||||
|       break; | ||||
|     case 'darwin': | ||||
|       dataFileName = `osx-${osArch}-tar`; | ||||
|       break; | ||||
|     case 'win32': | ||||
|       dataFileName = `win-${osArch}-exe`; | ||||
|       break; | ||||
|     default: | ||||
|       throw new Error(`Unexpected OS '${osPlat}'`); | ||||
|   } | ||||
|  | ||||
|   if (!nodeVersions) { | ||||
|     core.debug('No dist manifest cached'); | ||||
|     nodeVersions = await getVersionsFromDist(); | ||||
|   } | ||||
|  | ||||
|   let versions: string[] = []; | ||||
|  | ||||
|   if (isLatestSyntax(versionSpec)) { | ||||
|     core.info(`getting latest node version...`); | ||||
|     return nodeVersions[0].version; | ||||
|   } | ||||
|  | ||||
|   nodeVersions.forEach((nodeVersion: INodeVersion) => { | ||||
|     // ensure this version supports your os and platform | ||||
|     if (nodeVersion.files.indexOf(dataFileName) >= 0) { | ||||
|       versions.push(nodeVersion.version); | ||||
|     } | ||||
|   }); | ||||
|  | ||||
|   // get the latest version that matches the version spec | ||||
|   let version: string = evaluateVersions(versions, versionSpec); | ||||
|   return version; | ||||
| } | ||||
|  | ||||
| export async function getVersionsFromDist(): Promise<INodeVersion[]> { | ||||
|   let dataUrl = 'https://nodejs.org/dist/index.json'; | ||||
|   let httpClient = new hc.HttpClient('setup-node', [], { | ||||
|     allowRetries: true, | ||||
|     maxRetries: 3 | ||||
|   }); | ||||
|   let response = await httpClient.getJson<INodeVersion[]>(dataUrl); | ||||
|   return response.result || []; | ||||
| } | ||||
|  | ||||
| // For non LTS versions of Node, the files we need (for Windows) are sometimes located | ||||
| // in a different folder than they normally are for other versions. | ||||
| // Normally the format is similar to: https://nodejs.org/dist/v5.10.1/node-v5.10.1-win-x64.7z | ||||
| // In this case, there will be two files located at: | ||||
| //      /dist/v5.10.1/win-x64/node.exe | ||||
| //      /dist/v5.10.1/win-x64/node.lib | ||||
| // If this is not the structure, there may also be two files located at: | ||||
| //      /dist/v0.12.18/node.exe | ||||
| //      /dist/v0.12.18/node.lib | ||||
| // 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. | ||||
| async function acquireNodeFromFallbackLocation( | ||||
|   version: string, | ||||
|   arch: string = os.arch() | ||||
| ): Promise<string> { | ||||
|   let osPlat: string = os.platform(); | ||||
|   let osArch: string = translateArchToDistUrl(arch); | ||||
|  | ||||
|   // Create temporary folder to download in to | ||||
|   const tempDownloadFolder: string = | ||||
|     'temp_' + Math.floor(Math.random() * 2000000000); | ||||
|   const tempDirectory = process.env['RUNNER_TEMP'] || ''; | ||||
|   assert.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined'); | ||||
|   const tempDir: string = path.join(tempDirectory, tempDownloadFolder); | ||||
|   await io.mkdirP(tempDir); | ||||
|   let exeUrl: string; | ||||
|   let libUrl: string; | ||||
|   try { | ||||
|     exeUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.exe`; | ||||
|     libUrl = `https://nodejs.org/dist/v${version}/win-${osArch}/node.lib`; | ||||
|  | ||||
|     core.info(`Downloading only node binary from ${exeUrl}`); | ||||
|  | ||||
|     const exePath = await tc.downloadTool(exeUrl); | ||||
|     await io.cp(exePath, path.join(tempDir, 'node.exe')); | ||||
|     const libPath = await tc.downloadTool(libUrl); | ||||
|     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`; | ||||
|  | ||||
|       const exePath = await tc.downloadTool(exeUrl); | ||||
|       await io.cp(exePath, path.join(tempDir, 'node.exe')); | ||||
|       const libPath = await tc.downloadTool(libUrl); | ||||
|       await io.cp(libPath, path.join(tempDir, 'node.lib')); | ||||
|     } else { | ||||
|       throw err; | ||||
|     } | ||||
|   } | ||||
|   let toolPath = await tc.cacheDir(tempDir, 'node', version, arch); | ||||
|   core.addPath(toolPath); | ||||
|   return toolPath; | ||||
| } | ||||
|  | ||||
| // os.arch does not always match the relative download url, e.g. | ||||
| // os.arch == 'arm' != node-v12.13.1-linux-armv7l.tar.gz | ||||
| // All other currently supported architectures match, e.g.: | ||||
| //   os.arch = arm64 => https://nodejs.org/dist/v{VERSION}/node-v{VERSION}-{OS}-arm64.tar.gz | ||||
| //   os.arch = x64 => https://nodejs.org/dist/v{VERSION}/node-v{VERSION}-{OS}-x64.tar.gz | ||||
| function translateArchToDistUrl(arch: string): string { | ||||
|   switch (arch) { | ||||
|     case 'arm': | ||||
|       return 'armv7l'; | ||||
|     default: | ||||
|       return arch; | ||||
|   } | ||||
| } | ||||
|  | ||||
| export function parseNodeVersionFile(contents: string): string { | ||||
|   let nodeVersion: string | undefined; | ||||
|  | ||||
|   // Try parsing the file as an NPM `package.json` file. | ||||
|   try { | ||||
|     nodeVersion = JSON.parse(contents).volta?.node; | ||||
|     if (!nodeVersion) nodeVersion = JSON.parse(contents).engines?.node; | ||||
|   } catch { | ||||
|     core.info('Node version file is not JSON file'); | ||||
|   } | ||||
|  | ||||
|   if (!nodeVersion) { | ||||
|     const found = contents.match(/^(?:nodejs\s+)?v?(?<version>[^\s]+)$/m); | ||||
|     nodeVersion = found?.groups?.version; | ||||
|   } | ||||
|  | ||||
|   // In the case of an unknown format, | ||||
|   // return as is and evaluate the version separately. | ||||
|   if (!nodeVersion) nodeVersion = contents.trim(); | ||||
|  | ||||
|   return nodeVersion as string; | ||||
| } | ||||
|  | ||||
| function isLatestSyntax(versionSpec): boolean { | ||||
|   return ['current', 'latest', 'node'].includes(versionSpec); | ||||
| } | ||||
							
								
								
									
										69
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								src/main.ts
									
									
									
									
									
								
							| @ -1,12 +1,14 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as exec from '@actions/exec'; | ||||
| import * as installer from './installer'; | ||||
|  | ||||
| import fs from 'fs'; | ||||
| import os from 'os'; | ||||
|  | ||||
| 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 {isCacheFeatureAvailable} from './cache-utils'; | ||||
| import {getNodejsDistribution} from './distributions/installer-factory'; | ||||
| import {parseNodeVersionFile, printEnvDetailsAndSetOutput} from './util'; | ||||
|  | ||||
| export async function run() { | ||||
|   try { | ||||
| @ -14,7 +16,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,12 +34,21 @@ export async function run() { | ||||
|     } | ||||
|  | ||||
|     if (version) { | ||||
|       let token = core.getInput('token'); | ||||
|       let auth = !token || isGhes() ? 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); | ||||
|       const nodejsInfo = { | ||||
|         versionSpec: version, | ||||
|         checkLatest, | ||||
|         auth, | ||||
|         stable, | ||||
|         arch | ||||
|       }; | ||||
|       const nodeDistribution = getNodejsDistribution(nodejsInfo); | ||||
|       await nodeDistribution.setupNodeJs(); | ||||
|     } | ||||
|  | ||||
|     await printEnvDetailsAndSetOutput(); | ||||
| @ -92,48 +103,10 @@ function resolveVersionInput(): string { | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     version = installer.parseNodeVersionFile( | ||||
|       fs.readFileSync(versionFilePath, 'utf8') | ||||
|     ); | ||||
|     version = parseNodeVersionFile(fs.readFileSync(versionFilePath, 'utf8')); | ||||
|  | ||||
|     core.info(`Resolved ${versionFileInput} as ${version}`); | ||||
|   } | ||||
|  | ||||
|   return version; | ||||
| } | ||||
|  | ||||
| export async function printEnvDetailsAndSetOutput() { | ||||
|   core.startGroup('Environment details'); | ||||
|  | ||||
|   const promises = ['node', 'npm', 'yarn'].map(async tool => { | ||||
|     const output = await getToolVersion(tool, ['--version']); | ||||
|  | ||||
|     if (tool === 'node') { | ||||
|       core.setOutput(`${tool}-version`, output); | ||||
|     } | ||||
|  | ||||
|     core.info(`${tool}: ${output}`); | ||||
|   }); | ||||
|  | ||||
|   await Promise.all(promises); | ||||
|  | ||||
|   core.endGroup(); | ||||
| } | ||||
|  | ||||
| async function getToolVersion(tool: string, options: string[]) { | ||||
|   try { | ||||
|     const {stdout, stderr, exitCode} = await exec.getExecOutput(tool, options, { | ||||
|       ignoreReturnCode: true, | ||||
|       silent: true | ||||
|     }); | ||||
|  | ||||
|     if (exitCode > 0) { | ||||
|       core.warning(`[warning]${stderr}`); | ||||
|       return ''; | ||||
|     } | ||||
|  | ||||
|     return stdout; | ||||
|   } catch (err) { | ||||
|     return ''; | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										63
									
								
								src/util.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/util.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import * as exec from '@actions/exec'; | ||||
|  | ||||
| export function parseNodeVersionFile(contents: string): string { | ||||
|   let nodeVersion: string | undefined; | ||||
|  | ||||
|   // Try parsing the file as an NPM `package.json` file. | ||||
|   try { | ||||
|     nodeVersion = JSON.parse(contents).volta?.node; | ||||
|     if (!nodeVersion) nodeVersion = JSON.parse(contents).engines?.node; | ||||
|   } catch { | ||||
|     core.info('Node version file is not JSON file'); | ||||
|   } | ||||
|  | ||||
|   if (!nodeVersion) { | ||||
|     const found = contents.match(/^(?:nodejs\s+)?v?(?<version>[^\s]+)$/m); | ||||
|     nodeVersion = found?.groups?.version; | ||||
|   } | ||||
|  | ||||
|   // In the case of an unknown format, | ||||
|   // return as is and evaluate the version separately. | ||||
|   if (!nodeVersion) nodeVersion = contents.trim(); | ||||
|  | ||||
|   return nodeVersion as string; | ||||
| } | ||||
|  | ||||
| export async function printEnvDetailsAndSetOutput() { | ||||
|   core.startGroup('Environment details'); | ||||
|  | ||||
|   const promises = ['node', 'npm', 'yarn'].map(async tool => { | ||||
|     const output = await getToolVersion(tool, ['--version']); | ||||
|  | ||||
|     return {tool, output}; | ||||
|   }); | ||||
|  | ||||
|   const tools = await Promise.all(promises); | ||||
|   tools.forEach(({tool, output}) => { | ||||
|     if (tool === 'node') { | ||||
|       core.setOutput(`${tool}-version`, output); | ||||
|     } | ||||
|     core.info(`${tool}: ${output}`); | ||||
|   }); | ||||
|  | ||||
|   core.endGroup(); | ||||
| } | ||||
|  | ||||
| async function getToolVersion(tool: string, options: string[]) { | ||||
|   try { | ||||
|     const {stdout, stderr, exitCode} = await exec.getExecOutput(tool, options, { | ||||
|       ignoreReturnCode: true, | ||||
|       silent: true | ||||
|     }); | ||||
|  | ||||
|     if (exitCode > 0) { | ||||
|       core.info(`[warning]${stderr}`); | ||||
|       return ''; | ||||
|     } | ||||
|  | ||||
|     return stdout.trim(); | ||||
|   } catch (err) { | ||||
|     return ''; | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	