mirror of
				https://github.com/actions/setup-node.git
				synced 2025-11-04 13:29:12 +08:00 
			
		
		
		
	Add support for v8-canary, nightly and rc (#655)
This commit is contained in:
		
							
								
								
									
										20
									
								
								.github/workflows/versions.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								.github/workflows/versions.yml
									
									
									
									
										vendored
									
									
								
							@@ -51,6 +51,26 @@ 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:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
								
							@@ -128,16 +128,17 @@ If the runner is not able to access github.com, any Nodejs versions requested du
 | 
			
		||||
 | 
			
		||||
## 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. [Using nightly versions](docs/advanced-usage.md#nightly-versions)
 | 
			
		||||
5. [Using rc versions](docs/advanced-usage.md#rc-versions)
 | 
			
		||||
6. [Caching packages data](docs/advanced-usage.md#caching-packages-data)
 | 
			
		||||
7. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures)
 | 
			
		||||
8. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm)
 | 
			
		||||
9. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn)
 | 
			
		||||
10. [Using private packages](docs/advanced-usage.md#use-private-packages)
 | 
			
		||||
 - [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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										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,24 +1,26 @@
 | 
			
		||||
import * as core from '@actions/core';
 | 
			
		||||
import * as io from '@actions/io';
 | 
			
		||||
import * as tc from '@actions/tool-cache';
 | 
			
		||||
import * as exec from '@actions/exec';
 | 
			
		||||
import * as im from '../src/installer';
 | 
			
		||||
import * as cache from '@actions/cache';
 | 
			
		||||
import * as httpm from '@actions/http-client';
 | 
			
		||||
import * 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 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';
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +31,6 @@ describe('setup-node', () => {
 | 
			
		||||
  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;
 | 
			
		||||
@@ -42,7 +43,6 @@ 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;
 | 
			
		||||
@@ -71,8 +71,6 @@ describe('setup-node', () => {
 | 
			
		||||
    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');
 | 
			
		||||
@@ -94,25 +92,14 @@ describe('setup-node', () => {
 | 
			
		||||
      () => <tc.IToolRelease[]>nodeTestManifest
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    getDistSpy.mockImplementation(version => {
 | 
			
		||||
      const initialUrl = im.getNodejsDistUrl(version);
 | 
			
		||||
      if (initialUrl.endsWith('/rc')) {
 | 
			
		||||
        return <im.INodeVersion>nodeTestDistRc;
 | 
			
		||||
      } else if (initialUrl.endsWith('/nightly')) {
 | 
			
		||||
        return <im.INodeVersion>nodeTestDistNightly;
 | 
			
		||||
      } else {
 | 
			
		||||
        return <im.INodeVersion>nodeTestDist;
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    getJsonSpy.mockImplementation(url => {
 | 
			
		||||
      let res: any;
 | 
			
		||||
      if (url.includes('/rc')) {
 | 
			
		||||
        res = <im.INodeVersion>nodeTestDistRc;
 | 
			
		||||
        res = <INodeVersion>nodeTestDistRc;
 | 
			
		||||
      } else if (url.includes('/nightly')) {
 | 
			
		||||
        res = <im.INodeVersion>nodeTestDistNightly;
 | 
			
		||||
        res = <INodeVersion>nodeTestDistNightly;
 | 
			
		||||
      } else {
 | 
			
		||||
        res = <im.INodeVersion>nodeTestDist;
 | 
			
		||||
        res = <INodeVersion>nodeTestDist;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {result: res};
 | 
			
		||||
@@ -125,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
 | 
			
		||||
@@ -137,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
 | 
			
		||||
@@ -159,23 +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 () => {
 | 
			
		||||
    const versionSpec = '1.2.3';
 | 
			
		||||
    let versions: im.INodeVersion[] = await im.getVersionsFromDist(versionSpec);
 | 
			
		||||
    expect(versions).toBeDefined();
 | 
			
		||||
    expect(versions?.length).toBe(23);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it.each([
 | 
			
		||||
    ['12.16.2', 'darwin', '12.16.2', 'Erbium'],
 | 
			
		||||
    ['12', 'linux', '12.16.2', 'Erbium'],
 | 
			
		||||
@@ -315,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}`);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@@ -596,165 +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(warningSpy).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}`
 | 
			
		||||
        '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'
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('LTS version', () => {
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      os.platform = 'linux';
 | 
			
		||||
@@ -930,277 +738,6 @@ describe('setup-node', () => {
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('rc versions', () => {
 | 
			
		||||
    it.each([
 | 
			
		||||
      [
 | 
			
		||||
        '13.10.1-rc.0',
 | 
			
		||||
        '13.10.1-rc.0',
 | 
			
		||||
        'https://nodejs.org/download/rc/v13.10.1-rc.0/node-v13.10.1-rc.0-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '14.15.5-rc.1',
 | 
			
		||||
        '14.15.5-rc.1',
 | 
			
		||||
        'https://nodejs.org/download/rc/v14.15.5-rc.1/node-v14.15.5-rc.1-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '16.17.0-rc.1',
 | 
			
		||||
        '16.17.0-rc.1',
 | 
			
		||||
        'https://nodejs.org/download/rc/v16.17.0-rc.1/node-v16.17.0-rc.1-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '17.0.0-rc.1',
 | 
			
		||||
        '17.0.0-rc.1',
 | 
			
		||||
        'https://nodejs.org/download/rc/v17.0.0-rc.1/node-v17.0.0-rc.1-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '19.0.0-rc.2',
 | 
			
		||||
        '19.0.0-rc.2',
 | 
			
		||||
        'https://nodejs.org/download/rc/v19.0.0-rc.2/node-v19.0.0-rc.2-linux-x64.tar.gz'
 | 
			
		||||
      ]
 | 
			
		||||
    ])(
 | 
			
		||||
      'finds the versions in the index.json and installs it',
 | 
			
		||||
      async (input, expectedVersion, expectedUrl) => {
 | 
			
		||||
        const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
 | 
			
		||||
 | 
			
		||||
        findSpy.mockImplementation(() => '');
 | 
			
		||||
        findAllVersionsSpy.mockImplementation(() => []);
 | 
			
		||||
        dlSpy.mockImplementation(async () => '/some/temp/path');
 | 
			
		||||
        exSpy.mockImplementation(async () => '/some/other/temp/path');
 | 
			
		||||
        cacheSpy.mockImplementation(async () => toolPath);
 | 
			
		||||
 | 
			
		||||
        inputs['node-version'] = input;
 | 
			
		||||
        os['arch'] = 'x64';
 | 
			
		||||
        os['platform'] = 'linux';
 | 
			
		||||
        // act
 | 
			
		||||
        await main.run();
 | 
			
		||||
 | 
			
		||||
        // assert
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `Attempting to download ${input}...`
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `Acquiring ${expectedVersion} - ${os.arch} from ${expectedUrl}`
 | 
			
		||||
        );
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith('Extracting ...');
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...');
 | 
			
		||||
        expect(cnSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it.each([
 | 
			
		||||
      ['13.10.1-rc.0', '13.10.1-rc.0'],
 | 
			
		||||
      ['14.15.5-rc.1', '14.15.5-rc.1'],
 | 
			
		||||
      ['16.17.0-rc.1', '16.17.0-rc.1'],
 | 
			
		||||
      ['17.0.0-rc.1', '17.0.0-rc.1']
 | 
			
		||||
    ])(
 | 
			
		||||
      'finds the %s version in the hostedToolcache',
 | 
			
		||||
      async (input, expectedVersion) => {
 | 
			
		||||
        const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
 | 
			
		||||
        findSpy.mockReturnValue(toolPath);
 | 
			
		||||
 | 
			
		||||
        inputs['node-version'] = input;
 | 
			
		||||
        os['arch'] = 'x64';
 | 
			
		||||
        os['platform'] = 'linux';
 | 
			
		||||
 | 
			
		||||
        // act
 | 
			
		||||
        await main.run();
 | 
			
		||||
 | 
			
		||||
        // assert
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
 | 
			
		||||
        expect(cnSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it('throws an error if version is not found', async () => {
 | 
			
		||||
      const versionSpec = '19.0.0-rc.3';
 | 
			
		||||
 | 
			
		||||
      findSpy.mockImplementation(() => '');
 | 
			
		||||
      findAllVersionsSpy.mockImplementation(() => []);
 | 
			
		||||
      dlSpy.mockImplementation(async () => '/some/temp/path');
 | 
			
		||||
      exSpy.mockImplementation(async () => '/some/other/temp/path');
 | 
			
		||||
 | 
			
		||||
      inputs['node-version'] = versionSpec;
 | 
			
		||||
      os['arch'] = 'x64';
 | 
			
		||||
      os['platform'] = 'linux';
 | 
			
		||||
      // act
 | 
			
		||||
      await main.run();
 | 
			
		||||
 | 
			
		||||
      // assert
 | 
			
		||||
      expect(logSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `Attempting to download ${versionSpec}...`
 | 
			
		||||
      );
 | 
			
		||||
      expect(cnSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `::error::Unable to find Node version '${versionSpec}' for platform ${os.platform} and architecture ${os.arch}.${osm.EOL}`
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('nightly versions', () => {
 | 
			
		||||
    it.each([
 | 
			
		||||
      [
 | 
			
		||||
        '17.5.0-nightly',
 | 
			
		||||
        '17.5.0-nightly20220209e43808936a',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v17.5.0-nightly20220209e43808936a/node-v17.5.0-nightly20220209e43808936a-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '17-nightly',
 | 
			
		||||
        '17.5.0-nightly20220209e43808936a',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v17.5.0-nightly20220209e43808936a/node-v17.5.0-nightly20220209e43808936a-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '18.0.0-nightly',
 | 
			
		||||
        '18.0.0-nightly20220419bde889bd4e',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v18.0.0-nightly20220419bde889bd4e/node-v18.0.0-nightly20220419bde889bd4e-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '18-nightly',
 | 
			
		||||
        '18.0.0-nightly20220419bde889bd4e',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v18.0.0-nightly20220419bde889bd4e/node-v18.0.0-nightly20220419bde889bd4e-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '20.0.0-nightly',
 | 
			
		||||
        '20.0.0-nightly2022101987cdf7d412',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v20.0.0-nightly2022101987cdf7d412/node-v20.0.0-nightly2022101987cdf7d412-linux-x64.tar.gz'
 | 
			
		||||
      ]
 | 
			
		||||
    ])(
 | 
			
		||||
      'finds the versions in the index.json and installs it',
 | 
			
		||||
      async (input, expectedVersion, expectedUrl) => {
 | 
			
		||||
        const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
 | 
			
		||||
 | 
			
		||||
        findSpy.mockImplementation(() => '');
 | 
			
		||||
        findAllVersionsSpy.mockImplementation(() => []);
 | 
			
		||||
        dlSpy.mockImplementation(async () => '/some/temp/path');
 | 
			
		||||
        exSpy.mockImplementation(async () => '/some/other/temp/path');
 | 
			
		||||
        cacheSpy.mockImplementation(async () => toolPath);
 | 
			
		||||
 | 
			
		||||
        inputs['node-version'] = input;
 | 
			
		||||
        os['arch'] = 'x64';
 | 
			
		||||
        os['platform'] = 'linux';
 | 
			
		||||
        // act
 | 
			
		||||
        await main.run();
 | 
			
		||||
 | 
			
		||||
        // assert
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `Attempting to download ${input}...`
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `Acquiring ${expectedVersion} - ${os.arch} from ${expectedUrl}`
 | 
			
		||||
        );
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith('Extracting ...');
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...');
 | 
			
		||||
        expect(cnSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it.each([
 | 
			
		||||
      ['17.5.0-nightly', '17.5.0-nightly20220209e43808936a'],
 | 
			
		||||
      ['17-nightly', '17.5.0-nightly20220209e43808936a'],
 | 
			
		||||
      ['20.0.0-nightly', '20.0.0-nightly2022101987cdf7d412']
 | 
			
		||||
    ])(
 | 
			
		||||
      'finds the %s version in the hostedToolcache',
 | 
			
		||||
      async (input, expectedVersion) => {
 | 
			
		||||
        const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
 | 
			
		||||
        findSpy.mockReturnValue(toolPath);
 | 
			
		||||
        findAllVersionsSpy.mockReturnValue([
 | 
			
		||||
          '17.5.0-nightly20220209e43808936a',
 | 
			
		||||
          '17.5.0-nightly20220209e43808935a',
 | 
			
		||||
          '20.0.0-nightly2022101987cdf7d412',
 | 
			
		||||
          '20.0.0-nightly2022101987cdf7d411'
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        inputs['node-version'] = input;
 | 
			
		||||
        os['arch'] = 'x64';
 | 
			
		||||
        os['platform'] = 'linux';
 | 
			
		||||
 | 
			
		||||
        // act
 | 
			
		||||
        await main.run();
 | 
			
		||||
 | 
			
		||||
        // assert
 | 
			
		||||
        expect(findAllVersionsSpy).toHaveBeenCalled();
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
 | 
			
		||||
        expect(cnSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it.each([
 | 
			
		||||
      [
 | 
			
		||||
        '17.5.0-nightly',
 | 
			
		||||
        '17.5.0-nightly20220209e43808936a',
 | 
			
		||||
        '17.0.0-nightly202110193f11666dc7',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v17.5.0-nightly20220209e43808936a/node-v17.5.0-nightly20220209e43808936a-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '17-nightly',
 | 
			
		||||
        '17.5.0-nightly20220209e43808936a',
 | 
			
		||||
        '17.0.0-nightly202110193f11666dc7',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v17.5.0-nightly20220209e43808936a/node-v17.5.0-nightly20220209e43808936a-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '18.0.0-nightly',
 | 
			
		||||
        '18.0.0-nightly20220419bde889bd4e',
 | 
			
		||||
        '18.0.0-nightly202204180699150267',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v18.0.0-nightly20220419bde889bd4e/node-v18.0.0-nightly20220419bde889bd4e-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '18-nightly',
 | 
			
		||||
        '18.0.0-nightly20220419bde889bd4e',
 | 
			
		||||
        '18.0.0-nightly202204180699150267',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v18.0.0-nightly20220419bde889bd4e/node-v18.0.0-nightly20220419bde889bd4e-linux-x64.tar.gz'
 | 
			
		||||
      ],
 | 
			
		||||
      [
 | 
			
		||||
        '20.0.0-nightly',
 | 
			
		||||
        '20.0.0-nightly2022101987cdf7d412',
 | 
			
		||||
        '20.0.0-nightly2022101987cdf7d411',
 | 
			
		||||
        'https://nodejs.org/download/nightly/v20.0.0-nightly2022101987cdf7d412/node-v20.0.0-nightly2022101987cdf7d412-linux-x64.tar.gz'
 | 
			
		||||
      ]
 | 
			
		||||
    ])(
 | 
			
		||||
      'get %s version from dist if check-latest is true',
 | 
			
		||||
      async (input, expectedVersion, foundVersion, expectedUrl) => {
 | 
			
		||||
        const foundToolPath = path.normalize(`/cache/node/${foundVersion}/x64`);
 | 
			
		||||
        const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`);
 | 
			
		||||
 | 
			
		||||
        inputs['node-version'] = input;
 | 
			
		||||
        inputs['check-latest'] = 'true';
 | 
			
		||||
        os['arch'] = 'x64';
 | 
			
		||||
        os['platform'] = 'linux';
 | 
			
		||||
 | 
			
		||||
        findSpy.mockReturnValue(foundToolPath);
 | 
			
		||||
        findAllVersionsSpy.mockReturnValue([
 | 
			
		||||
          '17.0.0-nightly202110193f11666dc7',
 | 
			
		||||
          '18.0.0-nightly202204180699150267',
 | 
			
		||||
          '20.0.0-nightly2022101987cdf7d411'
 | 
			
		||||
        ]);
 | 
			
		||||
        dlSpy.mockImplementation(async () => '/some/temp/path');
 | 
			
		||||
        exSpy.mockImplementation(async () => '/some/other/temp/path');
 | 
			
		||||
        cacheSpy.mockImplementation(async () => toolPath);
 | 
			
		||||
 | 
			
		||||
        // act
 | 
			
		||||
        await main.run();
 | 
			
		||||
 | 
			
		||||
        // assert
 | 
			
		||||
        expect(findAllVersionsSpy).toHaveBeenCalled();
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `Acquiring ${expectedVersion} - ${os.arch} from ${expectedUrl}`
 | 
			
		||||
        );
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith('Extracting ...');
 | 
			
		||||
        expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...');
 | 
			
		||||
        expect(cnSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('latest alias syntax', () => {
 | 
			
		||||
    it.each(['latest', 'current', 'node'])(
 | 
			
		||||
      'download the %s version if alias is provided',
 | 
			
		||||
@@ -1241,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}`
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										64
									
								
								dist/cache-save/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								dist/cache-save/index.js
									
									
									
									
										vendored
									
									
								
							@@ -61019,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) {
 | 
			
		||||
@@ -61028,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));
 | 
			
		||||
@@ -61095,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) {
 | 
			
		||||
@@ -61104,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));
 | 
			
		||||
@@ -61133,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()
 | 
			
		||||
@@ -61143,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) {
 | 
			
		||||
@@ -61150,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;
 | 
			
		||||
    }
 | 
			
		||||
@@ -61171,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}`);
 | 
			
		||||
@@ -61179,6 +61207,7 @@ 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';
 | 
			
		||||
@@ -61205,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";
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1146
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1146
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -104,6 +104,57 @@ 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. 
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										46
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -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": {
 | 
			
		||||
@@ -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"
 | 
			
		||||
      },
 | 
			
		||||
@@ -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",
 | 
			
		||||
@@ -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",
 | 
			
		||||
@@ -8229,12 +8217,6 @@
 | 
			
		||||
        "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": {
 | 
			
		||||
 
 | 
			
		||||
@@ -43,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"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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';
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										606
									
								
								src/installer.ts
									
									
									
									
									
								
							
							
						
						
									
										606
									
								
								src/installer.ts
									
									
									
									
									
								
							@@ -1,606 +0,0 @@
 | 
			
		||||
import os from '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 from 'fs';
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Node versions interface
 | 
			
		||||
// see https://nodejs.org/dist/index.json
 | 
			
		||||
// for nightly https://nodejs.org/download/nightly/index.json
 | 
			
		||||
// for rc https://nodejs.org/download/rc/index.json
 | 
			
		||||
//
 | 
			
		||||
export interface INodeVersion {
 | 
			
		||||
  version: string;
 | 
			
		||||
  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 isNightly = versionSpec.includes('nightly');
 | 
			
		||||
  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);
 | 
			
		||||
    versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions);
 | 
			
		||||
    core.info(`getting latest node version...`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (isNightly && checkLatest) {
 | 
			
		||||
    nodeVersions = await getVersionsFromDist(versionSpec);
 | 
			
		||||
    versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (checkLatest && !isNightly) {
 | 
			
		||||
    core.info('Attempt to resolve the latest version from manifest...');
 | 
			
		||||
    const resolvedVersion = await resolveVersionFromManifest(
 | 
			
		||||
      versionSpec,
 | 
			
		||||
      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;
 | 
			
		||||
  if (isNightly) {
 | 
			
		||||
    const nightlyVersion = findNightlyVersionInHostedToolcache(
 | 
			
		||||
      versionSpec,
 | 
			
		||||
      osArch
 | 
			
		||||
    );
 | 
			
		||||
    toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch);
 | 
			
		||||
  } else {
 | 
			
		||||
    toolPath = tc.find('node', versionSpec, osArch);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If not found in cache, download
 | 
			
		||||
  if (toolPath) {
 | 
			
		||||
    core.info(`Found in cache @ ${toolPath}`);
 | 
			
		||||
  } 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 findNightlyVersionInHostedToolcache(
 | 
			
		||||
  versionsSpec: string,
 | 
			
		||||
  osArch: string
 | 
			
		||||
) {
 | 
			
		||||
  const foundAllVersions = tc.findAllVersions('node', osArch);
 | 
			
		||||
  const version = evaluateVersions(foundAllVersions, versionsSpec);
 | 
			
		||||
 | 
			
		||||
  return version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isLtsAlias(versionSpec: string): boolean {
 | 
			
		||||
  return versionSpec.startsWith('lts/');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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`;
 | 
			
		||||
  const initialUrl = getNodejsDistUrl(versionSpec);
 | 
			
		||||
  const url = `${initialUrl}/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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function evaluateNightlyVersions(
 | 
			
		||||
  versions: string[],
 | 
			
		||||
  versionSpec: string
 | 
			
		||||
): string {
 | 
			
		||||
  let version = '';
 | 
			
		||||
  let range: string | undefined;
 | 
			
		||||
  const [raw, prerelease] = versionSpec.split('-');
 | 
			
		||||
  const isValidVersion = semver.valid(raw);
 | 
			
		||||
  const rawVersion = isValidVersion ? raw : semver.coerce(raw);
 | 
			
		||||
  if (rawVersion) {
 | 
			
		||||
    if (prerelease !== 'nightly') {
 | 
			
		||||
      range = `${rawVersion}-${prerelease.replace('nightly', 'nightly.')}`;
 | 
			
		||||
    } else {
 | 
			
		||||
      range = `${semver.validRange(`^${rawVersion}-0`)}-0`;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (range) {
 | 
			
		||||
    versions.sort(semver.rcompare);
 | 
			
		||||
    for (const currentVersion of versions) {
 | 
			
		||||
      const satisfied: boolean =
 | 
			
		||||
        semver.satisfies(
 | 
			
		||||
          currentVersion.replace('-nightly', '-nightly.'),
 | 
			
		||||
          range,
 | 
			
		||||
          {includePrerelease: true}
 | 
			
		||||
        ) && currentVersion.includes('nightly');
 | 
			
		||||
      if (satisfied) {
 | 
			
		||||
        version = currentVersion;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (version) {
 | 
			
		||||
    core.debug(`matched: ${version}`);
 | 
			
		||||
  } else {
 | 
			
		||||
    core.debug('match not found');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO - should we just export this from @actions/tool-cache? Lifted directly from there
 | 
			
		||||
function evaluateVersions(versions: string[], versionSpec: string): string {
 | 
			
		||||
  let version = '';
 | 
			
		||||
  core.debug(`evaluating ${versions.length} versions`);
 | 
			
		||||
 | 
			
		||||
  if (versionSpec.includes('nightly')) {
 | 
			
		||||
    return evaluateNightlyVersions(versions, versionSpec);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  versions = versions.sort(semver.rcompare);
 | 
			
		||||
  for (let i = versions.length - 1; i >= 0; i--) {
 | 
			
		||||
    const potential: string = versions[i];
 | 
			
		||||
    const satisfied: boolean = semver.satisfies(potential, versionSpec);
 | 
			
		||||
    if (satisfied) {
 | 
			
		||||
      version = potential;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (version) {
 | 
			
		||||
    core.debug(`matched: ${version}`);
 | 
			
		||||
  } else {
 | 
			
		||||
    core.debug('match not found');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getNodejsDistUrl(version: string) {
 | 
			
		||||
  const prerelease = semver.prerelease(version);
 | 
			
		||||
  if (version.includes('nightly')) {
 | 
			
		||||
    return 'https://nodejs.org/download/nightly';
 | 
			
		||||
  } else if (prerelease) {
 | 
			
		||||
    return 'https://nodejs.org/download/rc';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 'https://nodejs.org/dist';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function queryDistForMatch(
 | 
			
		||||
  versionSpec: string,
 | 
			
		||||
  arch: string = os.arch(),
 | 
			
		||||
  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(versionSpec);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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 = evaluateVersions(versions, versionSpec);
 | 
			
		||||
  return version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function getVersionsFromDist(
 | 
			
		||||
  versionSpec: string
 | 
			
		||||
): Promise<INodeVersion[]> {
 | 
			
		||||
  const initialUrl = getNodejsDistUrl(versionSpec);
 | 
			
		||||
  const dataUrl = `${initialUrl}/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> {
 | 
			
		||||
  const initialUrl = getNodejsDistUrl(version);
 | 
			
		||||
  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 = `${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;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								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 from 'os';
 | 
			
		||||
import {isCacheFeatureAvailable} from './cache-utils';
 | 
			
		||||
import {getNodejsDistribution} from './distributions/installer-factory';
 | 
			
		||||
import {parseNodeVersionFile, printEnvDetailsAndSetOutput} from './util';
 | 
			
		||||
 | 
			
		||||
export async function run() {
 | 
			
		||||
  try {
 | 
			
		||||
@@ -38,7 +40,15 @@ export async function run() {
 | 
			
		||||
        (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();
 | 
			
		||||
@@ -93,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.trim();
 | 
			
		||||
  } 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