From 9c158b3dbdc1f44c1417d04feb9d888fc038a8c4 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Wed, 9 Nov 2022 20:39:42 +0100 Subject: [PATCH 01/51] Add support of v8 canary release --- src/installer.ts | 72 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/src/installer.ts b/src/installer.ts index 1b5659b6a..24b53970c 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -30,6 +30,9 @@ interface INodeRelease extends tc.IToolRelease { lts?: string; } +const isVersionCanary = (versionSpec: string): boolean => + versionSpec.includes(`-v8-canary`); + export async function getNode( versionSpec: string, stable: boolean, @@ -43,6 +46,7 @@ export async function getNode( let isNightly = versionSpec.includes('nightly'); let osPlat: string = os.platform(); let osArch: string = translateArchToDistUrl(arch); + let isCanary = isVersionCanary(versionSpec); if (isLtsAlias(versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); @@ -53,10 +57,15 @@ export async function getNode( versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } - if (isLatestSyntax(versionSpec)) { + // evaluate exact versionSpec from input + if (isLatestSyntax(versionSpec) || isCanary) { nodeVersions = await getVersionsFromDist(versionSpec); versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); - core.info(`getting latest node version...`); + core.info( + `getting ${ + isCanary ? 'v8-canary' : 'latest' + } node version ${versionSpec}...` + ); } if (isNightly && checkLatest) { @@ -82,6 +91,7 @@ export async function getNode( } // check cache + core.info('Attempt to find existing version in cache...'); let toolPath: string; if (isNightly) { const nightlyVersion = findNightlyVersionInHostedToolcache( @@ -89,6 +99,9 @@ export async function getNode( osArch ); toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch); + } else if (isCanary) { + const localVersions = tc.findAllVersions('node', osArch); + toolPath = evaluateVersions(localVersions, versionSpec); } else { toolPath = tc.find('node', versionSpec, osArch); } @@ -417,9 +430,14 @@ function evaluateVersions(versions: string[], versionSpec: string): string { } versions = versions.sort(semver.rcompare); + + const matcher: (potential: string) => boolean = isVersionCanary(versionSpec) + ? evaluateCanaryMatcher(versionSpec) + : potential => semver.satisfies(potential, versionSpec); + for (let i = versions.length - 1; i >= 0; i--) { const potential: string = versions[i]; - const satisfied: boolean = semver.satisfies(potential, versionSpec); + const satisfied: boolean = matcher(potential); if (satisfied) { version = potential; break; @@ -438,15 +456,19 @@ function evaluateVersions(versions: string[], versionSpec: string): string { export function getNodejsDistUrl(version: string) { const prerelease = semver.prerelease(version); if (version.includes('nightly')) { + core.debug('requested nightly distribution'); return 'https://nodejs.org/download/nightly'; } else if (prerelease) { return 'https://nodejs.org/download/rc'; + } else if (isVersionCanary(version)) { + core.debug('requested v8 canary distribution'); + return 'https://nodejs.org/download/v8-canary'; + } else { + return 'https://nodejs.org/dist'; } - - return 'https://nodejs.org/dist'; } -async function queryDistForMatch( +export async function queryDistForMatch( versionSpec: string, arch: string = os.arch(), nodeVersions?: INodeVersion[] @@ -475,13 +497,12 @@ async function queryDistForMatch( nodeVersions = await getVersionsFromDist(versionSpec); } - let versions: string[] = []; - if (isLatestSyntax(versionSpec)) { core.info(`getting latest node version...`); return nodeVersions[0].version; } + let versions: string[] = []; nodeVersions.forEach((nodeVersion: INodeVersion) => { // ensure this version supports your os and platform if (nodeVersion.files.indexOf(dataFileName) >= 0) { @@ -497,8 +518,8 @@ async function queryDistForMatch( export async function getVersionsFromDist( versionSpec: string ): Promise { - const initialUrl = getNodejsDistUrl(versionSpec); - const dataUrl = `${initialUrl}/index.json`; + const distUrl = getNodejsDistUrl(versionSpec); + const dataUrl = `${distUrl}/index.json`; let httpClient = new hc.HttpClient('setup-node', [], { allowRetries: true, maxRetries: 3 @@ -604,3 +625,34 @@ export function parseNodeVersionFile(contents: string): string { function isLatestSyntax(versionSpec): boolean { return ['current', 'latest', 'node'].includes(versionSpec); } + +export function evaluateCanaryMatcher( + versionSpec: string +): (potential: string) => boolean { + const [raw, prerelease] = versionSpec.split(/-(.*)/s); + const isValidVersion = semver.valid(raw); + const rawVersion = isValidVersion ? raw : semver.coerce(raw)?.version; + if (rawVersion) { + if (prerelease === 'v8-canary') { + // it means versionSpec does not have timestamp + const range = semver.validRange(`^${rawVersion}`); + return (potential: string) => + semver.satisfies( + // TODO: check latest? + potential.replace('-v8-canary', '+v8-canary.'), + range + ); + } else { + // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 + // there must be exact match + const range = `${rawVersion}-${prerelease}`; + return (potential: string) => + semver.satisfies( + // TODO: check latest? + potential, + range + ); + } + } + return () => false; +} From 588599b9441f1a1afdc6b3a79c8ad3cb9b40a12d Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Wed, 9 Nov 2022 20:41:33 +0100 Subject: [PATCH 02/51] Add v8 canary unit tests --- __tests__/data/v8-canary-dist-index.json | 537 +++++++++++++++++++++++ __tests__/installer.test.ts | 268 ++++++++++- src/installer.ts | 15 +- 3 files changed, 811 insertions(+), 9 deletions(-) create mode 100644 __tests__/data/v8-canary-dist-index.json diff --git a/__tests__/data/v8-canary-dist-index.json b/__tests__/data/v8-canary-dist-index.json new file mode 100644 index 000000000..2c06a072e --- /dev/null +++ b/__tests__/data/v8-canary-dist-index.json @@ -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 + } +] \ No newline at end of file diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 3c3105e2c..321034ae2 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -1,10 +1,10 @@ import * as core from '@actions/core'; import * as io from '@actions/io'; import * as tc from '@actions/tool-cache'; +import * as httpm from '@actions/http-client'; import * as exec from '@actions/exec'; import * as im from '../src/installer'; import * as cache from '@actions/cache'; -import * as httpm from '@actions/http-client'; import fs from 'fs'; import cp from 'child_process'; import osm from 'os'; @@ -17,6 +17,7 @@ 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; @@ -71,6 +72,7 @@ describe('setup-node', () => { exSpy = jest.spyOn(tc, 'extractTar'); cacheSpy = jest.spyOn(tc, 'cacheDir'); getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo'); + // @ts-ignore getDistSpy = jest.spyOn(im, 'getVersionsFromDist'); parseNodeVersionSpy = jest.spyOn(im, 'parseNodeVersionFile'); @@ -137,7 +139,7 @@ describe('setup-node', () => { }); warningSpy.mockImplementation(msg => { // uncomment to debug - // process.stderr.write('log:' + line + '\n'); + // process.stderr.write('log:' + msg + '\n'); }); // @actions/exec @@ -1252,6 +1254,268 @@ describe('setup-node', () => { } ); }); + + describe('setup-node v8 canary unit tests', () => { + it('is not LTS alias', async () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const isLtsAlias = im.isLtsAlias(versionSpec); + expect(isLtsAlias).toBeFalsy(); + }); + + it('is not isLatestSyntax', async () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const isLatestSyntax = im.isLatestSyntax(versionSpec); + expect(isLatestSyntax).toBeFalsy(); + }); + + it('dist url to be https://nodejs.org/download/v8-canary for input versionSpec', () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const url = im.getNodejsDistUrl(versionSpec); + expect(url).toBe('https://nodejs.org/download/v8-canary'); + }); + + it('dist url to be https://nodejs.org/download/v8-canary for full versionSpec', () => { + const versionSpec = 'v20.0.0-v8-canary20221103f7e2421e91'; + // @ts-ignore + const url = im.getNodejsDistUrl(versionSpec); + expect(url).toBe('https://nodejs.org/download/v8-canary'); + }); + + it('v20-v8-canary should match any minor and patch version', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20-v8-canary'); + expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); + }); + + it('v20-v8-canary should not match v21.x & v19.x', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20-v8-canary'); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.1.1-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.1.-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); + + it('v20.1-v8-canary should match any v20.1 patch version and minor above or eq v20.1', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.1-v8-canary'); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); + expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + }); + + it('v20.2-v8-canary should not match v21.x, v19.x, and v20 minor less v20.2', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.2-v8-canary'); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); + + it('v20.1.1-v8-canary should match v20.1.x patch versions above or eq v20.1.1', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + }); + + it('v20.1.1-v8-canary should match patch versions with any canary timestamp', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); + }); + + it('v20.1.1-v8-canary should not match any other minor versions and patch versions below v20.1.1', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); + + it('v20.0.0-v8-canary20221103f7e2421e91 should match only v20.0.0-v8-canary20221103f7e2421e91', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher( + 'v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 + expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); + }); + + it('v8 canary evaluateVersions without timestamp', () => { + const versions = [ + 'v20.0.0-v8-canary20221103f7e2421e91', + 'v20.0.1-v8-canary20221103f7e2421e91', + 'v20.1.0-v8-canary20221103f7e2421e91', + 'v20.1.1-v8-canary20221103f7e2421e91', + 'v21.1.0-v8-canary20221103f7e2421e91', + 'v19.1.0-v8-canary20221103f7e2421e91' + ]; + // @ts-ignore + const version = im.evaluateVersions(versions, 'v20-v8-canary'); + expect(version).toBe('v20.1.1-v8-canary20221103f7e2421e91'); + }); + + it('v8 canary evaluateVersions with timestamp', () => { + const versions = [ + 'v20.0.0-v8-canary20221103f7e2421e91', + 'v20.0.1-v8-canary20221103f7e2421e91', + 'v20.0.1-v8-canary20221103f7e2421e92', + 'v20.0.1-v8-canary20221103f7e2421e93', + 'v20.0.2-v8-canary20221103f7e2421e91' + ]; + // @ts-ignore + const version = im.evaluateVersions( + versions, + 'v20.0.1-v8-canary20221103f7e2421e92' + ); + expect(version).toBe('v20.0.1-v8-canary20221103f7e2421e92'); + }); + + it('v8 canary queryDistForMatch', async () => { + jest.spyOn(osm, 'platform').mockImplementationOnce(() => 'linux'); + // @ts-ignore + const version = await im.queryDistForMatch( + 'v20-v8-canary', + 'x64', + nodeV8CanaryTestDist + ); + expect(version).toBe('v20.0.0-v8-canary20221103f7e2421e91'); + }); + }); + + describe('setup-node v8 canary e2e tests', () => { + // @actions/http-client + let getDistIndexJsonSpy: jest.SpyInstance; + let findAllVersionSpy: jest.SpyInstance; + + beforeEach(() => { + // @actions/http-client + getDistIndexJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); + getDistIndexJsonSpy.mockImplementation(() => ({ + result: nodeV8CanaryTestDist + })); + + // @actions/tool-cache + findAllVersionSpy = jest.spyOn(tc, 'findAllVersions'); + }); + + it('v8 canary setup node flow without cached', async () => { + let versionSpec = 'v20-v8-canary'; + + inputs['node-version'] = versionSpec; + inputs['always-auth'] = false; + inputs['token'] = 'faketoken'; + + os.platform = 'linux'; + os.arch = 'x64'; + + findAllVersionSpy.mockImplementation(() => []); + + findSpy.mockImplementation(() => ''); + + dlSpy.mockImplementation(async () => '/some/temp/path'); + let toolPath = path.normalize('/cache/node/12.16.2/x64'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + + await main.run(); + + expect(dbgSpy.mock.calls[0][0]).toBe('requested v8 canary distribution'); + expect(dbgSpy.mock.calls[1][0]).toBe('evaluating 17 versions'); + expect(dbgSpy.mock.calls[2][0]).toBe( + 'matched: v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(logSpy.mock.calls[0][0]).toBe( + 'getting v8-canary node version v20.0.0-v8-canary20221103f7e2421e91...' + ); + expect(logSpy.mock.calls[1][0]).toBe( + 'Attempt to find existing version in cache...' + ); + expect(dbgSpy.mock.calls[3][0]).toBe('evaluating 0 versions'); + expect(dbgSpy.mock.calls[4][0]).toBe('match not found'); + expect(logSpy.mock.calls[2][0]).toBe( + 'Attempting to download v20.0.0-v8-canary20221103f7e2421e91...' + ); + expect(dbgSpy.mock.calls[5][0]).toBe('No manifest cached'); + expect(dbgSpy.mock.calls[6][0]).toBe( + 'Getting manifest from actions/node-versions@main' + ); + expect(dbgSpy.mock.calls[7][0].slice(0, 6)).toBe('check '); + expect(dbgSpy.mock.calls[13][0].slice(0, 6)).toBe('check '); + expect(logSpy.mock.calls[3][0]).toBe( + 'Not found in manifest. Falling back to download directly from Node' + ); + expect(dbgSpy.mock.calls[14][0]).toBe('evaluating 17 versions'); + expect(dbgSpy.mock.calls[15][0]).toBe( + 'matched: v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(dbgSpy.mock.calls[16][0]).toBe('requested v8 canary distribution'); + expect(logSpy.mock.calls[4][0]).toBe( + 'Acquiring 20.0.0-v8-canary20221103f7e2421e91 - x64 from https://nodejs.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz' + ); + + expect(dlSpy).toHaveBeenCalledTimes(1); + expect(exSpy).toHaveBeenCalledTimes(1); + expect(cacheSpy).toHaveBeenCalledTimes(1); + }); + + 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'; + + findAllVersionSpy.mockImplementation(() => [ + 'v20.0.0-v8-canary20221103f7e2421e91' + ]); + + await main.run(); + + expect(dbgSpy.mock.calls[0][0]).toBe('requested v8 canary distribution'); + expect(dbgSpy.mock.calls[1][0]).toBe('evaluating 17 versions'); + expect(dbgSpy.mock.calls[2][0]).toBe( + 'matched: v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(logSpy.mock.calls[0][0]).toBe( + 'getting v8-canary node version v20.0.0-v8-canary20221103f7e2421e91...' + ); + expect(logSpy.mock.calls[1][0]).toBe( + 'Attempt to find existing version in cache...' + ); + expect(dbgSpy.mock.calls[3][0]).toBe('evaluating 1 versions'); + expect(dbgSpy.mock.calls[4][0]).toBe( + 'matched: v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(logSpy.mock.calls[2][0]).toBe( + 'Found in cache @ v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(cnSpy.mock.calls[1][0].trim()).toBe( + `::add-path::v20.0.0-v8-canary20221103f7e2421e91${path.sep}bin` + ); + + expect(dlSpy).not.toHaveBeenCalled(); + expect(exSpy).not.toHaveBeenCalled(); + expect(cacheSpy).not.toHaveBeenCalled(); + }); + }); }); describe('helper methods', () => { diff --git a/src/installer.ts b/src/installer.ts index 24b53970c..fa86711fc 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -233,12 +233,10 @@ function findNightlyVersionInHostedToolcache( osArch: string ) { const foundAllVersions = tc.findAllVersions('node', osArch); - const version = evaluateVersions(foundAllVersions, versionsSpec); - - return version; + return evaluateVersions(foundAllVersions, versionsSpec); } -function isLtsAlias(versionSpec: string): boolean { +export function isLtsAlias(versionSpec: string): boolean { return versionSpec.startsWith('lts/'); } @@ -247,7 +245,7 @@ function getManifest(auth: string | undefined): Promise { return tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); } -function resolveLtsAliasFromManifest( +export function resolveLtsAliasFromManifest( versionSpec: string, stable: boolean, manifest: INodeRelease[] @@ -421,7 +419,10 @@ function evaluateNightlyVersions( } // TODO - should we just export this from @actions/tool-cache? Lifted directly from there -function evaluateVersions(versions: string[], versionSpec: string): string { +export function evaluateVersions( + versions: string[], + versionSpec: string +): string { let version = ''; core.debug(`evaluating ${versions.length} versions`); @@ -622,7 +623,7 @@ export function parseNodeVersionFile(contents: string): string { return nodeVersion as string; } -function isLatestSyntax(versionSpec): boolean { +export function isLatestSyntax(versionSpec): boolean { return ['current', 'latest', 'node'].includes(versionSpec); } From 3e844cd766709ca2a5d7821a641644295bfe3f92 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Wed, 9 Nov 2022 20:42:30 +0100 Subject: [PATCH 03/51] Add v8 canary tests to workflow --- .github/workflows/versions.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index 88a1b0f2c..481ca1e43 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -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-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: From 21a386952d4bfce39160fd6d7a6431a5c583327c Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Wed, 9 Nov 2022 20:43:04 +0100 Subject: [PATCH 04/51] Change docs --- README.md | 19 +++++++-------- docs/advanced-usage.md | 52 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f2fbd3d99..61edf1e26 100644 --- a/README.md +++ b/README.md @@ -129,15 +129,16 @@ 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 nigthly versions](docs/advanced-usage.md#nightly-versions) -5. [Using rc versions](docs/advanced-usage.md#rc-versions) -6. [Caching packages data](docs/advanced-usage.md#caching-packages-data) -7. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures) -8. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) -9. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) -10. [Using private packages](docs/advanced-usage.md#use-private-packages) +1. [Using a node version file](docs/advanced-usage.md#node-version-file) +1. [Using different architectures](docs/advanced-usage.md#architecture) +1. [Using v8 canary versions](docs/advanced-usage.md#v8-canary-versions) +1. [Using nigthly versions](docs/advanced-usage.md#nightly-versions) +1. [Using rc versions](docs/advanced-usage.md#rc-versions) +1. [Caching packages data](docs/advanced-usage.md#caching-packages-data) +1. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures) +1. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) +1. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) +1. [Using private packages](docs/advanced-usage.md#use-private-packages) ## License diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 4789f2ead..771d0b829 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -104,6 +104,58 @@ 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 +>>>>>>> d703091 (Change docs) + +```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. From bced0aece0e7e3d1cd8189f551fd797e0d252af6 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Wed, 9 Nov 2022 20:43:40 +0100 Subject: [PATCH 05/51] Build compiled js code --- dist/setup/index.js | 65 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index aa4f708af..291a6a129 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73216,6 +73216,7 @@ const tc = __importStar(__nccwpck_require__(7784)); const path = __importStar(__nccwpck_require__(1017)); const semver = __importStar(__nccwpck_require__(5911)); const fs_1 = __importDefault(__nccwpck_require__(7147)); +const isVersionCanary = (versionSpec) => versionSpec.includes(`-v8-canary`); function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arch()) { return __awaiter(this, void 0, void 0, function* () { // Store manifest data to avoid multiple calls @@ -73224,16 +73225,18 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arc let isNightly = versionSpec.includes('nightly'); let osPlat = os_1.default.platform(); let osArch = translateArchToDistUrl(arch); + let isCanary = isVersionCanary(versionSpec); 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 = yield getManifest(auth); versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } - if (isLatestSyntax(versionSpec)) { + // evaluate exact versionSpec from input + if (isLatestSyntax(versionSpec) || isCanary) { nodeVersions = yield getVersionsFromDist(versionSpec); versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); - core.info(`getting latest node version...`); + core.info(`getting ${isCanary ? 'v8-canary' : 'latest'} node version ${versionSpec}...`); } if (isNightly && checkLatest) { nodeVersions = yield getVersionsFromDist(versionSpec); @@ -73251,11 +73254,16 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arc } } // check cache + core.info('Attempt to find existing version in cache...'); let toolPath; if (isNightly) { const nightlyVersion = findNightlyVersionInHostedToolcache(versionSpec, osArch); toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch); } + else if (isCanary) { + const localVersions = tc.findAllVersions('node', osArch); + toolPath = evaluateVersions(localVersions, versionSpec); + } else { toolPath = tc.find('node', versionSpec, osArch); } @@ -73356,12 +73364,12 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arc exports.getNode = getNode; function findNightlyVersionInHostedToolcache(versionsSpec, osArch) { const foundAllVersions = tc.findAllVersions('node', osArch); - const version = evaluateVersions(foundAllVersions, versionsSpec); - return version; + return evaluateVersions(foundAllVersions, versionsSpec); } function isLtsAlias(versionSpec) { return versionSpec.startsWith('lts/'); } +exports.isLtsAlias = isLtsAlias; function getManifest(auth) { core.debug('Getting manifest from actions/node-versions@main'); return tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); @@ -73391,6 +73399,7 @@ function resolveLtsAliasFromManifest(versionSpec, stable, manifest) { core.debug(`Found LTS release '${release.version}' for Node version '${versionSpec}'`); return release.version.split('.')[0]; } +exports.resolveLtsAliasFromManifest = resolveLtsAliasFromManifest; function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os_1.default.arch()), manifest) { return __awaiter(this, void 0, void 0, function* () { let info = null; @@ -73487,9 +73496,12 @@ function evaluateVersions(versions, versionSpec) { return evaluateNightlyVersions(versions, versionSpec); } versions = versions.sort(semver.rcompare); + const matcher = isVersionCanary(versionSpec) + ? evaluateCanaryMatcher(versionSpec) + : potential => semver.satisfies(potential, versionSpec); for (let i = versions.length - 1; i >= 0; i--) { const potential = versions[i]; - const satisfied = semver.satisfies(potential, versionSpec); + const satisfied = matcher(potential); if (satisfied) { version = potential; break; @@ -73503,15 +73515,23 @@ function evaluateVersions(versions, versionSpec) { } return version; } +exports.evaluateVersions = evaluateVersions; function getNodejsDistUrl(version) { const prerelease = semver.prerelease(version); if (version.includes('nightly')) { + core.debug('requested nightly distribution'); return 'https://nodejs.org/download/nightly'; } else if (prerelease) { return 'https://nodejs.org/download/rc'; } - return 'https://nodejs.org/dist'; + else if (isVersionCanary(version)) { + core.debug('requested v8 canary distribution'); + return 'https://nodejs.org/download/v8-canary'; + } + else { + return 'https://nodejs.org/dist'; + } } exports.getNodejsDistUrl = getNodejsDistUrl; function queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions) { @@ -73537,11 +73557,11 @@ function queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions core.debug('No dist manifest cached'); nodeVersions = yield getVersionsFromDist(versionSpec); } - let versions = []; if (isLatestSyntax(versionSpec)) { core.info(`getting latest node version...`); return nodeVersions[0].version; } + let versions = []; nodeVersions.forEach((nodeVersion) => { // ensure this version supports your os and platform if (nodeVersion.files.indexOf(dataFileName) >= 0) { @@ -73553,10 +73573,11 @@ function queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions return version; }); } +exports.queryDistForMatch = queryDistForMatch; function getVersionsFromDist(versionSpec) { return __awaiter(this, void 0, void 0, function* () { - const initialUrl = getNodejsDistUrl(versionSpec); - const dataUrl = `${initialUrl}/index.json`; + const distUrl = getNodejsDistUrl(versionSpec); + const dataUrl = `${distUrl}/index.json`; let httpClient = new hc.HttpClient('setup-node', [], { allowRetries: true, maxRetries: 3 @@ -73657,6 +73678,32 @@ exports.parseNodeVersionFile = parseNodeVersionFile; function isLatestSyntax(versionSpec) { return ['current', 'latest', 'node'].includes(versionSpec); } +exports.isLatestSyntax = isLatestSyntax; +function evaluateCanaryMatcher(versionSpec) { + var _a; + const [raw, prerelease] = versionSpec.split(/-(.*)/s); + const isValidVersion = semver.valid(raw); + const rawVersion = isValidVersion ? raw : (_a = semver.coerce(raw)) === null || _a === void 0 ? void 0 : _a.version; + if (rawVersion) { + if (prerelease === 'v8-canary') { + // it means versionSpec does not have timestamp + const range = semver.validRange(`^${rawVersion}`); + return (potential) => semver.satisfies( + // TODO: check latest? + potential.replace('-v8-canary', '+v8-canary.'), range); + } + else { + // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 + // there must be exact match + const range = `${rawVersion}-${prerelease}`; + return (potential) => semver.satisfies( + // TODO: check latest? + potential, range); + } + } + return () => false; +} +exports.evaluateCanaryMatcher = evaluateCanaryMatcher; /***/ }), From f40727714820d76fb8172952495c82468d7a0693 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Fri, 11 Nov 2022 09:10:22 +0100 Subject: [PATCH 06/51] Apply requested changes --- dist/setup/index.js | 3 +-- src/installer.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 291a6a129..887654434 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73569,8 +73569,7 @@ function queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions } }); // get the latest version that matches the version spec - let version = evaluateVersions(versions, versionSpec); - return version; + return evaluateVersions(versions, versionSpec); }); } exports.queryDistForMatch = queryDistForMatch; diff --git a/src/installer.ts b/src/installer.ts index fa86711fc..cb6826982 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -512,8 +512,7 @@ export async function queryDistForMatch( }); // get the latest version that matches the version spec - let version = evaluateVersions(versions, versionSpec); - return version; + return evaluateVersions(versions, versionSpec); } export async function getVersionsFromDist( From 5f26e47b75365cc7598c597b01ab90f57e594469 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Tue, 22 Nov 2022 12:33:08 +0100 Subject: [PATCH 07/51] fixes after rebase --- src/installer.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/installer.ts b/src/installer.ts index cb6826982..2e54ba41b 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -273,8 +273,8 @@ export function resolveLtsAliasFromManifest( alias === '*' ? numbered[numbered.length - 1] : n < 0 - ? numbered[numbered.length - 1 + n] - : aliases[alias]; + ? numbered[numbered.length - 1 + n] + : aliases[alias]; if (!release) { throw new Error( @@ -419,31 +419,27 @@ function evaluateNightlyVersions( } // TODO - should we just export this from @actions/tool-cache? Lifted directly from there -export function evaluateVersions( - versions: string[], - versionSpec: string -): string { - let version = ''; +export function evaluateVersions(versions: string[], versionSpec: string): string { core.debug(`evaluating ${versions.length} versions`); if (versionSpec.includes('nightly')) { return evaluateNightlyVersions(versions, versionSpec); } - versions = versions.sort(semver.rcompare); - const matcher: (potential: string) => boolean = isVersionCanary(versionSpec) ? evaluateCanaryMatcher(versionSpec) : potential => semver.satisfies(potential, versionSpec); - for (let i = versions.length - 1; i >= 0; i--) { + const version = versions.sort(semver.rcompare).find(matcher) || '' + /* + for (let i = 0; i< versions.length; i++) { const potential: string = versions[i]; const satisfied: boolean = matcher(potential); if (satisfied) { version = potential; break; } - } + }*/ if (version) { core.debug(`matched: ${version}`); @@ -455,7 +451,7 @@ export function evaluateVersions( } export function getNodejsDistUrl(version: string) { - const prerelease = semver.prerelease(version); + const prerelease = semver.prerelease(version) && !isVersionCanary(version); if (version.includes('nightly')) { core.debug('requested nightly distribution'); return 'https://nodejs.org/download/nightly'; From 0081915898fa7e1a84ed846a623d023eb40b0996 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 05:16:09 +0100 Subject: [PATCH 08/51] refactor nightly and rc --- __tests__/installer.unit.test.ts | 1551 ++++++++++++++++++++++++++++++ src/installer.ts | 265 ++--- 2 files changed, 1686 insertions(+), 130 deletions(-) create mode 100644 __tests__/installer.unit.test.ts diff --git a/__tests__/installer.unit.test.ts b/__tests__/installer.unit.test.ts new file mode 100644 index 000000000..a38a75361 --- /dev/null +++ b/__tests__/installer.unit.test.ts @@ -0,0 +1,1551 @@ +import * as core from '@actions/core'; +import * as io from '@actions/io'; +import * as tc from '@actions/tool-cache'; +import * as httpm from '@actions/http-client'; +import * as exec from '@actions/exec'; +import * as im from '../src/installer'; +import * as cache from '@actions/cache'; +import fs from 'fs'; +import cp from 'child_process'; +import osm from 'os'; +import path from 'path'; +import each from 'jest-each'; +import * as main from '../src/main'; +import * as auth from '../src/authutil'; + +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'); + // @ts-ignore + getDistSpy = jest.spyOn(im, 'getVersionsFromDist'); + parseNodeVersionSpy = jest.spyOn(im, 'parseNodeVersionFile'); + + // http-client + getJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); + + // io + whichSpy = jest.spyOn(io, 'which'); + existsSpy = jest.spyOn(fs, 'existsSync'); + 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( + () => nodeTestManifest + ); + + getDistSpy.mockImplementation(version => { + const initialUrl = im.getNodejsDistUrl(version); + if (initialUrl.endsWith('/rc')) { + return nodeTestDistRc; + } else if (initialUrl.endsWith('/nightly')) { + return nodeTestDistNightly; + } else { + return nodeTestDist; + } + }); + + getJsonSpy.mockImplementation(url => { + let res: any; + if (url.includes('/rc')) { + res = nodeTestDistRc; + } else if (url.includes('/nightly')) { + res = nodeTestDistNightly; + } else { + res = nodeTestDist; + } + + return {result: res}; + }); + + // writes + cnSpy = jest.spyOn(process.stdout, 'write'); + 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); + + //-------------------------------------------------- + // 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'], + ['10', 'win32', '10.20.1', 'Dubnium'], + ['*', 'linux', '14.0.0', 'Fermium'] + ])( + 'can find %s from manifest on %s', + async (versionSpec, platform, expectedVersion, expectedLts) => { + os.platform = platform; + os.arch = 'x64'; + let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo( + 'actions', + 'node-versions', + 'mocktoken' + ); + expect(versions).toBeDefined(); + let match = await tc.findFromManifest(versionSpec, true, versions); + expect(match).toBeDefined(); + expect(match?.version).toBe(expectedVersion); + expect((match as any).lts).toBe(expectedLts); + } + ); + + //-------------------------------------------------- + // Found in cache tests + //-------------------------------------------------- + + it('finds version in cache with stable true', async () => { + inputs['node-version'] = '12'; + inputs.stable = 'true'; + + let toolPath = path.normalize('/cache/node/12.16.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'; + + inSpy.mockImplementation(name => inputs[name]); + + let toolPath = path.normalize('/cache/node/12.16.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'; + + inSpy.mockImplementation(name => inputs[name]); + + let toolPath = path.normalize('/cache/node/12.16.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'; + + findSpy.mockImplementation(() => { + throw new Error(errMsg); + }); + + await main.run(); + + expect(cnSpy).toHaveBeenCalledWith('::error::' + errMsg + osm.EOL); + }); + + //-------------------------------------------------- + // Manifest tests + //-------------------------------------------------- + + it('downloads a version from a manifest match', async () => { + os.platform = 'linux'; + os.arch = 'x64'; + + // a version which is in the manifest + let versionSpec = '12.16.2'; + 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/12.16.2/x64'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + + await main.run(); + + let expPath = path.join(toolPath, 'bin'); + + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'node', + ['--version'], + expect.anything() + ); + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'npm', + ['--version'], + expect.anything() + ); + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'yarn', + ['--version'], + expect.anything() + ); + expect(dlSpy).toHaveBeenCalled(); + expect(exSpy).toHaveBeenCalled(); + expect(logSpy).toHaveBeenCalledWith( + `Acquiring ${resolvedVersion} - ${os.arch} from ${expectedUrl}` + ); + expect(logSpy).toHaveBeenCalledWith( + `Attempting to download ${versionSpec}...` + ); + expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${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 = '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'); + 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 = '9.99.9'; + inputs['node-version'] = versionSpec; + + findSpy.mockImplementation(() => ''); + await main.run(); + + expect(logSpy).toHaveBeenCalledWith( + 'Not found in manifest. Falling back to download directly from Node' + ); + 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}` + ); + }); + + 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 = '12.16.2'; + let resolvedVersion = versionSpec; + + inputs['node-version'] = versionSpec; + inputs['always-auth'] = false; + inputs['token'] = 'faketoken'; + + findSpy.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: '12.16.2', osSpec: 'win32'}, + {arch: 'x86', version: '14.0.0', osSpec: 'win32'} + ]) { + os.platform = osSpec; + os.arch = arch; + const fileExtension = os.platform === 'win32' ? '7z' : 'tar.gz'; + const platform = { + linux: 'linux', + darwin: 'darwin', + win32: 'win' + }[os.platform]; + + inputs['node-version'] = version; + inputs['architecture'] = arch; + inputs['always-auth'] = false; + inputs['token'] = 'faketoken'; + + let expectedUrl = + arch === 'x64' + ? `https://github.com/actions/node-versions/releases/download/${version}/node-${version}-${platform}-${arch}.zip` + : `https://nodejs.org/dist/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`; + + // ... but not in the local cache + findSpy.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('check-latest flag', () => { + it('use local version and dont check manifest if check-latest is not specified', async () => { + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = '12'; + inputs['check-latest'] = 'false'; + + const toolPath = path.normalize('/cache/node/12.16.1/x64'); + findSpy.mockReturnValue(toolPath); + await main.run(); + + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + expect(logSpy).not.toHaveBeenCalledWith( + 'Attempt to resolve the latest version from manifest...' + ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); + expect(dbgSpy).not.toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + }); + + it('check latest version and resolve it from local cache', async () => { + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = '12'; + inputs['check-latest'] = 'true'; + + const toolPath = path.normalize('/cache/node/12.16.2/x64'); + findSpy.mockReturnValue(toolPath); + dlSpy.mockImplementation(async () => '/some/temp/path'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + + await main.run(); + + expect(logSpy).toHaveBeenCalledWith( + 'Attempt to resolve the latest version from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + }); + + it('check latest version and install it from manifest', async () => { + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = '12'; + inputs['check-latest'] = 'true'; + + findSpy.mockImplementation(() => ''); + dlSpy.mockImplementation(async () => '/some/temp/path'); + const toolPath = path.normalize('/cache/node/12.16.2/x64'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + const expectedUrl = + 'https://github.com/actions/node-versions/releases/download/12.16.2-20200507.95/node-12.16.2-linux-x64.tar.gz'; + + await main.run(); + + expect(logSpy).toHaveBeenCalledWith( + 'Attempt to resolve the latest version from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); + expect(logSpy).toHaveBeenCalledWith( + `Acquiring 12.16.2 - ${os.arch} from ${expectedUrl}` + ); + expect(logSpy).toHaveBeenCalledWith('Extracting ...'); + }); + + it('fallback to dist if version if not found in manifest', async () => { + os.platform = 'linux'; + os.arch = 'x64'; + + // a version which is not in the manifest but is in node dist + let versionSpec = '11'; + + inputs['node-version'] = versionSpec; + inputs['check-latest'] = 'true'; + 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( + 'Attempt to resolve the latest version from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(logSpy).toHaveBeenCalledWith( + `Failed to resolve version ${versionSpec} from manifest` + ); + expect(logSpy).toHaveBeenCalledWith( + `Attempting to download ${versionSpec}...` + ); + expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); + }); + + it('fallback to dist if manifest is not available', async () => { + os.platform = 'linux'; + os.arch = 'x64'; + + // a version which is not in the manifest but is in node dist + let versionSpec = '12'; + + inputs['node-version'] = versionSpec; + inputs['check-latest'] = 'true'; + inputs['always-auth'] = false; + inputs['token'] = 'faketoken'; + + // ... but not in the local cache + findSpy.mockImplementation(() => ''); + getManifestSpy.mockImplementation(() => { + throw new Error('Unable to download manifest'); + }); + + dlSpy.mockImplementation(async () => '/some/temp/path'); + let toolPath = path.normalize('/cache/node/12.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( + 'Attempt to resolve the latest version from manifest...' + ); + expect(logSpy).toHaveBeenCalledWith( + 'Unable to resolve version from manifest...' + ); + expect(logSpy).toHaveBeenCalledWith( + `Failed to resolve version ${versionSpec} from manifest` + ); + expect(logSpy).toHaveBeenCalledWith( + `Attempting to download ${versionSpec}...` + ); + expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); + }); + }); + + describe('node-version-file flag', () => { + it('not used if node-version is provided', async () => { + // Arrange + inputs['node-version'] = '12'; + + // Act + await main.run(); + + // Assert + expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); + }); + + it('not used if node-version-file not provided', async () => { + // Act + await main.run(); + + // Assert + expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); + }); + + it('reads node-version-file if provided', async () => { + // Arrange + const versionSpec = 'v14'; + const versionFile = '.nvmrc'; + const expectedVersionSpec = '14'; + process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data'); + inputs['node-version-file'] = versionFile; + + parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); + existsSpy.mockImplementationOnce( + input => input === path.join(__dirname, 'data', versionFile) + ); + + // Act + await main.run(); + + // Assert + expect(existsSpy).toHaveBeenCalledTimes(1); + expect(existsSpy).toHaveReturnedWith(true); + expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec); + expect(logSpy).toHaveBeenCalledWith( + `Resolved ${versionFile} as ${expectedVersionSpec}` + ); + }); + + it('reads package.json as node-version-file if provided', async () => { + // Arrange + const versionSpec = fs.readFileSync( + path.join(__dirname, 'data/package.json'), + 'utf-8' + ); + const versionFile = 'package.json'; + const expectedVersionSpec = '14'; + process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data'); + inputs['node-version-file'] = versionFile; + + parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); + existsSpy.mockImplementationOnce( + input => input === path.join(__dirname, 'data', versionFile) + ); + // Act + await main.run(); + + // Assert + expect(existsSpy).toHaveBeenCalledTimes(1); + expect(existsSpy).toHaveReturnedWith(true); + expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec); + expect(logSpy).toHaveBeenCalledWith( + `Resolved ${versionFile} as ${expectedVersionSpec}` + ); + }); + + it('both node-version-file and node-version are provided', async () => { + inputs['node-version'] = '12'; + const versionSpec = 'v14'; + const versionFile = '.nvmrc'; + const expectedVersionSpec = '14'; + process.env['GITHUB_WORKSPACE'] = path.join(__dirname, '..'); + inputs['node-version-file'] = versionFile; + + parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); + + // Act + await main.run(); + + // Assert + expect(existsSpy).toHaveBeenCalledTimes(0); + expect(parseNodeVersionSpy).not.toHaveBeenCalled(); + expect(warningSpy).toHaveBeenCalledWith( + 'Both node-version and node-version-file inputs are specified, only node-version will be used' + ); + }); + + it('should throw an error if node-version-file is not found', async () => { + const versionFile = '.nvmrc'; + const versionFilePath = path.join(__dirname, '..', versionFile); + inputs['node-version-file'] = versionFile; + + inSpy.mockImplementation(name => inputs[name]); + existsSpy.mockImplementationOnce( + input => input === path.join(__dirname, 'data', versionFile) + ); + + // Act + await main.run(); + + // Assert + expect(existsSpy).toHaveBeenCalled(); + expect(existsSpy).toHaveReturnedWith(false); + expect(parseNodeVersionSpy).not.toHaveBeenCalled(); + expect(cnSpy).toHaveBeenCalledWith( + `::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}` + ); + }); + }); + + describe('cache on GHES', () => { + it('Should throw an error, because cache is not supported', async () => { + inputs['node-version'] = '12'; + inputs['cache'] = 'npm'; + + inSpy.mockImplementation(name => inputs[name]); + + let toolPath = path.normalize('/cache/node/12.16.1/x64'); + findSpy.mockImplementation(() => toolPath); + + // expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + process.env['GITHUB_SERVER_URL'] = 'https://www.test.com'; + isCacheActionAvailable.mockImplementation(() => false); + + await main.run(); + + expect(cnSpy).toHaveBeenCalledWith( + `::error::Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.${osm.EOL}` + ); + }); + + it('Should throw an internal error', async () => { + inputs['node-version'] = '12'; + inputs['cache'] = 'npm'; + + inSpy.mockImplementation(name => inputs[name]); + + let toolPath = path.normalize('/cache/node/12.16.1/x64'); + findSpy.mockImplementation(() => toolPath); + + // expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + process.env['GITHUB_SERVER_URL'] = ''; + isCacheActionAvailable.mockImplementation(() => false); + + await main.run(); + + expect(warningSpy).toHaveBeenCalledWith( + 'The runner was not able to contact the cache service. Caching will be skipped' + ); + }); + }); + + describe('LTS version', () => { + beforeEach(() => { + os.platform = 'linux'; + os.arch = 'x64'; + inputs.stable = 'true'; + }); + + it.each([ + ['erbium', '12.16.2'], + ['*', '14.0.0'], + ['-1', '12.16.2'] + ])( + 'find latest LTS version and resolve it from local cache (lts/%s)', + async (lts, expectedVersion) => { + // arrange + inputs['node-version'] = `lts/${lts}`; + + const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); + findSpy.mockReturnValue(toolPath); + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith( + 'Attempt to resolve LTS alias from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); + expect(dbgSpy).toHaveBeenCalledWith( + `LTS alias '${lts}' for Node version 'lts/${lts}'` + ); + expect(dbgSpy).toHaveBeenCalledWith( + `Found LTS release '${expectedVersion}' for Node version 'lts/${lts}'` + ); + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + expect(cnSpy).toHaveBeenCalledWith( + `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` + ); + } + ); + + it.each([ + [ + 'erbium', + '12.16.2', + 'https://github.com/actions/node-versions/releases/download/12.16.2-20200507.95/node-12.16.2-linux-x64.tar.gz' + ], + [ + '*', + '14.0.0', + 'https://github.com/actions/node-versions/releases/download/14.0.0-20200507.99/node-14.0.0-linux-x64.tar.gz' + ], + [ + '-1', + '12.16.2', + 'https://github.com/actions/node-versions/releases/download/12.16.2-20200507.95/node-12.16.2-linux-x64.tar.gz' + ] + ])( + 'find latest LTS version and install it from manifest (lts/%s)', + async (lts, expectedVersion, expectedUrl) => { + // arrange + inputs['node-version'] = `lts/${lts}`; + + const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); + findSpy.mockImplementation(() => ''); + dlSpy.mockImplementation(async () => '/some/temp/path'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + const expectedMajor = expectedVersion.split('.')[0]; + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith( + 'Attempt to resolve LTS alias from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); + expect(dbgSpy).toHaveBeenCalledWith( + `LTS alias '${lts}' for Node version 'lts/${lts}'` + ); + expect(dbgSpy).toHaveBeenCalledWith( + `Found LTS release '${expectedVersion}' for Node version 'lts/${lts}'` + ); + expect(logSpy).toHaveBeenCalledWith( + `Attempting to download ${expectedMajor}...` + ); + 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('fail with unable to parse LTS alias (lts/)', async () => { + // arrange + inputs['node-version'] = 'lts/'; + + findSpy.mockImplementation(() => ''); + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith( + 'Attempt to resolve LTS alias from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(cnSpy).toHaveBeenCalledWith( + `::error::Unable to parse LTS alias for Node version 'lts/'${osm.EOL}` + ); + }); + + it('fail to find LTS version (lts/unknown)', async () => { + // arrange + inputs['node-version'] = 'lts/unknown'; + + findSpy.mockImplementation(() => ''); + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith( + 'Attempt to resolve LTS alias from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(dbgSpy).toHaveBeenCalledWith( + `LTS alias 'unknown' for Node version 'lts/unknown'` + ); + expect(cnSpy).toHaveBeenCalledWith( + `::error::Unable to find LTS release 'unknown' for Node version 'lts/unknown'.${osm.EOL}` + ); + }); + + it('fail if manifest is not available', async () => { + // arrange + inputs['node-version'] = 'lts/erbium'; + + // ... but not in the local cache + findSpy.mockImplementation(() => ''); + getManifestSpy.mockImplementation(() => { + throw new Error('Unable to download manifest'); + }); + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith( + 'Attempt to resolve LTS alias from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(cnSpy).toHaveBeenCalledWith( + `::error::Unable to download manifest${osm.EOL}` + ); + }); + }); + + 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.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(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', + async inputVersion => { + // Arrange + inputs['node-version'] = inputVersion; + + os.platform = 'darwin'; + os.arch = 'x64'; + + findSpy.mockImplementation(() => ''); + getManifestSpy.mockImplementation(() => { + throw new Error('Unable to download manifest'); + }); + + // Act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith('Unable to download manifest'); + + expect(logSpy).toHaveBeenCalledWith('getting latest node version...'); + } + ); + }); + + describe('latest alias syntax from cache', () => { + it.each(['latest', 'current', 'node'])( + 'download the %s version if alias is provided', + async inputVersion => { + // Arrange + inputs['node-version'] = inputVersion; + const expectedVersion = nodeTestDist[0]; + + os.platform = 'darwin'; + os.arch = 'x64'; + + const toolPath = path.normalize( + `/cache/node/${expectedVersion.version}/x64` + ); + findSpy.mockReturnValue(toolPath); + + // Act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + + expect(logSpy).toHaveBeenCalledWith('getting latest node version...'); + } + ); + }); + + describe('setup-node v8 canary unit tests', () => { + + it('v20-v8-canary should match any minor and patch version', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20-v8-canary'); + expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); + }); + + it('v20-v8-canary should not match v21.x & v19.x', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20-v8-canary'); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.1.1-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.1.-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); + + it('v20.1-v8-canary should match any v20.1 patch version and minor above or eq v20.1', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.1-v8-canary'); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); + expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + }); + + it('v20.2-v8-canary should not match v21.x, v19.x, and v20 minor less v20.2', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.2-v8-canary'); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); + + it('v20.1.1-v8-canary should match v20.1.x patch versions above or eq v20.1.1', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + }); + + it('v20.1.1-v8-canary should match patch versions with any canary timestamp', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); + }); + + it('v20.1.1-v8-canary should not match any other minor versions and patch versions below v20.1.1', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); + + it('v20.0.0-v8-canary20221103f7e2421e91 should match only v20.0.0-v8-canary20221103f7e2421e91', () => { + // @ts-ignore + const matcher = im.evaluateCanaryMatcher( + 'v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 + expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); + }); + + it('v8 canary evaluateVersions without timestamp', () => { + const versions = [ + 'v20.0.0-v8-canary20221103f7e2421e91', + 'v20.0.1-v8-canary20221103f7e2421e91', + 'v20.1.0-v8-canary20221103f7e2421e91', + 'v20.1.1-v8-canary20221103f7e2421e91', + 'v21.1.0-v8-canary20221103f7e2421e91', + 'v19.1.0-v8-canary20221103f7e2421e91' + ]; + // @ts-ignore + const version = im.evaluateVersions(versions, 'v20-v8-canary'); + expect(version).toBe('v20.1.1-v8-canary20221103f7e2421e91'); + }); + + it('v8 canary evaluateVersions with timestamp', () => { + const versions = [ + 'v20.0.0-v8-canary20221103f7e2421e91', + 'v20.0.1-v8-canary20221103f7e2421e91', + 'v20.0.1-v8-canary20221103f7e2421e92', + 'v20.0.1-v8-canary20221103f7e2421e93', + 'v20.0.2-v8-canary20221103f7e2421e91' + ]; + // @ts-ignore + const version = im.evaluateVersions( + versions, + 'v20.0.1-v8-canary20221103f7e2421e92' + ); + expect(version).toBe('v20.0.1-v8-canary20221103f7e2421e92'); + }); + + it('v8 canary queryDistForMatch', async () => { + jest.spyOn(osm, 'platform').mockImplementationOnce(() => 'linux'); + // @ts-ignore + const version = await im.queryDistForMatch( + 'v20-v8-canary', + 'x64', + nodeV8CanaryTestDist + ); + expect(version).toBe('v20.0.0-v8-canary20221103f7e2421e91'); + }); + }); + + describe('setup-node v8 canary e2e tests', () => { + // @actions/http-client + let getDistIndexJsonSpy: jest.SpyInstance; + let findAllVersionSpy: jest.SpyInstance; + + beforeEach(() => { + // @actions/http-client + getDistIndexJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); + getDistIndexJsonSpy.mockImplementation(() => ({ + result: nodeV8CanaryTestDist + })); + + // @actions/tool-cache + findAllVersionSpy = jest.spyOn(tc, 'findAllVersions'); + }); + + it('v8 canary setup node flow without cached', async () => { + let versionSpec = 'v20-v8-canary'; + + inputs['node-version'] = versionSpec; + inputs['always-auth'] = false; + inputs['token'] = 'faketoken'; + + os.platform = 'linux'; + os.arch = 'x64'; + + findAllVersionSpy.mockImplementation(() => []); + + findSpy.mockImplementation(() => ''); + + dlSpy.mockImplementation(async () => '/some/temp/path'); + let toolPath = path.normalize('/cache/node/12.16.2/x64'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + + await main.run(); + + expect(dbgSpy.mock.calls[0][0]).toBe('requested v8 canary distribution'); + expect(dbgSpy.mock.calls[1][0]).toBe('evaluating 17 versions'); + expect(dbgSpy.mock.calls[2][0]).toBe( + 'matched: v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(logSpy.mock.calls[0][0]).toBe( + 'getting v8-canary node version v20.0.0-v8-canary20221103f7e2421e91...' + ); + expect(logSpy.mock.calls[1][0]).toBe( + 'Attempt to find existing version in cache...' + ); + expect(dbgSpy.mock.calls[3][0]).toBe('evaluating 0 versions'); + expect(dbgSpy.mock.calls[4][0]).toBe('match not found'); + expect(logSpy.mock.calls[2][0]).toBe( + 'Attempting to download v20.0.0-v8-canary20221103f7e2421e91...' + ); + expect(dbgSpy.mock.calls[5][0]).toBe('No manifest cached'); + expect(dbgSpy.mock.calls[6][0]).toBe( + 'Getting manifest from actions/node-versions@main' + ); + expect(dbgSpy.mock.calls[7][0].slice(0, 6)).toBe('check '); + expect(dbgSpy.mock.calls[13][0].slice(0, 6)).toBe('check '); + expect(logSpy.mock.calls[3][0]).toBe( + 'Not found in manifest. Falling back to download directly from Node' + ); + expect(dbgSpy.mock.calls[14][0]).toBe('evaluating 17 versions'); + expect(dbgSpy.mock.calls[15][0]).toBe( + 'matched: v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(dbgSpy.mock.calls[16][0]).toBe('requested v8 canary distribution'); + expect(logSpy.mock.calls[4][0]).toBe( + 'Acquiring 20.0.0-v8-canary20221103f7e2421e91 - x64 from https://nodejs.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz' + ); + + expect(dlSpy).toHaveBeenCalledTimes(1); + expect(exSpy).toHaveBeenCalledTimes(1); + expect(cacheSpy).toHaveBeenCalledTimes(1); + }); + + 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'; + + findAllVersionSpy.mockImplementation(() => [ + 'v20.0.0-v8-canary20221103f7e2421e91' + ]); + + await main.run(); + + expect(dbgSpy.mock.calls[0][0]).toBe('requested v8 canary distribution'); + expect(dbgSpy.mock.calls[1][0]).toBe('evaluating 17 versions'); + expect(dbgSpy.mock.calls[2][0]).toBe( + 'matched: v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(logSpy.mock.calls[0][0]).toBe( + 'getting v8-canary node version v20.0.0-v8-canary20221103f7e2421e91...' + ); + expect(logSpy.mock.calls[1][0]).toBe( + 'Attempt to find existing version in cache...' + ); + expect(dbgSpy.mock.calls[3][0]).toBe('evaluating 1 versions'); + expect(dbgSpy.mock.calls[4][0]).toBe( + 'matched: v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(logSpy.mock.calls[2][0]).toBe( + 'Found in cache @ v20.0.0-v8-canary20221103f7e2421e91' + ); + expect(cnSpy.mock.calls[1][0].trim()).toBe( + `::add-path::v20.0.0-v8-canary20221103f7e2421e91${path.sep}bin` + ); + + expect(dlSpy).not.toHaveBeenCalled(); + expect(exSpy).not.toHaveBeenCalled(); + expect(cacheSpy).not.toHaveBeenCalled(); + }); + }); +}); + +describe('helper methods', () => { + it('is not LTS alias', async () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const isLtsAlias = im.isLtsAlias(versionSpec); + expect(isLtsAlias).toBeFalsy(); + }); + + it('is not isLatestSyntax', async () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const isLatestSyntax = im.isLatestSyntax(versionSpec); + expect(isLatestSyntax).toBeFalsy(); + }); + + describe('getNodejsDistUrl', () => { + it('dist url to be https://nodejs.org/download/v8-canary for input versionSpec', () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const url = im.getNodejsDistUrl(versionSpec); + expect(url).toBe('https://nodejs.org/download/v8-canary'); + }); + + it('dist url to be https://nodejs.org/download/v8-canary for full versionSpec', () => { + const versionSpec = 'v20.0.0-v8-canary20221103f7e2421e91'; + // @ts-ignore + const url = im.getNodejsDistUrl(versionSpec); + expect(url).toBe('https://nodejs.org/download/v8-canary'); + }); + }); + + 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); + }); + }); +}); diff --git a/src/installer.ts b/src/installer.ts index 2e54ba41b..fcd871eb7 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -30,8 +30,112 @@ interface INodeRelease extends tc.IToolRelease { lts?: string; } -const isVersionCanary = (versionSpec: string): boolean => - versionSpec.includes(`-v8-canary`); +export enum Distributions { + DEFAULT, + CANARY, + NIGHTLY, + RC, +} + +export const distributionOf = (versionSpec: string): Distributions => + versionSpec.includes('-v8-canary') + ? Distributions.CANARY + // TODO: i'd like to have this check, do you? + : versionSpec.includes('-canary') + ? (() => { + throw Error('Canary version must have "-v8-canary suffix"') + })() + : versionSpec.includes('nightly') + ? Distributions.NIGHTLY + : semver.prerelease(versionSpec) + ? Distributions.RC + : Distributions.DEFAULT + +interface VersionMatcher { + (potential: string): boolean + + // memoize the factory for testing and debug purposes + factory: ((ver: string, suffix: string) => VersionMatcher) | + ((semverRanger: string) => VersionMatcher) | (() => VersionMatcher) +} + +export const semverVersionMatcherFactory = (range: string): VersionMatcher => { + const matcher = (potential: string): boolean => semver.satisfies(potential, range); + matcher.factory = semverVersionMatcherFactory + return matcher +} + +export const canaryRangeVersionMatcherFactory = (version: string): VersionMatcher => { + const range = semver.validRange(`^${version}`) + const matcher = (potential: string): boolean => + semver.satisfies(potential.replace('-v8-canary', '+v8-canary.'), range); + matcher.factory = canaryRangeVersionMatcherFactory + return matcher +} + +export const canaryExactVersionMatcherFactory = (version: string, timestamp: string): VersionMatcher => { + const range = `${version}-${timestamp}` + const matcher = (potential: string): boolean => + semver.satisfies(potential, range); + matcher.factory = canaryExactVersionMatcherFactory + return matcher +} + +export const nightlyRangeVersionMatcherFactory = (version: string): VersionMatcher => { + const range = `${semver.validRange(`^${version}-0`)}-0` + const matcher = (potential: string): boolean => + distributionOf(potential) === Distributions.NIGHTLY && + semver.satisfies(potential.replace('-nightly', '-nightly.'), range, {includePrerelease: true}) + matcher.factory = nightlyRangeVersionMatcherFactory + return matcher +} + +export const nightlyExactVersionMatcherFactory = (version: string, prerelease_tag: string): VersionMatcher => { + const range = `${version}-${prerelease_tag.replace('nightly', 'nightly.')}`; + const matcher = (potential: string): boolean => + distributionOf(potential) === Distributions.NIGHTLY && + semver.satisfies(potential.replace('-nightly', '-nightly.'), range, {includePrerelease: true}) + matcher.factory = nightlyExactVersionMatcherFactory + return matcher +} + +const alwaysFalseVersionMatcherFactory = (): VersionMatcher => { + const matcher = () => false; + matcher.factory = alwaysFalseVersionMatcherFactory + return matcher +} + +const alwaysFalseVersionMatcher = alwaysFalseVersionMatcherFactory() + +// [raw, prerelease] +export const splitVersionSpec = (versionSpec: string): string[] => versionSpec.split(/-(.*)/s); + +export function versionMatcherFactory(versionSpec: string): VersionMatcher { + const [raw, prerelease] = splitVersionSpec(versionSpec) + const validVersion = semver.valid(raw) ? raw : semver.coerce(raw)?.version; + + if (validVersion) { + switch (distributionOf(versionSpec)) { + case Distributions.CANARY: + return (prerelease === 'v8-canary') // this means versionSpec does not have timestamp + ? canaryRangeVersionMatcherFactory(validVersion) + : canaryExactVersionMatcherFactory(validVersion, prerelease) + case Distributions.NIGHTLY: + return (prerelease === 'nightly') // this means versionSpec does not have prerelease tag + ? nightlyRangeVersionMatcherFactory(validVersion) + : nightlyExactVersionMatcherFactory(validVersion, prerelease) + case Distributions.RC: + case Distributions.DEFAULT: + return semverVersionMatcherFactory(versionSpec) + } + } else { + // TODO: i prefer to have implicit exception for the malformed input + throw Error(`Invalid version input "${versionSpec}"`) + + // TODO: but it is possible to silently fail + // return alwaysFalseVersionMatcher + } +} export async function getNode( versionSpec: string, @@ -43,10 +147,9 @@ export async function getNode( // Store manifest data to avoid multiple calls let manifest: INodeRelease[] | undefined; let nodeVersions: INodeVersion[] | undefined; - let isNightly = versionSpec.includes('nightly'); - let osPlat: string = os.platform(); - let osArch: string = translateArchToDistUrl(arch); - let isCanary = isVersionCanary(versionSpec); + const osPlat: string = os.platform(); + const osArch: string = translateArchToDistUrl(arch); + const distribution = distributionOf(versionSpec) if (isLtsAlias(versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); @@ -57,23 +160,23 @@ export async function getNode( versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } - // evaluate exact versionSpec from input - if (isLatestSyntax(versionSpec) || isCanary) { + // TODO: 121-127 and 131-132 seems to be the same. Why do we need them? + if (isLatestSyntax(versionSpec) || distribution == Distributions.CANARY) { nodeVersions = await getVersionsFromDist(versionSpec); versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); core.info( `getting ${ - isCanary ? 'v8-canary' : 'latest' + distribution == Distributions.CANARY ? 'v8-canary' : 'latest' } node version ${versionSpec}...` ); } - if (isNightly && checkLatest) { + if (distribution === Distributions.NIGHTLY && checkLatest) { nodeVersions = await getVersionsFromDist(versionSpec); versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); } - if (checkLatest && !isNightly) { + if (checkLatest && distribution !== Distributions.NIGHTLY) { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = await resolveVersionFromManifest( versionSpec, @@ -93,17 +196,12 @@ export async function getNode( // check cache core.info('Attempt to find existing version in cache...'); let toolPath: string; - if (isNightly) { - const nightlyVersion = findNightlyVersionInHostedToolcache( - versionSpec, - osArch - ); - toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch); - } else if (isCanary) { - const localVersions = tc.findAllVersions('node', osArch); - toolPath = evaluateVersions(localVersions, versionSpec); - } else { + if (distribution === Distributions.DEFAULT) { toolPath = tc.find('node', versionSpec, osArch); + } else { + const localVersionPaths = tc.findAllVersions('node', osArch) + const localVersion = evaluateVersions(localVersionPaths, versionSpec); + toolPath = localVersion && tc.find('node', localVersion, osArch); } // If not found in cache, download @@ -228,14 +326,6 @@ export async function getNode( core.addPath(toolPath); } -function findNightlyVersionInHostedToolcache( - versionsSpec: string, - osArch: string -) { - const foundAllVersions = tc.findAllVersions('node', osArch); - return evaluateVersions(foundAllVersions, versionsSpec); -} - export function isLtsAlias(versionSpec: string): boolean { return versionSpec.startsWith('lts/'); } @@ -376,70 +466,15 @@ async function resolveVersionFromManifest( } } -function evaluateNightlyVersions( - versions: string[], - versionSpec: string -): string { - let version = ''; - let range: string | undefined; - const [raw, prerelease] = versionSpec.split('-'); - const isValidVersion = semver.valid(raw); - const rawVersion = isValidVersion ? raw : semver.coerce(raw); - if (rawVersion) { - if (prerelease !== 'nightly') { - range = `${rawVersion}-${prerelease.replace('nightly', 'nightly.')}`; - } else { - range = `${semver.validRange(`^${rawVersion}-0`)}-0`; - } - } - - if (range) { - versions.sort(semver.rcompare); - for (const currentVersion of versions) { - const satisfied: boolean = - semver.satisfies( - currentVersion.replace('-nightly', '-nightly.'), - range, - {includePrerelease: true} - ) && currentVersion.includes('nightly'); - if (satisfied) { - version = currentVersion; - break; - } - } - } - - if (version) { - core.debug(`matched: ${version}`); - } else { - core.debug('match not found'); - } - - return version; -} - // TODO - should we just export this from @actions/tool-cache? Lifted directly from there +// - the answer from dsame@github.com - we have customized matcher and can not +// export `evaluateVersions` from tc. But it would be possible to modify tc to accept +// the matcher as an optional parameter to `evaluateVersions` export function evaluateVersions(versions: string[], versionSpec: string): string { core.debug(`evaluating ${versions.length} versions`); - if (versionSpec.includes('nightly')) { - return evaluateNightlyVersions(versions, versionSpec); - } - - const matcher: (potential: string) => boolean = isVersionCanary(versionSpec) - ? evaluateCanaryMatcher(versionSpec) - : potential => semver.satisfies(potential, versionSpec); - + const matcher = versionMatcherFactory(versionSpec) const version = versions.sort(semver.rcompare).find(matcher) || '' - /* - for (let i = 0; i< versions.length; i++) { - const potential: string = versions[i]; - const satisfied: boolean = matcher(potential); - if (satisfied) { - version = potential; - break; - } - }*/ if (version) { core.debug(`matched: ${version}`); @@ -451,17 +486,18 @@ export function evaluateVersions(versions: string[], versionSpec: string): strin } export function getNodejsDistUrl(version: string) { - const prerelease = semver.prerelease(version) && !isVersionCanary(version); - if (version.includes('nightly')) { - core.debug('requested nightly distribution'); - return 'https://nodejs.org/download/nightly'; - } else if (prerelease) { - return 'https://nodejs.org/download/rc'; - } else if (isVersionCanary(version)) { - core.debug('requested v8 canary distribution'); - return 'https://nodejs.org/download/v8-canary'; - } else { - return 'https://nodejs.org/dist'; + switch (distributionOf(version)) { + case Distributions.CANARY: + core.debug('requested v8 canary distribution'); + return 'https://nodejs.org/download/v8-canary'; + case Distributions.NIGHTLY: + core.debug('requested nightly distribution'); + return 'https://nodejs.org/download/nightly'; + case Distributions.RC: + core.debug('requested release candidates distribution'); + return 'https://nodejs.org/download/rc'; + case Distributions.DEFAULT: + return 'https://nodejs.org/dist'; } } @@ -621,34 +657,3 @@ export function parseNodeVersionFile(contents: string): string { export function isLatestSyntax(versionSpec): boolean { return ['current', 'latest', 'node'].includes(versionSpec); } - -export function evaluateCanaryMatcher( - versionSpec: string -): (potential: string) => boolean { - const [raw, prerelease] = versionSpec.split(/-(.*)/s); - const isValidVersion = semver.valid(raw); - const rawVersion = isValidVersion ? raw : semver.coerce(raw)?.version; - if (rawVersion) { - if (prerelease === 'v8-canary') { - // it means versionSpec does not have timestamp - const range = semver.validRange(`^${rawVersion}`); - return (potential: string) => - semver.satisfies( - // TODO: check latest? - potential.replace('-v8-canary', '+v8-canary.'), - range - ); - } else { - // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 - // there must be exact match - const range = `${rawVersion}-${prerelease}`; - return (potential: string) => - semver.satisfies( - // TODO: check latest? - potential, - range - ); - } - } - return () => false; -} From 1536edb40eb53d15caf27da3e2bc63fd5c2d0681 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 05:16:27 +0100 Subject: [PATCH 09/51] Add tests --- __tests__/installer.test.ts | 217 +--- __tests__/installer.unit.test.ts | 1636 +++--------------------------- 2 files changed, 203 insertions(+), 1650 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 321034ae2..893f2471a 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -89,7 +89,8 @@ describe('setup-node', () => { // disable authentication portion for installer tests authSpy = jest.spyOn(auth, 'configAuthentication'); - authSpy.mockImplementation(() => {}); + authSpy.mockImplementation(() => { + }); // gets getManifestSpy.mockImplementation( @@ -1000,7 +1001,15 @@ describe('setup-node', () => { 'finds the %s version in the hostedToolcache', async (input, expectedVersion) => { const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); - findSpy.mockReturnValue(toolPath); + 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'; @@ -1255,149 +1264,7 @@ describe('setup-node', () => { ); }); - describe('setup-node v8 canary unit tests', () => { - it('is not LTS alias', async () => { - const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore - const isLtsAlias = im.isLtsAlias(versionSpec); - expect(isLtsAlias).toBeFalsy(); - }); - - it('is not isLatestSyntax', async () => { - const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore - const isLatestSyntax = im.isLatestSyntax(versionSpec); - expect(isLatestSyntax).toBeFalsy(); - }); - - it('dist url to be https://nodejs.org/download/v8-canary for input versionSpec', () => { - const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore - const url = im.getNodejsDistUrl(versionSpec); - expect(url).toBe('https://nodejs.org/download/v8-canary'); - }); - - it('dist url to be https://nodejs.org/download/v8-canary for full versionSpec', () => { - const versionSpec = 'v20.0.0-v8-canary20221103f7e2421e91'; - // @ts-ignore - const url = im.getNodejsDistUrl(versionSpec); - expect(url).toBe('https://nodejs.org/download/v8-canary'); - }); - - it('v20-v8-canary should match any minor and patch version', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20-v8-canary'); - expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); - }); - - it('v20-v8-canary should not match v21.x & v19.x', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20-v8-canary'); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.1.1-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.1.-v8-canary20221103f7e2421e91')).toBeFalsy(); - }); - - it('v20.1-v8-canary should match any v20.1 patch version and minor above or eq v20.1', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.1-v8-canary'); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); - expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - }); - - it('v20.2-v8-canary should not match v21.x, v19.x, and v20 minor less v20.2', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.2-v8-canary'); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - }); - - it('v20.1.1-v8-canary should match v20.1.x patch versions above or eq v20.1.1', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - }); - - it('v20.1.1-v8-canary should match patch versions with any canary timestamp', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); - }); - - it('v20.1.1-v8-canary should not match any other minor versions and patch versions below v20.1.1', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - }); - - it('v20.0.0-v8-canary20221103f7e2421e91 should match only v20.0.0-v8-canary20221103f7e2421e91', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher( - 'v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 - expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); - }); - - it('v8 canary evaluateVersions without timestamp', () => { - const versions = [ - 'v20.0.0-v8-canary20221103f7e2421e91', - 'v20.0.1-v8-canary20221103f7e2421e91', - 'v20.1.0-v8-canary20221103f7e2421e91', - 'v20.1.1-v8-canary20221103f7e2421e91', - 'v21.1.0-v8-canary20221103f7e2421e91', - 'v19.1.0-v8-canary20221103f7e2421e91' - ]; - // @ts-ignore - const version = im.evaluateVersions(versions, 'v20-v8-canary'); - expect(version).toBe('v20.1.1-v8-canary20221103f7e2421e91'); - }); - - it('v8 canary evaluateVersions with timestamp', () => { - const versions = [ - 'v20.0.0-v8-canary20221103f7e2421e91', - 'v20.0.1-v8-canary20221103f7e2421e91', - 'v20.0.1-v8-canary20221103f7e2421e92', - 'v20.0.1-v8-canary20221103f7e2421e93', - 'v20.0.2-v8-canary20221103f7e2421e91' - ]; - // @ts-ignore - const version = im.evaluateVersions( - versions, - 'v20.0.1-v8-canary20221103f7e2421e92' - ); - expect(version).toBe('v20.0.1-v8-canary20221103f7e2421e92'); - }); - - it('v8 canary queryDistForMatch', async () => { - jest.spyOn(osm, 'platform').mockImplementationOnce(() => 'linux'); - // @ts-ignore - const version = await im.queryDistForMatch( - 'v20-v8-canary', - 'x64', - nodeV8CanaryTestDist - ); - expect(version).toBe('v20.0.0-v8-canary20221103f7e2421e91'); - }); - }); - - describe('setup-node v8 canary e2e tests', () => { + describe('setup-node v8 canary tests', () => { // @actions/http-client let getDistIndexJsonSpy: jest.SpyInstance; let findAllVersionSpy: jest.SpyInstance; @@ -1483,33 +1350,15 @@ describe('setup-node', () => { os.platform = 'linux'; os.arch = 'x64'; - findAllVersionSpy.mockImplementation(() => [ - 'v20.0.0-v8-canary20221103f7e2421e91' - ]); + const versionExpected = 'v20.0.0-v8-canary20221103f7e2421e91' + findAllVersionSpy.mockImplementation(() => [ versionExpected]); + + let toolPath = path.normalize(`/cache/node/${versionExpected}/x64`); + findSpy.mockImplementation((version) => toolPath); await main.run(); - expect(dbgSpy.mock.calls[0][0]).toBe('requested v8 canary distribution'); - expect(dbgSpy.mock.calls[1][0]).toBe('evaluating 17 versions'); - expect(dbgSpy.mock.calls[2][0]).toBe( - 'matched: v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(logSpy.mock.calls[0][0]).toBe( - 'getting v8-canary node version v20.0.0-v8-canary20221103f7e2421e91...' - ); - expect(logSpy.mock.calls[1][0]).toBe( - 'Attempt to find existing version in cache...' - ); - expect(dbgSpy.mock.calls[3][0]).toBe('evaluating 1 versions'); - expect(dbgSpy.mock.calls[4][0]).toBe( - 'matched: v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(logSpy.mock.calls[2][0]).toBe( - 'Found in cache @ v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(cnSpy.mock.calls[1][0].trim()).toBe( - `::add-path::v20.0.0-v8-canary20221103f7e2421e91${path.sep}bin` - ); + expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`) expect(dlSpy).not.toHaveBeenCalled(); expect(exSpy).not.toHaveBeenCalled(); @@ -1519,6 +1368,36 @@ describe('setup-node', () => { }); describe('helper methods', () => { + it('is not LTS alias', async () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const isLtsAlias = im.isLtsAlias(versionSpec); + expect(isLtsAlias).toBeFalsy(); + }); + + it('is not isLatestSyntax', async () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const isLatestSyntax = im.isLatestSyntax(versionSpec); + expect(isLatestSyntax).toBeFalsy(); + }); + + describe('getNodejsDistUrl', () => { + it('dist url to be https://nodejs.org/download/v8-canary for input versionSpec', () => { + const versionSpec = 'v99.0.0-v8-canary'; + // @ts-ignore + const url = im.getNodejsDistUrl(versionSpec); + expect(url).toBe('https://nodejs.org/download/v8-canary'); + }); + + it('dist url to be https://nodejs.org/download/v8-canary for full versionSpec', () => { + const versionSpec = 'v20.0.0-v8-canary20221103f7e2421e91'; + // @ts-ignore + const url = im.getNodejsDistUrl(versionSpec); + expect(url).toBe('https://nodejs.org/download/v8-canary'); + }); + }); + describe('parseNodeVersionFile', () => { each` contents | expected diff --git a/__tests__/installer.unit.test.ts b/__tests__/installer.unit.test.ts index a38a75361..5e271681c 100644 --- a/__tests__/installer.unit.test.ts +++ b/__tests__/installer.unit.test.ts @@ -1,1274 +1,114 @@ -import * as core from '@actions/core'; -import * as io from '@actions/io'; -import * as tc from '@actions/tool-cache'; -import * as httpm from '@actions/http-client'; -import * as exec from '@actions/exec'; -import * as im from '../src/installer'; -import * as cache from '@actions/cache'; -import fs from 'fs'; -import cp from 'child_process'; -import osm from 'os'; -import path from 'path'; -import each from 'jest-each'; -import * as main from '../src/main'; -import * as auth from '../src/authutil'; - -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'); - // @ts-ignore - getDistSpy = jest.spyOn(im, 'getVersionsFromDist'); - parseNodeVersionSpy = jest.spyOn(im, 'parseNodeVersionFile'); - - // http-client - getJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); - - // io - whichSpy = jest.spyOn(io, 'which'); - existsSpy = jest.spyOn(fs, 'existsSync'); - 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( - () => nodeTestManifest - ); - - getDistSpy.mockImplementation(version => { - const initialUrl = im.getNodejsDistUrl(version); - if (initialUrl.endsWith('/rc')) { - return nodeTestDistRc; - } else if (initialUrl.endsWith('/nightly')) { - return nodeTestDistNightly; - } else { - return nodeTestDist; - } - }); - - getJsonSpy.mockImplementation(url => { - let res: any; - if (url.includes('/rc')) { - res = nodeTestDistRc; - } else if (url.includes('/nightly')) { - res = nodeTestDistNightly; - } else { - res = nodeTestDist; - } - - return {result: res}; - }); - - // writes - cnSpy = jest.spyOn(process.stdout, 'write'); - 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); - - //-------------------------------------------------- - // 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'], - ['10', 'win32', '10.20.1', 'Dubnium'], - ['*', 'linux', '14.0.0', 'Fermium'] - ])( - 'can find %s from manifest on %s', - async (versionSpec, platform, expectedVersion, expectedLts) => { - os.platform = platform; - os.arch = 'x64'; - let versions: tc.IToolRelease[] | null = await tc.getManifestFromRepo( - 'actions', - 'node-versions', - 'mocktoken' - ); - expect(versions).toBeDefined(); - let match = await tc.findFromManifest(versionSpec, true, versions); - expect(match).toBeDefined(); - expect(match?.version).toBe(expectedVersion); - expect((match as any).lts).toBe(expectedLts); - } - ); - - //-------------------------------------------------- - // Found in cache tests - //-------------------------------------------------- - - it('finds version in cache with stable true', async () => { - inputs['node-version'] = '12'; - inputs.stable = 'true'; - - let toolPath = path.normalize('/cache/node/12.16.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'; - - inSpy.mockImplementation(name => inputs[name]); - - let toolPath = path.normalize('/cache/node/12.16.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'; - - inSpy.mockImplementation(name => inputs[name]); - - let toolPath = path.normalize('/cache/node/12.16.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'; - - findSpy.mockImplementation(() => { - throw new Error(errMsg); - }); - - await main.run(); - - expect(cnSpy).toHaveBeenCalledWith('::error::' + errMsg + osm.EOL); - }); - - //-------------------------------------------------- - // Manifest tests - //-------------------------------------------------- - - it('downloads a version from a manifest match', async () => { - os.platform = 'linux'; - os.arch = 'x64'; - - // a version which is in the manifest - let versionSpec = '12.16.2'; - 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/12.16.2/x64'); - exSpy.mockImplementation(async () => '/some/other/temp/path'); - cacheSpy.mockImplementation(async () => toolPath); - - await main.run(); - - let expPath = path.join(toolPath, 'bin'); - - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'node', - ['--version'], - expect.anything() - ); - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'npm', - ['--version'], - expect.anything() - ); - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'yarn', - ['--version'], - expect.anything() - ); - expect(dlSpy).toHaveBeenCalled(); - expect(exSpy).toHaveBeenCalled(); - expect(logSpy).toHaveBeenCalledWith( - `Acquiring ${resolvedVersion} - ${os.arch} from ${expectedUrl}` - ); - expect(logSpy).toHaveBeenCalledWith( - `Attempting to download ${versionSpec}...` - ); - expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${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 = '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'); - 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 = '9.99.9'; - inputs['node-version'] = versionSpec; - - findSpy.mockImplementation(() => ''); - await main.run(); - - expect(logSpy).toHaveBeenCalledWith( - 'Not found in manifest. Falling back to download directly from Node' - ); - 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}` - ); - }); - - 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 = '12.16.2'; - let resolvedVersion = versionSpec; - - inputs['node-version'] = versionSpec; - inputs['always-auth'] = false; - inputs['token'] = 'faketoken'; - - findSpy.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: '12.16.2', osSpec: 'win32'}, - {arch: 'x86', version: '14.0.0', osSpec: 'win32'} - ]) { - os.platform = osSpec; - os.arch = arch; - const fileExtension = os.platform === 'win32' ? '7z' : 'tar.gz'; - const platform = { - linux: 'linux', - darwin: 'darwin', - win32: 'win' - }[os.platform]; - - inputs['node-version'] = version; - inputs['architecture'] = arch; - inputs['always-auth'] = false; - inputs['token'] = 'faketoken'; - - let expectedUrl = - arch === 'x64' - ? `https://github.com/actions/node-versions/releases/download/${version}/node-${version}-${platform}-${arch}.zip` - : `https://nodejs.org/dist/v${version}/node-v${version}-${platform}-${arch}.${fileExtension}`; - - // ... but not in the local cache - findSpy.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('check-latest flag', () => { - it('use local version and dont check manifest if check-latest is not specified', async () => { - os.platform = 'linux'; - os.arch = 'x64'; - - inputs['node-version'] = '12'; - inputs['check-latest'] = 'false'; - - const toolPath = path.normalize('/cache/node/12.16.1/x64'); - findSpy.mockReturnValue(toolPath); - await main.run(); - - expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); - expect(logSpy).not.toHaveBeenCalledWith( - 'Attempt to resolve the latest version from manifest...' - ); - expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); - expect(dbgSpy).not.toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - }); - - it('check latest version and resolve it from local cache', async () => { - os.platform = 'linux'; - os.arch = 'x64'; - - inputs['node-version'] = '12'; - inputs['check-latest'] = 'true'; - - const toolPath = path.normalize('/cache/node/12.16.2/x64'); - findSpy.mockReturnValue(toolPath); - dlSpy.mockImplementation(async () => '/some/temp/path'); - exSpy.mockImplementation(async () => '/some/other/temp/path'); - cacheSpy.mockImplementation(async () => toolPath); - - await main.run(); - - expect(logSpy).toHaveBeenCalledWith( - 'Attempt to resolve the latest version from manifest...' - ); - expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); - expect(dbgSpy).toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); - expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); - }); - - it('check latest version and install it from manifest', async () => { - os.platform = 'linux'; - os.arch = 'x64'; - - inputs['node-version'] = '12'; - inputs['check-latest'] = 'true'; - - findSpy.mockImplementation(() => ''); - dlSpy.mockImplementation(async () => '/some/temp/path'); - const toolPath = path.normalize('/cache/node/12.16.2/x64'); - exSpy.mockImplementation(async () => '/some/other/temp/path'); - cacheSpy.mockImplementation(async () => toolPath); - const expectedUrl = - 'https://github.com/actions/node-versions/releases/download/12.16.2-20200507.95/node-12.16.2-linux-x64.tar.gz'; - - await main.run(); - - expect(logSpy).toHaveBeenCalledWith( - 'Attempt to resolve the latest version from manifest...' - ); - expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); - expect(dbgSpy).toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); - expect(logSpy).toHaveBeenCalledWith( - `Acquiring 12.16.2 - ${os.arch} from ${expectedUrl}` - ); - expect(logSpy).toHaveBeenCalledWith('Extracting ...'); - }); - - it('fallback to dist if version if not found in manifest', async () => { - os.platform = 'linux'; - os.arch = 'x64'; - - // a version which is not in the manifest but is in node dist - let versionSpec = '11'; - - inputs['node-version'] = versionSpec; - inputs['check-latest'] = 'true'; - 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( - 'Attempt to resolve the latest version from manifest...' - ); - expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); - expect(dbgSpy).toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - expect(logSpy).toHaveBeenCalledWith( - `Failed to resolve version ${versionSpec} from manifest` - ); - expect(logSpy).toHaveBeenCalledWith( - `Attempting to download ${versionSpec}...` - ); - expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); - }); - - it('fallback to dist if manifest is not available', async () => { - os.platform = 'linux'; - os.arch = 'x64'; - - // a version which is not in the manifest but is in node dist - let versionSpec = '12'; - - inputs['node-version'] = versionSpec; - inputs['check-latest'] = 'true'; - inputs['always-auth'] = false; - inputs['token'] = 'faketoken'; - - // ... but not in the local cache - findSpy.mockImplementation(() => ''); - getManifestSpy.mockImplementation(() => { - throw new Error('Unable to download manifest'); - }); - - dlSpy.mockImplementation(async () => '/some/temp/path'); - let toolPath = path.normalize('/cache/node/12.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( - 'Attempt to resolve the latest version from manifest...' - ); - expect(logSpy).toHaveBeenCalledWith( - 'Unable to resolve version from manifest...' - ); - expect(logSpy).toHaveBeenCalledWith( - `Failed to resolve version ${versionSpec} from manifest` - ); - expect(logSpy).toHaveBeenCalledWith( - `Attempting to download ${versionSpec}...` - ); - expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); - }); - }); - - describe('node-version-file flag', () => { - it('not used if node-version is provided', async () => { - // Arrange - inputs['node-version'] = '12'; - - // Act - await main.run(); - - // Assert - expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); - }); - - it('not used if node-version-file not provided', async () => { - // Act - await main.run(); - - // Assert - expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); - }); - - it('reads node-version-file if provided', async () => { - // Arrange - const versionSpec = 'v14'; - const versionFile = '.nvmrc'; - const expectedVersionSpec = '14'; - process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data'); - inputs['node-version-file'] = versionFile; - - parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); - existsSpy.mockImplementationOnce( - input => input === path.join(__dirname, 'data', versionFile) - ); - - // Act - await main.run(); - - // Assert - expect(existsSpy).toHaveBeenCalledTimes(1); - expect(existsSpy).toHaveReturnedWith(true); - expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec); - expect(logSpy).toHaveBeenCalledWith( - `Resolved ${versionFile} as ${expectedVersionSpec}` - ); - }); - - it('reads package.json as node-version-file if provided', async () => { - // Arrange - const versionSpec = fs.readFileSync( - path.join(__dirname, 'data/package.json'), - 'utf-8' - ); - const versionFile = 'package.json'; - const expectedVersionSpec = '14'; - process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data'); - inputs['node-version-file'] = versionFile; - - parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); - existsSpy.mockImplementationOnce( - input => input === path.join(__dirname, 'data', versionFile) - ); - // Act - await main.run(); - - // Assert - expect(existsSpy).toHaveBeenCalledTimes(1); - expect(existsSpy).toHaveReturnedWith(true); - expect(parseNodeVersionSpy).toHaveBeenCalledWith(versionSpec); - expect(logSpy).toHaveBeenCalledWith( - `Resolved ${versionFile} as ${expectedVersionSpec}` - ); - }); - - it('both node-version-file and node-version are provided', async () => { - inputs['node-version'] = '12'; - const versionSpec = 'v14'; - const versionFile = '.nvmrc'; - const expectedVersionSpec = '14'; - process.env['GITHUB_WORKSPACE'] = path.join(__dirname, '..'); - inputs['node-version-file'] = versionFile; - - parseNodeVersionSpy.mockImplementation(() => expectedVersionSpec); - - // Act - await main.run(); - - // Assert - expect(existsSpy).toHaveBeenCalledTimes(0); - expect(parseNodeVersionSpy).not.toHaveBeenCalled(); - expect(warningSpy).toHaveBeenCalledWith( - 'Both node-version and node-version-file inputs are specified, only node-version will be used' - ); - }); - - it('should throw an error if node-version-file is not found', async () => { - const versionFile = '.nvmrc'; - const versionFilePath = path.join(__dirname, '..', versionFile); - inputs['node-version-file'] = versionFile; - - inSpy.mockImplementation(name => inputs[name]); - existsSpy.mockImplementationOnce( - input => input === path.join(__dirname, 'data', versionFile) - ); - - // Act - await main.run(); - - // Assert - expect(existsSpy).toHaveBeenCalled(); - expect(existsSpy).toHaveReturnedWith(false); - expect(parseNodeVersionSpy).not.toHaveBeenCalled(); - expect(cnSpy).toHaveBeenCalledWith( - `::error::The specified node version file at: ${versionFilePath} does not exist${osm.EOL}` - ); - }); - }); - - describe('cache on GHES', () => { - it('Should throw an error, because cache is not supported', async () => { - inputs['node-version'] = '12'; - inputs['cache'] = 'npm'; - - inSpy.mockImplementation(name => inputs[name]); - - let toolPath = path.normalize('/cache/node/12.16.1/x64'); - findSpy.mockImplementation(() => toolPath); - - // expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); - process.env['GITHUB_SERVER_URL'] = 'https://www.test.com'; - isCacheActionAvailable.mockImplementation(() => false); - - await main.run(); - - expect(cnSpy).toHaveBeenCalledWith( - `::error::Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.${osm.EOL}` - ); - }); - - it('Should throw an internal error', async () => { - inputs['node-version'] = '12'; - inputs['cache'] = 'npm'; - - inSpy.mockImplementation(name => inputs[name]); - - let toolPath = path.normalize('/cache/node/12.16.1/x64'); - findSpy.mockImplementation(() => toolPath); - - // expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); - process.env['GITHUB_SERVER_URL'] = ''; - isCacheActionAvailable.mockImplementation(() => false); - - await main.run(); - - expect(warningSpy).toHaveBeenCalledWith( - 'The runner was not able to contact the cache service. Caching will be skipped' - ); - }); - }); - - describe('LTS version', () => { - beforeEach(() => { - os.platform = 'linux'; - os.arch = 'x64'; - inputs.stable = 'true'; - }); - - it.each([ - ['erbium', '12.16.2'], - ['*', '14.0.0'], - ['-1', '12.16.2'] - ])( - 'find latest LTS version and resolve it from local cache (lts/%s)', - async (lts, expectedVersion) => { - // arrange - inputs['node-version'] = `lts/${lts}`; - - const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); - findSpy.mockReturnValue(toolPath); - - // act - await main.run(); - - // assert - expect(logSpy).toHaveBeenCalledWith( - 'Attempt to resolve LTS alias from manifest...' - ); - expect(dbgSpy).toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); - expect(dbgSpy).toHaveBeenCalledWith( - `LTS alias '${lts}' for Node version 'lts/${lts}'` - ); - expect(dbgSpy).toHaveBeenCalledWith( - `Found LTS release '${expectedVersion}' for Node version 'lts/${lts}'` - ); - expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); - expect(cnSpy).toHaveBeenCalledWith( - `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` - ); - } - ); - - it.each([ - [ - 'erbium', - '12.16.2', - 'https://github.com/actions/node-versions/releases/download/12.16.2-20200507.95/node-12.16.2-linux-x64.tar.gz' - ], - [ - '*', - '14.0.0', - 'https://github.com/actions/node-versions/releases/download/14.0.0-20200507.99/node-14.0.0-linux-x64.tar.gz' - ], - [ - '-1', - '12.16.2', - 'https://github.com/actions/node-versions/releases/download/12.16.2-20200507.95/node-12.16.2-linux-x64.tar.gz' - ] - ])( - 'find latest LTS version and install it from manifest (lts/%s)', - async (lts, expectedVersion, expectedUrl) => { - // arrange - inputs['node-version'] = `lts/${lts}`; - - const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); - findSpy.mockImplementation(() => ''); - dlSpy.mockImplementation(async () => '/some/temp/path'); - exSpy.mockImplementation(async () => '/some/other/temp/path'); - cacheSpy.mockImplementation(async () => toolPath); - const expectedMajor = expectedVersion.split('.')[0]; - - // act - await main.run(); - - // assert - expect(logSpy).toHaveBeenCalledWith( - 'Attempt to resolve LTS alias from manifest...' - ); - expect(dbgSpy).toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); - expect(dbgSpy).toHaveBeenCalledWith( - `LTS alias '${lts}' for Node version 'lts/${lts}'` - ); - expect(dbgSpy).toHaveBeenCalledWith( - `Found LTS release '${expectedVersion}' for Node version 'lts/${lts}'` - ); - expect(logSpy).toHaveBeenCalledWith( - `Attempting to download ${expectedMajor}...` - ); - 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('fail with unable to parse LTS alias (lts/)', async () => { - // arrange - inputs['node-version'] = 'lts/'; - - findSpy.mockImplementation(() => ''); - - // act - await main.run(); - - // assert - expect(logSpy).toHaveBeenCalledWith( - 'Attempt to resolve LTS alias from manifest...' - ); - expect(dbgSpy).toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - expect(cnSpy).toHaveBeenCalledWith( - `::error::Unable to parse LTS alias for Node version 'lts/'${osm.EOL}` - ); - }); - - it('fail to find LTS version (lts/unknown)', async () => { - // arrange - inputs['node-version'] = 'lts/unknown'; - - findSpy.mockImplementation(() => ''); - - // act - await main.run(); - - // assert - expect(logSpy).toHaveBeenCalledWith( - 'Attempt to resolve LTS alias from manifest...' - ); - expect(dbgSpy).toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - expect(dbgSpy).toHaveBeenCalledWith( - `LTS alias 'unknown' for Node version 'lts/unknown'` - ); - expect(cnSpy).toHaveBeenCalledWith( - `::error::Unable to find LTS release 'unknown' for Node version 'lts/unknown'.${osm.EOL}` - ); - }); - - it('fail if manifest is not available', async () => { - // arrange - inputs['node-version'] = 'lts/erbium'; - - // ... but not in the local cache - findSpy.mockImplementation(() => ''); - getManifestSpy.mockImplementation(() => { - throw new Error('Unable to download manifest'); - }); - - // act - await main.run(); - - // assert - expect(logSpy).toHaveBeenCalledWith( - 'Attempt to resolve LTS alias from manifest...' - ); - expect(dbgSpy).toHaveBeenCalledWith( - 'Getting manifest from actions/node-versions@main' - ); - expect(cnSpy).toHaveBeenCalledWith( - `::error::Unable to download manifest${osm.EOL}` - ); - }); - }); - - 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.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(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', - async inputVersion => { - // Arrange - inputs['node-version'] = inputVersion; - - os.platform = 'darwin'; - os.arch = 'x64'; - - findSpy.mockImplementation(() => ''); - getManifestSpy.mockImplementation(() => { - throw new Error('Unable to download manifest'); - }); - - // Act - await main.run(); - - // assert - expect(logSpy).toHaveBeenCalledWith('Unable to download manifest'); - - expect(logSpy).toHaveBeenCalledWith('getting latest node version...'); - } - ); - }); - - describe('latest alias syntax from cache', () => { - it.each(['latest', 'current', 'node'])( - 'download the %s version if alias is provided', - async inputVersion => { - // Arrange - inputs['node-version'] = inputVersion; - const expectedVersion = nodeTestDist[0]; - - os.platform = 'darwin'; - os.arch = 'x64'; - - const toolPath = path.normalize( - `/cache/node/${expectedVersion.version}/x64` - ); - findSpy.mockReturnValue(toolPath); - - // Act - await main.run(); - - // assert - expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); - - expect(logSpy).toHaveBeenCalledWith('getting latest node version...'); - } - ); - }); - - describe('setup-node v8 canary unit tests', () => { +import semver from 'semver'; +import { + canaryExactVersionMatcherFactory, + canaryRangeVersionMatcherFactory, + distributionOf, + Distributions, + evaluateVersions, + getNodejsDistUrl, + nightlyExactVersionMatcherFactory, + nightlyRangeVersionMatcherFactory, + semverVersionMatcherFactory, + splitVersionSpec, + versionMatcherFactory +} from '../src/installer'; + +describe('setup-node unit tests', () => { + describe('splitVersionSpec', () => { + it('splitVersionSpec correctly splits version spec without dashes', () => { + const [raw, prerelease] = splitVersionSpec('1.1.1') + expect(raw).toBe('1.1.1') + expect(prerelease).toBeUndefined() + }) + it('splitVersionSpec correctly splits version spec with one dash', () => { + const [raw, prerelease] = splitVersionSpec('1.1.1-nightly12345678') + expect(raw).toBe('1.1.1') + expect(prerelease).toBe('nightly12345678') + }) + it('splitVersionSpec correctly splits version spec with 2 dashes', () => { + const [raw, prerelease] = splitVersionSpec('1.1.1-v8-canary12345678') + expect(raw).toBe('1.1.1') + expect(prerelease).toBe('v8-canary12345678') + }) + }) + + describe('distributionOf', () => { + it('1.1.1-v8-canary should be CANARY', () => { + expect(distributionOf('1.1.1-v8-canary')).toBe(Distributions.CANARY) + }) + it('1.1.1-v8-canary20221103f7e2421e91 should be CANARY', () => { + expect(distributionOf('1.1.1-v8-canary20221103f7e2421e91')).toBe(Distributions.CANARY) + }) + it('1.1.1-canary should throw exception', () => { + expect(() => distributionOf('1.1.1-canary')).toThrow('Canary version must have "-v8-canary suffix"') + }) + it('1.1.1-canary20221103f7e2421e91 should throw exception', () => { + expect(() => distributionOf('1.1.1-canary20221103f7e2421e91')).toThrow('Canary version must have "-v8-canary suffix"') + }) + it('1.1.1-nightly should be NIGHTLY', () => { + expect(distributionOf('1.1.1-nightly')).toBe(Distributions.NIGHTLY) + }) + it('1.1.1-nightly20221103f7e2421e91 should be NIGHTLY', () => { + expect(distributionOf('1.1.1-nightly20221103f7e2421e91')).toBe(Distributions.NIGHTLY) + }) + it('1.1.1-rc.0 should be RC', () => { + expect(distributionOf('1.1.1-rc.0')).toBe(Distributions.RC) + }) + }) + + describe('versionMatcherFactory', () => { + it('1.1.1 should be handled by semverVersionMatcherFactory', () => { + expect(versionMatcherFactory('1.1.1').factory).toBe(semverVersionMatcherFactory) + }) + it('v1.1.1 should be handled by semverVersionMatcherFactory', () => { + expect(versionMatcherFactory('v1.1.1').factory).toBe(semverVersionMatcherFactory) + }) + it('v1.1.1-v8-canary should be handled by canaryRangeVersionMatcherFactory', () => { + expect(versionMatcherFactory('v1.1.1-v8-canary').factory).toBe(canaryRangeVersionMatcherFactory) + }) + it('v1.1.1-v8-canary123 should be handled by canaryExactVersionMatcherFactory', () => { + expect(versionMatcherFactory('v1.1.1-v8-canary123').factory).toBe(canaryExactVersionMatcherFactory) + }) + it('v1.1.1-nightly should be handled by nightlyRangeVersionMatcherFactory', () => { + expect(versionMatcherFactory('v1.1.1-nightly').factory).toBe(nightlyRangeVersionMatcherFactory) + }) + it('v1.1.1-nigthly123 should be handled by nightlyExactVersionMatcherFactory', () => { + expect(versionMatcherFactory('v1.1.1-nightly123').factory).toBe(nightlyExactVersionMatcherFactory) + }) + it('v1.1.1-rc should be handled by semverVersionMatcherFactory', () => { + expect(versionMatcherFactory('v1.1.1-rc').factory).toBe(semverVersionMatcherFactory) + }) + it('v1.1.1-rc.1 should be handled by semverVersionMatcherFactory', () => { + expect(versionMatcherFactory('v1.1.1-rc.1').factory).toBe(semverVersionMatcherFactory) + }) + }) + + describe('Version spec matchers', () => { + it('semverVersionMatcher should always work as semver.satisfies does', () => { + const rangePlain = '1.1.1' + const matcherPlain = semverVersionMatcherFactory(rangePlain) + expect(matcherPlain('1.1.1')).toBe(semver.satisfies('1.1.1', rangePlain)) + expect(matcherPlain('1.1.2')).toBe(semver.satisfies('1.1.2', rangePlain)) + + const rangeEq = '=1.1.1' + const matcherEq = semverVersionMatcherFactory(rangeEq) + expect(matcherEq('1.1.1')).toBe(semver.satisfies('1.1.1', rangeEq)) + expect(matcherEq('1.1.2')).toBe(semver.satisfies('1.1.2', rangeEq)) + + // TODO: add for discovered issues if any + }) + + it('canaryExactVersionMatcher should match v20.0.0-v8-canary20221103f7e2421e91 only v20.0.0-v8-canary20221103f7e2421e91', () => { + const version = semver.coerce('v20.0.0')!.version + const matcher = canaryExactVersionMatcherFactory(version, 'v8-canary20221103f7e2421e91'); + expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 + expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); + }) - it('v20-v8-canary should match any minor and patch version', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20-v8-canary'); + it('canaryRangeVersionMatcherFactory should match v20-v8-canary to any minor and patch version', () => { + const version = semver.coerce('v20')!.version + const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); @@ -1276,9 +116,9 @@ describe('setup-node', () => { expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); }); - it('v20-v8-canary should not match v21.x & v19.x', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20-v8-canary'); + it('canaryRangeVersionMatcherFactory should not match v20-v8-canary to v21.x & v19.x', () => { + const version = semver.coerce('v20')!.version + const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.1.1-v8-canary20221103f7e2421e91')).toBeFalsy(); @@ -1287,57 +127,49 @@ describe('setup-node', () => { expect(matcher('v19.1.-v8-canary20221103f7e2421e91')).toBeFalsy(); }); - it('v20.1-v8-canary should match any v20.1 patch version and minor above or eq v20.1', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.1-v8-canary'); + it('canaryRangeVersionMatcherFactory should match v20.1-v8-canary to any v20.1 patch version and minor above or eq v20.1', () => { + const version = semver.coerce('v20.1')!.version + const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); }); - it('v20.2-v8-canary should not match v21.x, v19.x, and v20 minor less v20.2', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.2-v8-canary'); + it('canaryRangeVersionMatcherFactory should not match canaryRangeVersionMatcherFactory to v21.x, v19.x, and v20 minor less v20.2', () => { + const version = semver.coerce('v20.2')!.version + const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); }); - it('v20.1.1-v8-canary should match v20.1.x patch versions above or eq v20.1.1', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary v20.1.x to patch versions above or eq v20.1.1', () => { + const version = semver.coerce('v20.1.1')!.version + const matcher = canaryRangeVersionMatcherFactory('v20.1.1-v8-canary'); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); }); - it('v20.1.1-v8-canary should match patch versions with any canary timestamp', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to patch versions with any canary timestamp', () => { + const version = semver.coerce('v20.1.1')!.version + const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); }); - it('v20.1.1-v8-canary should not match any other minor versions and patch versions below v20.1.1', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher('v20.1.1-v8-canary'); + it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary to any other minor versions and patch versions below v20.1.1', () => { + const version = semver.coerce('v20.1.1')!.version + const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); }); + }) - it('v20.0.0-v8-canary20221103f7e2421e91 should match only v20.0.0-v8-canary20221103f7e2421e91', () => { - // @ts-ignore - const matcher = im.evaluateCanaryMatcher( - 'v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 - expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); - }); - - it('v8 canary evaluateVersions without timestamp', () => { + describe('evaluateVersions', () => { + it('evaluateVersions should handle v8-canary version spec without timestamp', () => { const versions = [ 'v20.0.0-v8-canary20221103f7e2421e91', 'v20.0.1-v8-canary20221103f7e2421e91', @@ -1346,12 +178,11 @@ describe('setup-node', () => { 'v21.1.0-v8-canary20221103f7e2421e91', 'v19.1.0-v8-canary20221103f7e2421e91' ]; - // @ts-ignore - const version = im.evaluateVersions(versions, 'v20-v8-canary'); + const version = evaluateVersions(versions, 'v20-v8-canary'); expect(version).toBe('v20.1.1-v8-canary20221103f7e2421e91'); }); - it('v8 canary evaluateVersions with timestamp', () => { + it('evaluateVersions should handle v8-canary version spec with timestamp', () => { const versions = [ 'v20.0.0-v8-canary20221103f7e2421e91', 'v20.0.1-v8-canary20221103f7e2421e91', @@ -1359,193 +190,36 @@ describe('setup-node', () => { 'v20.0.1-v8-canary20221103f7e2421e93', 'v20.0.2-v8-canary20221103f7e2421e91' ]; - // @ts-ignore - const version = im.evaluateVersions( - versions, - 'v20.0.1-v8-canary20221103f7e2421e92' - ); + const version = evaluateVersions(versions, 'v20.0.1-v8-canary20221103f7e2421e92'); expect(version).toBe('v20.0.1-v8-canary20221103f7e2421e92'); }); + }) - it('v8 canary queryDistForMatch', async () => { - jest.spyOn(osm, 'platform').mockImplementationOnce(() => 'linux'); - // @ts-ignore - const version = await im.queryDistForMatch( - 'v20-v8-canary', - 'x64', - nodeV8CanaryTestDist - ); - expect(version).toBe('v20.0.0-v8-canary20221103f7e2421e91'); - }); - }); - - describe('setup-node v8 canary e2e tests', () => { - // @actions/http-client - let getDistIndexJsonSpy: jest.SpyInstance; - let findAllVersionSpy: jest.SpyInstance; - - beforeEach(() => { - // @actions/http-client - getDistIndexJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); - getDistIndexJsonSpy.mockImplementation(() => ({ - result: nodeV8CanaryTestDist - })); - - // @actions/tool-cache - findAllVersionSpy = jest.spyOn(tc, 'findAllVersions'); - }); - - it('v8 canary setup node flow without cached', async () => { - let versionSpec = 'v20-v8-canary'; - - inputs['node-version'] = versionSpec; - inputs['always-auth'] = false; - inputs['token'] = 'faketoken'; - - os.platform = 'linux'; - os.arch = 'x64'; - - findAllVersionSpy.mockImplementation(() => []); - - findSpy.mockImplementation(() => ''); - - dlSpy.mockImplementation(async () => '/some/temp/path'); - let toolPath = path.normalize('/cache/node/12.16.2/x64'); - exSpy.mockImplementation(async () => '/some/other/temp/path'); - cacheSpy.mockImplementation(async () => toolPath); - - await main.run(); - - expect(dbgSpy.mock.calls[0][0]).toBe('requested v8 canary distribution'); - expect(dbgSpy.mock.calls[1][0]).toBe('evaluating 17 versions'); - expect(dbgSpy.mock.calls[2][0]).toBe( - 'matched: v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(logSpy.mock.calls[0][0]).toBe( - 'getting v8-canary node version v20.0.0-v8-canary20221103f7e2421e91...' - ); - expect(logSpy.mock.calls[1][0]).toBe( - 'Attempt to find existing version in cache...' - ); - expect(dbgSpy.mock.calls[3][0]).toBe('evaluating 0 versions'); - expect(dbgSpy.mock.calls[4][0]).toBe('match not found'); - expect(logSpy.mock.calls[2][0]).toBe( - 'Attempting to download v20.0.0-v8-canary20221103f7e2421e91...' - ); - expect(dbgSpy.mock.calls[5][0]).toBe('No manifest cached'); - expect(dbgSpy.mock.calls[6][0]).toBe( - 'Getting manifest from actions/node-versions@main' - ); - expect(dbgSpy.mock.calls[7][0].slice(0, 6)).toBe('check '); - expect(dbgSpy.mock.calls[13][0].slice(0, 6)).toBe('check '); - expect(logSpy.mock.calls[3][0]).toBe( - 'Not found in manifest. Falling back to download directly from Node' - ); - expect(dbgSpy.mock.calls[14][0]).toBe('evaluating 17 versions'); - expect(dbgSpy.mock.calls[15][0]).toBe( - 'matched: v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(dbgSpy.mock.calls[16][0]).toBe('requested v8 canary distribution'); - expect(logSpy.mock.calls[4][0]).toBe( - 'Acquiring 20.0.0-v8-canary20221103f7e2421e91 - x64 from https://nodejs.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz' - ); - - expect(dlSpy).toHaveBeenCalledTimes(1); - expect(exSpy).toHaveBeenCalledTimes(1); - expect(cacheSpy).toHaveBeenCalledTimes(1); - }); - - 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'; - - findAllVersionSpy.mockImplementation(() => [ - 'v20.0.0-v8-canary20221103f7e2421e91' - ]); - - await main.run(); - - expect(dbgSpy.mock.calls[0][0]).toBe('requested v8 canary distribution'); - expect(dbgSpy.mock.calls[1][0]).toBe('evaluating 17 versions'); - expect(dbgSpy.mock.calls[2][0]).toBe( - 'matched: v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(logSpy.mock.calls[0][0]).toBe( - 'getting v8-canary node version v20.0.0-v8-canary20221103f7e2421e91...' - ); - expect(logSpy.mock.calls[1][0]).toBe( - 'Attempt to find existing version in cache...' - ); - expect(dbgSpy.mock.calls[3][0]).toBe('evaluating 1 versions'); - expect(dbgSpy.mock.calls[4][0]).toBe( - 'matched: v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(logSpy.mock.calls[2][0]).toBe( - 'Found in cache @ v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(cnSpy.mock.calls[1][0].trim()).toBe( - `::add-path::v20.0.0-v8-canary20221103f7e2421e91${path.sep}bin` - ); - - expect(dlSpy).not.toHaveBeenCalled(); - expect(exSpy).not.toHaveBeenCalled(); - expect(cacheSpy).not.toHaveBeenCalled(); + describe('getNodejsDistUrl', () => { + it('getNodejsDistUrl should handle v8 canary version spec', async () => { + expect(getNodejsDistUrl('1.1.1-v8-canary')).toBe('https://nodejs.org/download/v8-canary'); + expect(getNodejsDistUrl('1.1.1-v8-canary123')).toBe('https://nodejs.org/download/v8-canary'); + expect(getNodejsDistUrl('v1.1.1-v8-canary')).toBe('https://nodejs.org/download/v8-canary'); + expect(getNodejsDistUrl('v1.1.1-v8-canary123')).toBe('https://nodejs.org/download/v8-canary'); }); - }); -}); - -describe('helper methods', () => { - it('is not LTS alias', async () => { - const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore - const isLtsAlias = im.isLtsAlias(versionSpec); - expect(isLtsAlias).toBeFalsy(); - }); - it('is not isLatestSyntax', async () => { - const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore - const isLatestSyntax = im.isLatestSyntax(versionSpec); - expect(isLatestSyntax).toBeFalsy(); - }); - - describe('getNodejsDistUrl', () => { - it('dist url to be https://nodejs.org/download/v8-canary for input versionSpec', () => { - const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore - const url = im.getNodejsDistUrl(versionSpec); - expect(url).toBe('https://nodejs.org/download/v8-canary'); + it('getNodejsDistUrl should handle nightly version spec', async () => { + expect(getNodejsDistUrl('1.1.1-nightly')).toBe('https://nodejs.org/download/nightly'); + expect(getNodejsDistUrl('v1.1.1-nightly')).toBe('https://nodejs.org/download/nightly'); + expect(getNodejsDistUrl('1.1.1-nightly123')).toBe('https://nodejs.org/download/nightly'); + expect(getNodejsDistUrl('v1.1.1-nightly123')).toBe('https://nodejs.org/download/nightly'); }); - it('dist url to be https://nodejs.org/download/v8-canary for full versionSpec', () => { - const versionSpec = 'v20.0.0-v8-canary20221103f7e2421e91'; - // @ts-ignore - const url = im.getNodejsDistUrl(versionSpec); - expect(url).toBe('https://nodejs.org/download/v8-canary'); + it('getNodejsDistUrl should handle rc version spec', async () => { + expect(getNodejsDistUrl('1.1.1-rc')).toBe('https://nodejs.org/download/rc'); + expect(getNodejsDistUrl('v1.1.1-rc')).toBe('https://nodejs.org/download/rc'); + expect(getNodejsDistUrl('1.1.1-rc.0')).toBe('https://nodejs.org/download/rc'); + expect(getNodejsDistUrl('v1.1.1-rc.0')).toBe('https://nodejs.org/download/rc'); }); - }); - 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); + it('getNodejsDistUrl should handle unspecific version spec', async () => { + expect(getNodejsDistUrl('1.1.1')).toBe('https://nodejs.org/dist'); + expect(getNodejsDistUrl('v1.1.1')).toBe('https://nodejs.org/dist'); }); - }); + }) }); From d38528abe04d99a41a27fc6855cfb5f0fa6010d3 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 05:29:48 +0100 Subject: [PATCH 10/51] prettier --- __tests__/installer.test.ts | 21 +-- __tests__/installer.unit.test.ts | 214 +++++++++++++++++++------------ src/installer.ts | 143 ++++++++++++--------- 3 files changed, 228 insertions(+), 150 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 893f2471a..1f93e1f06 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -89,8 +89,7 @@ describe('setup-node', () => { // disable authentication portion for installer tests authSpy = jest.spyOn(auth, 'configAuthentication'); - authSpy.mockImplementation(() => { - }); + authSpy.mockImplementation(() => {}); // gets getManifestSpy.mockImplementation( @@ -1001,15 +1000,17 @@ describe('setup-node', () => { '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`)) + 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', - ]) + '3.3.3-rc.3' + ]); inputs['node-version'] = input; os['arch'] = 'x64'; @@ -1350,15 +1351,17 @@ describe('setup-node', () => { os.platform = 'linux'; os.arch = 'x64'; - const versionExpected = 'v20.0.0-v8-canary20221103f7e2421e91' - findAllVersionSpy.mockImplementation(() => [ versionExpected]); + const versionExpected = 'v20.0.0-v8-canary20221103f7e2421e91'; + findAllVersionSpy.mockImplementation(() => [versionExpected]); let toolPath = path.normalize(`/cache/node/${versionExpected}/x64`); - findSpy.mockImplementation((version) => toolPath); + findSpy.mockImplementation(version => toolPath); await main.run(); - expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`) + expect(cnSpy).toHaveBeenCalledWith( + `::add-path::${toolPath}/bin${osm.EOL}` + ); expect(dlSpy).not.toHaveBeenCalled(); expect(exSpy).not.toHaveBeenCalled(); diff --git a/__tests__/installer.unit.test.ts b/__tests__/installer.unit.test.ts index 5e271681c..622ba375e 100644 --- a/__tests__/installer.unit.test.ts +++ b/__tests__/installer.unit.test.ts @@ -16,98 +16,125 @@ import { describe('setup-node unit tests', () => { describe('splitVersionSpec', () => { it('splitVersionSpec correctly splits version spec without dashes', () => { - const [raw, prerelease] = splitVersionSpec('1.1.1') - expect(raw).toBe('1.1.1') - expect(prerelease).toBeUndefined() - }) + const [raw, prerelease] = splitVersionSpec('1.1.1'); + expect(raw).toBe('1.1.1'); + expect(prerelease).toBeUndefined(); + }); it('splitVersionSpec correctly splits version spec with one dash', () => { - const [raw, prerelease] = splitVersionSpec('1.1.1-nightly12345678') - expect(raw).toBe('1.1.1') - expect(prerelease).toBe('nightly12345678') - }) + const [raw, prerelease] = splitVersionSpec('1.1.1-nightly12345678'); + expect(raw).toBe('1.1.1'); + expect(prerelease).toBe('nightly12345678'); + }); it('splitVersionSpec correctly splits version spec with 2 dashes', () => { - const [raw, prerelease] = splitVersionSpec('1.1.1-v8-canary12345678') - expect(raw).toBe('1.1.1') - expect(prerelease).toBe('v8-canary12345678') - }) - }) + const [raw, prerelease] = splitVersionSpec('1.1.1-v8-canary12345678'); + expect(raw).toBe('1.1.1'); + expect(prerelease).toBe('v8-canary12345678'); + }); + }); describe('distributionOf', () => { it('1.1.1-v8-canary should be CANARY', () => { - expect(distributionOf('1.1.1-v8-canary')).toBe(Distributions.CANARY) - }) + expect(distributionOf('1.1.1-v8-canary')).toBe(Distributions.CANARY); + }); it('1.1.1-v8-canary20221103f7e2421e91 should be CANARY', () => { - expect(distributionOf('1.1.1-v8-canary20221103f7e2421e91')).toBe(Distributions.CANARY) - }) + expect(distributionOf('1.1.1-v8-canary20221103f7e2421e91')).toBe( + Distributions.CANARY + ); + }); it('1.1.1-canary should throw exception', () => { - expect(() => distributionOf('1.1.1-canary')).toThrow('Canary version must have "-v8-canary suffix"') - }) + expect(() => distributionOf('1.1.1-canary')).toThrow( + 'Canary version must have "-v8-canary suffix"' + ); + }); it('1.1.1-canary20221103f7e2421e91 should throw exception', () => { - expect(() => distributionOf('1.1.1-canary20221103f7e2421e91')).toThrow('Canary version must have "-v8-canary suffix"') - }) + expect(() => distributionOf('1.1.1-canary20221103f7e2421e91')).toThrow( + 'Canary version must have "-v8-canary suffix"' + ); + }); it('1.1.1-nightly should be NIGHTLY', () => { - expect(distributionOf('1.1.1-nightly')).toBe(Distributions.NIGHTLY) - }) + expect(distributionOf('1.1.1-nightly')).toBe(Distributions.NIGHTLY); + }); it('1.1.1-nightly20221103f7e2421e91 should be NIGHTLY', () => { - expect(distributionOf('1.1.1-nightly20221103f7e2421e91')).toBe(Distributions.NIGHTLY) - }) + expect(distributionOf('1.1.1-nightly20221103f7e2421e91')).toBe( + Distributions.NIGHTLY + ); + }); it('1.1.1-rc.0 should be RC', () => { - expect(distributionOf('1.1.1-rc.0')).toBe(Distributions.RC) - }) - }) + expect(distributionOf('1.1.1-rc.0')).toBe(Distributions.RC); + }); + }); describe('versionMatcherFactory', () => { it('1.1.1 should be handled by semverVersionMatcherFactory', () => { - expect(versionMatcherFactory('1.1.1').factory).toBe(semverVersionMatcherFactory) - }) + expect(versionMatcherFactory('1.1.1').factory).toBe( + semverVersionMatcherFactory + ); + }); it('v1.1.1 should be handled by semverVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1').factory).toBe(semverVersionMatcherFactory) - }) + expect(versionMatcherFactory('v1.1.1').factory).toBe( + semverVersionMatcherFactory + ); + }); it('v1.1.1-v8-canary should be handled by canaryRangeVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-v8-canary').factory).toBe(canaryRangeVersionMatcherFactory) - }) + expect(versionMatcherFactory('v1.1.1-v8-canary').factory).toBe( + canaryRangeVersionMatcherFactory + ); + }); it('v1.1.1-v8-canary123 should be handled by canaryExactVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-v8-canary123').factory).toBe(canaryExactVersionMatcherFactory) - }) + expect(versionMatcherFactory('v1.1.1-v8-canary123').factory).toBe( + canaryExactVersionMatcherFactory + ); + }); it('v1.1.1-nightly should be handled by nightlyRangeVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-nightly').factory).toBe(nightlyRangeVersionMatcherFactory) - }) + expect(versionMatcherFactory('v1.1.1-nightly').factory).toBe( + nightlyRangeVersionMatcherFactory + ); + }); it('v1.1.1-nigthly123 should be handled by nightlyExactVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-nightly123').factory).toBe(nightlyExactVersionMatcherFactory) - }) + expect(versionMatcherFactory('v1.1.1-nightly123').factory).toBe( + nightlyExactVersionMatcherFactory + ); + }); it('v1.1.1-rc should be handled by semverVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-rc').factory).toBe(semverVersionMatcherFactory) - }) + expect(versionMatcherFactory('v1.1.1-rc').factory).toBe( + semverVersionMatcherFactory + ); + }); it('v1.1.1-rc.1 should be handled by semverVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-rc.1').factory).toBe(semverVersionMatcherFactory) - }) - }) + expect(versionMatcherFactory('v1.1.1-rc.1').factory).toBe( + semverVersionMatcherFactory + ); + }); + }); describe('Version spec matchers', () => { it('semverVersionMatcher should always work as semver.satisfies does', () => { - const rangePlain = '1.1.1' - const matcherPlain = semverVersionMatcherFactory(rangePlain) - expect(matcherPlain('1.1.1')).toBe(semver.satisfies('1.1.1', rangePlain)) - expect(matcherPlain('1.1.2')).toBe(semver.satisfies('1.1.2', rangePlain)) + const rangePlain = '1.1.1'; + const matcherPlain = semverVersionMatcherFactory(rangePlain); + expect(matcherPlain('1.1.1')).toBe(semver.satisfies('1.1.1', rangePlain)); + expect(matcherPlain('1.1.2')).toBe(semver.satisfies('1.1.2', rangePlain)); - const rangeEq = '=1.1.1' - const matcherEq = semverVersionMatcherFactory(rangeEq) - expect(matcherEq('1.1.1')).toBe(semver.satisfies('1.1.1', rangeEq)) - expect(matcherEq('1.1.2')).toBe(semver.satisfies('1.1.2', rangeEq)) + const rangeEq = '=1.1.1'; + const matcherEq = semverVersionMatcherFactory(rangeEq); + expect(matcherEq('1.1.1')).toBe(semver.satisfies('1.1.1', rangeEq)); + expect(matcherEq('1.1.2')).toBe(semver.satisfies('1.1.2', rangeEq)); // TODO: add for discovered issues if any - }) + }); it('canaryExactVersionMatcher should match v20.0.0-v8-canary20221103f7e2421e91 only v20.0.0-v8-canary20221103f7e2421e91', () => { - const version = semver.coerce('v20.0.0')!.version - const matcher = canaryExactVersionMatcherFactory(version, 'v8-canary20221103f7e2421e91'); + const version = semver.coerce('v20.0.0')!.version; + const matcher = canaryExactVersionMatcherFactory( + version, + 'v8-canary20221103f7e2421e91' + ); expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); - }) + }); it('canaryRangeVersionMatcherFactory should match v20-v8-canary to any minor and patch version', () => { - const version = semver.coerce('v20')!.version + const version = semver.coerce('v20')!.version; const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); @@ -117,7 +144,7 @@ describe('setup-node unit tests', () => { }); it('canaryRangeVersionMatcherFactory should not match v20-v8-canary to v21.x & v19.x', () => { - const version = semver.coerce('v20')!.version + const version = semver.coerce('v20')!.version; const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); @@ -128,7 +155,7 @@ describe('setup-node unit tests', () => { }); it('canaryRangeVersionMatcherFactory should match v20.1-v8-canary to any v20.1 patch version and minor above or eq v20.1', () => { - const version = semver.coerce('v20.1')!.version + const version = semver.coerce('v20.1')!.version; const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); @@ -137,7 +164,7 @@ describe('setup-node unit tests', () => { }); it('canaryRangeVersionMatcherFactory should not match canaryRangeVersionMatcherFactory to v21.x, v19.x, and v20 minor less v20.2', () => { - const version = semver.coerce('v20.2')!.version + const version = semver.coerce('v20.2')!.version; const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); @@ -145,7 +172,7 @@ describe('setup-node unit tests', () => { }); it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary v20.1.x to patch versions above or eq v20.1.1', () => { - const version = semver.coerce('v20.1.1')!.version + const version = semver.coerce('v20.1.1')!.version; const matcher = canaryRangeVersionMatcherFactory('v20.1.1-v8-canary'); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); @@ -153,20 +180,20 @@ describe('setup-node unit tests', () => { }); it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to patch versions with any canary timestamp', () => { - const version = semver.coerce('v20.1.1')!.version + const version = semver.coerce('v20.1.1')!.version; const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); }); it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary to any other minor versions and patch versions below v20.1.1', () => { - const version = semver.coerce('v20.1.1')!.version + const version = semver.coerce('v20.1.1')!.version; const matcher = canaryRangeVersionMatcherFactory(version); expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); }); - }) + }); describe('evaluateVersions', () => { it('evaluateVersions should handle v8-canary version spec without timestamp', () => { @@ -190,36 +217,63 @@ describe('setup-node unit tests', () => { 'v20.0.1-v8-canary20221103f7e2421e93', 'v20.0.2-v8-canary20221103f7e2421e91' ]; - const version = evaluateVersions(versions, 'v20.0.1-v8-canary20221103f7e2421e92'); + const version = evaluateVersions( + versions, + 'v20.0.1-v8-canary20221103f7e2421e92' + ); expect(version).toBe('v20.0.1-v8-canary20221103f7e2421e92'); }); - }) + }); describe('getNodejsDistUrl', () => { it('getNodejsDistUrl should handle v8 canary version spec', async () => { - expect(getNodejsDistUrl('1.1.1-v8-canary')).toBe('https://nodejs.org/download/v8-canary'); - expect(getNodejsDistUrl('1.1.1-v8-canary123')).toBe('https://nodejs.org/download/v8-canary'); - expect(getNodejsDistUrl('v1.1.1-v8-canary')).toBe('https://nodejs.org/download/v8-canary'); - expect(getNodejsDistUrl('v1.1.1-v8-canary123')).toBe('https://nodejs.org/download/v8-canary'); + expect(getNodejsDistUrl('1.1.1-v8-canary')).toBe( + 'https://nodejs.org/download/v8-canary' + ); + expect(getNodejsDistUrl('1.1.1-v8-canary123')).toBe( + 'https://nodejs.org/download/v8-canary' + ); + expect(getNodejsDistUrl('v1.1.1-v8-canary')).toBe( + 'https://nodejs.org/download/v8-canary' + ); + expect(getNodejsDistUrl('v1.1.1-v8-canary123')).toBe( + 'https://nodejs.org/download/v8-canary' + ); }); it('getNodejsDistUrl should handle nightly version spec', async () => { - expect(getNodejsDistUrl('1.1.1-nightly')).toBe('https://nodejs.org/download/nightly'); - expect(getNodejsDistUrl('v1.1.1-nightly')).toBe('https://nodejs.org/download/nightly'); - expect(getNodejsDistUrl('1.1.1-nightly123')).toBe('https://nodejs.org/download/nightly'); - expect(getNodejsDistUrl('v1.1.1-nightly123')).toBe('https://nodejs.org/download/nightly'); + expect(getNodejsDistUrl('1.1.1-nightly')).toBe( + 'https://nodejs.org/download/nightly' + ); + expect(getNodejsDistUrl('v1.1.1-nightly')).toBe( + 'https://nodejs.org/download/nightly' + ); + expect(getNodejsDistUrl('1.1.1-nightly123')).toBe( + 'https://nodejs.org/download/nightly' + ); + expect(getNodejsDistUrl('v1.1.1-nightly123')).toBe( + 'https://nodejs.org/download/nightly' + ); }); it('getNodejsDistUrl should handle rc version spec', async () => { - expect(getNodejsDistUrl('1.1.1-rc')).toBe('https://nodejs.org/download/rc'); - expect(getNodejsDistUrl('v1.1.1-rc')).toBe('https://nodejs.org/download/rc'); - expect(getNodejsDistUrl('1.1.1-rc.0')).toBe('https://nodejs.org/download/rc'); - expect(getNodejsDistUrl('v1.1.1-rc.0')).toBe('https://nodejs.org/download/rc'); + expect(getNodejsDistUrl('1.1.1-rc')).toBe( + 'https://nodejs.org/download/rc' + ); + expect(getNodejsDistUrl('v1.1.1-rc')).toBe( + 'https://nodejs.org/download/rc' + ); + expect(getNodejsDistUrl('1.1.1-rc.0')).toBe( + 'https://nodejs.org/download/rc' + ); + expect(getNodejsDistUrl('v1.1.1-rc.0')).toBe( + 'https://nodejs.org/download/rc' + ); }); it('getNodejsDistUrl should handle unspecific version spec', async () => { expect(getNodejsDistUrl('1.1.1')).toBe('https://nodejs.org/dist'); expect(getNodejsDistUrl('v1.1.1')).toBe('https://nodejs.org/dist'); }); - }) + }); }); diff --git a/src/installer.ts b/src/installer.ts index fcd871eb7..e9f252f98 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -34,103 +34,121 @@ export enum Distributions { DEFAULT, CANARY, NIGHTLY, - RC, + RC } export const distributionOf = (versionSpec: string): Distributions => versionSpec.includes('-v8-canary') ? Distributions.CANARY - // TODO: i'd like to have this check, do you? - : versionSpec.includes('-canary') - ? (() => { - throw Error('Canary version must have "-v8-canary suffix"') + : // TODO: i'd like to have this check, do you? + versionSpec.includes('-canary') + ? (() => { + throw Error('Canary version must have "-v8-canary suffix"'); })() - : versionSpec.includes('nightly') - ? Distributions.NIGHTLY - : semver.prerelease(versionSpec) - ? Distributions.RC - : Distributions.DEFAULT + : versionSpec.includes('nightly') + ? Distributions.NIGHTLY + : semver.prerelease(versionSpec) + ? Distributions.RC + : Distributions.DEFAULT; interface VersionMatcher { - (potential: string): boolean + (potential: string): boolean; // memoize the factory for testing and debug purposes - factory: ((ver: string, suffix: string) => VersionMatcher) | - ((semverRanger: string) => VersionMatcher) | (() => VersionMatcher) + factory: + | ((ver: string, suffix: string) => VersionMatcher) + | ((semverRanger: string) => VersionMatcher) + | (() => VersionMatcher); } export const semverVersionMatcherFactory = (range: string): VersionMatcher => { - const matcher = (potential: string): boolean => semver.satisfies(potential, range); - matcher.factory = semverVersionMatcherFactory - return matcher -} - -export const canaryRangeVersionMatcherFactory = (version: string): VersionMatcher => { - const range = semver.validRange(`^${version}`) + const matcher = (potential: string): boolean => + semver.satisfies(potential, range); + matcher.factory = semverVersionMatcherFactory; + return matcher; +}; + +export const canaryRangeVersionMatcherFactory = ( + version: string +): VersionMatcher => { + const range = semver.validRange(`^${version}`); const matcher = (potential: string): boolean => semver.satisfies(potential.replace('-v8-canary', '+v8-canary.'), range); - matcher.factory = canaryRangeVersionMatcherFactory - return matcher -} + matcher.factory = canaryRangeVersionMatcherFactory; + return matcher; +}; -export const canaryExactVersionMatcherFactory = (version: string, timestamp: string): VersionMatcher => { - const range = `${version}-${timestamp}` +export const canaryExactVersionMatcherFactory = ( + version: string, + timestamp: string +): VersionMatcher => { + const range = `${version}-${timestamp}`; const matcher = (potential: string): boolean => semver.satisfies(potential, range); - matcher.factory = canaryExactVersionMatcherFactory - return matcher -} - -export const nightlyRangeVersionMatcherFactory = (version: string): VersionMatcher => { - const range = `${semver.validRange(`^${version}-0`)}-0` + matcher.factory = canaryExactVersionMatcherFactory; + return matcher; +}; + +export const nightlyRangeVersionMatcherFactory = ( + version: string +): VersionMatcher => { + const range = `${semver.validRange(`^${version}-0`)}-0`; const matcher = (potential: string): boolean => distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies(potential.replace('-nightly', '-nightly.'), range, {includePrerelease: true}) - matcher.factory = nightlyRangeVersionMatcherFactory - return matcher -} - -export const nightlyExactVersionMatcherFactory = (version: string, prerelease_tag: string): VersionMatcher => { + semver.satisfies(potential.replace('-nightly', '-nightly.'), range, { + includePrerelease: true + }); + matcher.factory = nightlyRangeVersionMatcherFactory; + return matcher; +}; + +export const nightlyExactVersionMatcherFactory = ( + version: string, + prerelease_tag: string +): VersionMatcher => { const range = `${version}-${prerelease_tag.replace('nightly', 'nightly.')}`; const matcher = (potential: string): boolean => distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies(potential.replace('-nightly', '-nightly.'), range, {includePrerelease: true}) - matcher.factory = nightlyExactVersionMatcherFactory - return matcher -} + semver.satisfies(potential.replace('-nightly', '-nightly.'), range, { + includePrerelease: true + }); + matcher.factory = nightlyExactVersionMatcherFactory; + return matcher; +}; const alwaysFalseVersionMatcherFactory = (): VersionMatcher => { const matcher = () => false; - matcher.factory = alwaysFalseVersionMatcherFactory - return matcher -} + matcher.factory = alwaysFalseVersionMatcherFactory; + return matcher; +}; -const alwaysFalseVersionMatcher = alwaysFalseVersionMatcherFactory() +const alwaysFalseVersionMatcher = alwaysFalseVersionMatcherFactory(); // [raw, prerelease] -export const splitVersionSpec = (versionSpec: string): string[] => versionSpec.split(/-(.*)/s); +export const splitVersionSpec = (versionSpec: string): string[] => + versionSpec.split(/-(.*)/s); export function versionMatcherFactory(versionSpec: string): VersionMatcher { - const [raw, prerelease] = splitVersionSpec(versionSpec) + const [raw, prerelease] = splitVersionSpec(versionSpec); const validVersion = semver.valid(raw) ? raw : semver.coerce(raw)?.version; if (validVersion) { switch (distributionOf(versionSpec)) { case Distributions.CANARY: - return (prerelease === 'v8-canary') // this means versionSpec does not have timestamp + return prerelease === 'v8-canary' // this means versionSpec does not have timestamp ? canaryRangeVersionMatcherFactory(validVersion) - : canaryExactVersionMatcherFactory(validVersion, prerelease) + : canaryExactVersionMatcherFactory(validVersion, prerelease); case Distributions.NIGHTLY: - return (prerelease === 'nightly') // this means versionSpec does not have prerelease tag - ? nightlyRangeVersionMatcherFactory(validVersion) - : nightlyExactVersionMatcherFactory(validVersion, prerelease) + return prerelease === 'nightly' // this means versionSpec does not have prerelease tag + ? nightlyRangeVersionMatcherFactory(validVersion) + : nightlyExactVersionMatcherFactory(validVersion, prerelease); case Distributions.RC: case Distributions.DEFAULT: - return semverVersionMatcherFactory(versionSpec) + return semverVersionMatcherFactory(versionSpec); } } else { // TODO: i prefer to have implicit exception for the malformed input - throw Error(`Invalid version input "${versionSpec}"`) + throw Error(`Invalid version input "${versionSpec}"`); // TODO: but it is possible to silently fail // return alwaysFalseVersionMatcher @@ -149,7 +167,7 @@ export async function getNode( let nodeVersions: INodeVersion[] | undefined; const osPlat: string = os.platform(); const osArch: string = translateArchToDistUrl(arch); - const distribution = distributionOf(versionSpec) + const distribution = distributionOf(versionSpec); if (isLtsAlias(versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); @@ -199,7 +217,7 @@ export async function getNode( if (distribution === Distributions.DEFAULT) { toolPath = tc.find('node', versionSpec, osArch); } else { - const localVersionPaths = tc.findAllVersions('node', osArch) + const localVersionPaths = tc.findAllVersions('node', osArch); const localVersion = evaluateVersions(localVersionPaths, versionSpec); toolPath = localVersion && tc.find('node', localVersion, osArch); } @@ -363,8 +381,8 @@ export function resolveLtsAliasFromManifest( alias === '*' ? numbered[numbered.length - 1] : n < 0 - ? numbered[numbered.length - 1 + n] - : aliases[alias]; + ? numbered[numbered.length - 1 + n] + : aliases[alias]; if (!release) { throw new Error( @@ -470,11 +488,14 @@ async function resolveVersionFromManifest( // - the answer from dsame@github.com - we have customized matcher and can not // export `evaluateVersions` from tc. But it would be possible to modify tc to accept // the matcher as an optional parameter to `evaluateVersions` -export function evaluateVersions(versions: string[], versionSpec: string): string { +export function evaluateVersions( + versions: string[], + versionSpec: string +): string { core.debug(`evaluating ${versions.length} versions`); - const matcher = versionMatcherFactory(versionSpec) - const version = versions.sort(semver.rcompare).find(matcher) || '' + const matcher = versionMatcherFactory(versionSpec); + const version = versions.sort(semver.rcompare).find(matcher) || ''; if (version) { core.debug(`matched: ${version}`); From a3c8983ccb38e3b5753494c89a440c6d50ce07c9 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 05:30:41 +0100 Subject: [PATCH 11/51] dist --- dist/setup/index.js | 228 +++++++++++++++++++++++--------------------- 1 file changed, 119 insertions(+), 109 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 887654434..edaf1ed08 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73216,33 +73216,120 @@ const tc = __importStar(__nccwpck_require__(7784)); const path = __importStar(__nccwpck_require__(1017)); const semver = __importStar(__nccwpck_require__(5911)); const fs_1 = __importDefault(__nccwpck_require__(7147)); -const isVersionCanary = (versionSpec) => versionSpec.includes(`-v8-canary`); +var Distributions; +(function (Distributions) { + Distributions[Distributions["DEFAULT"] = 0] = "DEFAULT"; + Distributions[Distributions["CANARY"] = 1] = "CANARY"; + Distributions[Distributions["NIGHTLY"] = 2] = "NIGHTLY"; + Distributions[Distributions["RC"] = 3] = "RC"; +})(Distributions = exports.Distributions || (exports.Distributions = {})); +exports.distributionOf = (versionSpec) => versionSpec.includes('-v8-canary') + ? Distributions.CANARY + : // TODO: i'd like to have this check, do you? + versionSpec.includes('-canary') + ? (() => { + throw Error('Canary version must have "-v8-canary suffix"'); + })() + : versionSpec.includes('nightly') + ? Distributions.NIGHTLY + : semver.prerelease(versionSpec) + ? Distributions.RC + : Distributions.DEFAULT; +exports.semverVersionMatcherFactory = (range) => { + const matcher = (potential) => semver.satisfies(potential, range); + matcher.factory = exports.semverVersionMatcherFactory; + return matcher; +}; +exports.canaryRangeVersionMatcherFactory = (version) => { + const range = semver.validRange(`^${version}`); + const matcher = (potential) => semver.satisfies(potential.replace('-v8-canary', '+v8-canary.'), range); + matcher.factory = exports.canaryRangeVersionMatcherFactory; + return matcher; +}; +exports.canaryExactVersionMatcherFactory = (version, timestamp) => { + const range = `${version}-${timestamp}`; + const matcher = (potential) => semver.satisfies(potential, range); + matcher.factory = exports.canaryExactVersionMatcherFactory; + return matcher; +}; +exports.nightlyRangeVersionMatcherFactory = (version) => { + const range = `${semver.validRange(`^${version}-0`)}-0`; + const matcher = (potential) => exports.distributionOf(potential) === Distributions.NIGHTLY && + semver.satisfies(potential.replace('-nightly', '-nightly.'), range, { + includePrerelease: true + }); + matcher.factory = exports.nightlyRangeVersionMatcherFactory; + return matcher; +}; +exports.nightlyExactVersionMatcherFactory = (version, prerelease_tag) => { + const range = `${version}-${prerelease_tag.replace('nightly', 'nightly.')}`; + const matcher = (potential) => exports.distributionOf(potential) === Distributions.NIGHTLY && + semver.satisfies(potential.replace('-nightly', '-nightly.'), range, { + includePrerelease: true + }); + matcher.factory = exports.nightlyExactVersionMatcherFactory; + return matcher; +}; +const alwaysFalseVersionMatcherFactory = () => { + const matcher = () => false; + matcher.factory = alwaysFalseVersionMatcherFactory; + return matcher; +}; +const alwaysFalseVersionMatcher = alwaysFalseVersionMatcherFactory(); +// [raw, prerelease] +exports.splitVersionSpec = (versionSpec) => versionSpec.split(/-(.*)/s); +function versionMatcherFactory(versionSpec) { + var _a; + const [raw, prerelease] = exports.splitVersionSpec(versionSpec); + const validVersion = semver.valid(raw) ? raw : (_a = semver.coerce(raw)) === null || _a === void 0 ? void 0 : _a.version; + if (validVersion) { + switch (exports.distributionOf(versionSpec)) { + case Distributions.CANARY: + return prerelease === 'v8-canary' // this means versionSpec does not have timestamp + ? exports.canaryRangeVersionMatcherFactory(validVersion) + : exports.canaryExactVersionMatcherFactory(validVersion, prerelease); + case Distributions.NIGHTLY: + return prerelease === 'nightly' // this means versionSpec does not have prerelease tag + ? exports.nightlyRangeVersionMatcherFactory(validVersion) + : exports.nightlyExactVersionMatcherFactory(validVersion, prerelease); + case Distributions.RC: + case Distributions.DEFAULT: + return exports.semverVersionMatcherFactory(versionSpec); + } + } + else { + // TODO: i prefer to have implicit exception for the malformed input + throw Error(`Invalid version input "${versionSpec}"`); + // TODO: but it is possible to silently fail + // return alwaysFalseVersionMatcher + } +} +exports.versionMatcherFactory = versionMatcherFactory; function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arch()) { return __awaiter(this, void 0, void 0, function* () { // Store manifest data to avoid multiple calls let manifest; let nodeVersions; - let isNightly = versionSpec.includes('nightly'); - let osPlat = os_1.default.platform(); - let osArch = translateArchToDistUrl(arch); - let isCanary = isVersionCanary(versionSpec); + const osPlat = os_1.default.platform(); + const osArch = translateArchToDistUrl(arch); + const distribution = exports.distributionOf(versionSpec); 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 = yield getManifest(auth); versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } - // evaluate exact versionSpec from input - if (isLatestSyntax(versionSpec) || isCanary) { + // TODO: 121-127 and 131-132 seems to be the same. Why do we need them? + if (isLatestSyntax(versionSpec) || distribution == Distributions.CANARY) { nodeVersions = yield getVersionsFromDist(versionSpec); versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); - core.info(`getting ${isCanary ? 'v8-canary' : 'latest'} node version ${versionSpec}...`); + core.info(`getting ${distribution == Distributions.CANARY ? 'v8-canary' : 'latest'} node version ${versionSpec}...`); } - if (isNightly && checkLatest) { + if (distribution === Distributions.NIGHTLY && checkLatest) { nodeVersions = yield getVersionsFromDist(versionSpec); versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); } - if (checkLatest && !isNightly) { + if (checkLatest && distribution !== Distributions.NIGHTLY) { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = yield resolveVersionFromManifest(versionSpec, stable, auth, osArch, manifest); if (resolvedVersion) { @@ -73256,16 +73343,13 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arc // check cache core.info('Attempt to find existing version in cache...'); let toolPath; - if (isNightly) { - const nightlyVersion = findNightlyVersionInHostedToolcache(versionSpec, osArch); - toolPath = nightlyVersion && tc.find('node', nightlyVersion, osArch); - } - else if (isCanary) { - const localVersions = tc.findAllVersions('node', osArch); - toolPath = evaluateVersions(localVersions, versionSpec); + if (distribution === Distributions.DEFAULT) { + toolPath = tc.find('node', versionSpec, osArch); } else { - toolPath = tc.find('node', versionSpec, osArch); + const localVersionPaths = tc.findAllVersions('node', osArch); + const localVersion = evaluateVersions(localVersionPaths, versionSpec); + toolPath = localVersion && tc.find('node', localVersion, osArch); } // If not found in cache, download if (toolPath) { @@ -73362,10 +73446,6 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arc }); } exports.getNode = getNode; -function findNightlyVersionInHostedToolcache(versionsSpec, osArch) { - const foundAllVersions = tc.findAllVersions('node', osArch); - return evaluateVersions(foundAllVersions, versionsSpec); -} function isLtsAlias(versionSpec) { return versionSpec.startsWith('lts/'); } @@ -73456,57 +73536,14 @@ function resolveVersionFromManifest(versionSpec, stable, auth, osArch = translat } }); } -function evaluateNightlyVersions(versions, versionSpec) { - let version = ''; - let range; - const [raw, prerelease] = versionSpec.split('-'); - const isValidVersion = semver.valid(raw); - const rawVersion = isValidVersion ? raw : semver.coerce(raw); - if (rawVersion) { - if (prerelease !== 'nightly') { - range = `${rawVersion}-${prerelease.replace('nightly', 'nightly.')}`; - } - else { - range = `${semver.validRange(`^${rawVersion}-0`)}-0`; - } - } - if (range) { - versions.sort(semver.rcompare); - for (const currentVersion of versions) { - const satisfied = semver.satisfies(currentVersion.replace('-nightly', '-nightly.'), range, { includePrerelease: true }) && currentVersion.includes('nightly'); - if (satisfied) { - version = currentVersion; - break; - } - } - } - if (version) { - core.debug(`matched: ${version}`); - } - else { - core.debug('match not found'); - } - return version; -} // TODO - should we just export this from @actions/tool-cache? Lifted directly from there +// - the answer from dsame@github.com - we have customized matcher and can not +// export `evaluateVersions` from tc. But it would be possible to modify tc to accept +// the matcher as an optional parameter to `evaluateVersions` function evaluateVersions(versions, versionSpec) { - let version = ''; core.debug(`evaluating ${versions.length} versions`); - if (versionSpec.includes('nightly')) { - return evaluateNightlyVersions(versions, versionSpec); - } - versions = versions.sort(semver.rcompare); - const matcher = isVersionCanary(versionSpec) - ? evaluateCanaryMatcher(versionSpec) - : potential => semver.satisfies(potential, versionSpec); - for (let i = versions.length - 1; i >= 0; i--) { - const potential = versions[i]; - const satisfied = matcher(potential); - if (satisfied) { - version = potential; - break; - } - } + const matcher = versionMatcherFactory(versionSpec); + const version = versions.sort(semver.rcompare).find(matcher) || ''; if (version) { core.debug(`matched: ${version}`); } @@ -73517,20 +73554,18 @@ function evaluateVersions(versions, versionSpec) { } exports.evaluateVersions = evaluateVersions; function getNodejsDistUrl(version) { - const prerelease = semver.prerelease(version); - if (version.includes('nightly')) { - core.debug('requested nightly distribution'); - return 'https://nodejs.org/download/nightly'; - } - else if (prerelease) { - return 'https://nodejs.org/download/rc'; - } - else if (isVersionCanary(version)) { - core.debug('requested v8 canary distribution'); - return 'https://nodejs.org/download/v8-canary'; - } - else { - return 'https://nodejs.org/dist'; + switch (exports.distributionOf(version)) { + case Distributions.CANARY: + core.debug('requested v8 canary distribution'); + return 'https://nodejs.org/download/v8-canary'; + case Distributions.NIGHTLY: + core.debug('requested nightly distribution'); + return 'https://nodejs.org/download/nightly'; + case Distributions.RC: + core.debug('requested release candidates distribution'); + return 'https://nodejs.org/download/rc'; + case Distributions.DEFAULT: + return 'https://nodejs.org/dist'; } } exports.getNodejsDistUrl = getNodejsDistUrl; @@ -73678,31 +73713,6 @@ function isLatestSyntax(versionSpec) { return ['current', 'latest', 'node'].includes(versionSpec); } exports.isLatestSyntax = isLatestSyntax; -function evaluateCanaryMatcher(versionSpec) { - var _a; - const [raw, prerelease] = versionSpec.split(/-(.*)/s); - const isValidVersion = semver.valid(raw); - const rawVersion = isValidVersion ? raw : (_a = semver.coerce(raw)) === null || _a === void 0 ? void 0 : _a.version; - if (rawVersion) { - if (prerelease === 'v8-canary') { - // it means versionSpec does not have timestamp - const range = semver.validRange(`^${rawVersion}`); - return (potential) => semver.satisfies( - // TODO: check latest? - potential.replace('-v8-canary', '+v8-canary.'), range); - } - else { - // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 - // there must be exact match - const range = `${rawVersion}-${prerelease}`; - return (potential) => semver.satisfies( - // TODO: check latest? - potential, range); - } - } - return () => false; -} -exports.evaluateCanaryMatcher = evaluateCanaryMatcher; /***/ }), From 6e2b26d0977fdb8673930619737c6f4cbf0d535a Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 08:42:52 +0100 Subject: [PATCH 12/51] Fix windows test --- __tests__/installer.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 1f93e1f06..0041ab849 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -1354,13 +1354,13 @@ describe('setup-node', () => { const versionExpected = 'v20.0.0-v8-canary20221103f7e2421e91'; findAllVersionSpy.mockImplementation(() => [versionExpected]); - let toolPath = path.normalize(`/cache/node/${versionExpected}/x64`); + const toolPath = path.normalize(`/cache/node/${versionExpected}/x64`); findSpy.mockImplementation(version => toolPath); await main.run(); expect(cnSpy).toHaveBeenCalledWith( - `::add-path::${toolPath}/bin${osm.EOL}` + `::add-path::${toolPath}${path.sep}bin${osm.EOL}` ); expect(dlSpy).not.toHaveBeenCalled(); From 505679238a1a9cc4655c8a4490e1436cfe386fad Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 12:15:42 +0100 Subject: [PATCH 13/51] Fix nightly unit tests --- __tests__/installer.unit.test.ts | 235 +++++++++++++++++++++---------- src/installer.ts | 28 ++-- 2 files changed, 184 insertions(+), 79 deletions(-) diff --git a/__tests__/installer.unit.test.ts b/__tests__/installer.unit.test.ts index 622ba375e..26c674d48 100644 --- a/__tests__/installer.unit.test.ts +++ b/__tests__/installer.unit.test.ts @@ -108,90 +108,183 @@ describe('setup-node unit tests', () => { }); describe('Version spec matchers', () => { - it('semverVersionMatcher should always work as semver.satisfies does', () => { - const rangePlain = '1.1.1'; - const matcherPlain = semverVersionMatcherFactory(rangePlain); - expect(matcherPlain('1.1.1')).toBe(semver.satisfies('1.1.1', rangePlain)); - expect(matcherPlain('1.1.2')).toBe(semver.satisfies('1.1.2', rangePlain)); + describe('semverVersionMatcher', () => { + it('semverVersionMatcher should always work as semver.satisfies does', () => { + const rangePlain = '1.1.1'; + const matcherPlain = semverVersionMatcherFactory(rangePlain); + expect(matcherPlain('1.1.1')).toBe( + semver.satisfies('1.1.1', rangePlain) + ); + expect(matcherPlain('1.1.2')).toBe( + semver.satisfies('1.1.2', rangePlain) + ); - const rangeEq = '=1.1.1'; - const matcherEq = semverVersionMatcherFactory(rangeEq); - expect(matcherEq('1.1.1')).toBe(semver.satisfies('1.1.1', rangeEq)); - expect(matcherEq('1.1.2')).toBe(semver.satisfies('1.1.2', rangeEq)); + const rangeEq = '=1.1.1'; + const matcherEq = semverVersionMatcherFactory(rangeEq); + expect(matcherEq('1.1.1')).toBe(semver.satisfies('1.1.1', rangeEq)); + expect(matcherEq('1.1.2')).toBe(semver.satisfies('1.1.2', rangeEq)); - // TODO: add for discovered issues if any - }); + // TODO: add for discovered issues if any + }); - it('canaryExactVersionMatcher should match v20.0.0-v8-canary20221103f7e2421e91 only v20.0.0-v8-canary20221103f7e2421e91', () => { - const version = semver.coerce('v20.0.0')!.version; - const matcher = canaryExactVersionMatcherFactory( - version, - 'v8-canary20221103f7e2421e91' - ); - expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 - expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); - }); + it("semverVersionMatcher should match release candidate as semver.satisfies does'", () => { + const rangePlain = 'v19.0.0-rc.2'; + const matcherPlain = semverVersionMatcherFactory(rangePlain); + expect(matcherPlain('v19.0.0-rc.2')).toBe( + semver.satisfies('v19.0.0-rc.2', rangePlain) + ); + expect(matcherPlain('v19.0.1-rc.2')).toBe( + semver.satisfies('v19.0.01rc.2', rangePlain) + ); - it('canaryRangeVersionMatcherFactory should match v20-v8-canary to any minor and patch version', () => { - const version = semver.coerce('v20')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); + const rangeEq = '=1.1.1'; + const matcherEq = semverVersionMatcherFactory(rangeEq); + expect(matcherPlain('v19.0.0-rc.2')).toBe( + semver.satisfies('v19.0.0-rc.2', rangePlain) + ); + expect(matcherPlain('v19.0.1-rc.2')).toBe( + semver.satisfies('v19.0.1-rc.2', rangePlain) + ); + }); }); - it('canaryRangeVersionMatcherFactory should not match v20-v8-canary to v21.x & v19.x', () => { - const version = semver.coerce('v20')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.1.1-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.1.-v8-canary20221103f7e2421e91')).toBeFalsy(); + describe('canaryExactVersionMatcher', () => { + it('canaryExactVersionMatcher should match v20.0.0-v8-canary20221103f7e2421e91 only v20.0.0-v8-canary20221103f7e2421e91', () => { + const version = semver.coerce('v20.0.0')!.version; + const matcher = canaryExactVersionMatcherFactory( + version, + 'v8-canary20221103f7e2421e91' + ); + expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 + expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); + }); }); - it('canaryRangeVersionMatcherFactory should match v20.1-v8-canary to any v20.1 patch version and minor above or eq v20.1', () => { - const version = semver.coerce('v20.1')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); - expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - }); + describe('canaryRangeVersionMatcherFactory', () => { + it('canaryRangeVersionMatcherFactory should match v20-v8-canary to any v20.x.x', () => { + const version = semver.coerce('v20')!.version; + const matcher = canaryRangeVersionMatcherFactory(version); + expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); + }); - it('canaryRangeVersionMatcherFactory should not match canaryRangeVersionMatcherFactory to v21.x, v19.x, and v20 minor less v20.2', () => { - const version = semver.coerce('v20.2')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - }); + it('canaryRangeVersionMatcherFactory should not match v20-v8-canary to v21.x & v19.x', () => { + const version = semver.coerce('v20')!.version; + const matcher = canaryRangeVersionMatcherFactory(version); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.1.1-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.1.-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); - it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary v20.1.x to patch versions above or eq v20.1.1', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = canaryRangeVersionMatcherFactory('v20.1.1-v8-canary'); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - }); + it('canaryRangeVersionMatcherFactory should match v20.1-v8-canary to any v20.1.x patch version and minor above or eq v20.1', () => { + const version = semver.coerce('v20.1')!.version; + const matcher = canaryRangeVersionMatcherFactory(version); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); + expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + }); + + it('canaryRangeVersionMatcherFactory should not match v20.2-v8-canary to v21.x, v19.x, and v20 minor less than v20.2', () => { + const version = semver.coerce('v20.2')!.version; + const matcher = canaryRangeVersionMatcherFactory(version); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); + + it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to v20.1.x patch versions above or eq v20.1.1', () => { + const version = semver.coerce('v20.1.1')!.version; + const matcher = canaryRangeVersionMatcherFactory('v20.1.1-v8-canary'); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); + }); - it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to patch versions with any canary timestamp', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); + it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary to any other minor versions and patch versions below v20.1.1', () => { + const version = semver.coerce('v20.1.1')!.version; + const matcher = canaryRangeVersionMatcherFactory(version); + expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + }); + + it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to patch versions with any canary timestamp', () => { + const version = semver.coerce('v20.1.1')!.version; + const matcher = canaryRangeVersionMatcherFactory(version); + expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); + }); }); - it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary to any other minor versions and patch versions below v20.1.1', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); + describe('nightlyRangeVersionMatcherFactory', () => { + it('nightlyRangeVersionMatcherFactory should match v20-nightly to any v20.x.x', () => { + const version = semver.coerce('v20')!.version; + const matcher = nightlyRangeVersionMatcherFactory(version); + expect(matcher('v20.0.0-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.0.1-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.0-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.0.0-nightly202211026bf85d0fb4')).toBeTruthy(); + }); + + it('nightlyRangeVersionMatcherFactory should not match v20-nightly to v21.x & v19.x', () => { + const version = semver.coerce('v20')!.version; + const matcher = nightlyRangeVersionMatcherFactory(version); + expect(matcher('v21.0.0-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.1.0-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.1.1-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.1.0-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.1.-nightly20221103f7e2421e91')).toBeFalsy(); + }); + + it('nightlyRangeVersionMatcherFactory should match v20.1-nightly to any v20.1.x patch version and minor above or eq v20.1', () => { + const version = semver.coerce('v20.1')!.version; + const matcher = nightlyRangeVersionMatcherFactory(version); + expect(matcher('v20.1.0-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.0-nightly202211026bf85d0fb4')).toBeTruthy(); + expect(matcher('v20.2.0-nightly20221103f7e2421e91')).toBeTruthy(); + }); + + it('nightlyRangeVersionMatcherFactory should not match v20.2-nightly to v21.x, v19.x, and v20 minor less v20.2', () => { + const version = semver.coerce('v20.2')!.version; + const matcher = nightlyRangeVersionMatcherFactory(version); + expect(matcher('v20.1.0-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.0.0-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-nightly20221103f7e2421e91')).toBeFalsy(); + }); + + it('nightlyRangeVersionMatcherFactory should match v20.1.1-nightly to v20.1.x patch versions above or eq v20.1.1', () => { + const version = semver.coerce('v20.1.1')!.version; + const matcher = nightlyRangeVersionMatcherFactory('v20.1.1-nightly'); + expect(matcher('v20.1.1-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.2-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.2.0-nightly20221103f7e2421e91')).toBeTruthy(); + }); + + it('nightlyRangeVersionMatcherFactory should not match v20.1.1-nightly to any other minor versions and patch versions below v20.1.1', () => { + const version = semver.coerce('v20.1.1')!.version; + const matcher = nightlyRangeVersionMatcherFactory(version); + expect(matcher('v20.1.0-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v21.0.0-nightly20221103f7e2421e91')).toBeFalsy(); + expect(matcher('v19.0.0-nightly20221103f7e2421e91')).toBeFalsy(); + }); + + it('nightlyRangeVersionMatcherFactory should match v20.1.1-nightly to patch versions with any timestamp', () => { + const version = semver.coerce('v20.1.1')!.version; + const matcher = nightlyRangeVersionMatcherFactory(version); + expect(matcher('v20.1.1-nightly20221103f7e2421e91')).toBeTruthy(); + expect(matcher('v20.1.1-nightly202211026bf85d0fb4')).toBeTruthy(); + }); }); }); diff --git a/src/installer.ts b/src/installer.ts index e9f252f98..e3c4df473 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -92,26 +92,38 @@ export const canaryExactVersionMatcherFactory = ( export const nightlyRangeVersionMatcherFactory = ( version: string ): VersionMatcher => { - const range = `${semver.validRange(`^${version}-0`)}-0`; + const range = semver.validRange(`^${version}`); + // TODO: this makes v20.1.1-nightly to do not match v20.1.1-nightly20221103f7e2421e91 + // const range = `${semver.validRange(`^${version}-0`)}-0`; const matcher = (potential: string): boolean => distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies(potential.replace('-nightly', '-nightly.'), range, { + // TODO: dmitry's variant was potential.replace('-nightly', '-nightly.') that made + // all unit tests to fail + semver.satisfies( + potential.replace('-nightly', '+nightly.'), + range /*, { + // TODO: what is for? includePrerelease: true - }); + }*/ + ); matcher.factory = nightlyRangeVersionMatcherFactory; return matcher; }; export const nightlyExactVersionMatcherFactory = ( version: string, - prerelease_tag: string + timestamp: string ): VersionMatcher => { - const range = `${version}-${prerelease_tag.replace('nightly', 'nightly.')}`; + const range = `${version}-${timestamp.replace('nightly', 'nightly.')}`; const matcher = (potential: string): boolean => distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies(potential.replace('-nightly', '-nightly.'), range, { + semver.satisfies( + potential.replace('-nightly', '-nightly.'), + range /*, { + // TODO: what is for? includePrerelease: true - }); + }*/ + ); matcher.factory = nightlyExactVersionMatcherFactory; return matcher; }; @@ -178,7 +190,7 @@ export async function getNode( versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } - // TODO: 121-127 and 131-132 seems to be the same. Why do we need them? + // TODO: 183-189 and 193-194 seems to be the same. Why do we need them? if (isLatestSyntax(versionSpec) || distribution == Distributions.CANARY) { nodeVersions = await getVersionsFromDist(versionSpec); versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); From d2ef4bc907656a1c4b2e718604b21a5ae875b089 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 12:21:17 +0100 Subject: [PATCH 14/51] build dist --- dist/setup/index.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index edaf1ed08..848bec334 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73253,20 +73253,26 @@ exports.canaryExactVersionMatcherFactory = (version, timestamp) => { return matcher; }; exports.nightlyRangeVersionMatcherFactory = (version) => { - const range = `${semver.validRange(`^${version}-0`)}-0`; + const range = semver.validRange(`^${version}`); + // TODO: this makes v20.1.1-nightly to do not match v20.1.1-nightly20221103f7e2421e91 + // const range = `${semver.validRange(`^${version}-0`)}-0`; const matcher = (potential) => exports.distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies(potential.replace('-nightly', '-nightly.'), range, { - includePrerelease: true - }); + // TODO: dmitry's variant was potential.replace('-nightly', '-nightly.') that made + // all unit tests to fail + semver.satisfies(potential.replace('-nightly', '+nightly.'), range /*, { + // TODO: what is for? + includePrerelease: true + }*/); matcher.factory = exports.nightlyRangeVersionMatcherFactory; return matcher; }; -exports.nightlyExactVersionMatcherFactory = (version, prerelease_tag) => { - const range = `${version}-${prerelease_tag.replace('nightly', 'nightly.')}`; +exports.nightlyExactVersionMatcherFactory = (version, timestamp) => { + const range = `${version}-${timestamp.replace('nightly', 'nightly.')}`; const matcher = (potential) => exports.distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies(potential.replace('-nightly', '-nightly.'), range, { - includePrerelease: true - }); + semver.satisfies(potential.replace('-nightly', '-nightly.'), range /*, { + // TODO: what is for? + includePrerelease: true + }*/); matcher.factory = exports.nightlyExactVersionMatcherFactory; return matcher; }; @@ -73319,7 +73325,7 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arc manifest = yield getManifest(auth); versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } - // TODO: 121-127 and 131-132 seems to be the same. Why do we need them? + // TODO: 183-189 and 193-194 seems to be the same. Why do we need them? if (isLatestSyntax(versionSpec) || distribution == Distributions.CANARY) { nodeVersions = yield getVersionsFromDist(versionSpec); versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); From 4a961ae73713a08c1ceaf29e3a859be30c992613 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 13:29:42 +0100 Subject: [PATCH 15/51] Fix docs --- docs/advanced-usage.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 771d0b829..79998680d 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -124,7 +124,6 @@ jobs: - run: npm test ``` ### Install v8 canary build for major node version ->>>>>>> d703091 (Change docs) ```yaml jobs: From e542443cfac067650cd454b4930f083030bb3278 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 13:30:14 +0100 Subject: [PATCH 16/51] Fix versions.yml --- .github/workflows/versions.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index 481ca1e43..6dd6f646a 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -58,18 +58,18 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] node-version: ['20-v8-canary', '20.0-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 + 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 }} From 63e6b4af5a2ebbad34940b7e196ce06da96ae3cb Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 16:34:12 +0100 Subject: [PATCH 17/51] change numbered list to bullet --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 61edf1e26..f075d0cfa 100644 --- a/README.md +++ b/README.md @@ -128,17 +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) -1. [Using a node version file](docs/advanced-usage.md#node-version-file) -1. [Using different architectures](docs/advanced-usage.md#architecture) -1. [Using v8 canary versions](docs/advanced-usage.md#v8-canary-versions) -1. [Using nigthly versions](docs/advanced-usage.md#nightly-versions) -1. [Using rc versions](docs/advanced-usage.md#rc-versions) -1. [Caching packages data](docs/advanced-usage.md#caching-packages-data) -1. [Using multiple operating systems and architectures](docs/advanced-usage.md#multiple-operating-systems-and-architectures) -1. [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) -1. [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) -1. [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 From 658b51b920c3c16aa0a14fe22636755c8b9ad38f Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Thu, 24 Nov 2022 18:52:31 +0100 Subject: [PATCH 18/51] requested changes --- __tests__/installer.test.ts | 39 ++++++---------------- __tests__/installer.unit.test.ts | 10 ------ dist/setup/index.js | 51 ++++++++++++++-------------- src/installer.ts | 57 ++++++++++++++------------------ 4 files changed, 60 insertions(+), 97 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 0041ab849..3ec837c22 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -72,7 +72,6 @@ describe('setup-node', () => { exSpy = jest.spyOn(tc, 'extractTar'); cacheSpy = jest.spyOn(tc, 'cacheDir'); getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo'); - // @ts-ignore getDistSpy = jest.spyOn(im, 'getVersionsFromDist'); parseNodeVersionSpy = jest.spyOn(im, 'parseNodeVersionFile'); @@ -1302,37 +1301,25 @@ describe('setup-node', () => { await main.run(); - expect(dbgSpy.mock.calls[0][0]).toBe('requested v8 canary distribution'); - expect(dbgSpy.mock.calls[1][0]).toBe('evaluating 17 versions'); - expect(dbgSpy.mock.calls[2][0]).toBe( - 'matched: v20.0.0-v8-canary20221103f7e2421e91' - ); + expect(dbgSpy.mock.calls[0][0]).toBe('evaluating 0 versions'); + expect(dbgSpy.mock.calls[1][0]).toBe('match not found'); expect(logSpy.mock.calls[0][0]).toBe( - 'getting v8-canary node version v20.0.0-v8-canary20221103f7e2421e91...' - ); - expect(logSpy.mock.calls[1][0]).toBe( - 'Attempt to find existing version in cache...' - ); - expect(dbgSpy.mock.calls[3][0]).toBe('evaluating 0 versions'); - expect(dbgSpy.mock.calls[4][0]).toBe('match not found'); - expect(logSpy.mock.calls[2][0]).toBe( - 'Attempting to download v20.0.0-v8-canary20221103f7e2421e91...' + `Attempting to download ${versionSpec}...` ); - expect(dbgSpy.mock.calls[5][0]).toBe('No manifest cached'); - expect(dbgSpy.mock.calls[6][0]).toBe( + expect(dbgSpy.mock.calls[2][0]).toBe('No manifest cached'); + expect(dbgSpy.mock.calls[3][0]).toBe( 'Getting manifest from actions/node-versions@main' ); - expect(dbgSpy.mock.calls[7][0].slice(0, 6)).toBe('check '); - expect(dbgSpy.mock.calls[13][0].slice(0, 6)).toBe('check '); - expect(logSpy.mock.calls[3][0]).toBe( + expect(dbgSpy.mock.calls[4][0].slice(0, 6)).toBe('check '); + expect(dbgSpy.mock.calls[10][0].slice(0, 6)).toBe('check '); + expect(logSpy.mock.calls[1][0]).toBe( 'Not found in manifest. Falling back to download directly from Node' ); - expect(dbgSpy.mock.calls[14][0]).toBe('evaluating 17 versions'); - expect(dbgSpy.mock.calls[15][0]).toBe( + expect(dbgSpy.mock.calls[12][0]).toBe('evaluating 17 versions'); + expect(dbgSpy.mock.calls[13][0]).toBe( 'matched: v20.0.0-v8-canary20221103f7e2421e91' ); - expect(dbgSpy.mock.calls[16][0]).toBe('requested v8 canary distribution'); - expect(logSpy.mock.calls[4][0]).toBe( + expect(logSpy.mock.calls[2][0]).toBe( 'Acquiring 20.0.0-v8-canary20221103f7e2421e91 - x64 from https://nodejs.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz' ); @@ -1373,14 +1360,12 @@ describe('setup-node', () => { describe('helper methods', () => { it('is not LTS alias', async () => { const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore const isLtsAlias = im.isLtsAlias(versionSpec); expect(isLtsAlias).toBeFalsy(); }); it('is not isLatestSyntax', async () => { const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore const isLatestSyntax = im.isLatestSyntax(versionSpec); expect(isLatestSyntax).toBeFalsy(); }); @@ -1388,14 +1373,12 @@ describe('helper methods', () => { describe('getNodejsDistUrl', () => { it('dist url to be https://nodejs.org/download/v8-canary for input versionSpec', () => { const versionSpec = 'v99.0.0-v8-canary'; - // @ts-ignore const url = im.getNodejsDistUrl(versionSpec); expect(url).toBe('https://nodejs.org/download/v8-canary'); }); it('dist url to be https://nodejs.org/download/v8-canary for full versionSpec', () => { const versionSpec = 'v20.0.0-v8-canary20221103f7e2421e91'; - // @ts-ignore const url = im.getNodejsDistUrl(versionSpec); expect(url).toBe('https://nodejs.org/download/v8-canary'); }); diff --git a/__tests__/installer.unit.test.ts b/__tests__/installer.unit.test.ts index 26c674d48..11d4b1bb0 100644 --- a/__tests__/installer.unit.test.ts +++ b/__tests__/installer.unit.test.ts @@ -41,16 +41,6 @@ describe('setup-node unit tests', () => { Distributions.CANARY ); }); - it('1.1.1-canary should throw exception', () => { - expect(() => distributionOf('1.1.1-canary')).toThrow( - 'Canary version must have "-v8-canary suffix"' - ); - }); - it('1.1.1-canary20221103f7e2421e91 should throw exception', () => { - expect(() => distributionOf('1.1.1-canary20221103f7e2421e91')).toThrow( - 'Canary version must have "-v8-canary suffix"' - ); - }); it('1.1.1-nightly should be NIGHTLY', () => { expect(distributionOf('1.1.1-nightly')).toBe(Distributions.NIGHTLY); }); diff --git a/dist/setup/index.js b/dist/setup/index.js index 848bec334..2d4f882fb 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73218,23 +73218,20 @@ const semver = __importStar(__nccwpck_require__(5911)); const fs_1 = __importDefault(__nccwpck_require__(7147)); var Distributions; (function (Distributions) { - Distributions[Distributions["DEFAULT"] = 0] = "DEFAULT"; - Distributions[Distributions["CANARY"] = 1] = "CANARY"; - Distributions[Distributions["NIGHTLY"] = 2] = "NIGHTLY"; - Distributions[Distributions["RC"] = 3] = "RC"; + Distributions["DEFAULT"] = "default"; + Distributions["CANARY"] = "v8-canary"; + Distributions["NIGHTLY"] = "nightly"; + Distributions["RC"] = "rc"; })(Distributions = exports.Distributions || (exports.Distributions = {})); -exports.distributionOf = (versionSpec) => versionSpec.includes('-v8-canary') - ? Distributions.CANARY - : // TODO: i'd like to have this check, do you? - versionSpec.includes('-canary') - ? (() => { - throw Error('Canary version must have "-v8-canary suffix"'); - })() - : versionSpec.includes('nightly') - ? Distributions.NIGHTLY - : semver.prerelease(versionSpec) - ? Distributions.RC - : Distributions.DEFAULT; +exports.distributionOf = (versionSpec) => { + if (versionSpec.includes('-v8-canary')) + return Distributions.CANARY; + if (versionSpec.includes('nightly')) + return Distributions.NIGHTLY; + if (semver.prerelease(versionSpec)) + return Distributions.RC; + return Distributions.DEFAULT; +}; exports.semverVersionMatcherFactory = (range) => { const matcher = (potential) => semver.satisfies(potential, range); matcher.factory = exports.semverVersionMatcherFactory; @@ -73325,17 +73322,20 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arc manifest = yield getManifest(auth); versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } - // TODO: 183-189 and 193-194 seems to be the same. Why do we need them? - if (isLatestSyntax(versionSpec) || distribution == Distributions.CANARY) { + if (isLatestSyntax(versionSpec)) { nodeVersions = yield getVersionsFromDist(versionSpec); versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); - core.info(`getting ${distribution == Distributions.CANARY ? 'v8-canary' : 'latest'} node version ${versionSpec}...`); + core.info(`getting latest node version ${versionSpec}...`); } - if (distribution === Distributions.NIGHTLY && checkLatest) { + if ((distribution === Distributions.NIGHTLY || + distribution === Distributions.CANARY) && + checkLatest) { nodeVersions = yield getVersionsFromDist(versionSpec); versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); } - if (checkLatest && distribution !== Distributions.NIGHTLY) { + if (checkLatest && + distribution !== Distributions.NIGHTLY && + distribution !== Distributions.CANARY) { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = yield resolveVersionFromManifest(versionSpec, stable, auth, osArch, manifest); if (resolvedVersion) { @@ -73347,7 +73347,6 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arc } } // check cache - core.info('Attempt to find existing version in cache...'); let toolPath; if (distribution === Distributions.DEFAULT) { toolPath = tc.find('node', versionSpec, osArch); @@ -73562,13 +73561,10 @@ exports.evaluateVersions = evaluateVersions; function getNodejsDistUrl(version) { switch (exports.distributionOf(version)) { case Distributions.CANARY: - core.debug('requested v8 canary distribution'); return 'https://nodejs.org/download/v8-canary'; case Distributions.NIGHTLY: - core.debug('requested nightly distribution'); return 'https://nodejs.org/download/nightly'; case Distributions.RC: - core.debug('requested release candidates distribution'); return 'https://nodejs.org/download/rc'; case Distributions.DEFAULT: return 'https://nodejs.org/dist'; @@ -73602,7 +73598,7 @@ function queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions core.info(`getting latest node version...`); return nodeVersions[0].version; } - let versions = []; + const versions = []; nodeVersions.forEach((nodeVersion) => { // ensure this version supports your os and platform if (nodeVersion.files.indexOf(dataFileName) >= 0) { @@ -73610,7 +73606,8 @@ function queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions } }); // get the latest version that matches the version spec - return evaluateVersions(versions, versionSpec); + const version = evaluateVersions(versions, versionSpec); + return version; }); } exports.queryDistForMatch = queryDistForMatch; diff --git a/src/installer.ts b/src/installer.ts index e3c4df473..c3dc349ff 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -31,25 +31,18 @@ interface INodeRelease extends tc.IToolRelease { } export enum Distributions { - DEFAULT, - CANARY, - NIGHTLY, - RC + DEFAULT = 'default', + CANARY = 'v8-canary', + NIGHTLY = 'nightly', + RC = 'rc' } -export const distributionOf = (versionSpec: string): Distributions => - versionSpec.includes('-v8-canary') - ? Distributions.CANARY - : // TODO: i'd like to have this check, do you? - versionSpec.includes('-canary') - ? (() => { - throw Error('Canary version must have "-v8-canary suffix"'); - })() - : versionSpec.includes('nightly') - ? Distributions.NIGHTLY - : semver.prerelease(versionSpec) - ? Distributions.RC - : Distributions.DEFAULT; +export const distributionOf = (versionSpec: string): Distributions => { + if (versionSpec.includes('-v8-canary')) return Distributions.CANARY; + if (versionSpec.includes('nightly')) return Distributions.NIGHTLY; + if (semver.prerelease(versionSpec)) return Distributions.RC; + return Distributions.DEFAULT; +}; interface VersionMatcher { (potential: string): boolean; @@ -190,23 +183,26 @@ export async function getNode( versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } - // TODO: 183-189 and 193-194 seems to be the same. Why do we need them? - if (isLatestSyntax(versionSpec) || distribution == Distributions.CANARY) { + if (isLatestSyntax(versionSpec)) { nodeVersions = await getVersionsFromDist(versionSpec); versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); - core.info( - `getting ${ - distribution == Distributions.CANARY ? 'v8-canary' : 'latest' - } node version ${versionSpec}...` - ); + core.info(`getting latest node version ${versionSpec}...`); } - if (distribution === Distributions.NIGHTLY && checkLatest) { + if ( + (distribution === Distributions.NIGHTLY || + distribution === Distributions.CANARY) && + checkLatest + ) { nodeVersions = await getVersionsFromDist(versionSpec); versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); } - if (checkLatest && distribution !== Distributions.NIGHTLY) { + if ( + checkLatest && + distribution !== Distributions.NIGHTLY && + distribution !== Distributions.CANARY + ) { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = await resolveVersionFromManifest( versionSpec, @@ -224,7 +220,6 @@ export async function getNode( } // check cache - core.info('Attempt to find existing version in cache...'); let toolPath: string; if (distribution === Distributions.DEFAULT) { toolPath = tc.find('node', versionSpec, osArch); @@ -521,13 +516,10 @@ export function evaluateVersions( export function getNodejsDistUrl(version: string) { switch (distributionOf(version)) { case Distributions.CANARY: - core.debug('requested v8 canary distribution'); return 'https://nodejs.org/download/v8-canary'; case Distributions.NIGHTLY: - core.debug('requested nightly distribution'); return 'https://nodejs.org/download/nightly'; case Distributions.RC: - core.debug('requested release candidates distribution'); return 'https://nodejs.org/download/rc'; case Distributions.DEFAULT: return 'https://nodejs.org/dist'; @@ -568,7 +560,7 @@ export async function queryDistForMatch( return nodeVersions[0].version; } - let versions: string[] = []; + const versions: string[] = []; nodeVersions.forEach((nodeVersion: INodeVersion) => { // ensure this version supports your os and platform if (nodeVersion.files.indexOf(dataFileName) >= 0) { @@ -577,7 +569,8 @@ export async function queryDistForMatch( }); // get the latest version that matches the version spec - return evaluateVersions(versions, versionSpec); + const version = evaluateVersions(versions, versionSpec); + return version; } export async function getVersionsFromDist( From d8923d1f9d5d11f347df63c2770cbc06ff09d802 Mon Sep 17 00:00:00 2001 From: Sergey Dolin Date: Fri, 25 Nov 2022 09:44:05 +0100 Subject: [PATCH 19/51] remove v20.0.0 from workflow check --- .github/workflows/versions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index 6dd6f646a..1482ae289 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -57,7 +57,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: ['20-v8-canary', '20.0-v8-canary', '20.0.0-v8-canary','20.0.0-v8-canary20221103f7e2421e91'] + node-version: ['20-v8-canary', '20.0.0-v8-canary','20.0.0-v8-canary20221103f7e2421e91'] steps: - uses: actions/checkout@v3 - name: Setup Node From c849fe68249ef8cad2991ad052e78d20edbbf79c Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 29 Nov 2022 16:06:13 +0100 Subject: [PATCH 20/51] convert logic initial --- dist/setup/index.js | 87 +++++++++++++----------------- src/installer.ts | 126 ++++++++++++++++++++------------------------ 2 files changed, 95 insertions(+), 118 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 2d4f882fb..80f0f8f0e 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73218,93 +73218,80 @@ const semver = __importStar(__nccwpck_require__(5911)); const fs_1 = __importDefault(__nccwpck_require__(7147)); var Distributions; (function (Distributions) { - Distributions["DEFAULT"] = "default"; - Distributions["CANARY"] = "v8-canary"; - Distributions["NIGHTLY"] = "nightly"; - Distributions["RC"] = "rc"; + Distributions["DEFAULT"] = ""; + Distributions["CANARY"] = "-v8-canary"; + Distributions["NIGHTLY"] = "-nightly"; + Distributions["RC"] = "-rc"; })(Distributions = exports.Distributions || (exports.Distributions = {})); exports.distributionOf = (versionSpec) => { - if (versionSpec.includes('-v8-canary')) + if (versionSpec.includes(Distributions.CANARY)) return Distributions.CANARY; - if (versionSpec.includes('nightly')) + if (versionSpec.includes(Distributions.NIGHTLY)) return Distributions.NIGHTLY; if (semver.prerelease(versionSpec)) return Distributions.RC; return Distributions.DEFAULT; }; exports.semverVersionMatcherFactory = (range) => { - const matcher = (potential) => semver.satisfies(potential, range); + const matcher = (potential) => { + core.debug(`potential is ${potential}`); + return semver.satisfies(potential, range); + }; + core.debug(`range is ${range}`); matcher.factory = exports.semverVersionMatcherFactory; return matcher; }; exports.canaryRangeVersionMatcherFactory = (version) => { - const range = semver.validRange(`^${version}`); - const matcher = (potential) => semver.satisfies(potential.replace('-v8-canary', '+v8-canary.'), range); + const { range, includePrerelease } = createRangePreRelease(version, Distributions.CANARY); + const matcher = (potential) => semver.satisfies(potential.replace(Distributions.CANARY, `${Distributions.CANARY}.`), range, { includePrerelease: includePrerelease }); matcher.factory = exports.canaryRangeVersionMatcherFactory; return matcher; }; -exports.canaryExactVersionMatcherFactory = (version, timestamp) => { - const range = `${version}-${timestamp}`; - const matcher = (potential) => semver.satisfies(potential, range); - matcher.factory = exports.canaryExactVersionMatcherFactory; - return matcher; -}; exports.nightlyRangeVersionMatcherFactory = (version) => { - const range = semver.validRange(`^${version}`); - // TODO: this makes v20.1.1-nightly to do not match v20.1.1-nightly20221103f7e2421e91 - // const range = `${semver.validRange(`^${version}-0`)}-0`; + const { range, includePrerelease } = createRangePreRelease(version, Distributions.NIGHTLY); const matcher = (potential) => exports.distributionOf(potential) === Distributions.NIGHTLY && - // TODO: dmitry's variant was potential.replace('-nightly', '-nightly.') that made - // all unit tests to fail - semver.satisfies(potential.replace('-nightly', '+nightly.'), range /*, { - // TODO: what is for? - includePrerelease: true - }*/); + semver.satisfies(potential.replace(Distributions.NIGHTLY, `${Distributions.NIGHTLY}.`), range, { includePrerelease: includePrerelease }); matcher.factory = exports.nightlyRangeVersionMatcherFactory; return matcher; }; -exports.nightlyExactVersionMatcherFactory = (version, timestamp) => { - const range = `${version}-${timestamp.replace('nightly', 'nightly.')}`; - const matcher = (potential) => exports.distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies(potential.replace('-nightly', '-nightly.'), range /*, { - // TODO: what is for? - includePrerelease: true - }*/); - matcher.factory = exports.nightlyExactVersionMatcherFactory; - return matcher; -}; -const alwaysFalseVersionMatcherFactory = () => { - const matcher = () => false; - matcher.factory = alwaysFalseVersionMatcherFactory; - return matcher; -}; -const alwaysFalseVersionMatcher = alwaysFalseVersionMatcherFactory(); // [raw, prerelease] exports.splitVersionSpec = (versionSpec) => versionSpec.split(/-(.*)/s); +const createRangePreRelease = (versionSpec, preRelease = '') => { + let range; + const [raw, prerelease] = exports.splitVersionSpec(versionSpec); + const isValidVersion = semver.valid(raw); + const rawVersion = isValidVersion ? raw : semver.coerce(raw); + if (rawVersion) { + if (`-${prerelease}` !== preRelease) { + core.debug(`came to full version ${preRelease}`); + range = `${rawVersion}${`-${prerelease}`.replace(preRelease, `${preRelease}.`)}`; + } + else { + core.debug('came to range version'); + range = `${semver.validRange(`^${rawVersion}${preRelease}`)}-0`; + } + } + core.debug(`prerelease is ${prerelease}, preRelease is ${preRelease}`); + core.debug(`Version Range for ${versionSpec} is ${range}`); + return { range, includePrerelease: !isValidVersion }; +}; function versionMatcherFactory(versionSpec) { var _a; - const [raw, prerelease] = exports.splitVersionSpec(versionSpec); + const raw = exports.splitVersionSpec(versionSpec)[0]; const validVersion = semver.valid(raw) ? raw : (_a = semver.coerce(raw)) === null || _a === void 0 ? void 0 : _a.version; if (validVersion) { switch (exports.distributionOf(versionSpec)) { case Distributions.CANARY: - return prerelease === 'v8-canary' // this means versionSpec does not have timestamp - ? exports.canaryRangeVersionMatcherFactory(validVersion) - : exports.canaryExactVersionMatcherFactory(validVersion, prerelease); + return exports.canaryRangeVersionMatcherFactory(versionSpec); case Distributions.NIGHTLY: - return prerelease === 'nightly' // this means versionSpec does not have prerelease tag - ? exports.nightlyRangeVersionMatcherFactory(validVersion) - : exports.nightlyExactVersionMatcherFactory(validVersion, prerelease); + return exports.nightlyRangeVersionMatcherFactory(versionSpec); case Distributions.RC: case Distributions.DEFAULT: return exports.semverVersionMatcherFactory(versionSpec); } } else { - // TODO: i prefer to have implicit exception for the malformed input throw Error(`Invalid version input "${versionSpec}"`); - // TODO: but it is possible to silently fail - // return alwaysFalseVersionMatcher } } exports.versionMatcherFactory = versionMatcherFactory; diff --git a/src/installer.ts b/src/installer.ts index c3dc349ff..5e1fc2cc3 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -13,6 +13,7 @@ import fs from 'fs'; // 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 +// for canary https://nodejs.org/download/v8-canary/index.json // export interface INodeVersion { version: string; @@ -31,15 +32,15 @@ interface INodeRelease extends tc.IToolRelease { } export enum Distributions { - DEFAULT = 'default', - CANARY = 'v8-canary', - NIGHTLY = 'nightly', - RC = 'rc' + DEFAULT = '', + CANARY = '-v8-canary', + NIGHTLY = '-nightly', + RC = '-rc' } export const distributionOf = (versionSpec: string): Distributions => { - if (versionSpec.includes('-v8-canary')) return Distributions.CANARY; - if (versionSpec.includes('nightly')) return Distributions.NIGHTLY; + if (versionSpec.includes(Distributions.CANARY)) return Distributions.CANARY; + if (versionSpec.includes(Distributions.NIGHTLY)) return Distributions.NIGHTLY; if (semver.prerelease(versionSpec)) return Distributions.RC; return Distributions.DEFAULT; }; @@ -55,8 +56,11 @@ interface VersionMatcher { } export const semverVersionMatcherFactory = (range: string): VersionMatcher => { - const matcher = (potential: string): boolean => - semver.satisfies(potential, range); + const matcher = (potential: string): boolean =>{ + core.debug(`potential is ${potential}`) + return semver.satisfies(potential, range); + } + core.debug(`range is ${range}`); matcher.factory = semverVersionMatcherFactory; return matcher; }; @@ -64,99 +68,85 @@ export const semverVersionMatcherFactory = (range: string): VersionMatcher => { export const canaryRangeVersionMatcherFactory = ( version: string ): VersionMatcher => { - const range = semver.validRange(`^${version}`); + const {range, includePrerelease} = createRangePreRelease( + version, + Distributions.CANARY + )!; const matcher = (potential: string): boolean => - semver.satisfies(potential.replace('-v8-canary', '+v8-canary.'), range); + semver.satisfies( + potential.replace(Distributions.CANARY, `${Distributions.CANARY}.`), + range!, + {includePrerelease: includePrerelease} + ); matcher.factory = canaryRangeVersionMatcherFactory; return matcher; }; -export const canaryExactVersionMatcherFactory = ( - version: string, - timestamp: string -): VersionMatcher => { - const range = `${version}-${timestamp}`; - const matcher = (potential: string): boolean => - semver.satisfies(potential, range); - matcher.factory = canaryExactVersionMatcherFactory; - return matcher; -}; - export const nightlyRangeVersionMatcherFactory = ( version: string ): VersionMatcher => { - const range = semver.validRange(`^${version}`); - // TODO: this makes v20.1.1-nightly to do not match v20.1.1-nightly20221103f7e2421e91 - // const range = `${semver.validRange(`^${version}-0`)}-0`; + const {range, includePrerelease} = createRangePreRelease( + version, + Distributions.NIGHTLY + )!; const matcher = (potential: string): boolean => distributionOf(potential) === Distributions.NIGHTLY && - // TODO: dmitry's variant was potential.replace('-nightly', '-nightly.') that made - // all unit tests to fail semver.satisfies( - potential.replace('-nightly', '+nightly.'), - range /*, { - // TODO: what is for? - includePrerelease: true - }*/ + potential.replace(Distributions.NIGHTLY, `${Distributions.NIGHTLY}.`), + range!, + {includePrerelease: includePrerelease} ); matcher.factory = nightlyRangeVersionMatcherFactory; return matcher; }; -export const nightlyExactVersionMatcherFactory = ( - version: string, - timestamp: string -): VersionMatcher => { - const range = `${version}-${timestamp.replace('nightly', 'nightly.')}`; - const matcher = (potential: string): boolean => - distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies( - potential.replace('-nightly', '-nightly.'), - range /*, { - // TODO: what is for? - includePrerelease: true - }*/ - ); - matcher.factory = nightlyExactVersionMatcherFactory; - return matcher; -}; - -const alwaysFalseVersionMatcherFactory = (): VersionMatcher => { - const matcher = () => false; - matcher.factory = alwaysFalseVersionMatcherFactory; - return matcher; -}; - -const alwaysFalseVersionMatcher = alwaysFalseVersionMatcherFactory(); - // [raw, prerelease] export const splitVersionSpec = (versionSpec: string): string[] => versionSpec.split(/-(.*)/s); -export function versionMatcherFactory(versionSpec: string): VersionMatcher { +const createRangePreRelease = ( + versionSpec: string, + preRelease: string = '' +) => { + let range: string | undefined; const [raw, prerelease] = splitVersionSpec(versionSpec); + const isValidVersion = semver.valid(raw); + const rawVersion = isValidVersion ? raw : semver.coerce(raw); + + if (rawVersion) { + if (`-${prerelease}` !== preRelease) { + core.debug(`came to full version ${preRelease}`); + range = `${rawVersion}${`-${prerelease}`.replace( + preRelease, + `${preRelease}.` + )}`; + } else { + core.debug('came to range version'); + range = `${semver.validRange(`^${rawVersion}${preRelease}`)}-0`; + } + } + core.debug(`prerelease is ${prerelease}, preRelease is ${preRelease}`); + core.debug(`Version Range for ${versionSpec} is ${range}`); + + return {range, includePrerelease: !isValidVersion}; +}; + +export function versionMatcherFactory(versionSpec: string): VersionMatcher { + const raw = splitVersionSpec(versionSpec)[0]; const validVersion = semver.valid(raw) ? raw : semver.coerce(raw)?.version; if (validVersion) { switch (distributionOf(versionSpec)) { case Distributions.CANARY: - return prerelease === 'v8-canary' // this means versionSpec does not have timestamp - ? canaryRangeVersionMatcherFactory(validVersion) - : canaryExactVersionMatcherFactory(validVersion, prerelease); + return canaryRangeVersionMatcherFactory(versionSpec); case Distributions.NIGHTLY: - return prerelease === 'nightly' // this means versionSpec does not have prerelease tag - ? nightlyRangeVersionMatcherFactory(validVersion) - : nightlyExactVersionMatcherFactory(validVersion, prerelease); + return nightlyRangeVersionMatcherFactory(versionSpec); case Distributions.RC: case Distributions.DEFAULT: return semverVersionMatcherFactory(versionSpec); } } else { - // TODO: i prefer to have implicit exception for the malformed input throw Error(`Invalid version input "${versionSpec}"`); - - // TODO: but it is possible to silently fail - // return alwaysFalseVersionMatcher } } From e25fd13757c25a111a5eea56327baa391dc9b925 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 29 Nov 2022 16:14:33 +0100 Subject: [PATCH 21/51] comment code --- dist/setup/index.js | 46 +++++++++++++++++--------------- src/installer.ts | 65 +++++++++++++++++++++++---------------------- 2 files changed, 57 insertions(+), 54 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 80f0f8f0e..d2061e7d1 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73233,28 +73233,33 @@ exports.distributionOf = (versionSpec) => { return Distributions.DEFAULT; }; exports.semverVersionMatcherFactory = (range) => { - const matcher = (potential) => { - core.debug(`potential is ${potential}`); - return semver.satisfies(potential, range); - }; - core.debug(`range is ${range}`); + const matcher = (potential) => semver.satisfies(potential, range); matcher.factory = exports.semverVersionMatcherFactory; return matcher; }; -exports.canaryRangeVersionMatcherFactory = (version) => { - const { range, includePrerelease } = createRangePreRelease(version, Distributions.CANARY); - const matcher = (potential) => semver.satisfies(potential.replace(Distributions.CANARY, `${Distributions.CANARY}.`), range, { includePrerelease: includePrerelease }); - matcher.factory = exports.canaryRangeVersionMatcherFactory; - return matcher; -}; -exports.nightlyRangeVersionMatcherFactory = (version) => { - const { range, includePrerelease } = createRangePreRelease(version, Distributions.NIGHTLY); - const matcher = (potential) => exports.distributionOf(potential) === Distributions.NIGHTLY && - semver.satisfies(potential.replace(Distributions.NIGHTLY, `${Distributions.NIGHTLY}.`), range, { includePrerelease: includePrerelease }); +// export const canaryRangeVersionMatcherFactory = ( +// version: string +// ): VersionMatcher => { +// const {range, includePrerelease} = createRangePreRelease( +// version, +// Distributions.CANARY +// )!; +// const matcher = (potential: string): boolean => +// semver.satisfies( +// potential.replace(Distributions.CANARY, `${Distributions.CANARY}.`), +// range!, +// {includePrerelease: includePrerelease} +// ); +// matcher.factory = canaryRangeVersionMatcherFactory; +// return matcher; +// }; +exports.nightlyRangeVersionMatcherFactory = (version, distribution) => { + const { range, includePrerelease } = createRangePreRelease(version, distribution); + const matcher = (potential) => exports.distributionOf(potential) === distribution && + semver.satisfies(potential.replace(distribution, `${distribution}.`), range, { includePrerelease: includePrerelease }); matcher.factory = exports.nightlyRangeVersionMatcherFactory; return matcher; }; -// [raw, prerelease] exports.splitVersionSpec = (versionSpec) => versionSpec.split(/-(.*)/s); const createRangePreRelease = (versionSpec, preRelease = '') => { let range; @@ -73263,16 +73268,12 @@ const createRangePreRelease = (versionSpec, preRelease = '') => { const rawVersion = isValidVersion ? raw : semver.coerce(raw); if (rawVersion) { if (`-${prerelease}` !== preRelease) { - core.debug(`came to full version ${preRelease}`); range = `${rawVersion}${`-${prerelease}`.replace(preRelease, `${preRelease}.`)}`; } else { - core.debug('came to range version'); range = `${semver.validRange(`^${rawVersion}${preRelease}`)}-0`; } } - core.debug(`prerelease is ${prerelease}, preRelease is ${preRelease}`); - core.debug(`Version Range for ${versionSpec} is ${range}`); return { range, includePrerelease: !isValidVersion }; }; function versionMatcherFactory(versionSpec) { @@ -73282,9 +73283,10 @@ function versionMatcherFactory(versionSpec) { if (validVersion) { switch (exports.distributionOf(versionSpec)) { case Distributions.CANARY: - return exports.canaryRangeVersionMatcherFactory(versionSpec); case Distributions.NIGHTLY: - return exports.nightlyRangeVersionMatcherFactory(versionSpec); + return exports.nightlyRangeVersionMatcherFactory(versionSpec, Distributions.CANARY); + case Distributions.NIGHTLY: + return exports.nightlyRangeVersionMatcherFactory(versionSpec, Distributions.NIGHTLY); case Distributions.RC: case Distributions.DEFAULT: return exports.semverVersionMatcherFactory(versionSpec); diff --git a/src/installer.ts b/src/installer.ts index 5e1fc2cc3..7049b538d 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -56,43 +56,42 @@ interface VersionMatcher { } export const semverVersionMatcherFactory = (range: string): VersionMatcher => { - const matcher = (potential: string): boolean =>{ - core.debug(`potential is ${potential}`) - return semver.satisfies(potential, range); - } - core.debug(`range is ${range}`); + const matcher = (potential: string): boolean => + semver.satisfies(potential, range); + matcher.factory = semverVersionMatcherFactory; return matcher; }; -export const canaryRangeVersionMatcherFactory = ( - version: string -): VersionMatcher => { - const {range, includePrerelease} = createRangePreRelease( - version, - Distributions.CANARY - )!; - const matcher = (potential: string): boolean => - semver.satisfies( - potential.replace(Distributions.CANARY, `${Distributions.CANARY}.`), - range!, - {includePrerelease: includePrerelease} - ); - matcher.factory = canaryRangeVersionMatcherFactory; - return matcher; -}; +// export const canaryRangeVersionMatcherFactory = ( +// version: string +// ): VersionMatcher => { +// const {range, includePrerelease} = createRangePreRelease( +// version, +// Distributions.CANARY +// )!; +// const matcher = (potential: string): boolean => +// semver.satisfies( +// potential.replace(Distributions.CANARY, `${Distributions.CANARY}.`), +// range!, +// {includePrerelease: includePrerelease} +// ); +// matcher.factory = canaryRangeVersionMatcherFactory; +// return matcher; +// }; export const nightlyRangeVersionMatcherFactory = ( - version: string + version: string, + distribution: string ): VersionMatcher => { const {range, includePrerelease} = createRangePreRelease( version, - Distributions.NIGHTLY + distribution )!; const matcher = (potential: string): boolean => - distributionOf(potential) === Distributions.NIGHTLY && + distributionOf(potential) === distribution && semver.satisfies( - potential.replace(Distributions.NIGHTLY, `${Distributions.NIGHTLY}.`), + potential.replace(distribution, `${distribution}.`), range!, {includePrerelease: includePrerelease} ); @@ -100,7 +99,6 @@ export const nightlyRangeVersionMatcherFactory = ( return matcher; }; -// [raw, prerelease] export const splitVersionSpec = (versionSpec: string): string[] => versionSpec.split(/-(.*)/s); @@ -115,18 +113,14 @@ const createRangePreRelease = ( if (rawVersion) { if (`-${prerelease}` !== preRelease) { - core.debug(`came to full version ${preRelease}`); range = `${rawVersion}${`-${prerelease}`.replace( preRelease, `${preRelease}.` )}`; } else { - core.debug('came to range version'); range = `${semver.validRange(`^${rawVersion}${preRelease}`)}-0`; } } - core.debug(`prerelease is ${prerelease}, preRelease is ${preRelease}`); - core.debug(`Version Range for ${versionSpec} is ${range}`); return {range, includePrerelease: !isValidVersion}; }; @@ -138,9 +132,16 @@ export function versionMatcherFactory(versionSpec: string): VersionMatcher { if (validVersion) { switch (distributionOf(versionSpec)) { case Distributions.CANARY: - return canaryRangeVersionMatcherFactory(versionSpec); case Distributions.NIGHTLY: - return nightlyRangeVersionMatcherFactory(versionSpec); + return nightlyRangeVersionMatcherFactory( + versionSpec, + Distributions.CANARY + ); + case Distributions.NIGHTLY: + return nightlyRangeVersionMatcherFactory( + versionSpec, + Distributions.NIGHTLY + ); case Distributions.RC: case Distributions.DEFAULT: return semverVersionMatcherFactory(versionSpec); From 3533caf801cfa60263878fc6ad3b17ce6d3c8647 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 29 Nov 2022 16:25:39 +0100 Subject: [PATCH 22/51] remove case for Nightly --- dist/setup/index.js | 1 - src/installer.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index d2061e7d1..b0c6cbcd9 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73283,7 +73283,6 @@ function versionMatcherFactory(versionSpec) { if (validVersion) { switch (exports.distributionOf(versionSpec)) { case Distributions.CANARY: - case Distributions.NIGHTLY: return exports.nightlyRangeVersionMatcherFactory(versionSpec, Distributions.CANARY); case Distributions.NIGHTLY: return exports.nightlyRangeVersionMatcherFactory(versionSpec, Distributions.NIGHTLY); diff --git a/src/installer.ts b/src/installer.ts index 7049b538d..238337a55 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -132,7 +132,6 @@ export function versionMatcherFactory(versionSpec: string): VersionMatcher { if (validVersion) { switch (distributionOf(versionSpec)) { case Distributions.CANARY: - case Distributions.NIGHTLY: return nightlyRangeVersionMatcherFactory( versionSpec, Distributions.CANARY From b3720569394241a2be1c3e05fb25874bdfe561ce Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 29 Nov 2022 16:31:20 +0100 Subject: [PATCH 23/51] remove unused code --- dist/setup/index.js | 24 ++++-------------------- src/installer.ts | 25 ++++--------------------- 2 files changed, 8 insertions(+), 41 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index b0c6cbcd9..912c7c584 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73237,27 +73237,11 @@ exports.semverVersionMatcherFactory = (range) => { matcher.factory = exports.semverVersionMatcherFactory; return matcher; }; -// export const canaryRangeVersionMatcherFactory = ( -// version: string -// ): VersionMatcher => { -// const {range, includePrerelease} = createRangePreRelease( -// version, -// Distributions.CANARY -// )!; -// const matcher = (potential: string): boolean => -// semver.satisfies( -// potential.replace(Distributions.CANARY, `${Distributions.CANARY}.`), -// range!, -// {includePrerelease: includePrerelease} -// ); -// matcher.factory = canaryRangeVersionMatcherFactory; -// return matcher; -// }; -exports.nightlyRangeVersionMatcherFactory = (version, distribution) => { +exports.nightlyV8MatcherFactory = (version, distribution) => { const { range, includePrerelease } = createRangePreRelease(version, distribution); const matcher = (potential) => exports.distributionOf(potential) === distribution && semver.satisfies(potential.replace(distribution, `${distribution}.`), range, { includePrerelease: includePrerelease }); - matcher.factory = exports.nightlyRangeVersionMatcherFactory; + matcher.factory = exports.nightlyV8MatcherFactory; return matcher; }; exports.splitVersionSpec = (versionSpec) => versionSpec.split(/-(.*)/s); @@ -73283,9 +73267,9 @@ function versionMatcherFactory(versionSpec) { if (validVersion) { switch (exports.distributionOf(versionSpec)) { case Distributions.CANARY: - return exports.nightlyRangeVersionMatcherFactory(versionSpec, Distributions.CANARY); + return exports.nightlyV8MatcherFactory(versionSpec, Distributions.CANARY); case Distributions.NIGHTLY: - return exports.nightlyRangeVersionMatcherFactory(versionSpec, Distributions.NIGHTLY); + return exports.nightlyV8MatcherFactory(versionSpec, Distributions.NIGHTLY); case Distributions.RC: case Distributions.DEFAULT: return exports.semverVersionMatcherFactory(versionSpec); diff --git a/src/installer.ts b/src/installer.ts index 238337a55..50d89921b 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -63,24 +63,7 @@ export const semverVersionMatcherFactory = (range: string): VersionMatcher => { return matcher; }; -// export const canaryRangeVersionMatcherFactory = ( -// version: string -// ): VersionMatcher => { -// const {range, includePrerelease} = createRangePreRelease( -// version, -// Distributions.CANARY -// )!; -// const matcher = (potential: string): boolean => -// semver.satisfies( -// potential.replace(Distributions.CANARY, `${Distributions.CANARY}.`), -// range!, -// {includePrerelease: includePrerelease} -// ); -// matcher.factory = canaryRangeVersionMatcherFactory; -// return matcher; -// }; - -export const nightlyRangeVersionMatcherFactory = ( +export const nightlyV8MatcherFactory = ( version: string, distribution: string ): VersionMatcher => { @@ -95,7 +78,7 @@ export const nightlyRangeVersionMatcherFactory = ( range!, {includePrerelease: includePrerelease} ); - matcher.factory = nightlyRangeVersionMatcherFactory; + matcher.factory = nightlyV8MatcherFactory; return matcher; }; @@ -132,12 +115,12 @@ export function versionMatcherFactory(versionSpec: string): VersionMatcher { if (validVersion) { switch (distributionOf(versionSpec)) { case Distributions.CANARY: - return nightlyRangeVersionMatcherFactory( + return nightlyV8MatcherFactory( versionSpec, Distributions.CANARY ); case Distributions.NIGHTLY: - return nightlyRangeVersionMatcherFactory( + return nightlyV8MatcherFactory( versionSpec, Distributions.NIGHTLY ); From b717bf1b71931ecfc9fcd85912c79bc8c546b2a2 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Wed, 30 Nov 2022 11:48:41 +0100 Subject: [PATCH 24/51] remove if --- dist/setup/index.js | 22 ++++++++++------------ src/installer.ts | 34 +++++++++++++--------------------- 2 files changed, 23 insertions(+), 33 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 912c7c584..522ca2a32 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73245,18 +73245,16 @@ exports.nightlyV8MatcherFactory = (version, distribution) => { return matcher; }; exports.splitVersionSpec = (versionSpec) => versionSpec.split(/-(.*)/s); -const createRangePreRelease = (versionSpec, preRelease = '') => { +const createRangePreRelease = (versionSpec, distribution = '') => { let range; const [raw, prerelease] = exports.splitVersionSpec(versionSpec); const isValidVersion = semver.valid(raw); - const rawVersion = isValidVersion ? raw : semver.coerce(raw); - if (rawVersion) { - if (`-${prerelease}` !== preRelease) { - range = `${rawVersion}${`-${prerelease}`.replace(preRelease, `${preRelease}.`)}`; - } - else { - range = `${semver.validRange(`^${rawVersion}${preRelease}`)}-0`; - } + const rawVersion = (isValidVersion ? raw : semver.coerce(raw)); + if (`-${prerelease}` !== distribution) { + range = `${rawVersion}${`-${prerelease}`.replace(distribution, `${distribution}.`)}`; + } + else { + range = `${semver.validRange(`^${rawVersion}${distribution}`)}-0`; } return { range, includePrerelease: !isValidVersion }; }; @@ -73264,12 +73262,12 @@ function versionMatcherFactory(versionSpec) { var _a; const raw = exports.splitVersionSpec(versionSpec)[0]; const validVersion = semver.valid(raw) ? raw : (_a = semver.coerce(raw)) === null || _a === void 0 ? void 0 : _a.version; + const distribution = exports.distributionOf(versionSpec); if (validVersion) { - switch (exports.distributionOf(versionSpec)) { + switch (distribution) { case Distributions.CANARY: - return exports.nightlyV8MatcherFactory(versionSpec, Distributions.CANARY); case Distributions.NIGHTLY: - return exports.nightlyV8MatcherFactory(versionSpec, Distributions.NIGHTLY); + return exports.nightlyV8MatcherFactory(versionSpec, distribution); case Distributions.RC: case Distributions.DEFAULT: return exports.semverVersionMatcherFactory(versionSpec); diff --git a/src/installer.ts b/src/installer.ts index 50d89921b..ffee7dd5e 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -87,22 +87,20 @@ export const splitVersionSpec = (versionSpec: string): string[] => const createRangePreRelease = ( versionSpec: string, - preRelease: string = '' + distribution: string = '' ) => { let range: string | undefined; const [raw, prerelease] = splitVersionSpec(versionSpec); const isValidVersion = semver.valid(raw); - const rawVersion = isValidVersion ? raw : semver.coerce(raw); - - if (rawVersion) { - if (`-${prerelease}` !== preRelease) { - range = `${rawVersion}${`-${prerelease}`.replace( - preRelease, - `${preRelease}.` - )}`; - } else { - range = `${semver.validRange(`^${rawVersion}${preRelease}`)}-0`; - } + const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; + + if (`-${prerelease}` !== distribution) { + range = `${rawVersion}${`-${prerelease}`.replace( + distribution, + `${distribution}.` + )}`; + } else { + range = `${semver.validRange(`^${rawVersion}${distribution}`)}-0`; } return {range, includePrerelease: !isValidVersion}; @@ -111,19 +109,13 @@ const createRangePreRelease = ( export function versionMatcherFactory(versionSpec: string): VersionMatcher { const raw = splitVersionSpec(versionSpec)[0]; const validVersion = semver.valid(raw) ? raw : semver.coerce(raw)?.version; + const distribution = distributionOf(versionSpec); if (validVersion) { - switch (distributionOf(versionSpec)) { + switch (distribution) { case Distributions.CANARY: - return nightlyV8MatcherFactory( - versionSpec, - Distributions.CANARY - ); case Distributions.NIGHTLY: - return nightlyV8MatcherFactory( - versionSpec, - Distributions.NIGHTLY - ); + return nightlyV8MatcherFactory(versionSpec, distribution); case Distributions.RC: case Distributions.DEFAULT: return semverVersionMatcherFactory(versionSpec); From 40b42f047efece6eaa1e39f1c11f7d6b5319ae64 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 10:09:39 +0100 Subject: [PATCH 25/51] initial changes --- dist/setup/index.js | 734 +++++++++++++++++- src/distibutions/base-distribution.ts | 221 ++++++ src/distibutions/base-models.ts | 18 + src/distibutions/installer-factory.ts | 46 ++ src/distibutions/nightly/nightly_builds.ts | 77 ++ .../official_builds/official_builds.ts | 273 +++++++ .../official_builds/rc/rc_builds.ts | 50 ++ src/distibutions/v8-canary/canary_builds.ts | 75 ++ src/main.ts | 14 +- 9 files changed, 1506 insertions(+), 2 deletions(-) create mode 100644 src/distibutions/base-distribution.ts create mode 100644 src/distibutions/base-models.ts create mode 100644 src/distibutions/installer-factory.ts create mode 100644 src/distibutions/nightly/nightly_builds.ts create mode 100644 src/distibutions/official_builds/official_builds.ts create mode 100644 src/distibutions/official_builds/rc/rc_builds.ts create mode 100644 src/distibutions/v8-canary/canary_builds.ts diff --git a/dist/setup/index.js b/dist/setup/index.js index 522ca2a32..b78ec2887 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73180,6 +73180,727 @@ var Outputs; })(Outputs = exports.Outputs || (exports.Outputs = {})); +/***/ }), + +/***/ 8653: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +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) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + 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 })); +const tc = __importStar(__nccwpck_require__(7784)); +const hc = __importStar(__nccwpck_require__(9925)); +const core = __importStar(__nccwpck_require__(2186)); +const io = __importStar(__nccwpck_require__(7436)); +const semver_1 = __importDefault(__nccwpck_require__(5911)); +const assert = __importStar(__nccwpck_require__(9491)); +const path = __importStar(__nccwpck_require__(1017)); +const os = __importStar(__nccwpck_require__(2037)); +const fs_1 = __importDefault(__nccwpck_require__(7147)); +class BaseDistribution { + constructor(nodeInfo) { + this.nodeInfo = nodeInfo; + this.osPlat = os.platform(); + this.httpClient = new hc.HttpClient('setup-node', [], { + allowRetries: true, + maxRetries: 3 + }); + } + getNodeJsInfo() { + return __awaiter(this, void 0, void 0, function* () { + let toolPath = this.findVersionInHoostedToolCacheDirectory(); + if (!toolPath) { + const versions = yield this.getNodejsVersions(); + const evaluatedVersion = this.evaluateVersions(versions); + const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); + toolPath = yield this.downloadNodejs(toolName); + } + core.addPath(toolPath); + }); + } + findVersionInHoostedToolCacheDirectory() { + return tc.find('node', this.nodeInfo.versionSpec, this.nodeInfo.arch); + } + getNodejsDistInfo(version, osPlat) { + let osArch = this.translateArchToDistUrl(this.nodeInfo.arch); + version = semver_1.default.clean(version) || ''; + let fileName = osPlat == 'win32' + ? `node-v${version}-win-${osArch}` + : `node-v${version}-${osPlat}-${osArch}`; + let urlFileName = osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; + const initialUrl = this.getDistributionUrl(); + const url = `${initialUrl}/v${version}/${urlFileName}`; + return { + downloadUrl: url, + resolvedVersion: version, + arch: osArch, + fileName: fileName + }; + } + downloadNodejs(info) { + return __awaiter(this, void 0, void 0, function* () { + let osPlat = os.platform(); + let downloadPath = ''; + try { + downloadPath = yield tc.downloadTool(info.downloadUrl); + } + catch (err) { + if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { + return yield this.acquireNodeFromFallbackLocation(info.resolvedVersion, info.arch); + } + throw err; + } + let toolPath = yield this.extractArchive(downloadPath, info); + core.info('Done'); + if (osPlat != 'win32') { + toolPath = path.join(toolPath, 'bin'); + } + return toolPath; + }); + } + acquireNodeFromFallbackLocation(version, arch = os.arch()) { + return __awaiter(this, void 0, void 0, function* () { + const initialUrl = this.getDistributionUrl(); + let osArch = this.translateArchToDistUrl(arch); + // Create temporary folder to download in to + const tempDownloadFolder = 'temp_' + Math.floor(Math.random() * 2000000000); + const tempDirectory = process.env['RUNNER_TEMP'] || ''; + assert.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined'); + const tempDir = path.join(tempDirectory, tempDownloadFolder); + yield io.mkdirP(tempDir); + let exeUrl; + let libUrl; + 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 = yield tc.downloadTool(exeUrl); + yield io.cp(exePath, path.join(tempDir, 'node.exe')); + const libPath = yield tc.downloadTool(libUrl); + yield 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 = yield tc.downloadTool(exeUrl); + yield io.cp(exePath, path.join(tempDir, 'node.exe')); + const libPath = yield tc.downloadTool(libUrl); + yield io.cp(libPath, path.join(tempDir, 'node.lib')); + } + else { + throw err; + } + } + const toolPath = yield tc.cacheDir(tempDir, 'node', version, arch); + return toolPath; + }); + } + extractArchive(downloadPath, info) { + return __awaiter(this, void 0, void 0, function* () { + // + // Extract + // + core.info('Extracting ...'); + let extPath; + info = info || {}; // satisfy compiler, never null when reaches here + if (this.osPlat == 'win32') { + let _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe'); + extPath = yield tc.extract7z(downloadPath, undefined, _7zPath); + // 7z extracts to folder matching file name + let nestedPath = path.join(extPath, path.basename(info.fileName, '.7z')); + if (fs_1.default.existsSync(nestedPath)) { + extPath = nestedPath; + } + } + else { + extPath = yield 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 = yield tc.cacheDir(extPath, 'node', info.resolvedVersion, info.arch); + return toolPath; + }); + } + getDistFileName(arch = os.arch()) { + let osPlat = os.platform(); + let osArch = this.translateArchToDistUrl(arch); + // node offers a json list of versions + let dataFileName; + 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}'`); + } + return dataFileName; + } + filterVersions(nodeVersions) { + let versions = []; + const dataFileName = this.getDistFileName(this.nodeInfo.arch); + nodeVersions.forEach((nodeVersion) => { + // ensure this version supports your os and platform + if (nodeVersion.files.indexOf(dataFileName) >= 0) { + versions.push(nodeVersion.version); + } + }); + return versions.sort(semver_1.default.rcompare); + } + translateArchToDistUrl(arch) { + switch (arch) { + case 'arm': + return 'armv7l'; + default: + return arch; + } + } +} +exports["default"] = BaseDistribution; + + +/***/ }), + +/***/ 1260: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const nightly_builds_1 = __importDefault(__nccwpck_require__(1002)); +const official_builds_1 = __importDefault(__nccwpck_require__(9856)); +const rc_builds_1 = __importDefault(__nccwpck_require__(6235)); +const canary_builds_1 = __importDefault(__nccwpck_require__(4833)); +var Distributions; +(function (Distributions) { + Distributions["DEFAULT"] = ""; + Distributions["CANARY"] = "v8-canary"; + Distributions["NIGHTLY"] = "nightly"; + Distributions["RC"] = "rc"; +})(Distributions || (Distributions = {})); +function identifyDistribution(versionSpec) { + let distribution = ''; + if (versionSpec.includes(Distributions.NIGHTLY)) { + distribution = Distributions.NIGHTLY; + } + else if (versionSpec.includes(Distributions.CANARY)) { + distribution = Distributions.CANARY; + } + else if (versionSpec.includes(Distributions.RC)) { + distribution = Distributions.RC; + } + else { + distribution = Distributions.DEFAULT; + } + return distribution; +} +function getNodejsDistribution(installerOptions) { + const distributionName = identifyDistribution(installerOptions.versionSpec); + switch (distributionName) { + case Distributions.NIGHTLY: + return new nightly_builds_1.default(installerOptions); + case Distributions.CANARY: + return new canary_builds_1.default(installerOptions); + case Distributions.RC: + return new rc_builds_1.default(installerOptions); + case Distributions.DEFAULT: + return new official_builds_1.default(installerOptions); + default: + return null; + } +} +exports.getNodejsDistribution = getNodejsDistribution; + + +/***/ }), + +/***/ 1002: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +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) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + 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 })); +const core = __importStar(__nccwpck_require__(2186)); +const semver_1 = __importDefault(__nccwpck_require__(5911)); +const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); +class NightlyNodejs extends base_distribution_1.default { + constructor(nodeInfo) { + super(nodeInfo); + } + evaluateVersions(nodeVersions) { + let version = ''; + const versions = this.filterVersions(nodeVersions); + core.debug(`evaluating ${versions.length} versions`); + const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-nightly'); + for (let i = versions.length - 1; i >= 0; i--) { + const potential = versions[i]; + const satisfied = semver_1.default.satisfies(potential, range, { + includePrerelease: includePrerelease + }); + if (satisfied) { + version = potential; + break; + } + } + if (version) { + core.debug(`matched: ${version}`); + } + else { + core.debug('match not found'); + } + return version; + } + getDistributionUrl() { + return 'https://nodejs.org/download/nightly'; + } + getNodejsVersions() { + return __awaiter(this, void 0, void 0, function* () { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + let response = yield this.httpClient.getJson(dataUrl); + return response.result || []; + }); + } + createRangePreRelease(versionSpec, distribution = '') { + let range; + const [raw, prerelease] = this.splitVersionSpec(versionSpec); + const isValidVersion = semver_1.default.valid(raw); + const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); + if (`-${prerelease}` !== distribution) { + range = `${rawVersion}${`-${prerelease}`.replace(distribution, `${distribution}.`)}`; + } + else { + range = `${semver_1.default.validRange(`^${rawVersion}${distribution}`)}-0`; + } + return { range, includePrerelease: !isValidVersion }; + } + splitVersionSpec(versionSpec) { + return versionSpec.split(/-(.*)/s); + } +} +exports["default"] = NightlyNodejs; + + +/***/ }), + +/***/ 9856: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +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) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + 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 })); +const core = __importStar(__nccwpck_require__(2186)); +const tc = __importStar(__nccwpck_require__(7784)); +const semver = __importStar(__nccwpck_require__(5911)); +const os_1 = __importDefault(__nccwpck_require__(2037)); +const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); +class OfficialBuilds extends base_distribution_1.default { + constructor(nodeInfo) { + super(nodeInfo); + } + queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions) { + return __awaiter(this, void 0, void 0, function* () { + let osPlat = os_1.default.platform(); + let osArch = this.translateArchToDistUrl(arch); + // node offers a json list of versions + let dataFileName; + 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 (this.isLatestSyntax(versionSpec)) { + core.info(`getting latest node version...`); + return nodeVersions[0].version; + } + const versions = []; + nodeVersions.forEach((nodeVersion) => { + // 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 + const version = this.evaluateVersions(nodeVersions); + return version; + }); + } + getNodeJsInfo() { + return __awaiter(this, void 0, void 0, function* () { + let manifest = []; + let nodeVersions = []; + 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 = yield this.getManifest(); + this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest(this.nodeInfo.versionSpec, true, manifest); + } + if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { + nodeVersions = yield this.getNodejsVersions(); + this.nodeInfo.versionSpec = yield this.queryDistForMatch(this.nodeInfo.versionSpec, this.nodeInfo.arch, nodeVersions); + core.info(`getting latest node version...`); + } + let toolPath = this.findVersionInHoostedToolCacheDirectory(); + if (!toolPath) { + try { + const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, true, this.nodeInfo.auth, this.nodeInfo.arch, undefined); + if (versionInfo) { + core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`); + toolPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.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'); + } + const versions = yield this.getNodejsVersions(); + const evaluatedVersion = this.evaluateVersions(versions); + const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); + toolPath = yield this.downloadNodejs(toolName); + } + core.addPath(toolPath); + }); + } + evaluateVersions(nodeVersions) { + let version = ''; + const versions = this.filterVersions(nodeVersions); + if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { + core.info(`getting latest node version...`); + return versions[0]; + } + core.debug(`evaluating ${versions.length} versions`); + for (let i = versions.length - 1; i >= 0; i--) { + const potential = versions[i]; + const satisfied = semver.satisfies(potential, this.nodeInfo.versionSpec); + if (satisfied) { + version = potential; + break; + } + } + if (version) { + core.debug(`matched: ${version}`); + } + else { + core.debug('match not found'); + } + return version; + } + getDistributionUrl() { + return `https://nodejs.org/dist`; + } + getNodejsVersions() { + return __awaiter(this, void 0, void 0, function* () { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + let response = yield this.httpClient.getJson(dataUrl); + return response.result || []; + }); + } + getManifest() { + core.debug('Getting manifest from actions/node-versions@main'); + return tc.getManifestFromRepo('actions', 'node-versions', this.nodeInfo.auth, 'main'); + } + resolveLtsAliasFromManifest(versionSpec, stable, manifest) { + var _a; + const alias = (_a = versionSpec.split('lts/')[1]) === null || _a === void 0 ? void 0 : _a.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/`, `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]; + } + getInfoFromManifest(versionSpec, stable, auth, osArch = this.translateArchToDistUrl(os_1.default.arch()), manifest) { + return __awaiter(this, void 0, void 0, function* () { + let info = null; + if (!manifest) { + core.debug('No manifest cached'); + manifest = yield this.getManifest(); + } + const rel = yield tc.findFromManifest(versionSpec, stable, manifest, osArch); + if (rel && rel.files.length > 0) { + info = {}; + 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; + }); + } + isLtsAlias(versionSpec) { + return versionSpec.startsWith('lts/'); + } + isLatestSyntax(versionSpec) { + return ['current', 'latest', 'node'].includes(versionSpec); + } +} +exports["default"] = OfficialBuilds; + + +/***/ }), + +/***/ 6235: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +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) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + 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 })); +const core = __importStar(__nccwpck_require__(2186)); +const semver = __importStar(__nccwpck_require__(5911)); +const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); +class RcBuild extends base_distribution_1.default { + constructor(nodeInfo) { + super(nodeInfo); + } + getNodejsVersions() { + return __awaiter(this, void 0, void 0, function* () { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + let response = yield this.httpClient.getJson(dataUrl); + return response.result || []; + }); + } + evaluateVersions(nodeVersions) { + let version = ''; + const versions = this.filterVersions(nodeVersions); + core.debug(`evaluating ${versions.length} versions`); + for (let i = versions.length - 1; i >= 0; i--) { + const potential = versions[i]; + const satisfied = semver.satisfies(potential, this.nodeInfo.versionSpec); + if (satisfied) { + version = potential; + break; + } + } + if (version) { + core.debug(`matched: ${version}`); + } + else { + core.debug('match not found'); + } + return version; + } + getDistributionUrl() { + return 'https://nodejs.org/download/rc'; + } +} +exports["default"] = RcBuild; + + +/***/ }), + +/***/ 4833: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +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) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + 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 })); +const core = __importStar(__nccwpck_require__(2186)); +const semver_1 = __importDefault(__nccwpck_require__(5911)); +const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); +class CanaryBuild extends base_distribution_1.default { + evaluateVersions(nodeVersions) { + let version = ''; + const versions = this.filterVersions(nodeVersions); + core.debug(`evaluating ${versions.length} versions`); + const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-v8-canary'); + for (let i = versions.length - 1; i >= 0; i--) { + const potential = versions[i]; + const satisfied = semver_1.default.satisfies(potential, range, { + includePrerelease: includePrerelease + }); + if (satisfied) { + version = potential; + break; + } + } + if (version) { + core.debug(`matched: ${version}`); + } + else { + core.debug('match not found'); + } + return version; + } + constructor(nodeInfo) { + super(nodeInfo); + } + getDistributionUrl() { + return 'https://nodejs.org/download/v8-canary'; + } + getNodejsVersions() { + return __awaiter(this, void 0, void 0, function* () { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + let response = yield this.httpClient.getJson(dataUrl); + return response.result || []; + }); + } + createRangePreRelease(versionSpec, distribution = '') { + let range; + const [raw, prerelease] = this.splitVersionSpec(versionSpec); + const isValidVersion = semver_1.default.valid(raw); + const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); + if (`-${prerelease}` !== distribution) { + range = `${rawVersion}${`-${prerelease}`.replace(distribution, `${distribution}.`)}`; + } + else { + range = `${semver_1.default.validRange(`^${rawVersion}${distribution}`)}-0`; + } + return { range, includePrerelease: !isValidVersion }; + } + splitVersionSpec(versionSpec) { + return versionSpec.split(/-(.*)/s); + } +} +exports["default"] = CanaryBuild; + + /***/ }), /***/ 2574: @@ -73724,6 +74445,7 @@ const path = __importStar(__nccwpck_require__(1017)); const cache_restore_1 = __nccwpck_require__(9517); const cache_utils_1 = __nccwpck_require__(1678); const os_1 = __importDefault(__nccwpck_require__(2037)); +const installer_factory_1 = __nccwpck_require__(1260); function run() { return __awaiter(this, void 0, void 0, function* () { try { @@ -73747,7 +74469,17 @@ function run() { const auth = !token ? undefined : `token ${token}`; const stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; - yield installer.getNode(version, stable, checkLatest, auth, arch); + const nodejsInfo = { + versionSpec: version, + checkLatest: checkLatest, + auth, + arch: arch + }; + const nodeDistribution = installer_factory_1.getNodejsDistribution(nodejsInfo); + if (nodeDistribution) { + yield (nodeDistribution === null || nodeDistribution === void 0 ? void 0 : nodeDistribution.getNodeJsInfo()); + } + // await installer.getNode(version, stable, checkLatest, auth, arch); } yield printEnvDetailsAndSetOutput(); const registryUrl = core.getInput('registry-url'); diff --git a/src/distibutions/base-distribution.ts b/src/distibutions/base-distribution.ts new file mode 100644 index 000000000..f61e6831d --- /dev/null +++ b/src/distibutions/base-distribution.ts @@ -0,0 +1,221 @@ +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 * as os from 'os'; +import fs from 'fs'; + +import {INodejs, INodeVersion, INodeVersionInfo} from './base-models'; + +export default abstract class BaseDistribution { + protected httpClient: hc.HttpClient; + protected osPlat = os.platform(); + + constructor(protected nodeInfo: INodejs) { + this.httpClient = new hc.HttpClient('setup-node', [], { + allowRetries: true, + maxRetries: 3 + }); + } + + protected abstract getDistributionUrl(): string; + protected abstract getNodejsVersions(): Promise; + protected abstract evaluateVersions(nodeVersions: INodeVersion[]): string; + + public async getNodeJsInfo() { + let toolPath = this.findVersionInHoostedToolCacheDirectory(); + if (!toolPath) { + const versions = await this.getNodejsVersions(); + const evaluatedVersion = this.evaluateVersions(versions); + const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); + toolPath = await this.downloadNodejs(toolName); + } + + core.addPath(toolPath); + } + + protected findVersionInHoostedToolCacheDirectory() { + return tc.find('node', this.nodeInfo.versionSpec, this.nodeInfo.arch); + } + + protected getNodejsDistInfo(version: string, osPlat: string) { + let osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch); + 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 = this.getDistributionUrl(); + const url = `${initialUrl}/v${version}/${urlFileName}`; + + return { + downloadUrl: url, + resolvedVersion: version, + arch: osArch, // have to be arch but not osArch, + fileName: fileName + }; + } + + protected async downloadNodejs(info: INodeVersionInfo) { + let osPlat: string = os.platform(); + let downloadPath = ''; + 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'); + + if (osPlat != 'win32') { + toolPath = path.join(toolPath, 'bin'); + } + + return toolPath; + } + + protected async acquireNodeFromFallbackLocation( + version: string, + arch: string = os.arch() + ): Promise { + 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') { + 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 ...'); + const toolPath = await tc.cacheDir( + extPath, + 'node', + info.resolvedVersion, + info.arch + ); + + return toolPath; + } + + protected getDistFileName(arch: string = os.arch()): string { + let osPlat: string = os.platform(); + let osArch: string = this.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}'`); + } + + return dataFileName; + } + + protected filterVersions(nodeVersions: INodeVersion[]) { + let versions: string[] = []; + + const dataFileName = this.getDistFileName(this.nodeInfo.arch); + + nodeVersions.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; + } + } +} diff --git a/src/distibutions/base-models.ts b/src/distibutions/base-models.ts new file mode 100644 index 000000000..300461bb0 --- /dev/null +++ b/src/distibutions/base-models.ts @@ -0,0 +1,18 @@ +export interface INodejs { + versionSpec: string; + arch: string; + auth?: string; + checkLatest: boolean; +} + +export interface INodeVersionInfo { + downloadUrl: string; + resolvedVersion: string; + arch: string; + fileName: string; +} + +export interface INodeVersion { + version: string; + files: string[]; +} diff --git a/src/distibutions/installer-factory.ts b/src/distibutions/installer-factory.ts new file mode 100644 index 000000000..4e694c05f --- /dev/null +++ b/src/distibutions/installer-factory.ts @@ -0,0 +1,46 @@ +import BaseDistribution from './base-distribution'; +import {INodejs} from './base-models'; +import NightlyNodejs from './nightly/nightly_builds'; +import OfficialBuilds from './official_builds/official_builds'; +import RcBuild from './official_builds/rc/rc_builds'; +import CanaryBuild from './v8-canary/canary_builds'; + +enum Distributions { + DEFAULT = '', + CANARY = 'v8-canary', + NIGHTLY = 'nightly', + RC = 'rc' +} + +function identifyDistribution(versionSpec: string) { + let distribution = ''; + if (versionSpec.includes(Distributions.NIGHTLY)) { + distribution = Distributions.NIGHTLY; + } else if (versionSpec.includes(Distributions.CANARY)) { + distribution = Distributions.CANARY; + } else if (versionSpec.includes(Distributions.RC)) { + distribution = Distributions.RC; + } else { + distribution = Distributions.DEFAULT; + } + + return distribution; +} + +export function getNodejsDistribution( + installerOptions: INodejs +): BaseDistribution | null { + const distributionName = identifyDistribution(installerOptions.versionSpec); + switch (distributionName) { + case Distributions.NIGHTLY: + return new NightlyNodejs(installerOptions); + case Distributions.CANARY: + return new CanaryBuild(installerOptions); + case Distributions.RC: + return new RcBuild(installerOptions); + case Distributions.DEFAULT: + return new OfficialBuilds(installerOptions); + default: + return null; + } +} diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts new file mode 100644 index 000000000..d3abb125b --- /dev/null +++ b/src/distibutions/nightly/nightly_builds.ts @@ -0,0 +1,77 @@ +import * as core from '@actions/core'; + +import semver from 'semver'; + +import BaseDistribution from '../base-distribution'; +import {INodejs, INodeVersion} from '../base-models'; + +export default class NightlyNodejs extends BaseDistribution { + constructor(nodeInfo: INodejs) { + super(nodeInfo); + } + + protected evaluateVersions(nodeVersions: INodeVersion[]): string { + let version = ''; + const versions = this.filterVersions(nodeVersions); + + core.debug(`evaluating ${versions.length} versions`); + + const {includePrerelease, range} = this.createRangePreRelease( + this.nodeInfo.versionSpec, + '-nightly' + ); + + for (let i = versions.length - 1; i >= 0; i--) { + const potential: string = versions[i]; + const satisfied: boolean = semver.satisfies(potential, range, { + includePrerelease: includePrerelease + }); + if (satisfied) { + version = potential; + break; + } + } + + if (version) { + core.debug(`matched: ${version}`); + } else { + core.debug('match not found'); + } + + return version; + } + + protected getDistributionUrl(): string { + return 'https://nodejs.org/download/nightly'; + } + + async getNodejsVersions(): Promise { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + + let response = await this.httpClient.getJson(dataUrl); + return response.result || []; + } + + createRangePreRelease(versionSpec: string, distribution: string = '') { + let range: string | undefined; + const [raw, prerelease] = this.splitVersionSpec(versionSpec); + const isValidVersion = semver.valid(raw); + const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; + + if (`-${prerelease}` !== distribution) { + range = `${rawVersion}${`-${prerelease}`.replace( + distribution, + `${distribution}.` + )}`; + } else { + range = `${semver.validRange(`^${rawVersion}${distribution}`)}-0`; + } + + return {range, includePrerelease: !isValidVersion}; + } + + splitVersionSpec(versionSpec: string) { + return versionSpec.split(/-(.*)/s); + } +} diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts new file mode 100644 index 000000000..34304e9fe --- /dev/null +++ b/src/distibutions/official_builds/official_builds.ts @@ -0,0 +1,273 @@ +import * as core from '@actions/core'; +import * as tc from '@actions/tool-cache'; +import * as semver from 'semver'; +import os from 'os'; + +import {INodeVersion} from '../../installer'; +import BaseDistribution from '../base-distribution'; +import {INodejs, INodeVersionInfo} from '../base-models'; + +interface INodeRelease extends tc.IToolRelease { + lts?: string; +} + +export default class OfficialBuilds extends BaseDistribution { + constructor(nodeInfo: INodejs) { + super(nodeInfo); + } + + protected async queryDistForMatch( + versionSpec: string, + arch: string = os.arch(), + nodeVersions: INodeVersion[] + ): Promise { + let osPlat: string = os.platform(); + let osArch: string = this.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 (this.isLatestSyntax(versionSpec)) { + core.info(`getting latest node version...`); + return nodeVersions[0].version; + } + + const versions: string[] = []; + 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 + const version = this.evaluateVersions(nodeVersions); + return version; + } + + public async getNodeJsInfo() { + let manifest: tc.IToolRelease[] = []; + let nodeVersions: INodeVersion[] = []; + 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, + true, + manifest + ); + } + + if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { + nodeVersions = await this.getNodejsVersions(); + this.nodeInfo.versionSpec = await this.queryDistForMatch( + this.nodeInfo.versionSpec, + this.nodeInfo.arch, + nodeVersions + ); + core.info(`getting latest node version...`); + } + + let toolPath = this.findVersionInHoostedToolCacheDirectory(); + + if (!toolPath) { + try { + const versionInfo = await this.getInfoFromManifest( + this.nodeInfo.versionSpec, + true, + this.nodeInfo.auth, + this.nodeInfo.arch, + undefined + ); + if (versionInfo) { + core.info( + `Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}` + ); + toolPath = await tc.downloadTool( + versionInfo.downloadUrl, + undefined, + this.nodeInfo.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'); + } + + const versions = await this.getNodejsVersions(); + const evaluatedVersion = this.evaluateVersions(versions); + const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); + toolPath = await this.downloadNodejs(toolName); + } + + core.addPath(toolPath); + } + + protected evaluateVersions(nodeVersions: INodeVersion[]): string { + let version = ''; + const versions = this.filterVersions(nodeVersions); + + if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { + core.info(`getting latest node version...`); + return versions[0]; + } + + core.debug(`evaluating ${versions.length} versions`); + + for (let i = versions.length - 1; i >= 0; i--) { + const potential: string = versions[i]; + const satisfied: boolean = semver.satisfies( + potential, + this.nodeInfo.versionSpec + ); + if (satisfied) { + version = potential; + break; + } + } + + if (version) { + core.debug(`matched: ${version}`); + } else { + core.debug('match not found'); + } + + return version; + } + + protected getDistributionUrl(): string { + return `https://nodejs.org/dist`; + } + + protected async getNodejsVersions(): Promise { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + + let response = await this.httpClient.getJson(dataUrl); + return response.result || []; + } + + private getManifest(): Promise { + 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/`, `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 getInfoFromManifest( + versionSpec: string, + stable: boolean, + auth: string | undefined, + osArch: string = this.translateArchToDistUrl(os.arch()), + manifest: tc.IToolRelease[] | undefined + ): Promise { + 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 = {}; + 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); + } +} diff --git a/src/distibutions/official_builds/rc/rc_builds.ts b/src/distibutions/official_builds/rc/rc_builds.ts new file mode 100644 index 000000000..8822a1bd6 --- /dev/null +++ b/src/distibutions/official_builds/rc/rc_builds.ts @@ -0,0 +1,50 @@ +import * as core from '@actions/core'; + +import * as semver from 'semver'; + +import BaseDistribution from '../../base-distribution'; +import {INodejs, INodeVersion} from '../../base-models'; + +export default class RcBuild extends BaseDistribution { + constructor(nodeInfo: INodejs) { + super(nodeInfo); + } + + protected async getNodejsVersions(): Promise { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + + let response = await this.httpClient.getJson(dataUrl); + return response.result || []; + } + + protected evaluateVersions(nodeVersions: INodeVersion[]): string { + let version = ''; + const versions = this.filterVersions(nodeVersions); + core.debug(`evaluating ${versions.length} versions`); + + for (let i = versions.length - 1; i >= 0; i--) { + const potential: string = versions[i]; + const satisfied: boolean = semver.satisfies( + potential, + this.nodeInfo.versionSpec + ); + if (satisfied) { + version = potential; + break; + } + } + + if (version) { + core.debug(`matched: ${version}`); + } else { + core.debug('match not found'); + } + + return version; + } + + getDistributionUrl(): string { + return 'https://nodejs.org/download/rc'; + } +} diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts new file mode 100644 index 000000000..f929c0356 --- /dev/null +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -0,0 +1,75 @@ +import * as core from '@actions/core'; + +import semver from 'semver'; + +import BaseDistribution from '../base-distribution'; +import {INodejs, INodeVersion} from '../base-models'; + +export default class CanaryBuild extends BaseDistribution { + protected evaluateVersions(nodeVersions: INodeVersion[]): string { + let version = ''; + const versions = this.filterVersions(nodeVersions); + + core.debug(`evaluating ${versions.length} versions`); + + const {includePrerelease, range} = this.createRangePreRelease( + this.nodeInfo.versionSpec, + '-v8-canary' + ); + + for (let i = versions.length - 1; i >= 0; i--) { + const potential: string = versions[i]; + const satisfied: boolean = semver.satisfies(potential, range, { + includePrerelease: includePrerelease + }); + if (satisfied) { + version = potential; + break; + } + } + + if (version) { + core.debug(`matched: ${version}`); + } else { + core.debug('match not found'); + } + + return version; + } + constructor(nodeInfo: INodejs) { + super(nodeInfo); + } + protected getDistributionUrl(): string { + return 'https://nodejs.org/download/v8-canary'; + } + + async getNodejsVersions(): Promise { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + + let response = await this.httpClient.getJson(dataUrl); + return response.result || []; + } + + createRangePreRelease(versionSpec: string, distribution: string = '') { + let range: string | undefined; + const [raw, prerelease] = this.splitVersionSpec(versionSpec); + const isValidVersion = semver.valid(raw); + const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; + + if (`-${prerelease}` !== distribution) { + range = `${rawVersion}${`-${prerelease}`.replace( + distribution, + `${distribution}.` + )}`; + } else { + range = `${semver.validRange(`^${rawVersion}${distribution}`)}-0`; + } + + return {range, includePrerelease: !isValidVersion}; + } + + splitVersionSpec(versionSpec: string) { + return versionSpec.split(/-(.*)/s); + } +} diff --git a/src/main.ts b/src/main.ts index 2a846b06e..b250085c4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,6 +7,7 @@ import * as path from 'path'; import {restoreCache} from './cache-restore'; import {isGhes, isCacheFeatureAvailable} from './cache-utils'; import os from 'os'; +import {getNodejsDistribution} from './distibutions/installer-factory'; export async function run() { try { @@ -38,7 +39,18 @@ 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: checkLatest, + auth, + arch: arch + }; + const nodeDistribution = getNodejsDistribution(nodejsInfo); + if (nodeDistribution) { + await nodeDistribution?.getNodeJsInfo(); + } + + // await installer.getNode(version, stable, checkLatest, auth, arch); } await printEnvDetailsAndSetOutput(); From 360977cce6377200141e5456dfccdc4bbd300b5f Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 10:25:41 +0100 Subject: [PATCH 26/51] minor fix --- dist/setup/index.js | 4 ++-- src/distibutions/nightly/nightly_builds.ts | 2 +- src/distibutions/v8-canary/canary_builds.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index b78ec2887..2cde2fb0f 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73486,7 +73486,7 @@ class NightlyNodejs extends base_distribution_1.default { core.debug(`evaluating ${versions.length} versions`); const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-nightly'); for (let i = versions.length - 1; i >= 0; i--) { - const potential = versions[i]; + const potential = versions[i].replace('nightly', 'nightly.'); const satisfied = semver_1.default.satisfies(potential, range, { includePrerelease: includePrerelease }); @@ -73850,7 +73850,7 @@ class CanaryBuild extends base_distribution_1.default { core.debug(`evaluating ${versions.length} versions`); const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-v8-canary'); for (let i = versions.length - 1; i >= 0; i--) { - const potential = versions[i]; + const potential = versions[i].replace('v8-canary', 'v8-canary.'); const satisfied = semver_1.default.satisfies(potential, range, { includePrerelease: includePrerelease }); diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index d3abb125b..558c47c48 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -22,7 +22,7 @@ export default class NightlyNodejs extends BaseDistribution { ); for (let i = versions.length - 1; i >= 0; i--) { - const potential: string = versions[i]; + const potential: string = versions[i].replace('nightly', 'nightly.'); const satisfied: boolean = semver.satisfies(potential, range, { includePrerelease: includePrerelease }); diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index f929c0356..b87576895 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -18,7 +18,7 @@ export default class CanaryBuild extends BaseDistribution { ); for (let i = versions.length - 1; i >= 0; i--) { - const potential: string = versions[i]; + const potential: string = versions[i].replace('v8-canary', 'v8-canary.'); const satisfied: boolean = semver.satisfies(potential, range, { includePrerelease: includePrerelease }); From 2d741fbf57e44d560538c1e59befdffb2a72b7ae Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 10:46:26 +0100 Subject: [PATCH 27/51] minor fix --- dist/setup/index.js | 8 ++++---- src/distibutions/nightly/nightly_builds.ts | 12 ++++++++---- src/distibutions/v8-canary/canary_builds.ts | 12 ++++++++---- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 2cde2fb0f..d994595f2 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73486,8 +73486,8 @@ class NightlyNodejs extends base_distribution_1.default { core.debug(`evaluating ${versions.length} versions`); const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-nightly'); for (let i = versions.length - 1; i >= 0; i--) { - const potential = versions[i].replace('nightly', 'nightly.'); - const satisfied = semver_1.default.satisfies(potential, range, { + const potential = versions[i]; + const satisfied = semver_1.default.satisfies(potential.replace('nightly', 'nightly.'), range, { includePrerelease: includePrerelease }); if (satisfied) { @@ -73850,8 +73850,8 @@ class CanaryBuild extends base_distribution_1.default { core.debug(`evaluating ${versions.length} versions`); const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-v8-canary'); for (let i = versions.length - 1; i >= 0; i--) { - const potential = versions[i].replace('v8-canary', 'v8-canary.'); - const satisfied = semver_1.default.satisfies(potential, range, { + const potential = versions[i]; + const satisfied = semver_1.default.satisfies(potential.replace('v8-canary', 'v8-canary.'), range, { includePrerelease: includePrerelease }); if (satisfied) { diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index 558c47c48..0df2e1c04 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -22,10 +22,14 @@ export default class NightlyNodejs extends BaseDistribution { ); for (let i = versions.length - 1; i >= 0; i--) { - const potential: string = versions[i].replace('nightly', 'nightly.'); - const satisfied: boolean = semver.satisfies(potential, range, { - includePrerelease: includePrerelease - }); + const potential: string = versions[i]; + const satisfied: boolean = semver.satisfies( + potential.replace('nightly', 'nightly.'), + range, + { + includePrerelease: includePrerelease + } + ); if (satisfied) { version = potential; break; diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index b87576895..db82b471b 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -18,10 +18,14 @@ export default class CanaryBuild extends BaseDistribution { ); for (let i = versions.length - 1; i >= 0; i--) { - const potential: string = versions[i].replace('v8-canary', 'v8-canary.'); - const satisfied: boolean = semver.satisfies(potential, range, { - includePrerelease: includePrerelease - }); + const potential: string = versions[i]; + const satisfied: boolean = semver.satisfies( + potential.replace('v8-canary', 'v8-canary.'), + range, + { + includePrerelease: includePrerelease + } + ); if (satisfied) { version = potential; break; From 292688b127a950b4fbec3e10bfa80f2e9b2fe524 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 11:25:04 +0100 Subject: [PATCH 28/51] minor fix --- dist/setup/index.js | 10 +++++++--- src/distibutions/base-distribution.ts | 8 ++++---- src/distibutions/official_builds/official_builds.ts | 5 +++++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index d994595f2..bf5973e9a 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73234,6 +73234,9 @@ class BaseDistribution { const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); toolPath = yield this.downloadNodejs(toolName); } + if (this.osPlat != 'win32') { + toolPath = path.join(toolPath, 'bin'); + } core.addPath(toolPath); }); } @@ -73271,9 +73274,6 @@ class BaseDistribution { } let toolPath = yield this.extractArchive(downloadPath, info); core.info('Done'); - if (osPlat != 'win32') { - toolPath = path.join(toolPath, 'bin'); - } return toolPath; }); } @@ -73565,6 +73565,7 @@ const core = __importStar(__nccwpck_require__(2186)); const tc = __importStar(__nccwpck_require__(7784)); const semver = __importStar(__nccwpck_require__(5911)); const os_1 = __importDefault(__nccwpck_require__(2037)); +const path_1 = __importDefault(__nccwpck_require__(1017)); const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); class OfficialBuilds extends base_distribution_1.default { constructor(nodeInfo) { @@ -73649,6 +73650,9 @@ class OfficialBuilds extends base_distribution_1.default { const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); toolPath = yield this.downloadNodejs(toolName); } + if (this.osPlat != 'win32') { + toolPath = path_1.default.join(toolPath, 'bin'); + } core.addPath(toolPath); }); } diff --git a/src/distibutions/base-distribution.ts b/src/distibutions/base-distribution.ts index f61e6831d..c898602f6 100644 --- a/src/distibutions/base-distribution.ts +++ b/src/distibutions/base-distribution.ts @@ -36,6 +36,10 @@ export default abstract class BaseDistribution { toolPath = await this.downloadNodejs(toolName); } + if (this.osPlat != 'win32') { + toolPath = path.join(toolPath, 'bin'); + } + core.addPath(toolPath); } @@ -82,10 +86,6 @@ export default abstract class BaseDistribution { let toolPath = await this.extractArchive(downloadPath, info); core.info('Done'); - if (osPlat != 'win32') { - toolPath = path.join(toolPath, 'bin'); - } - return toolPath; } diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts index 34304e9fe..249fbde09 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distibutions/official_builds/official_builds.ts @@ -2,6 +2,7 @@ import * as core from '@actions/core'; import * as tc from '@actions/tool-cache'; import * as semver from 'semver'; import os from 'os'; +import path from 'path'; import {INodeVersion} from '../../installer'; import BaseDistribution from '../base-distribution'; @@ -131,6 +132,10 @@ export default class OfficialBuilds extends BaseDistribution { toolPath = await this.downloadNodejs(toolName); } + if (this.osPlat != 'win32') { + toolPath = path.join(toolPath, 'bin'); + } + core.addPath(toolPath); } From 7fc684f251d0c1efee743eb031ea876cea7f510a Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 12:25:27 +0100 Subject: [PATCH 29/51] minor fix --- dist/setup/index.js | 8 ++++---- src/distibutions/nightly/nightly_builds.ts | 2 +- src/distibutions/official_builds/official_builds.ts | 2 +- src/distibutions/official_builds/rc/rc_builds.ts | 2 +- src/distibutions/v8-canary/canary_builds.ts | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index bf5973e9a..ee0682226 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73485,7 +73485,7 @@ class NightlyNodejs extends base_distribution_1.default { const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-nightly'); - for (let i = versions.length - 1; i >= 0; i--) { + for (let i = 0; i < versions.length; i++) { const potential = versions[i]; const satisfied = semver_1.default.satisfies(potential.replace('nightly', 'nightly.'), range, { includePrerelease: includePrerelease @@ -73664,7 +73664,7 @@ class OfficialBuilds extends base_distribution_1.default { return versions[0]; } core.debug(`evaluating ${versions.length} versions`); - for (let i = versions.length - 1; i >= 0; i--) { + for (let i = 0; i < versions.length; i++) { const potential = versions[i]; const satisfied = semver.satisfies(potential, this.nodeInfo.versionSpec); if (satisfied) { @@ -73794,7 +73794,7 @@ class RcBuild extends base_distribution_1.default { let version = ''; const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); - for (let i = versions.length - 1; i >= 0; i--) { + for (let i = 0; i < versions.length; i++) { const potential = versions[i]; const satisfied = semver.satisfies(potential, this.nodeInfo.versionSpec); if (satisfied) { @@ -73853,7 +73853,7 @@ class CanaryBuild extends base_distribution_1.default { const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-v8-canary'); - for (let i = versions.length - 1; i >= 0; i--) { + for (let i = 0; i < versions.length; i++) { const potential = versions[i]; const satisfied = semver_1.default.satisfies(potential.replace('v8-canary', 'v8-canary.'), range, { includePrerelease: includePrerelease diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index 0df2e1c04..b3a5654a6 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -21,7 +21,7 @@ export default class NightlyNodejs extends BaseDistribution { '-nightly' ); - for (let i = versions.length - 1; i >= 0; i--) { + for (let i = 0; i < versions.length; i++) { const potential: string = versions[i]; const satisfied: boolean = semver.satisfies( potential.replace('nightly', 'nightly.'), diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts index 249fbde09..beeb3fd03 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distibutions/official_builds/official_builds.ts @@ -150,7 +150,7 @@ export default class OfficialBuilds extends BaseDistribution { core.debug(`evaluating ${versions.length} versions`); - for (let i = versions.length - 1; i >= 0; i--) { + for (let i = 0; i < versions.length; i++) { const potential: string = versions[i]; const satisfied: boolean = semver.satisfies( potential, diff --git a/src/distibutions/official_builds/rc/rc_builds.ts b/src/distibutions/official_builds/rc/rc_builds.ts index 8822a1bd6..6339bd427 100644 --- a/src/distibutions/official_builds/rc/rc_builds.ts +++ b/src/distibutions/official_builds/rc/rc_builds.ts @@ -23,7 +23,7 @@ export default class RcBuild extends BaseDistribution { const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); - for (let i = versions.length - 1; i >= 0; i--) { + for (let i = 0; i < versions.length; i++) { const potential: string = versions[i]; const satisfied: boolean = semver.satisfies( potential, diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index db82b471b..19bc3b428 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -17,7 +17,7 @@ export default class CanaryBuild extends BaseDistribution { '-v8-canary' ); - for (let i = versions.length - 1; i >= 0; i--) { + for (let i = 0; i < versions.length; i++) { const potential: string = versions[i]; const satisfied: boolean = semver.satisfies( potential.replace('v8-canary', 'v8-canary.'), From 0d35e2c9381db3848e3293d567180384227ae4a9 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 14:19:28 +0100 Subject: [PATCH 30/51] add possible improvement for canary --- dist/setup/index.js | 24 ++++++++-------- src/distibutions/v8-canary/canary_builds.ts | 31 ++++++++++++--------- src/main.ts | 4 +-- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index ee0682226..a588788cc 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73848,11 +73848,17 @@ const core = __importStar(__nccwpck_require__(2186)); const semver_1 = __importDefault(__nccwpck_require__(5911)); const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); class CanaryBuild extends base_distribution_1.default { + constructor(nodeInfo) { + super(nodeInfo); + } + getDistributionUrl() { + return 'https://nodejs.org/download/v8-canary'; + } evaluateVersions(nodeVersions) { let version = ''; const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); - const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-v8-canary'); + const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, 'v8-canary'); for (let i = 0; i < versions.length; i++) { const potential = versions[i]; const satisfied = semver_1.default.satisfies(potential.replace('v8-canary', 'v8-canary.'), range, { @@ -73871,12 +73877,6 @@ class CanaryBuild extends base_distribution_1.default { } return version; } - constructor(nodeInfo) { - super(nodeInfo); - } - getDistributionUrl() { - return 'https://nodejs.org/download/v8-canary'; - } getNodejsVersions() { return __awaiter(this, void 0, void 0, function* () { const initialUrl = this.getDistributionUrl(); @@ -73890,11 +73890,11 @@ class CanaryBuild extends base_distribution_1.default { const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver_1.default.valid(raw); const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); - if (`-${prerelease}` !== distribution) { - range = `${rawVersion}${`-${prerelease}`.replace(distribution, `${distribution}.`)}`; + if (prerelease !== distribution) { + range = `${rawVersion}-${prerelease.replace(distribution, `${distribution}.`)}`; } else { - range = `${semver_1.default.validRange(`^${rawVersion}${distribution}`)}-0`; + range = `${semver_1.default.validRange(`^${rawVersion}-${distribution}`)}-0`; } return { range, includePrerelease: !isValidVersion }; } @@ -74471,7 +74471,6 @@ function run() { if (version) { const token = core.getInput('token'); const auth = !token ? undefined : `token ${token}`; - const stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; const nodejsInfo = { versionSpec: version, @@ -74483,6 +74482,9 @@ function run() { if (nodeDistribution) { yield (nodeDistribution === null || nodeDistribution === void 0 ? void 0 : nodeDistribution.getNodeJsInfo()); } + else { + throw new Error(`Could not resolve version: ${version} for build`); + } // await installer.getNode(version, stable, checkLatest, auth, arch); } yield printEnvDetailsAndSetOutput(); diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index 19bc3b428..2ebf5321e 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -6,6 +6,14 @@ import BaseDistribution from '../base-distribution'; import {INodejs, INodeVersion} from '../base-models'; export default class CanaryBuild extends BaseDistribution { + constructor(nodeInfo: INodejs) { + super(nodeInfo); + } + + protected getDistributionUrl(): string { + return 'https://nodejs.org/download/v8-canary'; + } + protected evaluateVersions(nodeVersions: INodeVersion[]): string { let version = ''; const versions = this.filterVersions(nodeVersions); @@ -14,7 +22,7 @@ export default class CanaryBuild extends BaseDistribution { const {includePrerelease, range} = this.createRangePreRelease( this.nodeInfo.versionSpec, - '-v8-canary' + 'v8-canary' ); for (let i = 0; i < versions.length; i++) { @@ -40,12 +48,6 @@ export default class CanaryBuild extends BaseDistribution { return version; } - constructor(nodeInfo: INodejs) { - super(nodeInfo); - } - protected getDistributionUrl(): string { - return 'https://nodejs.org/download/v8-canary'; - } async getNodejsVersions(): Promise { const initialUrl = this.getDistributionUrl(); @@ -55,25 +57,28 @@ export default class CanaryBuild extends BaseDistribution { return response.result || []; } - createRangePreRelease(versionSpec: string, distribution: string = '') { - let range: string | undefined; + protected createRangePreRelease( + versionSpec: string, + distribution: string = '' + ) { + let range: string; const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver.valid(raw); const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; - if (`-${prerelease}` !== distribution) { - range = `${rawVersion}${`-${prerelease}`.replace( + if (prerelease !== distribution) { + range = `${rawVersion}-${prerelease.replace( distribution, `${distribution}.` )}`; } else { - range = `${semver.validRange(`^${rawVersion}${distribution}`)}-0`; + range = `${semver.validRange(`^${rawVersion}-${distribution}`)}-0`; } return {range, includePrerelease: !isValidVersion}; } - splitVersionSpec(versionSpec: string) { + protected splitVersionSpec(versionSpec: string) { return versionSpec.split(/-(.*)/s); } } diff --git a/src/main.ts b/src/main.ts index b250085c4..fb7e92865 100644 --- a/src/main.ts +++ b/src/main.ts @@ -35,8 +35,6 @@ export async function run() { if (version) { const token = core.getInput('token'); const auth = !token ? undefined : `token ${token}`; - const stable = - (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; const nodejsInfo = { @@ -48,6 +46,8 @@ export async function run() { const nodeDistribution = getNodejsDistribution(nodejsInfo); if (nodeDistribution) { await nodeDistribution?.getNodeJsInfo(); + } else { + throw new Error(`Could not resolve version: ${version} for build`); } // await installer.getNode(version, stable, checkLatest, auth, arch); From 9eba46a481571156edad799d128f0d2ec454680c Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 15:31:03 +0100 Subject: [PATCH 31/51] change evaluateVersions --- dist/setup/index.js | 71 ++++++------------- src/distibutions/base-distribution.ts | 5 +- src/distibutions/nightly/nightly_builds.ts | 29 +++++--- .../official_builds/official_builds.ts | 56 ++------------- .../official_builds/rc/rc_builds.ts | 4 +- src/distibutions/v8-canary/canary_builds.ts | 3 +- 6 files changed, 53 insertions(+), 115 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index a588788cc..55f89f9f3 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73229,7 +73229,8 @@ class BaseDistribution { return __awaiter(this, void 0, void 0, function* () { let toolPath = this.findVersionInHoostedToolCacheDirectory(); if (!toolPath) { - const versions = yield this.getNodejsVersions(); + const nodeVersions = yield this.getNodejsVersions(); + const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); toolPath = yield this.downloadNodejs(toolName); @@ -73474,17 +73475,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__nccwpck_require__(2186)); +const tc = __importStar(__nccwpck_require__(7784)); const semver_1 = __importDefault(__nccwpck_require__(5911)); const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); class NightlyNodejs extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); } - evaluateVersions(nodeVersions) { + findVersionInHoostedToolCacheDirectory() { + const localVersionPaths = tc.findAllVersions('node', this.nodeInfo.arch); + const localVersion = this.evaluateVersions(localVersionPaths); + const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + return toolPath; + } + evaluateVersions(versions) { let version = ''; - const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); - const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, '-nightly'); + const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, 'nightly'); for (let i = 0; i < versions.length; i++) { const potential = versions[i]; const satisfied = semver_1.default.satisfies(potential.replace('nightly', 'nightly.'), range, { @@ -73519,11 +73526,11 @@ class NightlyNodejs extends base_distribution_1.default { const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver_1.default.valid(raw); const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); - if (`-${prerelease}` !== distribution) { - range = `${rawVersion}${`-${prerelease}`.replace(distribution, `${distribution}.`)}`; + if (prerelease !== distribution) { + range = `${rawVersion}-${prerelease.replace(distribution, `${distribution}.`)}`; } else { - range = `${semver_1.default.validRange(`^${rawVersion}${distribution}`)}-0`; + range = `${semver_1.default.validRange(`^${rawVersion}-${distribution}`)}-0`; } return { range, includePrerelease: !isValidVersion }; } @@ -73571,41 +73578,6 @@ class OfficialBuilds extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); } - queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions) { - return __awaiter(this, void 0, void 0, function* () { - let osPlat = os_1.default.platform(); - let osArch = this.translateArchToDistUrl(arch); - // node offers a json list of versions - let dataFileName; - 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 (this.isLatestSyntax(versionSpec)) { - core.info(`getting latest node version...`); - return nodeVersions[0].version; - } - const versions = []; - nodeVersions.forEach((nodeVersion) => { - // 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 - const version = this.evaluateVersions(nodeVersions); - return version; - }); - } getNodeJsInfo() { return __awaiter(this, void 0, void 0, function* () { let manifest = []; @@ -73618,7 +73590,8 @@ class OfficialBuilds extends base_distribution_1.default { } if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { nodeVersions = yield this.getNodejsVersions(); - this.nodeInfo.versionSpec = yield this.queryDistForMatch(this.nodeInfo.versionSpec, this.nodeInfo.arch, nodeVersions); + const versions = this.filterVersions(nodeVersions); + this.nodeInfo.versionSpec = this.evaluateVersions(versions); core.info(`getting latest node version...`); } let toolPath = this.findVersionInHoostedToolCacheDirectory(); @@ -73645,7 +73618,8 @@ class OfficialBuilds extends base_distribution_1.default { core.debug(err.stack); core.info('Falling back to download directly from Node'); } - const versions = yield this.getNodejsVersions(); + const nodeVersions = yield this.getNodejsVersions(); + const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); toolPath = yield this.downloadNodejs(toolName); @@ -73656,9 +73630,8 @@ class OfficialBuilds extends base_distribution_1.default { core.addPath(toolPath); }); } - evaluateVersions(nodeVersions) { + evaluateVersions(versions) { let version = ''; - const versions = this.filterVersions(nodeVersions); if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { core.info(`getting latest node version...`); return versions[0]; @@ -73790,9 +73763,8 @@ class RcBuild extends base_distribution_1.default { return response.result || []; }); } - evaluateVersions(nodeVersions) { + evaluateVersions(versions) { let version = ''; - const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); for (let i = 0; i < versions.length; i++) { const potential = versions[i]; @@ -73854,9 +73826,8 @@ class CanaryBuild extends base_distribution_1.default { getDistributionUrl() { return 'https://nodejs.org/download/v8-canary'; } - evaluateVersions(nodeVersions) { + evaluateVersions(versions) { let version = ''; - const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, 'v8-canary'); for (let i = 0; i < versions.length; i++) { diff --git a/src/distibutions/base-distribution.ts b/src/distibutions/base-distribution.ts index c898602f6..f843e7328 100644 --- a/src/distibutions/base-distribution.ts +++ b/src/distibutions/base-distribution.ts @@ -25,12 +25,13 @@ export default abstract class BaseDistribution { protected abstract getDistributionUrl(): string; protected abstract getNodejsVersions(): Promise; - protected abstract evaluateVersions(nodeVersions: INodeVersion[]): string; + protected abstract evaluateVersions(nodeVersions: string[]): string; public async getNodeJsInfo() { let toolPath = this.findVersionInHoostedToolCacheDirectory(); if (!toolPath) { - const versions = await this.getNodejsVersions(); + const nodeVersions = await this.getNodejsVersions(); + const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); toolPath = await this.downloadNodejs(toolName); diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index b3a5654a6..6ea3f80f5 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -1,4 +1,5 @@ import * as core from '@actions/core'; +import * as tc from '@actions/tool-cache'; import semver from 'semver'; @@ -10,15 +11,22 @@ export default class NightlyNodejs extends BaseDistribution { super(nodeInfo); } - protected evaluateVersions(nodeVersions: INodeVersion[]): string { + protected findVersionInHoostedToolCacheDirectory(): string { + const localVersionPaths = tc.findAllVersions('node', this.nodeInfo.arch); + const localVersion = this.evaluateVersions(localVersionPaths); + const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + + return toolPath; + } + + protected evaluateVersions(versions: string[]): string { let version = ''; - const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); const {includePrerelease, range} = this.createRangePreRelease( this.nodeInfo.versionSpec, - '-nightly' + 'nightly' ); for (let i = 0; i < versions.length; i++) { @@ -57,25 +65,28 @@ export default class NightlyNodejs extends BaseDistribution { return response.result || []; } - createRangePreRelease(versionSpec: string, distribution: string = '') { - let range: string | undefined; + protected createRangePreRelease( + versionSpec: string, + distribution: string = '' + ) { + let range: string; const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver.valid(raw); const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; - if (`-${prerelease}` !== distribution) { - range = `${rawVersion}${`-${prerelease}`.replace( + if (prerelease !== distribution) { + range = `${rawVersion}-${prerelease.replace( distribution, `${distribution}.` )}`; } else { - range = `${semver.validRange(`^${rawVersion}${distribution}`)}-0`; + range = `${semver.validRange(`^${rawVersion}-${distribution}`)}-0`; } return {range, includePrerelease: !isValidVersion}; } - splitVersionSpec(versionSpec: string) { + protected splitVersionSpec(versionSpec: string) { return versionSpec.split(/-(.*)/s); } } diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts index beeb3fd03..85e68efd2 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distibutions/official_builds/official_builds.ts @@ -17,48 +17,6 @@ export default class OfficialBuilds extends BaseDistribution { super(nodeInfo); } - protected async queryDistForMatch( - versionSpec: string, - arch: string = os.arch(), - nodeVersions: INodeVersion[] - ): Promise { - let osPlat: string = os.platform(); - let osArch: string = this.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 (this.isLatestSyntax(versionSpec)) { - core.info(`getting latest node version...`); - return nodeVersions[0].version; - } - - const versions: string[] = []; - 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 - const version = this.evaluateVersions(nodeVersions); - return version; - } - public async getNodeJsInfo() { let manifest: tc.IToolRelease[] = []; let nodeVersions: INodeVersion[] = []; @@ -77,11 +35,9 @@ export default class OfficialBuilds extends BaseDistribution { if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { nodeVersions = await this.getNodejsVersions(); - this.nodeInfo.versionSpec = await this.queryDistForMatch( - this.nodeInfo.versionSpec, - this.nodeInfo.arch, - nodeVersions - ); + const versions = this.filterVersions(nodeVersions); + this.nodeInfo.versionSpec = this.evaluateVersions(versions); + core.info(`getting latest node version...`); } @@ -126,7 +82,8 @@ export default class OfficialBuilds extends BaseDistribution { core.info('Falling back to download directly from Node'); } - const versions = await this.getNodejsVersions(); + const nodeVersions = await this.getNodejsVersions(); + const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); toolPath = await this.downloadNodejs(toolName); @@ -139,9 +96,8 @@ export default class OfficialBuilds extends BaseDistribution { core.addPath(toolPath); } - protected evaluateVersions(nodeVersions: INodeVersion[]): string { + protected evaluateVersions(versions: string[]): string { let version = ''; - const versions = this.filterVersions(nodeVersions); if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { core.info(`getting latest node version...`); diff --git a/src/distibutions/official_builds/rc/rc_builds.ts b/src/distibutions/official_builds/rc/rc_builds.ts index 6339bd427..3c95fc957 100644 --- a/src/distibutions/official_builds/rc/rc_builds.ts +++ b/src/distibutions/official_builds/rc/rc_builds.ts @@ -18,9 +18,9 @@ export default class RcBuild extends BaseDistribution { return response.result || []; } - protected evaluateVersions(nodeVersions: INodeVersion[]): string { + protected evaluateVersions(versions: string[]): string { let version = ''; - const versions = this.filterVersions(nodeVersions); + core.debug(`evaluating ${versions.length} versions`); for (let i = 0; i < versions.length; i++) { diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index 2ebf5321e..d4f3118a3 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -14,9 +14,8 @@ export default class CanaryBuild extends BaseDistribution { return 'https://nodejs.org/download/v8-canary'; } - protected evaluateVersions(nodeVersions: INodeVersion[]): string { + protected evaluateVersions(versions: string[]): string { let version = ''; - const versions = this.filterVersions(nodeVersions); core.debug(`evaluating ${versions.length} versions`); From 05e1c35e88201388b66007c7e8e79aa1bf55b1e0 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 16:27:32 +0100 Subject: [PATCH 32/51] add search in toolcache for canary --- dist/setup/index.js | 25 ++++++++++++++++++++- src/distibutions/nightly/nightly_builds.ts | 11 ++++++++- src/distibutions/v8-canary/canary_builds.ts | 19 ++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 55f89f9f3..8f1171e0f 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73483,7 +73483,15 @@ class NightlyNodejs extends base_distribution_1.default { super(nodeInfo); } findVersionInHoostedToolCacheDirectory() { - const localVersionPaths = tc.findAllVersions('node', this.nodeInfo.arch); + const localVersionPaths = tc + .findAllVersions('node', this.nodeInfo.arch) + .filter(i => { + const prerelease = semver_1.default.prerelease(i); + if (!prerelease) { + return false; + } + return prerelease[0].includes('nightly'); + }); const localVersion = this.evaluateVersions(localVersionPaths); const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); return toolPath; @@ -73817,12 +73825,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__nccwpck_require__(2186)); +const tc = __importStar(__nccwpck_require__(7784)); const semver_1 = __importDefault(__nccwpck_require__(5911)); const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); class CanaryBuild extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); } + findVersionInHoostedToolCacheDirectory() { + const localVersionPaths = tc + .findAllVersions('node', this.nodeInfo.arch) + .filter(i => { + const prerelease = semver_1.default.prerelease(i); + if (!prerelease) { + return false; + } + return prerelease[0].includes('v8-canary'); + }); + const localVersion = this.evaluateVersions(localVersionPaths); + const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + return toolPath; + } getDistributionUrl() { return 'https://nodejs.org/download/v8-canary'; } diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index 6ea3f80f5..d563fe6ab 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -12,7 +12,16 @@ export default class NightlyNodejs extends BaseDistribution { } protected findVersionInHoostedToolCacheDirectory(): string { - const localVersionPaths = tc.findAllVersions('node', this.nodeInfo.arch); + const localVersionPaths = tc + .findAllVersions('node', this.nodeInfo.arch) + .filter(i => { + const prerelease = semver.prerelease(i); + if (!prerelease) { + return false; + } + + return prerelease[0].includes('nightly'); + }); const localVersion = this.evaluateVersions(localVersionPaths); const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index d4f3118a3..e363bde9c 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -1,4 +1,5 @@ import * as core from '@actions/core'; +import * as tc from '@actions/tool-cache'; import semver from 'semver'; @@ -10,6 +11,24 @@ export default class CanaryBuild extends BaseDistribution { super(nodeInfo); } + protected findVersionInHoostedToolCacheDirectory(): string { + const localVersionPaths = tc + .findAllVersions('node', this.nodeInfo.arch) + .filter(i => { + const prerelease = semver.prerelease(i); + if (!prerelease) { + return false; + } + + return prerelease[0].includes('v8-canary'); + }); + + const localVersion = this.evaluateVersions(localVersionPaths); + const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + + return toolPath; + } + protected getDistributionUrl(): string { return 'https://nodejs.org/download/v8-canary'; } From 15798eaae79895846e6d5019bb40a9b4694f83a3 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 13 Dec 2022 16:33:20 +0100 Subject: [PATCH 33/51] minor fix --- dist/setup/index.js | 10 ++++++++-- src/distibutions/nightly/nightly_builds.ts | 5 ++++- src/distibutions/v8-canary/canary_builds.ts | 5 ++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 8f1171e0f..bb4428a49 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73483,6 +73483,7 @@ class NightlyNodejs extends base_distribution_1.default { super(nodeInfo); } findVersionInHoostedToolCacheDirectory() { + let toolPath = ''; const localVersionPaths = tc .findAllVersions('node', this.nodeInfo.arch) .filter(i => { @@ -73493,7 +73494,9 @@ class NightlyNodejs extends base_distribution_1.default { return prerelease[0].includes('nightly'); }); const localVersion = this.evaluateVersions(localVersionPaths); - const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + if (localVersion) { + toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + } return toolPath; } evaluateVersions(versions) { @@ -73833,6 +73836,7 @@ class CanaryBuild extends base_distribution_1.default { super(nodeInfo); } findVersionInHoostedToolCacheDirectory() { + let toolPath = ''; const localVersionPaths = tc .findAllVersions('node', this.nodeInfo.arch) .filter(i => { @@ -73843,7 +73847,9 @@ class CanaryBuild extends base_distribution_1.default { return prerelease[0].includes('v8-canary'); }); const localVersion = this.evaluateVersions(localVersionPaths); - const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + if (localVersion) { + toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + } return toolPath; } getDistributionUrl() { diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index d563fe6ab..ff8e824ec 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -12,6 +12,7 @@ export default class NightlyNodejs extends BaseDistribution { } protected findVersionInHoostedToolCacheDirectory(): string { + let toolPath = ''; const localVersionPaths = tc .findAllVersions('node', this.nodeInfo.arch) .filter(i => { @@ -23,7 +24,9 @@ export default class NightlyNodejs extends BaseDistribution { return prerelease[0].includes('nightly'); }); const localVersion = this.evaluateVersions(localVersionPaths); - const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + if (localVersion) { + toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + } return toolPath; } diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index e363bde9c..12d23eac8 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -12,6 +12,7 @@ export default class CanaryBuild extends BaseDistribution { } protected findVersionInHoostedToolCacheDirectory(): string { + let toolPath = ''; const localVersionPaths = tc .findAllVersions('node', this.nodeInfo.arch) .filter(i => { @@ -24,7 +25,9 @@ export default class CanaryBuild extends BaseDistribution { }); const localVersion = this.evaluateVersions(localVersionPaths); - const toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + if (localVersion) { + toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + } return toolPath; } From 785620d55b58aae21556e1b5ce1e78bb42d8541d Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Wed, 14 Dec 2022 19:08:19 +0100 Subject: [PATCH 34/51] optimize code --- dist/setup/index.js | 67 +++---------------- src/distibutions/base-distribution.ts | 9 ++- src/distibutions/nightly/nightly_builds.ts | 8 --- .../official_builds/official_builds.ts | 8 --- .../official_builds/rc/rc_builds.ts | 8 --- src/distibutions/v8-canary/canary_builds.ts | 8 --- 6 files changed, 16 insertions(+), 92 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index bb4428a49..857ffcbe8 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73244,6 +73244,14 @@ class BaseDistribution { findVersionInHoostedToolCacheDirectory() { return tc.find('node', this.nodeInfo.versionSpec, this.nodeInfo.arch); } + getNodejsVersions() { + return __awaiter(this, void 0, void 0, function* () { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + let response = yield this.httpClient.getJson(dataUrl); + return response.result || []; + }); + } getNodejsDistInfo(version, osPlat) { let osArch = this.translateArchToDistUrl(this.nodeInfo.arch); version = semver_1.default.clean(version) || ''; @@ -73454,15 +73462,6 @@ exports.getNodejsDistribution = getNodejsDistribution; "use strict"; -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) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; @@ -73524,14 +73523,6 @@ class NightlyNodejs extends base_distribution_1.default { getDistributionUrl() { return 'https://nodejs.org/download/nightly'; } - getNodejsVersions() { - return __awaiter(this, void 0, void 0, function* () { - const initialUrl = this.getDistributionUrl(); - const dataUrl = `${initialUrl}/index.json`; - let response = yield this.httpClient.getJson(dataUrl); - return response.result || []; - }); - } createRangePreRelease(versionSpec, distribution = '') { let range; const [raw, prerelease] = this.splitVersionSpec(versionSpec); @@ -73667,14 +73658,6 @@ class OfficialBuilds extends base_distribution_1.default { getDistributionUrl() { return `https://nodejs.org/dist`; } - getNodejsVersions() { - return __awaiter(this, void 0, void 0, function* () { - const initialUrl = this.getDistributionUrl(); - const dataUrl = `${initialUrl}/index.json`; - let response = yield this.httpClient.getJson(dataUrl); - return response.result || []; - }); - } getManifest() { core.debug('Getting manifest from actions/node-versions@main'); return tc.getManifestFromRepo('actions', 'node-versions', this.nodeInfo.auth, 'main'); @@ -73739,15 +73722,6 @@ exports["default"] = OfficialBuilds; "use strict"; -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) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; @@ -73766,14 +73740,6 @@ class RcBuild extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); } - getNodejsVersions() { - return __awaiter(this, void 0, void 0, function* () { - const initialUrl = this.getDistributionUrl(); - const dataUrl = `${initialUrl}/index.json`; - let response = yield this.httpClient.getJson(dataUrl); - return response.result || []; - }); - } evaluateVersions(versions) { let version = ''; core.debug(`evaluating ${versions.length} versions`); @@ -73807,15 +73773,6 @@ exports["default"] = RcBuild; "use strict"; -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) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; @@ -73877,14 +73834,6 @@ class CanaryBuild extends base_distribution_1.default { } return version; } - getNodejsVersions() { - return __awaiter(this, void 0, void 0, function* () { - const initialUrl = this.getDistributionUrl(); - const dataUrl = `${initialUrl}/index.json`; - let response = yield this.httpClient.getJson(dataUrl); - return response.result || []; - }); - } createRangePreRelease(versionSpec, distribution = '') { let range; const [raw, prerelease] = this.splitVersionSpec(versionSpec); diff --git a/src/distibutions/base-distribution.ts b/src/distibutions/base-distribution.ts index f843e7328..5d4889547 100644 --- a/src/distibutions/base-distribution.ts +++ b/src/distibutions/base-distribution.ts @@ -24,7 +24,6 @@ export default abstract class BaseDistribution { } protected abstract getDistributionUrl(): string; - protected abstract getNodejsVersions(): Promise; protected abstract evaluateVersions(nodeVersions: string[]): string; public async getNodeJsInfo() { @@ -48,6 +47,14 @@ export default abstract class BaseDistribution { return tc.find('node', this.nodeInfo.versionSpec, this.nodeInfo.arch); } + protected async getNodejsVersions(): Promise { + const initialUrl = this.getDistributionUrl(); + const dataUrl = `${initialUrl}/index.json`; + + let response = await this.httpClient.getJson(dataUrl); + return response.result || []; + } + protected getNodejsDistInfo(version: string, osPlat: string) { let osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch); version = semver.clean(version) || ''; diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index ff8e824ec..d40e930f9 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -69,14 +69,6 @@ export default class NightlyNodejs extends BaseDistribution { return 'https://nodejs.org/download/nightly'; } - async getNodejsVersions(): Promise { - const initialUrl = this.getDistributionUrl(); - const dataUrl = `${initialUrl}/index.json`; - - let response = await this.httpClient.getJson(dataUrl); - return response.result || []; - } - protected createRangePreRelease( versionSpec: string, distribution: string = '' diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts index 85e68efd2..cb2c2b46b 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distibutions/official_builds/official_builds.ts @@ -131,14 +131,6 @@ export default class OfficialBuilds extends BaseDistribution { return `https://nodejs.org/dist`; } - protected async getNodejsVersions(): Promise { - const initialUrl = this.getDistributionUrl(); - const dataUrl = `${initialUrl}/index.json`; - - let response = await this.httpClient.getJson(dataUrl); - return response.result || []; - } - private getManifest(): Promise { core.debug('Getting manifest from actions/node-versions@main'); return tc.getManifestFromRepo( diff --git a/src/distibutions/official_builds/rc/rc_builds.ts b/src/distibutions/official_builds/rc/rc_builds.ts index 3c95fc957..d6e2d893b 100644 --- a/src/distibutions/official_builds/rc/rc_builds.ts +++ b/src/distibutions/official_builds/rc/rc_builds.ts @@ -10,14 +10,6 @@ export default class RcBuild extends BaseDistribution { super(nodeInfo); } - protected async getNodejsVersions(): Promise { - const initialUrl = this.getDistributionUrl(); - const dataUrl = `${initialUrl}/index.json`; - - let response = await this.httpClient.getJson(dataUrl); - return response.result || []; - } - protected evaluateVersions(versions: string[]): string { let version = ''; diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index 12d23eac8..9568dad1f 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -70,14 +70,6 @@ export default class CanaryBuild extends BaseDistribution { return version; } - async getNodejsVersions(): Promise { - const initialUrl = this.getDistributionUrl(); - const dataUrl = `${initialUrl}/index.json`; - - let response = await this.httpClient.getJson(dataUrl); - return response.result || []; - } - protected createRangePreRelease( versionSpec: string, distribution: string = '' From 8dacd853a5e721224c4de8ae6029ac316a126077 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 20 Dec 2022 21:09:50 +0100 Subject: [PATCH 35/51] minor changes --- dist/setup/index.js | 598 ++-------------- src/distibutions/base-distribution.ts | 23 +- .../official_builds/official_builds.ts | 58 +- src/installer.ts | 650 ------------------ src/main.ts | 36 +- 5 files changed, 158 insertions(+), 1207 deletions(-) delete mode 100644 src/installer.ts diff --git a/dist/setup/index.js b/dist/setup/index.js index 857ffcbe8..202415643 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73228,7 +73228,10 @@ class BaseDistribution { getNodeJsInfo() { return __awaiter(this, void 0, void 0, function* () { let toolPath = this.findVersionInHoostedToolCacheDirectory(); - if (!toolPath) { + if (toolPath) { + core.info(`Found in cache @ ${toolPath}`); + } + else { const nodeVersions = yield this.getNodejsVersions(); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); @@ -73270,7 +73273,6 @@ class BaseDistribution { } downloadNodejs(info) { return __awaiter(this, void 0, void 0, function* () { - let osPlat = os.platform(); let downloadPath = ''; try { downloadPath = yield tc.downloadTool(info.downloadUrl); @@ -73333,10 +73335,10 @@ class BaseDistribution { let extPath; info = info || {}; // satisfy compiler, never null when reaches here if (this.osPlat == 'win32') { - let _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe'); + const _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe'); extPath = yield tc.extract7z(downloadPath, undefined, _7zPath); // 7z extracts to folder matching file name - let nestedPath = path.join(extPath, path.basename(info.fileName, '.7z')); + const nestedPath = path.join(extPath, path.basename(info.fileName, '.7z')); if (fs_1.default.existsSync(nestedPath)) { extPath = nestedPath; } @@ -73356,12 +73358,11 @@ class BaseDistribution { return toolPath; }); } - getDistFileName(arch = os.arch()) { - let osPlat = os.platform(); + getDistFileName(arch) { let osArch = this.translateArchToDistUrl(arch); // node offers a json list of versions let dataFileName; - switch (osPlat) { + switch (this.osPlat) { case 'linux': dataFileName = `linux-${osArch}`; break; @@ -73372,12 +73373,12 @@ class BaseDistribution { dataFileName = `win-${osArch}-exe`; break; default: - throw new Error(`Unexpected OS '${osPlat}'`); + throw new Error(`Unexpected OS '${this.osPlat}'`); } return dataFileName; } filterVersions(nodeVersions) { - let versions = []; + const versions = []; const dataFileName = this.getDistFileName(this.nodeInfo.arch); nodeVersions.forEach((nodeVersion) => { // ensure this version supports your os and platform @@ -73582,8 +73583,8 @@ class OfficialBuilds extends base_distribution_1.default { } getNodeJsInfo() { return __awaiter(this, void 0, void 0, function* () { - let manifest = []; - let nodeVersions = []; + let manifest; + let nodeVersions; 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 @@ -73596,10 +73597,26 @@ class OfficialBuilds extends base_distribution_1.default { 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 osArch = this.translateArchToDistUrl(this.nodeInfo.arch); + const resolvedVersion = yield this.resolveVersionFromManifest(this.nodeInfo.versionSpec, 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.findVersionInHoostedToolCacheDirectory(); - if (!toolPath) { + if (toolPath) { + core.info(`Found in cache @ ${toolPath}`); + } + else { try { - const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, true, this.nodeInfo.auth, this.nodeInfo.arch, undefined); + core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); + const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.arch, manifest); if (versionInfo) { core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`); toolPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.auth); @@ -73639,8 +73656,7 @@ class OfficialBuilds extends base_distribution_1.default { return versions[0]; } core.debug(`evaluating ${versions.length} versions`); - for (let i = 0; i < versions.length; i++) { - const potential = versions[i]; + for (let potential of versions) { const satisfied = semver.satisfies(potential, this.nodeInfo.versionSpec); if (satisfied) { version = potential; @@ -73687,8 +73703,21 @@ class OfficialBuilds extends base_distribution_1.default { core.debug(`Found LTS release '${release.version}' for Node version '${versionSpec}'`); return release.version.split('.')[0]; } - getInfoFromManifest(versionSpec, stable, auth, osArch = this.translateArchToDistUrl(os_1.default.arch()), manifest) { + resolveVersionFromManifest(versionSpec, osArch = this.translateArchToDistUrl(os_1.default.arch()), manifest) { + return __awaiter(this, void 0, void 0, function* () { + try { + const info = yield this.getInfoFromManifest(versionSpec, osArch, manifest); + return info === null || info === void 0 ? void 0 : info.resolvedVersion; + } + catch (err) { + core.info('Unable to resolve version from manifest...'); + core.debug(err.message); + } + }); + } + getInfoFromManifest(versionSpec, osArch = this.translateArchToDistUrl(os_1.default.arch()), manifest) { return __awaiter(this, void 0, void 0, function* () { + const stable = true; let info = null; if (!manifest) { core.debug('No manifest cached'); @@ -73854,514 +73883,6 @@ class CanaryBuild extends base_distribution_1.default { exports["default"] = CanaryBuild; -/***/ }), - -/***/ 2574: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -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) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - 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 })); -const os_1 = __importDefault(__nccwpck_require__(2037)); -const assert = __importStar(__nccwpck_require__(9491)); -const core = __importStar(__nccwpck_require__(2186)); -const hc = __importStar(__nccwpck_require__(9925)); -const io = __importStar(__nccwpck_require__(7436)); -const tc = __importStar(__nccwpck_require__(7784)); -const path = __importStar(__nccwpck_require__(1017)); -const semver = __importStar(__nccwpck_require__(5911)); -const fs_1 = __importDefault(__nccwpck_require__(7147)); -var Distributions; -(function (Distributions) { - Distributions["DEFAULT"] = ""; - Distributions["CANARY"] = "-v8-canary"; - Distributions["NIGHTLY"] = "-nightly"; - Distributions["RC"] = "-rc"; -})(Distributions = exports.Distributions || (exports.Distributions = {})); -exports.distributionOf = (versionSpec) => { - if (versionSpec.includes(Distributions.CANARY)) - return Distributions.CANARY; - if (versionSpec.includes(Distributions.NIGHTLY)) - return Distributions.NIGHTLY; - if (semver.prerelease(versionSpec)) - return Distributions.RC; - return Distributions.DEFAULT; -}; -exports.semverVersionMatcherFactory = (range) => { - const matcher = (potential) => semver.satisfies(potential, range); - matcher.factory = exports.semverVersionMatcherFactory; - return matcher; -}; -exports.nightlyV8MatcherFactory = (version, distribution) => { - const { range, includePrerelease } = createRangePreRelease(version, distribution); - const matcher = (potential) => exports.distributionOf(potential) === distribution && - semver.satisfies(potential.replace(distribution, `${distribution}.`), range, { includePrerelease: includePrerelease }); - matcher.factory = exports.nightlyV8MatcherFactory; - return matcher; -}; -exports.splitVersionSpec = (versionSpec) => versionSpec.split(/-(.*)/s); -const createRangePreRelease = (versionSpec, distribution = '') => { - let range; - const [raw, prerelease] = exports.splitVersionSpec(versionSpec); - const isValidVersion = semver.valid(raw); - const rawVersion = (isValidVersion ? raw : semver.coerce(raw)); - if (`-${prerelease}` !== distribution) { - range = `${rawVersion}${`-${prerelease}`.replace(distribution, `${distribution}.`)}`; - } - else { - range = `${semver.validRange(`^${rawVersion}${distribution}`)}-0`; - } - return { range, includePrerelease: !isValidVersion }; -}; -function versionMatcherFactory(versionSpec) { - var _a; - const raw = exports.splitVersionSpec(versionSpec)[0]; - const validVersion = semver.valid(raw) ? raw : (_a = semver.coerce(raw)) === null || _a === void 0 ? void 0 : _a.version; - const distribution = exports.distributionOf(versionSpec); - if (validVersion) { - switch (distribution) { - case Distributions.CANARY: - case Distributions.NIGHTLY: - return exports.nightlyV8MatcherFactory(versionSpec, distribution); - case Distributions.RC: - case Distributions.DEFAULT: - return exports.semverVersionMatcherFactory(versionSpec); - } - } - else { - throw Error(`Invalid version input "${versionSpec}"`); - } -} -exports.versionMatcherFactory = versionMatcherFactory; -function getNode(versionSpec, stable, checkLatest, auth, arch = os_1.default.arch()) { - return __awaiter(this, void 0, void 0, function* () { - // Store manifest data to avoid multiple calls - let manifest; - let nodeVersions; - const osPlat = os_1.default.platform(); - const osArch = translateArchToDistUrl(arch); - const distribution = exports.distributionOf(versionSpec); - 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 = yield getManifest(auth); - versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); - } - if (isLatestSyntax(versionSpec)) { - nodeVersions = yield getVersionsFromDist(versionSpec); - versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); - core.info(`getting latest node version ${versionSpec}...`); - } - if ((distribution === Distributions.NIGHTLY || - distribution === Distributions.CANARY) && - checkLatest) { - nodeVersions = yield getVersionsFromDist(versionSpec); - versionSpec = yield queryDistForMatch(versionSpec, arch, nodeVersions); - } - if (checkLatest && - distribution !== Distributions.NIGHTLY && - distribution !== Distributions.CANARY) { - core.info('Attempt to resolve the latest version from manifest...'); - const resolvedVersion = yield 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; - if (distribution === Distributions.DEFAULT) { - toolPath = tc.find('node', versionSpec, osArch); - } - else { - const localVersionPaths = tc.findAllVersions('node', osArch); - const localVersion = evaluateVersions(localVersionPaths, versionSpec); - toolPath = localVersion && tc.find('node', localVersion, 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 = null; - // - // Try download from internal distribution (popular versions only) - // - try { - info = yield getInfoFromManifest(versionSpec, stable, auth, osArch, manifest); - if (info) { - core.info(`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`); - downloadPath = yield 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 = yield 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 = yield tc.downloadTool(info.downloadUrl); - } - catch (err) { - if (err instanceof tc.HTTPError && err.httpStatusCode == 404) { - return yield acquireNodeFromFallbackLocation(info.resolvedVersion, info.arch); - } - throw err; - } - } - // - // Extract - // - core.info('Extracting ...'); - let extPath; - info = info || {}; // satisfy compiler, never null when reaches here - if (osPlat == 'win32') { - let _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe'); - extPath = yield tc.extract7z(downloadPath, undefined, _7zPath); - // 7z extracts to folder matching file name - let nestedPath = path.join(extPath, path.basename(info.fileName, '.7z')); - if (fs_1.default.existsSync(nestedPath)) { - extPath = nestedPath; - } - } - else { - extPath = yield 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 = yield 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); - }); -} -exports.getNode = getNode; -function isLtsAlias(versionSpec) { - return versionSpec.startsWith('lts/'); -} -exports.isLtsAlias = isLtsAlias; -function getManifest(auth) { - core.debug('Getting manifest from actions/node-versions@main'); - return tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); -} -function resolveLtsAliasFromManifest(versionSpec, stable, manifest) { - var _a; - const alias = (_a = versionSpec.split('lts/')[1]) === null || _a === void 0 ? void 0 : _a.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/`, `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]; -} -exports.resolveLtsAliasFromManifest = resolveLtsAliasFromManifest; -function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os_1.default.arch()), manifest) { - return __awaiter(this, void 0, void 0, function* () { - let info = null; - if (!manifest) { - core.debug('No manifest cached'); - manifest = yield getManifest(auth); - } - const rel = yield tc.findFromManifest(versionSpec, stable, manifest, osArch); - if (rel && rel.files.length > 0) { - info = {}; - 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; - }); -} -function getInfoFromDist(versionSpec, arch = os_1.default.arch(), nodeVersions) { - return __awaiter(this, void 0, void 0, function* () { - let osPlat = os_1.default.platform(); - let osArch = translateArchToDistUrl(arch); - let version = yield 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 = osPlat == 'win32' - ? `node-v${version}-win-${osArch}` - : `node-v${version}-${osPlat}-${osArch}`; - let urlFileName = osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; - const initialUrl = getNodejsDistUrl(versionSpec); - const url = `${initialUrl}/v${version}/${urlFileName}`; - return { - downloadUrl: url, - resolvedVersion: version, - arch: arch, - fileName: fileName - }; - }); -} -function resolveVersionFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os_1.default.arch()), manifest) { - return __awaiter(this, void 0, void 0, function* () { - try { - const info = yield getInfoFromManifest(versionSpec, stable, auth, osArch, manifest); - return info === null || info === void 0 ? void 0 : info.resolvedVersion; - } - catch (err) { - core.info('Unable to resolve version from manifest...'); - core.debug(err.message); - } - }); -} -// TODO - should we just export this from @actions/tool-cache? Lifted directly from there -// - the answer from dsame@github.com - we have customized matcher and can not -// export `evaluateVersions` from tc. But it would be possible to modify tc to accept -// the matcher as an optional parameter to `evaluateVersions` -function evaluateVersions(versions, versionSpec) { - core.debug(`evaluating ${versions.length} versions`); - const matcher = versionMatcherFactory(versionSpec); - const version = versions.sort(semver.rcompare).find(matcher) || ''; - if (version) { - core.debug(`matched: ${version}`); - } - else { - core.debug('match not found'); - } - return version; -} -exports.evaluateVersions = evaluateVersions; -function getNodejsDistUrl(version) { - switch (exports.distributionOf(version)) { - case Distributions.CANARY: - return 'https://nodejs.org/download/v8-canary'; - case Distributions.NIGHTLY: - return 'https://nodejs.org/download/nightly'; - case Distributions.RC: - return 'https://nodejs.org/download/rc'; - case Distributions.DEFAULT: - return 'https://nodejs.org/dist'; - } -} -exports.getNodejsDistUrl = getNodejsDistUrl; -function queryDistForMatch(versionSpec, arch = os_1.default.arch(), nodeVersions) { - return __awaiter(this, void 0, void 0, function* () { - let osPlat = os_1.default.platform(); - let osArch = translateArchToDistUrl(arch); - // node offers a json list of versions - let dataFileName; - 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 = yield getVersionsFromDist(versionSpec); - } - if (isLatestSyntax(versionSpec)) { - core.info(`getting latest node version...`); - return nodeVersions[0].version; - } - const versions = []; - nodeVersions.forEach((nodeVersion) => { - // 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 - const version = evaluateVersions(versions, versionSpec); - return version; - }); -} -exports.queryDistForMatch = queryDistForMatch; -function getVersionsFromDist(versionSpec) { - return __awaiter(this, void 0, void 0, function* () { - const distUrl = getNodejsDistUrl(versionSpec); - const dataUrl = `${distUrl}/index.json`; - let httpClient = new hc.HttpClient('setup-node', [], { - allowRetries: true, - maxRetries: 3 - }); - let response = yield httpClient.getJson(dataUrl); - return response.result || []; - }); -} -exports.getVersionsFromDist = getVersionsFromDist; -// 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. -function acquireNodeFromFallbackLocation(version, arch = os_1.default.arch()) { - return __awaiter(this, void 0, void 0, function* () { - const initialUrl = getNodejsDistUrl(version); - let osPlat = os_1.default.platform(); - let osArch = translateArchToDistUrl(arch); - // Create temporary folder to download in to - const tempDownloadFolder = 'temp_' + Math.floor(Math.random() * 2000000000); - const tempDirectory = process.env['RUNNER_TEMP'] || ''; - assert.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined'); - const tempDir = path.join(tempDirectory, tempDownloadFolder); - yield io.mkdirP(tempDir); - let exeUrl; - let libUrl; - 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 = yield tc.downloadTool(exeUrl); - yield io.cp(exePath, path.join(tempDir, 'node.exe')); - const libPath = yield tc.downloadTool(libUrl); - yield 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 = yield tc.downloadTool(exeUrl); - yield io.cp(exePath, path.join(tempDir, 'node.exe')); - const libPath = yield tc.downloadTool(libUrl); - yield io.cp(libPath, path.join(tempDir, 'node.lib')); - } - else { - throw err; - } - } - let toolPath = yield 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) { - switch (arch) { - case 'arm': - return 'armv7l'; - default: - return arch; - } -} -function parseNodeVersionFile(contents) { - var _a, _b, _c; - let nodeVersion; - // Try parsing the file as an NPM `package.json` file. - try { - nodeVersion = (_a = JSON.parse(contents).volta) === null || _a === void 0 ? void 0 : _a.node; - if (!nodeVersion) - nodeVersion = (_b = JSON.parse(contents).engines) === null || _b === void 0 ? void 0 : _b.node; - } - catch (_d) { - core.info('Node version file is not JSON file'); - } - if (!nodeVersion) { - const found = contents.match(/^(?:nodejs\s+)?v?(?[^\s]+)$/m); - nodeVersion = (_c = found === null || found === void 0 ? void 0 : found.groups) === null || _c === void 0 ? void 0 : _c.version; - } - // In the case of an unknown format, - // return as is and evaluate the version separately. - if (!nodeVersion) - nodeVersion = contents.trim(); - return nodeVersion; -} -exports.parseNodeVersionFile = parseNodeVersionFile; -function isLatestSyntax(versionSpec) { - return ['current', 'latest', 'node'].includes(versionSpec); -} -exports.isLatestSyntax = isLatestSyntax; - - /***/ }), /***/ 399: @@ -74391,13 +73912,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); -const installer = __importStar(__nccwpck_require__(2574)); const fs_1 = __importDefault(__nccwpck_require__(7147)); +const os_1 = __importDefault(__nccwpck_require__(2037)); const auth = __importStar(__nccwpck_require__(7573)); const path = __importStar(__nccwpck_require__(1017)); const cache_restore_1 = __nccwpck_require__(9517); const cache_utils_1 = __nccwpck_require__(1678); -const os_1 = __importDefault(__nccwpck_require__(2037)); const installer_factory_1 = __nccwpck_require__(1260); function run() { return __awaiter(this, void 0, void 0, function* () { @@ -74434,7 +73954,6 @@ function run() { else { throw new Error(`Could not resolve version: ${version} for build`); } - // await installer.getNode(version, stable, checkLatest, auth, arch); } yield printEnvDetailsAndSetOutput(); const registryUrl = core.getInput('registry-url'); @@ -74471,11 +73990,34 @@ function resolveVersionInput() { if (!fs_1.default.existsSync(versionFilePath)) { throw new Error(`The specified node version file at: ${versionFilePath} does not exist`); } - version = installer.parseNodeVersionFile(fs_1.default.readFileSync(versionFilePath, 'utf8')); + version = parseNodeVersionFile(fs_1.default.readFileSync(versionFilePath, 'utf8')); core.info(`Resolved ${versionFileInput} as ${version}`); } return version; } +function parseNodeVersionFile(contents) { + var _a, _b, _c; + let nodeVersion; + // Try parsing the file as an NPM `package.json` file. + try { + nodeVersion = (_a = JSON.parse(contents).volta) === null || _a === void 0 ? void 0 : _a.node; + if (!nodeVersion) + nodeVersion = (_b = JSON.parse(contents).engines) === null || _b === void 0 ? void 0 : _b.node; + } + catch (_d) { + core.info('Node version file is not JSON file'); + } + if (!nodeVersion) { + const found = contents.match(/^(?:nodejs\s+)?v?(?[^\s]+)$/m); + nodeVersion = (_c = found === null || found === void 0 ? void 0 : found.groups) === null || _c === void 0 ? void 0 : _c.version; + } + // In the case of an unknown format, + // return as is and evaluate the version separately. + if (!nodeVersion) + nodeVersion = contents.trim(); + return nodeVersion; +} +exports.parseNodeVersionFile = parseNodeVersionFile; function printEnvDetailsAndSetOutput() { return __awaiter(this, void 0, void 0, function* () { core.startGroup('Environment details'); diff --git a/src/distibutions/base-distribution.ts b/src/distibutions/base-distribution.ts index 5d4889547..74edb47f1 100644 --- a/src/distibutions/base-distribution.ts +++ b/src/distibutions/base-distribution.ts @@ -28,7 +28,9 @@ export default abstract class BaseDistribution { public async getNodeJsInfo() { let toolPath = this.findVersionInHoostedToolCacheDirectory(); - if (!toolPath) { + if (toolPath) { + core.info(`Found in cache @ ${toolPath}`); + } else { const nodeVersions = await this.getNodejsVersions(); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); @@ -76,7 +78,6 @@ export default abstract class BaseDistribution { } protected async downloadNodejs(info: INodeVersionInfo) { - let osPlat: string = os.platform(); let downloadPath = ''; try { downloadPath = await tc.downloadTool(info.downloadUrl); @@ -136,7 +137,9 @@ export default abstract class BaseDistribution { throw err; } } + const toolPath = await tc.cacheDir(tempDir, 'node', version, arch); + return toolPath; } @@ -151,10 +154,13 @@ export default abstract class BaseDistribution { let extPath: string; info = info || ({} as INodeVersionInfo); // satisfy compiler, never null when reaches here if (this.osPlat == 'win32') { - let _7zPath = path.join(__dirname, '../..', 'externals', '7zr.exe'); + const _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')); + const nestedPath = path.join( + extPath, + path.basename(info.fileName, '.7z') + ); if (fs.existsSync(nestedPath)) { extPath = nestedPath; } @@ -180,13 +186,12 @@ export default abstract class BaseDistribution { return toolPath; } - protected getDistFileName(arch: string = os.arch()): string { - let osPlat: string = os.platform(); + protected getDistFileName(arch: string): string { let osArch: string = this.translateArchToDistUrl(arch); // node offers a json list of versions let dataFileName: string; - switch (osPlat) { + switch (this.osPlat) { case 'linux': dataFileName = `linux-${osArch}`; break; @@ -197,14 +202,14 @@ export default abstract class BaseDistribution { dataFileName = `win-${osArch}-exe`; break; default: - throw new Error(`Unexpected OS '${osPlat}'`); + throw new Error(`Unexpected OS '${this.osPlat}'`); } return dataFileName; } protected filterVersions(nodeVersions: INodeVersion[]) { - let versions: string[] = []; + const versions: string[] = []; const dataFileName = this.getDistFileName(this.nodeInfo.arch); diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts index cb2c2b46b..f518ee1fe 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distibutions/official_builds/official_builds.ts @@ -4,9 +4,8 @@ import * as semver from 'semver'; import os from 'os'; import path from 'path'; -import {INodeVersion} from '../../installer'; import BaseDistribution from '../base-distribution'; -import {INodejs, INodeVersionInfo} from '../base-models'; +import {INodejs, INodeVersion, INodeVersionInfo} from '../base-models'; interface INodeRelease extends tc.IToolRelease { lts?: string; @@ -18,8 +17,8 @@ export default class OfficialBuilds extends BaseDistribution { } public async getNodeJsInfo() { - let manifest: tc.IToolRelease[] = []; - let nodeVersions: INodeVersion[] = []; + let manifest: tc.IToolRelease[] | undefined; + let nodeVersions: INodeVersion[] | undefined; if (this.isLtsAlias(this.nodeInfo.versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); @@ -41,16 +40,35 @@ export default class OfficialBuilds extends BaseDistribution { core.info(`getting latest node version...`); } + if (this.nodeInfo.checkLatest) { + core.info('Attempt to resolve the latest version from manifest...'); + const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); + const resolvedVersion = await this.resolveVersionFromManifest( + this.nodeInfo.versionSpec, + 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.findVersionInHoostedToolCacheDirectory(); - if (!toolPath) { + if (toolPath) { + core.info(`Found in cache @ ${toolPath}`); + } else { try { + core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); const versionInfo = await this.getInfoFromManifest( this.nodeInfo.versionSpec, - true, - this.nodeInfo.auth, this.nodeInfo.arch, - undefined + manifest ); if (versionInfo) { core.info( @@ -106,8 +124,7 @@ export default class OfficialBuilds extends BaseDistribution { core.debug(`evaluating ${versions.length} versions`); - for (let i = 0; i < versions.length; i++) { - const potential: string = versions[i]; + for (let potential of versions) { const satisfied: boolean = semver.satisfies( potential, this.nodeInfo.versionSpec @@ -185,13 +202,30 @@ export default class OfficialBuilds extends BaseDistribution { return release.version.split('.')[0]; } + private async resolveVersionFromManifest( + versionSpec: string, + osArch: string = this.translateArchToDistUrl(os.arch()), + manifest: tc.IToolRelease[] | undefined + ): Promise { + try { + const info = await this.getInfoFromManifest( + versionSpec, + 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, - auth: string | undefined, osArch: string = this.translateArchToDistUrl(os.arch()), manifest: tc.IToolRelease[] | undefined ): Promise { + const stable = true; let info: INodeVersionInfo | null = null; if (!manifest) { core.debug('No manifest cached'); diff --git a/src/installer.ts b/src/installer.ts deleted file mode 100644 index ffee7dd5e..000000000 --- a/src/installer.ts +++ /dev/null @@ -1,650 +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 -// for canary https://nodejs.org/download/v8-canary/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 enum Distributions { - DEFAULT = '', - CANARY = '-v8-canary', - NIGHTLY = '-nightly', - RC = '-rc' -} - -export const distributionOf = (versionSpec: string): Distributions => { - if (versionSpec.includes(Distributions.CANARY)) return Distributions.CANARY; - if (versionSpec.includes(Distributions.NIGHTLY)) return Distributions.NIGHTLY; - if (semver.prerelease(versionSpec)) return Distributions.RC; - return Distributions.DEFAULT; -}; - -interface VersionMatcher { - (potential: string): boolean; - - // memoize the factory for testing and debug purposes - factory: - | ((ver: string, suffix: string) => VersionMatcher) - | ((semverRanger: string) => VersionMatcher) - | (() => VersionMatcher); -} - -export const semverVersionMatcherFactory = (range: string): VersionMatcher => { - const matcher = (potential: string): boolean => - semver.satisfies(potential, range); - - matcher.factory = semverVersionMatcherFactory; - return matcher; -}; - -export const nightlyV8MatcherFactory = ( - version: string, - distribution: string -): VersionMatcher => { - const {range, includePrerelease} = createRangePreRelease( - version, - distribution - )!; - const matcher = (potential: string): boolean => - distributionOf(potential) === distribution && - semver.satisfies( - potential.replace(distribution, `${distribution}.`), - range!, - {includePrerelease: includePrerelease} - ); - matcher.factory = nightlyV8MatcherFactory; - return matcher; -}; - -export const splitVersionSpec = (versionSpec: string): string[] => - versionSpec.split(/-(.*)/s); - -const createRangePreRelease = ( - versionSpec: string, - distribution: string = '' -) => { - let range: string | undefined; - const [raw, prerelease] = splitVersionSpec(versionSpec); - const isValidVersion = semver.valid(raw); - const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; - - if (`-${prerelease}` !== distribution) { - range = `${rawVersion}${`-${prerelease}`.replace( - distribution, - `${distribution}.` - )}`; - } else { - range = `${semver.validRange(`^${rawVersion}${distribution}`)}-0`; - } - - return {range, includePrerelease: !isValidVersion}; -}; - -export function versionMatcherFactory(versionSpec: string): VersionMatcher { - const raw = splitVersionSpec(versionSpec)[0]; - const validVersion = semver.valid(raw) ? raw : semver.coerce(raw)?.version; - const distribution = distributionOf(versionSpec); - - if (validVersion) { - switch (distribution) { - case Distributions.CANARY: - case Distributions.NIGHTLY: - return nightlyV8MatcherFactory(versionSpec, distribution); - case Distributions.RC: - case Distributions.DEFAULT: - return semverVersionMatcherFactory(versionSpec); - } - } else { - throw Error(`Invalid version input "${versionSpec}"`); - } -} - -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; - const osPlat: string = os.platform(); - const osArch: string = translateArchToDistUrl(arch); - const distribution = distributionOf(versionSpec); - - 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 ${versionSpec}...`); - } - - if ( - (distribution === Distributions.NIGHTLY || - distribution === Distributions.CANARY) && - checkLatest - ) { - nodeVersions = await getVersionsFromDist(versionSpec); - versionSpec = await queryDistForMatch(versionSpec, arch, nodeVersions); - } - - if ( - checkLatest && - distribution !== Distributions.NIGHTLY && - distribution !== Distributions.CANARY - ) { - 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 (distribution === Distributions.DEFAULT) { - toolPath = tc.find('node', versionSpec, osArch); - } else { - const localVersionPaths = tc.findAllVersions('node', osArch); - const localVersion = evaluateVersions(localVersionPaths, versionSpec); - toolPath = localVersion && tc.find('node', localVersion, 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); -} - -export function isLtsAlias(versionSpec: string): boolean { - return versionSpec.startsWith('lts/'); -} - -function getManifest(auth: string | undefined): Promise { - core.debug('Getting manifest from actions/node-versions@main'); - return tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); -} - -export 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/`, `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 { - 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 = {}; - 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 { - 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 { - 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 { - try { - const info = await getInfoFromManifest( - versionSpec, - stable, - auth, - osArch, - manifest - ); - return info?.resolvedVersion; - } catch (err) { - core.info('Unable to resolve version from manifest...'); - core.debug(err.message); - } -} - -// TODO - should we just export this from @actions/tool-cache? Lifted directly from there -// - the answer from dsame@github.com - we have customized matcher and can not -// export `evaluateVersions` from tc. But it would be possible to modify tc to accept -// the matcher as an optional parameter to `evaluateVersions` -export function evaluateVersions( - versions: string[], - versionSpec: string -): string { - core.debug(`evaluating ${versions.length} versions`); - - const matcher = versionMatcherFactory(versionSpec); - const version = versions.sort(semver.rcompare).find(matcher) || ''; - - if (version) { - core.debug(`matched: ${version}`); - } else { - core.debug('match not found'); - } - - return version; -} - -export function getNodejsDistUrl(version: string) { - switch (distributionOf(version)) { - case Distributions.CANARY: - return 'https://nodejs.org/download/v8-canary'; - case Distributions.NIGHTLY: - return 'https://nodejs.org/download/nightly'; - case Distributions.RC: - return 'https://nodejs.org/download/rc'; - case Distributions.DEFAULT: - return 'https://nodejs.org/dist'; - } -} - -export async function queryDistForMatch( - versionSpec: string, - arch: string = os.arch(), - nodeVersions?: INodeVersion[] -): Promise { - 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); - } - - if (isLatestSyntax(versionSpec)) { - core.info(`getting latest node version...`); - return nodeVersions[0].version; - } - - const versions: string[] = []; - 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 - const version = evaluateVersions(versions, versionSpec); - return version; -} - -export async function getVersionsFromDist( - versionSpec: string -): Promise { - const distUrl = getNodejsDistUrl(versionSpec); - const dataUrl = `${distUrl}/index.json`; - let httpClient = new hc.HttpClient('setup-node', [], { - allowRetries: true, - maxRetries: 3 - }); - let response = await httpClient.getJson(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 { - 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?(?[^\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 function isLatestSyntax(versionSpec): boolean { - return ['current', 'latest', 'node'].includes(versionSpec); -} diff --git a/src/main.ts b/src/main.ts index fb7e92865..e2c985796 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,12 +1,13 @@ 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 './distibutions/installer-factory'; export async function run() { @@ -49,8 +50,6 @@ export async function run() { } else { throw new Error(`Could not resolve version: ${version} for build`); } - - // await installer.getNode(version, stable, checkLatest, auth, arch); } await printEnvDetailsAndSetOutput(); @@ -105,9 +104,7 @@ function resolveVersionInput(): string { ); } - version = installer.parseNodeVersionFile( - fs.readFileSync(versionFilePath, 'utf8') - ); + version = parseNodeVersionFile(fs.readFileSync(versionFilePath, 'utf8')); core.info(`Resolved ${versionFileInput} as ${version}`); } @@ -115,6 +112,29 @@ function resolveVersionInput(): string { return version; } +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?(?[^\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'); From 2723204c59432563a403f623c958794fab3aeae9 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 22 Dec 2022 00:05:42 +0100 Subject: [PATCH 36/51] restructure tests --- __tests__/canary-installer.test.ts | 531 ++++++++++++++ __tests__/installer.unit.test.ts | 362 ---------- __tests__/main.test.ts | 295 ++++++++ __tests__/nightly-installer.test.ts | 517 ++++++++++++++ ...ler.test.ts => official-installer.test.ts} | 649 +----------------- __tests__/rc-installer.test.ts | 402 +++++++++++ dist/setup/index.js | 107 ++- src/distibutions/base-distribution.ts | 20 +- src/distibutions/installer-factory.ts | 6 +- src/distibutions/nightly/nightly_builds.ts | 1 + .../official_builds/official_builds.ts | 32 +- src/distibutions/v8-canary/canary_builds.ts | 2 +- src/main.ts | 71 +- src/util.ts | 63 ++ 14 files changed, 1955 insertions(+), 1103 deletions(-) create mode 100644 __tests__/canary-installer.test.ts delete mode 100644 __tests__/installer.unit.test.ts create mode 100644 __tests__/main.test.ts create mode 100644 __tests__/nightly-installer.test.ts rename __tests__/{installer.test.ts => official-installer.test.ts} (53%) create mode 100644 __tests__/rc-installer.test.ts create mode 100644 src/util.ts diff --git a/__tests__/canary-installer.test.ts b/__tests__/canary-installer.test.ts new file mode 100644 index 000000000..9ce645c66 --- /dev/null +++ b/__tests__/canary-installer.test.ts @@ -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/distibutions/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( + () => nodeTestManifest + ); + + getJsonSpy.mockImplementation(url => { + let res: any; + if (url.includes('/rc')) { + res = nodeTestDistRc; + } else if (url.includes('/nightly')) { + res = nodeTestDistNightly; + } else if (url.includes('/v8-canary')) { + res = nodeV8CanaryTestDist; + } else { + res = 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(); + }); + }); +}); diff --git a/__tests__/installer.unit.test.ts b/__tests__/installer.unit.test.ts deleted file mode 100644 index 11d4b1bb0..000000000 --- a/__tests__/installer.unit.test.ts +++ /dev/null @@ -1,362 +0,0 @@ -import semver from 'semver'; -import { - canaryExactVersionMatcherFactory, - canaryRangeVersionMatcherFactory, - distributionOf, - Distributions, - evaluateVersions, - getNodejsDistUrl, - nightlyExactVersionMatcherFactory, - nightlyRangeVersionMatcherFactory, - semverVersionMatcherFactory, - splitVersionSpec, - versionMatcherFactory -} from '../src/installer'; - -describe('setup-node unit tests', () => { - describe('splitVersionSpec', () => { - it('splitVersionSpec correctly splits version spec without dashes', () => { - const [raw, prerelease] = splitVersionSpec('1.1.1'); - expect(raw).toBe('1.1.1'); - expect(prerelease).toBeUndefined(); - }); - it('splitVersionSpec correctly splits version spec with one dash', () => { - const [raw, prerelease] = splitVersionSpec('1.1.1-nightly12345678'); - expect(raw).toBe('1.1.1'); - expect(prerelease).toBe('nightly12345678'); - }); - it('splitVersionSpec correctly splits version spec with 2 dashes', () => { - const [raw, prerelease] = splitVersionSpec('1.1.1-v8-canary12345678'); - expect(raw).toBe('1.1.1'); - expect(prerelease).toBe('v8-canary12345678'); - }); - }); - - describe('distributionOf', () => { - it('1.1.1-v8-canary should be CANARY', () => { - expect(distributionOf('1.1.1-v8-canary')).toBe(Distributions.CANARY); - }); - it('1.1.1-v8-canary20221103f7e2421e91 should be CANARY', () => { - expect(distributionOf('1.1.1-v8-canary20221103f7e2421e91')).toBe( - Distributions.CANARY - ); - }); - it('1.1.1-nightly should be NIGHTLY', () => { - expect(distributionOf('1.1.1-nightly')).toBe(Distributions.NIGHTLY); - }); - it('1.1.1-nightly20221103f7e2421e91 should be NIGHTLY', () => { - expect(distributionOf('1.1.1-nightly20221103f7e2421e91')).toBe( - Distributions.NIGHTLY - ); - }); - it('1.1.1-rc.0 should be RC', () => { - expect(distributionOf('1.1.1-rc.0')).toBe(Distributions.RC); - }); - }); - - describe('versionMatcherFactory', () => { - it('1.1.1 should be handled by semverVersionMatcherFactory', () => { - expect(versionMatcherFactory('1.1.1').factory).toBe( - semverVersionMatcherFactory - ); - }); - it('v1.1.1 should be handled by semverVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1').factory).toBe( - semverVersionMatcherFactory - ); - }); - it('v1.1.1-v8-canary should be handled by canaryRangeVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-v8-canary').factory).toBe( - canaryRangeVersionMatcherFactory - ); - }); - it('v1.1.1-v8-canary123 should be handled by canaryExactVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-v8-canary123').factory).toBe( - canaryExactVersionMatcherFactory - ); - }); - it('v1.1.1-nightly should be handled by nightlyRangeVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-nightly').factory).toBe( - nightlyRangeVersionMatcherFactory - ); - }); - it('v1.1.1-nigthly123 should be handled by nightlyExactVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-nightly123').factory).toBe( - nightlyExactVersionMatcherFactory - ); - }); - it('v1.1.1-rc should be handled by semverVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-rc').factory).toBe( - semverVersionMatcherFactory - ); - }); - it('v1.1.1-rc.1 should be handled by semverVersionMatcherFactory', () => { - expect(versionMatcherFactory('v1.1.1-rc.1').factory).toBe( - semverVersionMatcherFactory - ); - }); - }); - - describe('Version spec matchers', () => { - describe('semverVersionMatcher', () => { - it('semverVersionMatcher should always work as semver.satisfies does', () => { - const rangePlain = '1.1.1'; - const matcherPlain = semverVersionMatcherFactory(rangePlain); - expect(matcherPlain('1.1.1')).toBe( - semver.satisfies('1.1.1', rangePlain) - ); - expect(matcherPlain('1.1.2')).toBe( - semver.satisfies('1.1.2', rangePlain) - ); - - const rangeEq = '=1.1.1'; - const matcherEq = semverVersionMatcherFactory(rangeEq); - expect(matcherEq('1.1.1')).toBe(semver.satisfies('1.1.1', rangeEq)); - expect(matcherEq('1.1.2')).toBe(semver.satisfies('1.1.2', rangeEq)); - - // TODO: add for discovered issues if any - }); - - it("semverVersionMatcher should match release candidate as semver.satisfies does'", () => { - const rangePlain = 'v19.0.0-rc.2'; - const matcherPlain = semverVersionMatcherFactory(rangePlain); - expect(matcherPlain('v19.0.0-rc.2')).toBe( - semver.satisfies('v19.0.0-rc.2', rangePlain) - ); - expect(matcherPlain('v19.0.1-rc.2')).toBe( - semver.satisfies('v19.0.01rc.2', rangePlain) - ); - - const rangeEq = '=1.1.1'; - const matcherEq = semverVersionMatcherFactory(rangeEq); - expect(matcherPlain('v19.0.0-rc.2')).toBe( - semver.satisfies('v19.0.0-rc.2', rangePlain) - ); - expect(matcherPlain('v19.0.1-rc.2')).toBe( - semver.satisfies('v19.0.1-rc.2', rangePlain) - ); - }); - }); - - describe('canaryExactVersionMatcher', () => { - it('canaryExactVersionMatcher should match v20.0.0-v8-canary20221103f7e2421e91 only v20.0.0-v8-canary20221103f7e2421e91', () => { - const version = semver.coerce('v20.0.0')!.version; - const matcher = canaryExactVersionMatcherFactory( - version, - 'v8-canary20221103f7e2421e91' - ); - expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - // see https://github.com/actions/setup-node/blob/00e1b6691b40cce14b5078cb411dd1ec7dab07f7/__tests__/verify-node.sh#L10 - expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeFalsy(); - }); - }); - - describe('canaryRangeVersionMatcherFactory', () => { - it('canaryRangeVersionMatcherFactory should match v20-v8-canary to any v20.x.x', () => { - const version = semver.coerce('v20')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.0.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.0.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.0.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); - }); - - it('canaryRangeVersionMatcherFactory should not match v20-v8-canary to v21.x & v19.x', () => { - const version = semver.coerce('v20')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.1.1-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.1.-v8-canary20221103f7e2421e91')).toBeFalsy(); - }); - - it('canaryRangeVersionMatcherFactory should match v20.1-v8-canary to any v20.1.x patch version and minor above or eq v20.1', () => { - const version = semver.coerce('v20.1')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.0-v8-canary202211026bf85d0fb4')).toBeTruthy(); - expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - }); - - it('canaryRangeVersionMatcherFactory should not match v20.2-v8-canary to v21.x, v19.x, and v20 minor less than v20.2', () => { - const version = semver.coerce('v20.2')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - }); - - it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to v20.1.x patch versions above or eq v20.1.1', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = canaryRangeVersionMatcherFactory('v20.1.1-v8-canary'); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.2-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.2.0-v8-canary20221103f7e2421e91')).toBeTruthy(); - }); - - it('canaryRangeVersionMatcherFactory should not match v20.1.1-v8-canary to any other minor versions and patch versions below v20.1.1', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-v8-canary20221103f7e2421e91')).toBeFalsy(); - }); - - it('canaryRangeVersionMatcherFactory should match v20.1.1-v8-canary to patch versions with any canary timestamp', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = canaryRangeVersionMatcherFactory(version); - expect(matcher('v20.1.1-v8-canary20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-v8-canary202211026bf85d0fb4')).toBeTruthy(); - }); - }); - - describe('nightlyRangeVersionMatcherFactory', () => { - it('nightlyRangeVersionMatcherFactory should match v20-nightly to any v20.x.x', () => { - const version = semver.coerce('v20')!.version; - const matcher = nightlyRangeVersionMatcherFactory(version); - expect(matcher('v20.0.0-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.0.1-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.0-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.0.0-nightly202211026bf85d0fb4')).toBeTruthy(); - }); - - it('nightlyRangeVersionMatcherFactory should not match v20-nightly to v21.x & v19.x', () => { - const version = semver.coerce('v20')!.version; - const matcher = nightlyRangeVersionMatcherFactory(version); - expect(matcher('v21.0.0-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.1.0-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.1.1-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.1.0-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.1.-nightly20221103f7e2421e91')).toBeFalsy(); - }); - - it('nightlyRangeVersionMatcherFactory should match v20.1-nightly to any v20.1.x patch version and minor above or eq v20.1', () => { - const version = semver.coerce('v20.1')!.version; - const matcher = nightlyRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.0-nightly202211026bf85d0fb4')).toBeTruthy(); - expect(matcher('v20.2.0-nightly20221103f7e2421e91')).toBeTruthy(); - }); - - it('nightlyRangeVersionMatcherFactory should not match v20.2-nightly to v21.x, v19.x, and v20 minor less v20.2', () => { - const version = semver.coerce('v20.2')!.version; - const matcher = nightlyRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.0.0-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-nightly20221103f7e2421e91')).toBeFalsy(); - }); - - it('nightlyRangeVersionMatcherFactory should match v20.1.1-nightly to v20.1.x patch versions above or eq v20.1.1', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = nightlyRangeVersionMatcherFactory('v20.1.1-nightly'); - expect(matcher('v20.1.1-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.2-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.2.0-nightly20221103f7e2421e91')).toBeTruthy(); - }); - - it('nightlyRangeVersionMatcherFactory should not match v20.1.1-nightly to any other minor versions and patch versions below v20.1.1', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = nightlyRangeVersionMatcherFactory(version); - expect(matcher('v20.1.0-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v21.0.0-nightly20221103f7e2421e91')).toBeFalsy(); - expect(matcher('v19.0.0-nightly20221103f7e2421e91')).toBeFalsy(); - }); - - it('nightlyRangeVersionMatcherFactory should match v20.1.1-nightly to patch versions with any timestamp', () => { - const version = semver.coerce('v20.1.1')!.version; - const matcher = nightlyRangeVersionMatcherFactory(version); - expect(matcher('v20.1.1-nightly20221103f7e2421e91')).toBeTruthy(); - expect(matcher('v20.1.1-nightly202211026bf85d0fb4')).toBeTruthy(); - }); - }); - }); - - describe('evaluateVersions', () => { - it('evaluateVersions should handle v8-canary version spec without timestamp', () => { - const versions = [ - 'v20.0.0-v8-canary20221103f7e2421e91', - 'v20.0.1-v8-canary20221103f7e2421e91', - 'v20.1.0-v8-canary20221103f7e2421e91', - 'v20.1.1-v8-canary20221103f7e2421e91', - 'v21.1.0-v8-canary20221103f7e2421e91', - 'v19.1.0-v8-canary20221103f7e2421e91' - ]; - const version = evaluateVersions(versions, 'v20-v8-canary'); - expect(version).toBe('v20.1.1-v8-canary20221103f7e2421e91'); - }); - - it('evaluateVersions should handle v8-canary version spec with timestamp', () => { - const versions = [ - 'v20.0.0-v8-canary20221103f7e2421e91', - 'v20.0.1-v8-canary20221103f7e2421e91', - 'v20.0.1-v8-canary20221103f7e2421e92', - 'v20.0.1-v8-canary20221103f7e2421e93', - 'v20.0.2-v8-canary20221103f7e2421e91' - ]; - const version = evaluateVersions( - versions, - 'v20.0.1-v8-canary20221103f7e2421e92' - ); - expect(version).toBe('v20.0.1-v8-canary20221103f7e2421e92'); - }); - }); - - describe('getNodejsDistUrl', () => { - it('getNodejsDistUrl should handle v8 canary version spec', async () => { - expect(getNodejsDistUrl('1.1.1-v8-canary')).toBe( - 'https://nodejs.org/download/v8-canary' - ); - expect(getNodejsDistUrl('1.1.1-v8-canary123')).toBe( - 'https://nodejs.org/download/v8-canary' - ); - expect(getNodejsDistUrl('v1.1.1-v8-canary')).toBe( - 'https://nodejs.org/download/v8-canary' - ); - expect(getNodejsDistUrl('v1.1.1-v8-canary123')).toBe( - 'https://nodejs.org/download/v8-canary' - ); - }); - - it('getNodejsDistUrl should handle nightly version spec', async () => { - expect(getNodejsDistUrl('1.1.1-nightly')).toBe( - 'https://nodejs.org/download/nightly' - ); - expect(getNodejsDistUrl('v1.1.1-nightly')).toBe( - 'https://nodejs.org/download/nightly' - ); - expect(getNodejsDistUrl('1.1.1-nightly123')).toBe( - 'https://nodejs.org/download/nightly' - ); - expect(getNodejsDistUrl('v1.1.1-nightly123')).toBe( - 'https://nodejs.org/download/nightly' - ); - }); - - it('getNodejsDistUrl should handle rc version spec', async () => { - expect(getNodejsDistUrl('1.1.1-rc')).toBe( - 'https://nodejs.org/download/rc' - ); - expect(getNodejsDistUrl('v1.1.1-rc')).toBe( - 'https://nodejs.org/download/rc' - ); - expect(getNodejsDistUrl('1.1.1-rc.0')).toBe( - 'https://nodejs.org/download/rc' - ); - expect(getNodejsDistUrl('v1.1.1-rc.0')).toBe( - 'https://nodejs.org/download/rc' - ); - }); - - it('getNodejsDistUrl should handle unspecific version spec', async () => { - expect(getNodejsDistUrl('1.1.1')).toBe('https://nodejs.org/dist'); - expect(getNodejsDistUrl('v1.1.1')).toBe('https://nodejs.org/dist'); - }); - }); -}); diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts new file mode 100644 index 000000000..3a7110969 --- /dev/null +++ b/__tests__/main.test.ts @@ -0,0 +1,295 @@ +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'; + +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; + + beforeEach(() => { + inputs = {}; + + // node + os = {}; + console.log('::stop-commands::stoptoken'); + 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'); + }); + }); + + 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); + }); + + 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}` + ); + }); + + 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}` + ); + }); + + 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' + ); + }); + }); +}); diff --git a/__tests__/nightly-installer.test.ts b/__tests__/nightly-installer.test.ts new file mode 100644 index 000000000..c37b72bdd --- /dev/null +++ b/__tests__/nightly-installer.test.ts @@ -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/distibutions/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 = nodeTestDistRc; + } else if (url.includes('/nightly')) { + res = nodeTestDistNightly; + } else { + res = 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}` + ); + } + ); + }); +}); diff --git a/__tests__/installer.test.ts b/__tests__/official-installer.test.ts similarity index 53% rename from __tests__/installer.test.ts rename to __tests__/official-installer.test.ts index 2f32aad0d..5061bdf6d 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/official-installer.test.ts @@ -3,15 +3,15 @@ import * as io from '@actions/io'; import * as tc from '@actions/tool-cache'; import * as httpm from '@actions/http-client'; import * as exec from '@actions/exec'; -import * as im from '../src/installer'; import * as cache from '@actions/cache'; import fs from 'fs'; import cp from 'child_process'; import osm 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/distibutions/official_builds/official_builds'; +import {INodeVersion} from '../src/distibutions/base-models'; const nodeTestManifest = require('./data/versions-manifest.json'); const nodeTestDist = require('./data/node-dist-index.json'); @@ -20,6 +20,7 @@ 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; @@ -30,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; @@ -43,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; @@ -72,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'); @@ -95,25 +92,14 @@ describe('setup-node', () => { () => nodeTestManifest ); - getDistSpy.mockImplementation(version => { - const initialUrl = im.getNodejsDistUrl(version); - if (initialUrl.endsWith('/rc')) { - return nodeTestDistRc; - } else if (initialUrl.endsWith('/nightly')) { - return nodeTestDistNightly; - } else { - return nodeTestDist; - } - }); - getJsonSpy.mockImplementation(url => { let res: any; if (url.includes('/rc')) { - res = nodeTestDistRc; + res = nodeTestDistRc; } else if (url.includes('/nightly')) { - res = nodeTestDistNightly; + res = nodeTestDistNightly; } else { - res = nodeTestDist; + res = nodeTestDist; } return {result: res}; @@ -126,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'); + // uncomment to debug + process.stderr.write('log:' + line + '\n'); }); dbgSpy.mockImplementation(msg => { // uncomment to see debug output @@ -160,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'], @@ -316,35 +285,33 @@ 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(getManifestSpy).toHaveBeenCalled(); expect(logSpy).toHaveBeenCalledWith( - 'Not found in manifest. Falling back to download directly from Node' + `Attempting to download ${versionSpec}...` ); expect(logSpy).toHaveBeenCalledWith( - `Attempting to download ${versionSpec}...` + 'Not found in manifest. Falling back to download directly from Node' ); + expect(logSpy).toHaveBeenCalledWith('came here undefined'); + expect(dlSpy).toHaveBeenCalled(); + expect(exSpy).toHaveBeenCalled(); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); }); @@ -597,165 +564,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'; @@ -931,287 +739,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.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(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', @@ -1252,154 +779,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('setup-node v8 canary tests', () => { - // @actions/http-client - let getDistIndexJsonSpy: jest.SpyInstance; - let findAllVersionSpy: jest.SpyInstance; - - beforeEach(() => { - // @actions/http-client - getDistIndexJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson'); - getDistIndexJsonSpy.mockImplementation(() => ({ - result: nodeV8CanaryTestDist - })); - - // @actions/tool-cache - findAllVersionSpy = jest.spyOn(tc, 'findAllVersions'); - }); - - it('v8 canary setup node flow without cached', async () => { - let versionSpec = 'v20-v8-canary'; - - inputs['node-version'] = versionSpec; - inputs['always-auth'] = false; - inputs['token'] = 'faketoken'; - - os.platform = 'linux'; - os.arch = 'x64'; - - findAllVersionSpy.mockImplementation(() => []); - - findSpy.mockImplementation(() => ''); - - dlSpy.mockImplementation(async () => '/some/temp/path'); - let toolPath = path.normalize('/cache/node/12.16.2/x64'); - exSpy.mockImplementation(async () => '/some/other/temp/path'); - cacheSpy.mockImplementation(async () => toolPath); - - await main.run(); - - expect(dbgSpy.mock.calls[0][0]).toBe('evaluating 0 versions'); - expect(dbgSpy.mock.calls[1][0]).toBe('match not found'); - expect(logSpy.mock.calls[0][0]).toBe( - `Attempting to download ${versionSpec}...` - ); - expect(dbgSpy.mock.calls[2][0]).toBe('No manifest cached'); - expect(dbgSpy.mock.calls[3][0]).toBe( - 'Getting manifest from actions/node-versions@main' - ); - expect(dbgSpy.mock.calls[4][0].slice(0, 6)).toBe('check '); - expect(dbgSpy.mock.calls[10][0].slice(0, 6)).toBe('check '); - expect(logSpy.mock.calls[1][0]).toBe( - 'Not found in manifest. Falling back to download directly from Node' - ); - expect(dbgSpy.mock.calls[12][0]).toBe('evaluating 17 versions'); - expect(dbgSpy.mock.calls[13][0]).toBe( - 'matched: v20.0.0-v8-canary20221103f7e2421e91' - ); - expect(logSpy.mock.calls[2][0]).toBe( - 'Acquiring 20.0.0-v8-canary20221103f7e2421e91 - x64 from https://nodejs.org/download/v8-canary/v20.0.0-v8-canary20221103f7e2421e91/node-v20.0.0-v8-canary20221103f7e2421e91-linux-x64.tar.gz' - ); - - expect(dlSpy).toHaveBeenCalledTimes(1); - expect(exSpy).toHaveBeenCalledTimes(1); - expect(cacheSpy).toHaveBeenCalledTimes(1); - }); - - 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'; - findAllVersionSpy.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(); - }); - }); -}); - -describe('helper methods', () => { - it('is not LTS alias', async () => { - const versionSpec = 'v99.0.0-v8-canary'; - const isLtsAlias = im.isLtsAlias(versionSpec); - expect(isLtsAlias).toBeFalsy(); - }); - - it('is not isLatestSyntax', async () => { - const versionSpec = 'v99.0.0-v8-canary'; - const isLatestSyntax = im.isLatestSyntax(versionSpec); - expect(isLatestSyntax).toBeFalsy(); - }); - - describe('getNodejsDistUrl', () => { - it('dist url to be https://nodejs.org/download/v8-canary for input versionSpec', () => { - const versionSpec = 'v99.0.0-v8-canary'; - const url = im.getNodejsDistUrl(versionSpec); - expect(url).toBe('https://nodejs.org/download/v8-canary'); - }); - - it('dist url to be https://nodejs.org/download/v8-canary for full versionSpec', () => { - const versionSpec = 'v20.0.0-v8-canary20221103f7e2421e91'; - const url = im.getNodejsDistUrl(versionSpec); - expect(url).toBe('https://nodejs.org/download/v8-canary'); - }); - }); - - 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); - }); - }); }); diff --git a/__tests__/rc-installer.test.ts b/__tests__/rc-installer.test.ts new file mode 100644 index 000000000..d9eae0811 --- /dev/null +++ b/__tests__/rc-installer.test.ts @@ -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/distibutions/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 = nodeTestDistRc; + } else if (url.includes('/nightly')) { + res = nodeTestDistNightly; + } else { + res = 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}` + ); + }); + }); +}); diff --git a/dist/setup/index.js b/dist/setup/index.js index fb9a9dfd2..fdbb66f26 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73210,12 +73210,12 @@ const io = __importStar(__nccwpck_require__(7436)); const semver_1 = __importDefault(__nccwpck_require__(5911)); const assert = __importStar(__nccwpck_require__(9491)); const path = __importStar(__nccwpck_require__(1017)); -const os = __importStar(__nccwpck_require__(2037)); +const os_1 = __importDefault(__nccwpck_require__(2037)); const fs_1 = __importDefault(__nccwpck_require__(7147)); class BaseDistribution { constructor(nodeInfo) { this.nodeInfo = nodeInfo; - this.osPlat = os.platform(); + this.osPlat = os_1.default.platform(); this.httpClient = new hc.HttpClient('setup-node', [], { allowRetries: true, maxRetries: 3 @@ -73223,6 +73223,14 @@ class BaseDistribution { } getNodeJsInfo() { return __awaiter(this, void 0, void 0, function* () { + if (this.nodeInfo.checkLatest) { + const nodeVersions = yield this.getNodejsVersions(); + const versions = this.filterVersions(nodeVersions); + const evaluatedVersion = this.evaluateVersions(versions); + if (evaluatedVersion) { + this.nodeInfo.versionSpec = evaluatedVersion; + } + } let toolPath = this.findVersionInHoostedToolCacheDirectory(); if (toolPath) { core.info(`Found in cache @ ${toolPath}`); @@ -73231,6 +73239,9 @@ class BaseDistribution { const nodeVersions = yield this.getNodejsVersions(); const versions = this.filterVersions(nodeVersions); 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, this.osPlat); toolPath = yield this.downloadNodejs(toolName); } @@ -73270,6 +73281,7 @@ class BaseDistribution { downloadNodejs(info) { return __awaiter(this, void 0, void 0, function* () { let downloadPath = ''; + core.info(`Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}`); try { downloadPath = yield tc.downloadTool(info.downloadUrl); } @@ -73284,7 +73296,7 @@ class BaseDistribution { return toolPath; }); } - acquireNodeFromFallbackLocation(version, arch = os.arch()) { + acquireNodeFromFallbackLocation(version, arch = os_1.default.arch()) { return __awaiter(this, void 0, void 0, function* () { const initialUrl = this.getDistributionUrl(); let osArch = this.translateArchToDistUrl(arch); @@ -73443,10 +73455,8 @@ function getNodejsDistribution(installerOptions) { return new canary_builds_1.default(installerOptions); case Distributions.RC: return new rc_builds_1.default(installerOptions); - case Distributions.DEFAULT: - return new official_builds_1.default(installerOptions); default: - return null; + return new official_builds_1.default(installerOptions); } } exports.getNodejsDistribution = getNodejsDistribution; @@ -73489,6 +73499,7 @@ class NightlyNodejs extends base_distribution_1.default { } return prerelease[0].includes('nightly'); }); + localVersionPaths.sort(semver_1.default.rcompare); const localVersion = this.evaluateVersions(localVersionPaths); if (localVersion) { toolPath = tc.find('node', localVersion, this.nodeInfo.arch); @@ -73591,7 +73602,7 @@ class OfficialBuilds extends base_distribution_1.default { nodeVersions = yield this.getNodejsVersions(); const versions = this.filterVersions(nodeVersions); this.nodeInfo.versionSpec = this.evaluateVersions(versions); - core.info(`getting latest node version...`); + core.info('getting latest node version...'); } if (this.nodeInfo.checkLatest) { core.info('Attempt to resolve the latest version from manifest...'); @@ -73610,12 +73621,17 @@ class OfficialBuilds extends base_distribution_1.default { core.info(`Found in cache @ ${toolPath}`); } else { + let downloadPath = ''; try { core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); - const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.arch, manifest); + const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); + const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, osArch, manifest); if (versionInfo) { core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`); - toolPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.auth); + downloadPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.auth); + if (downloadPath) { + toolPath = yield this.extractArchive(downloadPath, versionInfo); + } } else { core.info('Not found in manifest. Falling back to download directly from Node'); @@ -73633,11 +73649,17 @@ class OfficialBuilds extends base_distribution_1.default { core.debug(err.stack); core.info('Falling back to download directly from Node'); } - const nodeVersions = yield this.getNodejsVersions(); - const versions = this.filterVersions(nodeVersions); - const evaluatedVersion = this.evaluateVersions(versions); - const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); - toolPath = yield this.downloadNodejs(toolName); + if (!toolPath) { + const nodeVersions = yield this.getNodejsVersions(); + core.info('came here undefined'); + const versions = this.filterVersions(nodeVersions); + 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, this.osPlat); + toolPath = yield this.downloadNodejs(toolName); + } } if (this.osPlat != 'win32') { toolPath = path_1.default.join(toolPath, 'bin'); @@ -73699,7 +73721,7 @@ class OfficialBuilds extends base_distribution_1.default { core.debug(`Found LTS release '${release.version}' for Node version '${versionSpec}'`); return release.version.split('.')[0]; } - resolveVersionFromManifest(versionSpec, osArch = this.translateArchToDistUrl(os_1.default.arch()), manifest) { + resolveVersionFromManifest(versionSpec, osArch, manifest) { return __awaiter(this, void 0, void 0, function* () { try { const info = yield this.getInfoFromManifest(versionSpec, osArch, manifest); @@ -73828,6 +73850,7 @@ class CanaryBuild extends base_distribution_1.default { } return prerelease[0].includes('v8-canary'); }); + localVersionPaths.sort(semver_1.default.rcompare); const localVersion = this.evaluateVersions(localVersionPaths); if (localVersion) { toolPath = tc.find('node', localVersion, this.nodeInfo.arch); @@ -73907,7 +73930,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__nccwpck_require__(2186)); -const exec = __importStar(__nccwpck_require__(1514)); const fs_1 = __importDefault(__nccwpck_require__(7147)); const os_1 = __importDefault(__nccwpck_require__(2037)); const auth = __importStar(__nccwpck_require__(7573)); @@ -73915,6 +73937,7 @@ const path = __importStar(__nccwpck_require__(1017)); const cache_restore_1 = __nccwpck_require__(9517); const cache_utils_1 = __nccwpck_require__(1678); const installer_factory_1 = __nccwpck_require__(1260); +const util_1 = __nccwpck_require__(2629); function run() { return __awaiter(this, void 0, void 0, function* () { try { @@ -73939,19 +73962,14 @@ function run() { const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; const nodejsInfo = { versionSpec: version, - checkLatest: checkLatest, + checkLatest, auth, - arch: arch + arch }; const nodeDistribution = installer_factory_1.getNodejsDistribution(nodejsInfo); - if (nodeDistribution) { - yield (nodeDistribution === null || nodeDistribution === void 0 ? void 0 : nodeDistribution.getNodeJsInfo()); - } - else { - throw new Error(`Could not resolve version: ${version} for build`); - } + yield nodeDistribution.getNodeJsInfo(); } - yield printEnvDetailsAndSetOutput(); + yield util_1.printEnvDetailsAndSetOutput(); const registryUrl = core.getInput('registry-url'); const alwaysAuth = core.getInput('always-auth'); if (registryUrl) { @@ -73986,11 +74004,39 @@ function resolveVersionInput() { if (!fs_1.default.existsSync(versionFilePath)) { throw new Error(`The specified node version file at: ${versionFilePath} does not exist`); } - version = parseNodeVersionFile(fs_1.default.readFileSync(versionFilePath, 'utf8')); + version = util_1.parseNodeVersionFile(fs_1.default.readFileSync(versionFilePath, 'utf8')); core.info(`Resolved ${versionFileInput} as ${version}`); } return version; } + + +/***/ }), + +/***/ 2629: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +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) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + 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 })); +const core = __importStar(__nccwpck_require__(2186)); +const exec = __importStar(__nccwpck_require__(1514)); function parseNodeVersionFile(contents) { var _a, _b, _c; let nodeVersion; @@ -74019,12 +74065,15 @@ function printEnvDetailsAndSetOutput() { core.startGroup('Environment details'); const promises = ['node', 'npm', 'yarn'].map((tool) => __awaiter(this, void 0, void 0, function* () { const output = yield getToolVersion(tool, ['--version']); + return { tool, output }; + })); + const tools = yield Promise.all(promises); + tools.forEach(({ tool, output }) => { if (tool === 'node') { core.setOutput(`${tool}-version`, output); } core.info(`${tool}: ${output}`); - })); - yield Promise.all(promises); + }); core.endGroup(); }); } @@ -74037,7 +74086,7 @@ function getToolVersion(tool, options) { silent: true }); if (exitCode > 0) { - core.warning(`[warning]${stderr}`); + core.info(`[warning]${stderr}`); return ''; } return stdout.trim(); diff --git a/src/distibutions/base-distribution.ts b/src/distibutions/base-distribution.ts index 74edb47f1..2b8ebfbf8 100644 --- a/src/distibutions/base-distribution.ts +++ b/src/distibutions/base-distribution.ts @@ -7,7 +7,7 @@ import semver from 'semver'; import * as assert from 'assert'; import * as path from 'path'; -import * as os from 'os'; +import os from 'os'; import fs from 'fs'; import {INodejs, INodeVersion, INodeVersionInfo} from './base-models'; @@ -27,6 +27,16 @@ export default abstract class BaseDistribution { protected abstract evaluateVersions(nodeVersions: string[]): string; public async getNodeJsInfo() { + if (this.nodeInfo.checkLatest) { + const nodeVersions = await this.getNodejsVersions(); + const versions = this.filterVersions(nodeVersions); + const evaluatedVersion = this.evaluateVersions(versions); + + if (evaluatedVersion) { + this.nodeInfo.versionSpec = evaluatedVersion; + } + } + let toolPath = this.findVersionInHoostedToolCacheDirectory(); if (toolPath) { core.info(`Found in cache @ ${toolPath}`); @@ -34,6 +44,11 @@ export default abstract class BaseDistribution { const nodeVersions = await this.getNodejsVersions(); const versions = this.filterVersions(nodeVersions); 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, this.osPlat); toolPath = await this.downloadNodejs(toolName); } @@ -79,6 +94,9 @@ export default abstract class BaseDistribution { 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) { diff --git a/src/distibutions/installer-factory.ts b/src/distibutions/installer-factory.ts index 4e694c05f..56cc0bf80 100644 --- a/src/distibutions/installer-factory.ts +++ b/src/distibutions/installer-factory.ts @@ -29,7 +29,7 @@ function identifyDistribution(versionSpec: string) { export function getNodejsDistribution( installerOptions: INodejs -): BaseDistribution | null { +): BaseDistribution { const distributionName = identifyDistribution(installerOptions.versionSpec); switch (distributionName) { case Distributions.NIGHTLY: @@ -38,9 +38,7 @@ export function getNodejsDistribution( return new CanaryBuild(installerOptions); case Distributions.RC: return new RcBuild(installerOptions); - case Distributions.DEFAULT: - return new OfficialBuilds(installerOptions); default: - return null; + return new OfficialBuilds(installerOptions); } } diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index d40e930f9..48f080d95 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -23,6 +23,7 @@ export default class NightlyNodejs extends BaseDistribution { return prerelease[0].includes('nightly'); }); + localVersionPaths.sort(semver.rcompare); const localVersion = this.evaluateVersions(localVersionPaths); if (localVersion) { toolPath = tc.find('node', localVersion, this.nodeInfo.arch); diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts index f518ee1fe..7ef7b0e7b 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distibutions/official_builds/official_builds.ts @@ -37,7 +37,7 @@ export default class OfficialBuilds extends BaseDistribution { const versions = this.filterVersions(nodeVersions); this.nodeInfo.versionSpec = this.evaluateVersions(versions); - core.info(`getting latest node version...`); + core.info('getting latest node version...'); } if (this.nodeInfo.checkLatest) { @@ -63,22 +63,28 @@ export default class OfficialBuilds extends BaseDistribution { if (toolPath) { core.info(`Found in cache @ ${toolPath}`); } else { + let downloadPath = ''; try { core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); + const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); const versionInfo = await this.getInfoFromManifest( this.nodeInfo.versionSpec, - this.nodeInfo.arch, + osArch, manifest ); if (versionInfo) { core.info( `Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}` ); - toolPath = await tc.downloadTool( + 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' @@ -100,11 +106,19 @@ export default class OfficialBuilds extends BaseDistribution { core.info('Falling back to download directly from Node'); } - const nodeVersions = await this.getNodejsVersions(); - const versions = this.filterVersions(nodeVersions); - const evaluatedVersion = this.evaluateVersions(versions); - const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); - toolPath = await this.downloadNodejs(toolName); + if (!toolPath) { + const nodeVersions = await this.getNodejsVersions(); + core.info('came here undefined'); + const versions = this.filterVersions(nodeVersions); + 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, this.osPlat); + toolPath = await this.downloadNodejs(toolName); + } } if (this.osPlat != 'win32') { @@ -204,7 +218,7 @@ export default class OfficialBuilds extends BaseDistribution { private async resolveVersionFromManifest( versionSpec: string, - osArch: string = this.translateArchToDistUrl(os.arch()), + osArch: string, manifest: tc.IToolRelease[] | undefined ): Promise { try { diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index 9568dad1f..f785456aa 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -23,7 +23,7 @@ export default class CanaryBuild extends BaseDistribution { return prerelease[0].includes('v8-canary'); }); - + localVersionPaths.sort(semver.rcompare); const localVersion = this.evaluateVersions(localVersionPaths); if (localVersion) { toolPath = tc.find('node', localVersion, this.nodeInfo.arch); diff --git a/src/main.ts b/src/main.ts index e2c985796..61a2f9546 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,4 @@ import * as core from '@actions/core'; -import * as exec from '@actions/exec'; import fs from 'fs'; import os from 'os'; @@ -9,6 +8,7 @@ import * as path from 'path'; import {restoreCache} from './cache-restore'; import {isCacheFeatureAvailable} from './cache-utils'; import {getNodejsDistribution} from './distibutions/installer-factory'; +import {parseNodeVersionFile, printEnvDetailsAndSetOutput} from './util'; export async function run() { try { @@ -40,16 +40,12 @@ export async function run() { (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; const nodejsInfo = { versionSpec: version, - checkLatest: checkLatest, + checkLatest, auth, - arch: arch + arch }; const nodeDistribution = getNodejsDistribution(nodejsInfo); - if (nodeDistribution) { - await nodeDistribution?.getNodeJsInfo(); - } else { - throw new Error(`Could not resolve version: ${version} for build`); - } + await nodeDistribution.getNodeJsInfo(); } await printEnvDetailsAndSetOutput(); @@ -111,62 +107,3 @@ function resolveVersionInput(): string { return version; } - -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?(?[^\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']); - - 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 ''; - } -} diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 000000000..60f2649c2 --- /dev/null +++ b/src/util.ts @@ -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?(?[^\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 ''; + } +} From 5af9d8577eec0d90db3ba4fc0fd40b112f3729d4 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 22 Dec 2022 00:27:25 +0100 Subject: [PATCH 37/51] fixing main tests --- .github/workflows/build-test.yml | 1 + __tests__/main.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 61abfb4b9..6821688aa 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -15,6 +15,7 @@ jobs: build: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] steps: diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 3a7110969..e19ea56a9 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -178,7 +178,7 @@ describe('main tests', () => { expect(infoSpy).toHaveBeenCalledWith( `Resolved ${versionFile} as ${expectedVersionSpec}` ); - }); + }, 10000); it('reads package.json as node-version-file if provided', async () => { // Arrange @@ -205,7 +205,7 @@ describe('main tests', () => { expect(infoSpy).toHaveBeenCalledWith( `Resolved ${versionFile} as ${expectedVersionSpec}` ); - }); + }, 10000); it('both node-version-file and node-version are provided', async () => { inputs['node-version'] = '12'; From 15e57b56d6d6a48546781c4ee67e57691b858aa4 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 22 Dec 2022 00:43:00 +0100 Subject: [PATCH 38/51] add mock --- __tests__/main.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index e19ea56a9..b1d88f0c9 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -11,6 +11,7 @@ import each from 'jest-each'; import * as main from '../src/main'; import * as util from '../src/util'; +import OfficialBuilds from '../src/distibutions/official_builds/official_builds'; describe('main tests', () => { let inputs = {} as any; @@ -32,12 +33,16 @@ describe('main tests', () => { let findSpy: jest.SpyInstance; let isCacheActionAvailable: jest.SpyInstance; + let getNodeJsInfoSpy: 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'); @@ -64,6 +69,9 @@ describe('main tests', () => { // uncomment to debug // process.stderr.write('write:' + line + '\n'); }); + + getNodeJsInfoSpy = jest.spyOn(OfficialBuilds.prototype, 'getNodeJsInfo'); + getNodeJsInfoSpy.mockImplementation(() => {}); }); afterEach(() => { @@ -145,7 +153,7 @@ describe('main tests', () => { // Assert expect(parseNodeVersionSpy).toHaveBeenCalledTimes(0); - }); + }, 10000); it('not used if node-version-file not provided', async () => { // Act From f3c48890ed39bc0a69f1af98a44723d0057f407b Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 22 Dec 2022 01:09:28 +0100 Subject: [PATCH 39/51] minor polishing --- __tests__/official-installer.test.ts | 1 - dist/setup/index.js | 6 +----- src/distibutions/installer-factory.ts | 4 +--- src/distibutions/nightly/nightly_builds.ts | 2 +- src/distibutions/official_builds/official_builds.ts | 1 - src/distibutions/official_builds/rc/rc_builds.ts | 2 +- src/distibutions/v8-canary/canary_builds.ts | 2 +- 7 files changed, 5 insertions(+), 13 deletions(-) diff --git a/__tests__/official-installer.test.ts b/__tests__/official-installer.test.ts index 5061bdf6d..6dfac1c9f 100644 --- a/__tests__/official-installer.test.ts +++ b/__tests__/official-installer.test.ts @@ -309,7 +309,6 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Not found in manifest. Falling back to download directly from Node' ); - expect(logSpy).toHaveBeenCalledWith('came here undefined'); expect(dlSpy).toHaveBeenCalled(); expect(exSpy).toHaveBeenCalled(); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); diff --git a/dist/setup/index.js b/dist/setup/index.js index fdbb66f26..f5b224dd3 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73431,7 +73431,7 @@ var Distributions; Distributions["RC"] = "rc"; })(Distributions || (Distributions = {})); function identifyDistribution(versionSpec) { - let distribution = ''; + let distribution = Distributions.DEFAULT; if (versionSpec.includes(Distributions.NIGHTLY)) { distribution = Distributions.NIGHTLY; } @@ -73441,9 +73441,6 @@ function identifyDistribution(versionSpec) { else if (versionSpec.includes(Distributions.RC)) { distribution = Distributions.RC; } - else { - distribution = Distributions.DEFAULT; - } return distribution; } function getNodejsDistribution(installerOptions) { @@ -73651,7 +73648,6 @@ class OfficialBuilds extends base_distribution_1.default { } if (!toolPath) { const nodeVersions = yield this.getNodejsVersions(); - core.info('came here undefined'); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); if (!evaluatedVersion) { diff --git a/src/distibutions/installer-factory.ts b/src/distibutions/installer-factory.ts index 56cc0bf80..eccaa2f7d 100644 --- a/src/distibutions/installer-factory.ts +++ b/src/distibutions/installer-factory.ts @@ -13,15 +13,13 @@ enum Distributions { } function identifyDistribution(versionSpec: string) { - let distribution = ''; + let distribution = Distributions.DEFAULT; if (versionSpec.includes(Distributions.NIGHTLY)) { distribution = Distributions.NIGHTLY; } else if (versionSpec.includes(Distributions.CANARY)) { distribution = Distributions.CANARY; } else if (versionSpec.includes(Distributions.RC)) { distribution = Distributions.RC; - } else { - distribution = Distributions.DEFAULT; } return distribution; diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index 48f080d95..91a47d02c 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -4,7 +4,7 @@ import * as tc from '@actions/tool-cache'; import semver from 'semver'; import BaseDistribution from '../base-distribution'; -import {INodejs, INodeVersion} from '../base-models'; +import {INodejs} from '../base-models'; export default class NightlyNodejs extends BaseDistribution { constructor(nodeInfo: INodejs) { diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts index 7ef7b0e7b..f655c3b65 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distibutions/official_builds/official_builds.ts @@ -108,7 +108,6 @@ export default class OfficialBuilds extends BaseDistribution { if (!toolPath) { const nodeVersions = await this.getNodejsVersions(); - core.info('came here undefined'); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); if (!evaluatedVersion) { diff --git a/src/distibutions/official_builds/rc/rc_builds.ts b/src/distibutions/official_builds/rc/rc_builds.ts index d6e2d893b..666673f4e 100644 --- a/src/distibutions/official_builds/rc/rc_builds.ts +++ b/src/distibutions/official_builds/rc/rc_builds.ts @@ -3,7 +3,7 @@ import * as core from '@actions/core'; import * as semver from 'semver'; import BaseDistribution from '../../base-distribution'; -import {INodejs, INodeVersion} from '../../base-models'; +import {INodejs} from '../../base-models'; export default class RcBuild extends BaseDistribution { constructor(nodeInfo: INodejs) { diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index f785456aa..a1231cab0 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -4,7 +4,7 @@ import * as tc from '@actions/tool-cache'; import semver from 'semver'; import BaseDistribution from '../base-distribution'; -import {INodejs, INodeVersion} from '../base-models'; +import {INodejs} from '../base-models'; export default class CanaryBuild extends BaseDistribution { constructor(nodeInfo: INodejs) { From cd6d6a670004482c16881f8ff6d86b65ac5c29a3 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 22 Dec 2022 01:51:36 +0100 Subject: [PATCH 40/51] polish code --- dist/cache-save/index.js | 64 ++-- dist/setup/index.js | 277 +++++++++++++----- package-lock.json | 14 +- package.json | 2 +- src/distibutions/base-distribution.ts | 5 +- src/distibutions/nightly/nightly_builds.ts | 21 +- .../official_builds/official_builds.ts | 4 +- src/distibutions/v8-canary/canary_builds.ts | 21 +- 8 files changed, 283 insertions(+), 125 deletions(-) diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index d099eecba..92b5418f9 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -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"; diff --git a/dist/setup/index.js b/dist/setup/index.js index f5b224dd3..8cce9d250 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -72915,14 +72915,27 @@ function wrappy (fn, cb) { "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 (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + 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; }; Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.configAuthentication = void 0; const fs = __importStar(__nccwpck_require__(7147)); const os = __importStar(__nccwpck_require__(2037)); const path = __importStar(__nccwpck_require__(1017)); @@ -72977,6 +72990,25 @@ function writeRegistryToFile(registryUrl, fileLocation, alwaysAuth) { "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) { @@ -72986,17 +73018,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.restoreCache = void 0; const cache = __importStar(__nccwpck_require__(7799)); const core = __importStar(__nccwpck_require__(2186)); const glob = __importStar(__nccwpck_require__(8090)); @@ -73004,7 +73030,7 @@ const path_1 = __importDefault(__nccwpck_require__(1017)); const fs_1 = __importDefault(__nccwpck_require__(7147)); const constants_1 = __nccwpck_require__(9042); const cache_utils_1 = __nccwpck_require__(1678); -exports.restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { +const restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager); if (!packageManagerInfo) { throw new Error(`Caching for '${packageManager}' is not supported`); @@ -73030,6 +73056,7 @@ exports.restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0 core.saveState(constants_1.State.CacheMatchedKey, cacheKey); core.info(`Cache restored from key: ${cacheKey}`); }); +exports.restoreCache = restoreCache; const findLockFile = (packageManager) => { let lockFiles = packageManager.lockFilePatterns; const workspace = process.env.GITHUB_WORKSPACE; @@ -73049,6 +73076,25 @@ const findLockFile = (packageManager) => { "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) { @@ -73058,14 +73104,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)); @@ -73087,7 +73127,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() @@ -73097,6 +73137,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) { @@ -73104,7 +73145,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; } @@ -73125,7 +73166,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}`); @@ -73133,6 +73175,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'; @@ -73159,6 +73202,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"; @@ -73183,6 +73227,25 @@ var Outputs; "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) { @@ -73192,13 +73255,6 @@ 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 }; }; @@ -73223,8 +73279,9 @@ class BaseDistribution { } getNodeJsInfo() { return __awaiter(this, void 0, void 0, function* () { + let nodeVersions; if (this.nodeInfo.checkLatest) { - const nodeVersions = yield this.getNodejsVersions(); + nodeVersions = yield this.getNodejsVersions(); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); if (evaluatedVersion) { @@ -73236,7 +73293,7 @@ class BaseDistribution { core.info(`Found in cache @ ${toolPath}`); } else { - const nodeVersions = yield this.getNodejsVersions(); + nodeVersions !== null && nodeVersions !== void 0 ? nodeVersions : (nodeVersions = yield this.getNodejsVersions()); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); if (!evaluatedVersion) { @@ -73419,6 +73476,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getNodejsDistribution = void 0; const nightly_builds_1 = __importDefault(__nccwpck_require__(1002)); const official_builds_1 = __importDefault(__nccwpck_require__(9856)); const rc_builds_1 = __importDefault(__nccwpck_require__(6235)); @@ -73466,11 +73524,23 @@ exports.getNodejsDistribution = getNodejsDistribution; "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 (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + 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 __importDefault = (this && this.__importDefault) || function (mod) { @@ -73484,6 +73554,7 @@ const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); class NightlyNodejs extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); + this.distribution = 'nightly'; } findVersionInHoostedToolCacheDirectory() { let toolPath = ''; @@ -73494,7 +73565,7 @@ class NightlyNodejs extends base_distribution_1.default { if (!prerelease) { return false; } - return prerelease[0].includes('nightly'); + return prerelease[0].includes(this.distribution); }); localVersionPaths.sort(semver_1.default.rcompare); const localVersion = this.evaluateVersions(localVersionPaths); @@ -73506,10 +73577,10 @@ class NightlyNodejs extends base_distribution_1.default { evaluateVersions(versions) { let version = ''; core.debug(`evaluating ${versions.length} versions`); - const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, 'nightly'); + const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec); for (let i = 0; i < versions.length; i++) { const potential = versions[i]; - const satisfied = semver_1.default.satisfies(potential.replace('nightly', 'nightly.'), range, { + const satisfied = semver_1.default.satisfies(potential.replace(this.distribution, `${this.distribution}.`), range, { includePrerelease: includePrerelease }); if (satisfied) { @@ -73528,16 +73599,16 @@ class NightlyNodejs extends base_distribution_1.default { getDistributionUrl() { return 'https://nodejs.org/download/nightly'; } - createRangePreRelease(versionSpec, distribution = '') { + createRangePreRelease(versionSpec) { let range; const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver_1.default.valid(raw); const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); - if (prerelease !== distribution) { - range = `${rawVersion}-${prerelease.replace(distribution, `${distribution}.`)}`; + if (prerelease !== this.distribution) { + range = `${rawVersion}-${prerelease.replace(this.distribution, `${this.distribution}.`)}`; } else { - range = `${semver_1.default.validRange(`^${rawVersion}-${distribution}`)}-0`; + range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } return { range, includePrerelease: !isValidVersion }; } @@ -73555,6 +73626,25 @@ exports["default"] = NightlyNodejs; "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) { @@ -73564,13 +73654,6 @@ 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 }; }; @@ -73589,6 +73672,7 @@ class OfficialBuilds extends base_distribution_1.default { return __awaiter(this, void 0, void 0, function* () { let manifest; let nodeVersions; + 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 @@ -73603,7 +73687,6 @@ class OfficialBuilds extends base_distribution_1.default { } if (this.nodeInfo.checkLatest) { core.info('Attempt to resolve the latest version from manifest...'); - const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); const resolvedVersion = yield this.resolveVersionFromManifest(this.nodeInfo.versionSpec, osArch, manifest); if (resolvedVersion) { this.nodeInfo.versionSpec = resolvedVersion; @@ -73621,7 +73704,6 @@ class OfficialBuilds extends base_distribution_1.default { let downloadPath = ''; try { core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); - const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, osArch, manifest); if (versionInfo) { core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`); @@ -73765,11 +73847,23 @@ exports["default"] = OfficialBuilds; "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 (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + 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 __importDefault = (this && this.__importDefault) || function (mod) { @@ -73816,11 +73910,23 @@ exports["default"] = RcBuild; "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 (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + 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 __importDefault = (this && this.__importDefault) || function (mod) { @@ -73834,6 +73940,7 @@ const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); class CanaryBuild extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); + this.distribution = 'v8-canary'; } findVersionInHoostedToolCacheDirectory() { let toolPath = ''; @@ -73844,7 +73951,7 @@ class CanaryBuild extends base_distribution_1.default { if (!prerelease) { return false; } - return prerelease[0].includes('v8-canary'); + return prerelease[0].includes(this.distribution); }); localVersionPaths.sort(semver_1.default.rcompare); const localVersion = this.evaluateVersions(localVersionPaths); @@ -73859,10 +73966,10 @@ class CanaryBuild extends base_distribution_1.default { evaluateVersions(versions) { let version = ''; core.debug(`evaluating ${versions.length} versions`); - const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec, 'v8-canary'); + const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec); for (let i = 0; i < versions.length; i++) { const potential = versions[i]; - const satisfied = semver_1.default.satisfies(potential.replace('v8-canary', 'v8-canary.'), range, { + const satisfied = semver_1.default.satisfies(potential.replace(this.distribution, `${this.distribution}.`), range, { includePrerelease: includePrerelease }); if (satisfied) { @@ -73878,16 +73985,16 @@ class CanaryBuild extends base_distribution_1.default { } return version; } - createRangePreRelease(versionSpec, distribution = '') { + createRangePreRelease(versionSpec) { let range; const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver_1.default.valid(raw); const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); - if (prerelease !== distribution) { - range = `${rawVersion}-${prerelease.replace(distribution, `${distribution}.`)}`; + if (prerelease !== this.distribution) { + range = `${rawVersion}-${prerelease.replace(this.distribution, `${this.distribution}.`)}`; } else { - range = `${semver_1.default.validRange(`^${rawVersion}-${distribution}`)}-0`; + range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } return { range, includePrerelease: !isValidVersion }; } @@ -73905,6 +74012,25 @@ exports["default"] = CanaryBuild; "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) { @@ -73914,17 +74040,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 fs_1 = __importDefault(__nccwpck_require__(7147)); const os_1 = __importDefault(__nccwpck_require__(2037)); @@ -74014,6 +74134,25 @@ function resolveVersionInput() { "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) { @@ -74023,14 +74162,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.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0; const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); function parseNodeVersionFile(contents) { diff --git a/package-lock.json b/package-lock.json index 2b93205d3..c10ee29e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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": { @@ -4813,9 +4813,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", @@ -8861,9 +8861,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": { diff --git a/package.json b/package.json index a1b50bc7f..a8ba51a8b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,6 @@ "jest-circus": "^27.2.5", "prettier": "^1.19.1", "ts-jest": "^27.0.5", - "typescript": "^3.8.3" + "typescript": "^4.2.3" } } diff --git a/src/distibutions/base-distribution.ts b/src/distibutions/base-distribution.ts index 2b8ebfbf8..c12ca43b2 100644 --- a/src/distibutions/base-distribution.ts +++ b/src/distibutions/base-distribution.ts @@ -27,8 +27,9 @@ export default abstract class BaseDistribution { protected abstract evaluateVersions(nodeVersions: string[]): string; public async getNodeJsInfo() { + let nodeVersions: INodeVersion[] | undefined; if (this.nodeInfo.checkLatest) { - const nodeVersions = await this.getNodejsVersions(); + nodeVersions = await this.getNodejsVersions(); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); @@ -41,7 +42,7 @@ export default abstract class BaseDistribution { if (toolPath) { core.info(`Found in cache @ ${toolPath}`); } else { - const nodeVersions = await this.getNodejsVersions(); + nodeVersions ??= await this.getNodejsVersions(); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); if (!evaluatedVersion) { diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distibutions/nightly/nightly_builds.ts index 91a47d02c..f21c52508 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distibutions/nightly/nightly_builds.ts @@ -7,6 +7,7 @@ import BaseDistribution from '../base-distribution'; import {INodejs} from '../base-models'; export default class NightlyNodejs extends BaseDistribution { + protected distribution = 'nightly'; constructor(nodeInfo: INodejs) { super(nodeInfo); } @@ -21,7 +22,7 @@ export default class NightlyNodejs extends BaseDistribution { return false; } - return prerelease[0].includes('nightly'); + return prerelease[0].includes(this.distribution); }); localVersionPaths.sort(semver.rcompare); const localVersion = this.evaluateVersions(localVersionPaths); @@ -38,14 +39,13 @@ export default class NightlyNodejs extends BaseDistribution { core.debug(`evaluating ${versions.length} versions`); const {includePrerelease, range} = this.createRangePreRelease( - this.nodeInfo.versionSpec, - 'nightly' + this.nodeInfo.versionSpec ); for (let i = 0; i < versions.length; i++) { const potential: string = versions[i]; const satisfied: boolean = semver.satisfies( - potential.replace('nightly', 'nightly.'), + potential.replace(this.distribution, `${this.distribution}.`), range, { includePrerelease: includePrerelease @@ -70,22 +70,19 @@ export default class NightlyNodejs extends BaseDistribution { return 'https://nodejs.org/download/nightly'; } - protected createRangePreRelease( - versionSpec: string, - distribution: string = '' - ) { + protected createRangePreRelease(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 !== distribution) { + if (prerelease !== this.distribution) { range = `${rawVersion}-${prerelease.replace( - distribution, - `${distribution}.` + this.distribution, + `${this.distribution}.` )}`; } else { - range = `${semver.validRange(`^${rawVersion}-${distribution}`)}-0`; + range = `${semver.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } return {range, includePrerelease: !isValidVersion}; diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distibutions/official_builds/official_builds.ts index f655c3b65..a1a43c578 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distibutions/official_builds/official_builds.ts @@ -19,6 +19,7 @@ export default class OfficialBuilds extends BaseDistribution { public async getNodeJsInfo() { let manifest: tc.IToolRelease[] | undefined; let nodeVersions: INodeVersion[] | undefined; + const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); if (this.isLtsAlias(this.nodeInfo.versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); @@ -42,7 +43,6 @@ export default class OfficialBuilds extends BaseDistribution { if (this.nodeInfo.checkLatest) { core.info('Attempt to resolve the latest version from manifest...'); - const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); const resolvedVersion = await this.resolveVersionFromManifest( this.nodeInfo.versionSpec, osArch, @@ -66,7 +66,7 @@ export default class OfficialBuilds extends BaseDistribution { let downloadPath = ''; try { core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); - const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); + const versionInfo = await this.getInfoFromManifest( this.nodeInfo.versionSpec, osArch, diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distibutions/v8-canary/canary_builds.ts index a1231cab0..425ed54c1 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distibutions/v8-canary/canary_builds.ts @@ -7,6 +7,7 @@ import BaseDistribution from '../base-distribution'; import {INodejs} from '../base-models'; export default class CanaryBuild extends BaseDistribution { + protected distribution = 'v8-canary'; constructor(nodeInfo: INodejs) { super(nodeInfo); } @@ -21,7 +22,7 @@ export default class CanaryBuild extends BaseDistribution { return false; } - return prerelease[0].includes('v8-canary'); + return prerelease[0].includes(this.distribution); }); localVersionPaths.sort(semver.rcompare); const localVersion = this.evaluateVersions(localVersionPaths); @@ -42,14 +43,13 @@ export default class CanaryBuild extends BaseDistribution { core.debug(`evaluating ${versions.length} versions`); const {includePrerelease, range} = this.createRangePreRelease( - this.nodeInfo.versionSpec, - 'v8-canary' + this.nodeInfo.versionSpec ); for (let i = 0; i < versions.length; i++) { const potential: string = versions[i]; const satisfied: boolean = semver.satisfies( - potential.replace('v8-canary', 'v8-canary.'), + potential.replace(this.distribution, `${this.distribution}.`), range, { includePrerelease: includePrerelease @@ -70,22 +70,19 @@ export default class CanaryBuild extends BaseDistribution { return version; } - protected createRangePreRelease( - versionSpec: string, - distribution: string = '' - ) { + protected createRangePreRelease(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 !== distribution) { + if (prerelease !== this.distribution) { range = `${rawVersion}-${prerelease.replace( - distribution, - `${distribution}.` + this.distribution, + `${this.distribution}.` )}`; } else { - range = `${semver.validRange(`^${rawVersion}-${distribution}`)}-0`; + range = `${semver.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } return {range, includePrerelease: !isValidVersion}; From df00183c096c1a038c706e86091a84fe131d351c Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 22 Dec 2022 02:09:21 +0100 Subject: [PATCH 41/51] minor changes --- dist/setup/index.js | 2 +- src/distibutions/base-distribution.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 8cce9d250..cf9f4e0dc 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73293,7 +73293,7 @@ class BaseDistribution { core.info(`Found in cache @ ${toolPath}`); } else { - nodeVersions !== null && nodeVersions !== void 0 ? nodeVersions : (nodeVersions = yield this.getNodejsVersions()); + nodeVersions = nodeVersions !== null && nodeVersions !== void 0 ? nodeVersions : (yield this.getNodejsVersions()); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); if (!evaluatedVersion) { diff --git a/src/distibutions/base-distribution.ts b/src/distibutions/base-distribution.ts index c12ca43b2..e6827ad80 100644 --- a/src/distibutions/base-distribution.ts +++ b/src/distibutions/base-distribution.ts @@ -42,7 +42,7 @@ export default abstract class BaseDistribution { if (toolPath) { core.info(`Found in cache @ ${toolPath}`); } else { - nodeVersions ??= await this.getNodejsVersions(); + nodeVersions = nodeVersions ?? (await this.getNodejsVersions()); const versions = this.filterVersions(nodeVersions); const evaluatedVersion = this.evaluateVersions(versions); if (!evaluatedVersion) { From e81c4f8a2158605cadddce43678d0a2ec209bdd8 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 27 Dec 2022 17:44:25 +0100 Subject: [PATCH 42/51] resolve comments --- __tests__/canary-installer.test.ts | 4 +- __tests__/main.test.ts | 8 +- __tests__/nightly-installer.test.ts | 2 +- __tests__/official-installer.test.ts | 8 +- __tests__/rc-installer.test.ts | 2 +- dist/setup/index.js | 76 +++++++++---------- .../base-distribution.ts | 24 +++--- .../base-models.ts | 0 .../installer-factory.ts | 2 +- .../nightly/nightly_builds.ts | 2 +- .../official_builds/official_builds.ts | 18 ++--- .../rc/rc_builds.ts | 4 +- .../v8-canary/canary_builds.ts | 2 +- src/main.ts | 4 +- 14 files changed, 78 insertions(+), 78 deletions(-) rename src/{distibutions => distributions}/base-distribution.ts (91%) rename src/{distibutions => distributions}/base-models.ts (100%) rename src/{distibutions => distributions}/installer-factory.ts (95%) rename src/{distibutions => distributions}/nightly/nightly_builds.ts (97%) rename src/{distibutions => distributions}/official_builds/official_builds.ts (92%) rename src/{distibutions/official_builds => distributions}/rc/rc_builds.ts (89%) rename src/{distibutions => distributions}/v8-canary/canary_builds.ts (97%) diff --git a/__tests__/canary-installer.test.ts b/__tests__/canary-installer.test.ts index 9ce645c66..7eb196cf7 100644 --- a/__tests__/canary-installer.test.ts +++ b/__tests__/canary-installer.test.ts @@ -10,7 +10,7 @@ import osm from 'os'; import path from 'path'; import * as main from '../src/main'; import * as auth from '../src/authutil'; -import {INodeVersion} from '../src/distibutions/base-models'; +import {INodeVersion} from '../src/distributions/base-models'; const nodeTestManifest = require('./data/versions-manifest.json'); const nodeTestDist = require('./data/node-dist-index.json'); @@ -245,7 +245,7 @@ describe('setup-node', () => { expect(dlSpy).toHaveBeenCalled(); expect(exSpy).toHaveBeenCalled(); expect(logSpy).toHaveBeenCalledWith( - 'Not found in manifest. Falling back to download directly from Node' + 'Not found in manifest. Falling back to download directly from Node' ); expect(logSpy).toHaveBeenCalledWith( `Attempting to download ${versionSpec}...` diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index b1d88f0c9..abd3c022b 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -11,7 +11,7 @@ import each from 'jest-each'; import * as main from '../src/main'; import * as util from '../src/util'; -import OfficialBuilds from '../src/distibutions/official_builds/official_builds'; +import OfficialBuilds from '../src/distributions/official_builds/official_builds'; describe('main tests', () => { let inputs = {} as any; @@ -33,7 +33,7 @@ describe('main tests', () => { let findSpy: jest.SpyInstance; let isCacheActionAvailable: jest.SpyInstance; - let getNodeJsInfoSpy: jest.SpyInstance; + let setupNodeJsSpy: jest.SpyInstance; beforeEach(() => { inputs = {}; @@ -70,8 +70,8 @@ describe('main tests', () => { // process.stderr.write('write:' + line + '\n'); }); - getNodeJsInfoSpy = jest.spyOn(OfficialBuilds.prototype, 'getNodeJsInfo'); - getNodeJsInfoSpy.mockImplementation(() => {}); + setupNodeJsSpy = jest.spyOn(OfficialBuilds.prototype, 'setupNodeJs'); + setupNodeJsSpy.mockImplementation(() => {}); }); afterEach(() => { diff --git a/__tests__/nightly-installer.test.ts b/__tests__/nightly-installer.test.ts index c37b72bdd..853b204b1 100644 --- a/__tests__/nightly-installer.test.ts +++ b/__tests__/nightly-installer.test.ts @@ -10,7 +10,7 @@ import osm from 'os'; import path from 'path'; import * as main from '../src/main'; import * as auth from '../src/authutil'; -import {INodeVersion} from '../src/distibutions/base-models'; +import {INodeVersion} from '../src/distributions/base-models'; const nodeTestManifest = require('./data/versions-manifest.json'); const nodeTestDist = require('./data/node-dist-index.json'); diff --git a/__tests__/official-installer.test.ts b/__tests__/official-installer.test.ts index 6dfac1c9f..5309fbbac 100644 --- a/__tests__/official-installer.test.ts +++ b/__tests__/official-installer.test.ts @@ -10,8 +10,8 @@ import osm from 'os'; import path from 'path'; import * as main from '../src/main'; import * as auth from '../src/authutil'; -import OfficialBuilds from '../src/distibutions/official_builds/official_builds'; -import {INodeVersion} from '../src/distibutions/base-models'; +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'); @@ -307,7 +307,7 @@ describe('setup-node', () => { `Attempting to download ${versionSpec}...` ); expect(logSpy).toHaveBeenCalledWith( - 'Not found in manifest. Falling back to download directly from Node' + 'Not found in manifest. Falling back to download directly from Node' ); expect(dlSpy).toHaveBeenCalled(); expect(exSpy).toHaveBeenCalled(); @@ -325,7 +325,7 @@ describe('setup-node', () => { await main.run(); expect(logSpy).toHaveBeenCalledWith( - 'Not found in manifest. Falling back to download directly from Node' + 'Not found in manifest. Falling back to download directly from Node' ); expect(logSpy).toHaveBeenCalledWith( `Attempting to download ${versionSpec}...` diff --git a/__tests__/rc-installer.test.ts b/__tests__/rc-installer.test.ts index d9eae0811..7faff7a8a 100644 --- a/__tests__/rc-installer.test.ts +++ b/__tests__/rc-installer.test.ts @@ -10,7 +10,7 @@ import osm from 'os'; import path from 'path'; import * as main from '../src/main'; import * as auth from '../src/authutil'; -import {INodeVersion} from '../src/distibutions/base-models'; +import {INodeVersion} from '../src/distributions/base-models'; const nodeTestDist = require('./data/node-dist-index.json'); const nodeTestDistNightly = require('./data/node-nightly-index.json'); diff --git a/dist/setup/index.js b/dist/setup/index.js index cf9f4e0dc..659ecbe00 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73222,7 +73222,7 @@ var Outputs; /***/ }), -/***/ 8653: +/***/ 7: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -73277,24 +73277,24 @@ class BaseDistribution { maxRetries: 3 }); } - getNodeJsInfo() { + setupNodeJs() { return __awaiter(this, void 0, void 0, function* () { - let nodeVersions; + let nodeJsVersions; if (this.nodeInfo.checkLatest) { - nodeVersions = yield this.getNodejsVersions(); - const versions = this.filterVersions(nodeVersions); + nodeJsVersions = yield this.getNodeJsVersions(); + const versions = this.filterVersions(nodeJsVersions); const evaluatedVersion = this.evaluateVersions(versions); if (evaluatedVersion) { this.nodeInfo.versionSpec = evaluatedVersion; } } - let toolPath = this.findVersionInHoostedToolCacheDirectory(); + let toolPath = this.findVersionInHostedToolCacheDirectory(); if (toolPath) { core.info(`Found in cache @ ${toolPath}`); } else { - nodeVersions = nodeVersions !== null && nodeVersions !== void 0 ? nodeVersions : (yield this.getNodejsVersions()); - const versions = this.filterVersions(nodeVersions); + nodeJsVersions = nodeJsVersions !== null && nodeJsVersions !== void 0 ? nodeJsVersions : (yield 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}.`); @@ -73308,10 +73308,10 @@ class BaseDistribution { core.addPath(toolPath); }); } - findVersionInHoostedToolCacheDirectory() { + findVersionInHostedToolCacheDirectory() { return tc.find('node', this.nodeInfo.versionSpec, this.nodeInfo.arch); } - getNodejsVersions() { + getNodeJsVersions() { return __awaiter(this, void 0, void 0, function* () { const initialUrl = this.getDistributionUrl(); const dataUrl = `${initialUrl}/index.json`; @@ -73442,10 +73442,10 @@ class BaseDistribution { } return dataFileName; } - filterVersions(nodeVersions) { + filterVersions(nodeJsVersions) { const versions = []; const dataFileName = this.getDistFileName(this.nodeInfo.arch); - nodeVersions.forEach((nodeVersion) => { + nodeJsVersions.forEach((nodeVersion) => { // ensure this version supports your os and platform if (nodeVersion.files.indexOf(dataFileName) >= 0) { versions.push(nodeVersion.version); @@ -73467,7 +73467,7 @@ exports["default"] = BaseDistribution; /***/ }), -/***/ 1260: +/***/ 5617: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -73477,10 +73477,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getNodejsDistribution = void 0; -const nightly_builds_1 = __importDefault(__nccwpck_require__(1002)); -const official_builds_1 = __importDefault(__nccwpck_require__(9856)); -const rc_builds_1 = __importDefault(__nccwpck_require__(6235)); -const canary_builds_1 = __importDefault(__nccwpck_require__(4833)); +const nightly_builds_1 = __importDefault(__nccwpck_require__(7127)); +const official_builds_1 = __importDefault(__nccwpck_require__(7854)); +const rc_builds_1 = __importDefault(__nccwpck_require__(8837)); +const canary_builds_1 = __importDefault(__nccwpck_require__(969)); var Distributions; (function (Distributions) { Distributions["DEFAULT"] = ""; @@ -73519,7 +73519,7 @@ exports.getNodejsDistribution = getNodejsDistribution; /***/ }), -/***/ 1002: +/***/ 7127: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -73550,13 +73550,13 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__nccwpck_require__(2186)); const tc = __importStar(__nccwpck_require__(7784)); const semver_1 = __importDefault(__nccwpck_require__(5911)); -const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); +const base_distribution_1 = __importDefault(__nccwpck_require__(7)); class NightlyNodejs extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); this.distribution = 'nightly'; } - findVersionInHoostedToolCacheDirectory() { + findVersionInHostedToolCacheDirectory() { let toolPath = ''; const localVersionPaths = tc .findAllVersions('node', this.nodeInfo.arch) @@ -73621,7 +73621,7 @@ exports["default"] = NightlyNodejs; /***/ }), -/***/ 9856: +/***/ 7854: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -73663,15 +73663,15 @@ const tc = __importStar(__nccwpck_require__(7784)); const semver = __importStar(__nccwpck_require__(5911)); const os_1 = __importDefault(__nccwpck_require__(2037)); const path_1 = __importDefault(__nccwpck_require__(1017)); -const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); +const base_distribution_1 = __importDefault(__nccwpck_require__(7)); class OfficialBuilds extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); } - getNodeJsInfo() { + setupNodeJs() { return __awaiter(this, void 0, void 0, function* () { let manifest; - let nodeVersions; + let nodeJsVersions; const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); if (this.isLtsAlias(this.nodeInfo.versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); @@ -73680,8 +73680,8 @@ class OfficialBuilds extends base_distribution_1.default { this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest(this.nodeInfo.versionSpec, true, manifest); } if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { - nodeVersions = yield this.getNodejsVersions(); - const versions = this.filterVersions(nodeVersions); + nodeJsVersions = yield this.getNodeJsVersions(); + const versions = this.filterVersions(nodeJsVersions); this.nodeInfo.versionSpec = this.evaluateVersions(versions); core.info('getting latest node version...'); } @@ -73696,7 +73696,7 @@ class OfficialBuilds extends base_distribution_1.default { core.info(`Failed to resolve version ${this.nodeInfo.versionSpec} from manifest`); } } - let toolPath = this.findVersionInHoostedToolCacheDirectory(); + let toolPath = this.findVersionInHostedToolCacheDirectory(); if (toolPath) { core.info(`Found in cache @ ${toolPath}`); } @@ -73713,14 +73713,14 @@ class OfficialBuilds extends base_distribution_1.default { } } else { - core.info('Not found in manifest. Falling back to download directly from Node'); + 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`); + core.info(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`); } else { core.info(err.message); @@ -73729,8 +73729,8 @@ class OfficialBuilds extends base_distribution_1.default { core.info('Falling back to download directly from Node'); } if (!toolPath) { - const nodeVersions = yield this.getNodejsVersions(); - const versions = this.filterVersions(nodeVersions); + const nodeJsVersions = yield 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}.`); @@ -73842,7 +73842,7 @@ exports["default"] = OfficialBuilds; /***/ }), -/***/ 6235: +/***/ 8837: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -73872,7 +73872,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__nccwpck_require__(2186)); const semver = __importStar(__nccwpck_require__(5911)); -const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); +const base_distribution_1 = __importDefault(__nccwpck_require__(7)); class RcBuild extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); @@ -73905,7 +73905,7 @@ exports["default"] = RcBuild; /***/ }), -/***/ 4833: +/***/ 969: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { "use strict"; @@ -73936,13 +73936,13 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__nccwpck_require__(2186)); const tc = __importStar(__nccwpck_require__(7784)); const semver_1 = __importDefault(__nccwpck_require__(5911)); -const base_distribution_1 = __importDefault(__nccwpck_require__(8653)); +const base_distribution_1 = __importDefault(__nccwpck_require__(7)); class CanaryBuild extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); this.distribution = 'v8-canary'; } - findVersionInHoostedToolCacheDirectory() { + findVersionInHostedToolCacheDirectory() { let toolPath = ''; const localVersionPaths = tc .findAllVersions('node', this.nodeInfo.arch) @@ -74052,7 +74052,7 @@ const auth = __importStar(__nccwpck_require__(7573)); const path = __importStar(__nccwpck_require__(1017)); const cache_restore_1 = __nccwpck_require__(9517); const cache_utils_1 = __nccwpck_require__(1678); -const installer_factory_1 = __nccwpck_require__(1260); +const installer_factory_1 = __nccwpck_require__(5617); const util_1 = __nccwpck_require__(2629); function run() { return __awaiter(this, void 0, void 0, function* () { @@ -74083,7 +74083,7 @@ function run() { arch }; const nodeDistribution = installer_factory_1.getNodejsDistribution(nodejsInfo); - yield nodeDistribution.getNodeJsInfo(); + yield nodeDistribution.setupNodeJs(); } yield util_1.printEnvDetailsAndSetOutput(); const registryUrl = core.getInput('registry-url'); diff --git a/src/distibutions/base-distribution.ts b/src/distributions/base-distribution.ts similarity index 91% rename from src/distibutions/base-distribution.ts rename to src/distributions/base-distribution.ts index e6827ad80..06e06a86c 100644 --- a/src/distibutions/base-distribution.ts +++ b/src/distributions/base-distribution.ts @@ -26,11 +26,11 @@ export default abstract class BaseDistribution { protected abstract getDistributionUrl(): string; protected abstract evaluateVersions(nodeVersions: string[]): string; - public async getNodeJsInfo() { - let nodeVersions: INodeVersion[] | undefined; + public async setupNodeJs() { + let nodeJsVersions: INodeVersion[] | undefined; if (this.nodeInfo.checkLatest) { - nodeVersions = await this.getNodejsVersions(); - const versions = this.filterVersions(nodeVersions); + nodeJsVersions = await this.getNodeJsVersions(); + const versions = this.filterVersions(nodeJsVersions); const evaluatedVersion = this.evaluateVersions(versions); if (evaluatedVersion) { @@ -38,12 +38,12 @@ export default abstract class BaseDistribution { } } - let toolPath = this.findVersionInHoostedToolCacheDirectory(); + let toolPath = this.findVersionInHostedToolCacheDirectory(); if (toolPath) { core.info(`Found in cache @ ${toolPath}`); } else { - nodeVersions = nodeVersions ?? (await this.getNodejsVersions()); - const versions = this.filterVersions(nodeVersions); + nodeJsVersions = nodeJsVersions ?? (await this.getNodeJsVersions()); + const versions = this.filterVersions(nodeJsVersions); const evaluatedVersion = this.evaluateVersions(versions); if (!evaluatedVersion) { throw new Error( @@ -61,11 +61,11 @@ export default abstract class BaseDistribution { core.addPath(toolPath); } - protected findVersionInHoostedToolCacheDirectory() { + protected findVersionInHostedToolCacheDirectory() { return tc.find('node', this.nodeInfo.versionSpec, this.nodeInfo.arch); } - protected async getNodejsVersions(): Promise { + protected async getNodeJsVersions(): Promise { const initialUrl = this.getDistributionUrl(); const dataUrl = `${initialUrl}/index.json`; @@ -88,7 +88,7 @@ export default abstract class BaseDistribution { return { downloadUrl: url, resolvedVersion: version, - arch: osArch, // have to be arch but not osArch, + arch: osArch, fileName: fileName }; } @@ -227,12 +227,12 @@ export default abstract class BaseDistribution { return dataFileName; } - protected filterVersions(nodeVersions: INodeVersion[]) { + protected filterVersions(nodeJsVersions: INodeVersion[]) { const versions: string[] = []; const dataFileName = this.getDistFileName(this.nodeInfo.arch); - nodeVersions.forEach((nodeVersion: INodeVersion) => { + nodeJsVersions.forEach((nodeVersion: INodeVersion) => { // ensure this version supports your os and platform if (nodeVersion.files.indexOf(dataFileName) >= 0) { versions.push(nodeVersion.version); diff --git a/src/distibutions/base-models.ts b/src/distributions/base-models.ts similarity index 100% rename from src/distibutions/base-models.ts rename to src/distributions/base-models.ts diff --git a/src/distibutions/installer-factory.ts b/src/distributions/installer-factory.ts similarity index 95% rename from src/distibutions/installer-factory.ts rename to src/distributions/installer-factory.ts index eccaa2f7d..7106f5dbb 100644 --- a/src/distibutions/installer-factory.ts +++ b/src/distributions/installer-factory.ts @@ -2,7 +2,7 @@ import BaseDistribution from './base-distribution'; import {INodejs} from './base-models'; import NightlyNodejs from './nightly/nightly_builds'; import OfficialBuilds from './official_builds/official_builds'; -import RcBuild from './official_builds/rc/rc_builds'; +import RcBuild from './rc/rc_builds'; import CanaryBuild from './v8-canary/canary_builds'; enum Distributions { diff --git a/src/distibutions/nightly/nightly_builds.ts b/src/distributions/nightly/nightly_builds.ts similarity index 97% rename from src/distibutions/nightly/nightly_builds.ts rename to src/distributions/nightly/nightly_builds.ts index f21c52508..bf3692e99 100644 --- a/src/distibutions/nightly/nightly_builds.ts +++ b/src/distributions/nightly/nightly_builds.ts @@ -12,7 +12,7 @@ export default class NightlyNodejs extends BaseDistribution { super(nodeInfo); } - protected findVersionInHoostedToolCacheDirectory(): string { + protected findVersionInHostedToolCacheDirectory(): string { let toolPath = ''; const localVersionPaths = tc .findAllVersions('node', this.nodeInfo.arch) diff --git a/src/distibutions/official_builds/official_builds.ts b/src/distributions/official_builds/official_builds.ts similarity index 92% rename from src/distibutions/official_builds/official_builds.ts rename to src/distributions/official_builds/official_builds.ts index a1a43c578..91d6fe0c9 100644 --- a/src/distibutions/official_builds/official_builds.ts +++ b/src/distributions/official_builds/official_builds.ts @@ -16,9 +16,9 @@ export default class OfficialBuilds extends BaseDistribution { super(nodeInfo); } - public async getNodeJsInfo() { + public async setupNodeJs() { let manifest: tc.IToolRelease[] | undefined; - let nodeVersions: INodeVersion[] | 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...'); @@ -34,8 +34,8 @@ export default class OfficialBuilds extends BaseDistribution { } if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { - nodeVersions = await this.getNodejsVersions(); - const versions = this.filterVersions(nodeVersions); + nodeJsVersions = await this.getNodeJsVersions(); + const versions = this.filterVersions(nodeJsVersions); this.nodeInfo.versionSpec = this.evaluateVersions(versions); core.info('getting latest node version...'); @@ -58,7 +58,7 @@ export default class OfficialBuilds extends BaseDistribution { } } - let toolPath = this.findVersionInHoostedToolCacheDirectory(); + let toolPath = this.findVersionInHostedToolCacheDirectory(); if (toolPath) { core.info(`Found in cache @ ${toolPath}`); @@ -87,7 +87,7 @@ export default class OfficialBuilds extends BaseDistribution { } } else { core.info( - 'Not found in manifest. Falling back to download directly from Node' + 'Not found in manifest. Falling back to download directly from Node' ); } } catch (err) { @@ -97,7 +97,7 @@ export default class OfficialBuilds extends BaseDistribution { (err.httpStatusCode === 403 || err.httpStatusCode === 429) ) { core.info( - `Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded` + `Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded` ); } else { core.info(err.message); @@ -107,8 +107,8 @@ export default class OfficialBuilds extends BaseDistribution { } if (!toolPath) { - const nodeVersions = await this.getNodejsVersions(); - const versions = this.filterVersions(nodeVersions); + const nodeJsVersions = await this.getNodeJsVersions(); + const versions = this.filterVersions(nodeJsVersions); const evaluatedVersion = this.evaluateVersions(versions); if (!evaluatedVersion) { throw new Error( diff --git a/src/distibutions/official_builds/rc/rc_builds.ts b/src/distributions/rc/rc_builds.ts similarity index 89% rename from src/distibutions/official_builds/rc/rc_builds.ts rename to src/distributions/rc/rc_builds.ts index 666673f4e..3387a93ff 100644 --- a/src/distibutions/official_builds/rc/rc_builds.ts +++ b/src/distributions/rc/rc_builds.ts @@ -2,8 +2,8 @@ import * as core from '@actions/core'; import * as semver from 'semver'; -import BaseDistribution from '../../base-distribution'; -import {INodejs} from '../../base-models'; +import BaseDistribution from '../base-distribution'; +import {INodejs} from '../base-models'; export default class RcBuild extends BaseDistribution { constructor(nodeInfo: INodejs) { diff --git a/src/distibutions/v8-canary/canary_builds.ts b/src/distributions/v8-canary/canary_builds.ts similarity index 97% rename from src/distibutions/v8-canary/canary_builds.ts rename to src/distributions/v8-canary/canary_builds.ts index 425ed54c1..678f7d24a 100644 --- a/src/distibutions/v8-canary/canary_builds.ts +++ b/src/distributions/v8-canary/canary_builds.ts @@ -12,7 +12,7 @@ export default class CanaryBuild extends BaseDistribution { super(nodeInfo); } - protected findVersionInHoostedToolCacheDirectory(): string { + protected findVersionInHostedToolCacheDirectory(): string { let toolPath = ''; const localVersionPaths = tc .findAllVersions('node', this.nodeInfo.arch) diff --git a/src/main.ts b/src/main.ts index 61a2f9546..0b29faace 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,7 +7,7 @@ import * as auth from './authutil'; import * as path from 'path'; import {restoreCache} from './cache-restore'; import {isCacheFeatureAvailable} from './cache-utils'; -import {getNodejsDistribution} from './distibutions/installer-factory'; +import {getNodejsDistribution} from './distributions/installer-factory'; import {parseNodeVersionFile, printEnvDetailsAndSetOutput} from './util'; export async function run() { @@ -45,7 +45,7 @@ export async function run() { arch }; const nodeDistribution = getNodejsDistribution(nodejsInfo); - await nodeDistribution.getNodeJsInfo(); + await nodeDistribution.setupNodeJs(); } await printEnvDetailsAndSetOutput(); From 7f2fa590924c2d278930488d36d67245ddd7b1d8 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 27 Dec 2022 19:28:20 +0100 Subject: [PATCH 43/51] resolve comments --- dist/cache-save/index.js | 64 +--- dist/setup/index.js | 345 +++++------------- src/distributions/base-distribution.ts | 42 ++- src/distributions/installer-factory.ts | 31 +- .../official_builds/official_builds.ts | 25 +- src/distributions/rc/rc_builds.ts | 30 -- 6 files changed, 153 insertions(+), 384 deletions(-) diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index 92b5418f9..d099eecba 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -61019,25 +61019,6 @@ 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) { @@ -61047,11 +61028,17 @@ 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)); @@ -61108,25 +61095,6 @@ 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) { @@ -61136,8 +61104,14 @@ 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)); @@ -61159,7 +61133,7 @@ exports.supportedPackageManagers = { getCacheFolderCommand: 'yarn config get cacheFolder' } }; -const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () { +exports.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() @@ -61169,7 +61143,6 @@ const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, func } 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) { @@ -61177,7 +61150,7 @@ const getPackageManagerVersion = (packageManager, command) => __awaiter(void 0, } return stdOut; }); -const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () { +exports.getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () { if (packageManager === 'npm') { return exports.supportedPackageManagers.npm; } @@ -61198,8 +61171,7 @@ const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void return null; } }); -exports.getPackageManagerInfo = getPackageManagerInfo; -const getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaiter(void 0, void 0, void 0, function* () { +exports.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}`); @@ -61207,7 +61179,6 @@ const getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaiter( 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'; @@ -61234,7 +61205,6 @@ 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"; diff --git a/dist/setup/index.js b/dist/setup/index.js index 659ecbe00..54a6aab94 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -72915,27 +72915,14 @@ function wrappy (fn, cb) { "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); + 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.configAuthentication = void 0; const fs = __importStar(__nccwpck_require__(7147)); const os = __importStar(__nccwpck_require__(2037)); const path = __importStar(__nccwpck_require__(1017)); @@ -72990,25 +72977,6 @@ function writeRegistryToFile(registryUrl, fileLocation, alwaysAuth) { "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) { @@ -73018,11 +72986,17 @@ 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.restoreCache = void 0; const cache = __importStar(__nccwpck_require__(7799)); const core = __importStar(__nccwpck_require__(2186)); const glob = __importStar(__nccwpck_require__(8090)); @@ -73030,7 +73004,7 @@ const path_1 = __importDefault(__nccwpck_require__(1017)); const fs_1 = __importDefault(__nccwpck_require__(7147)); const constants_1 = __nccwpck_require__(9042); const cache_utils_1 = __nccwpck_require__(1678); -const restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { +exports.restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager); if (!packageManagerInfo) { throw new Error(`Caching for '${packageManager}' is not supported`); @@ -73056,7 +73030,6 @@ const restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, core.saveState(constants_1.State.CacheMatchedKey, cacheKey); core.info(`Cache restored from key: ${cacheKey}`); }); -exports.restoreCache = restoreCache; const findLockFile = (packageManager) => { let lockFiles = packageManager.lockFilePatterns; const workspace = process.env.GITHUB_WORKSPACE; @@ -73076,25 +73049,6 @@ const findLockFile = (packageManager) => { "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) { @@ -73104,8 +73058,14 @@ 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)); @@ -73127,7 +73087,7 @@ exports.supportedPackageManagers = { getCacheFolderCommand: 'yarn config get cacheFolder' } }; -const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, function* () { +exports.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() @@ -73137,7 +73097,6 @@ const getCommandOutput = (toolCommand) => __awaiter(void 0, void 0, void 0, func } 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) { @@ -73145,7 +73104,7 @@ const getPackageManagerVersion = (packageManager, command) => __awaiter(void 0, } return stdOut; }); -const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () { +exports.getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void 0, function* () { if (packageManager === 'npm') { return exports.supportedPackageManagers.npm; } @@ -73166,8 +73125,7 @@ const getPackageManagerInfo = (packageManager) => __awaiter(void 0, void 0, void return null; } }); -exports.getPackageManagerInfo = getPackageManagerInfo; -const getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaiter(void 0, void 0, void 0, function* () { +exports.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}`); @@ -73175,7 +73133,6 @@ const getCacheDirectoryPath = (packageManagerInfo, packageManager) => __awaiter( 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'; @@ -73202,7 +73159,6 @@ 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"; @@ -73227,25 +73183,6 @@ var Outputs; "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) { @@ -73255,6 +73192,13 @@ 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 }; }; @@ -73299,7 +73243,7 @@ class BaseDistribution { 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, this.osPlat); + const toolName = this.getNodejsDistInfo(evaluatedVersion); toolPath = yield this.downloadNodejs(toolName); } if (this.osPlat != 'win32') { @@ -73308,6 +73252,24 @@ class BaseDistribution { core.addPath(toolPath); }); } + evaluateVersions(versions) { + let version = ''; + core.debug(`evaluating ${versions.length} versions`); + for (let potential of versions) { + const satisfied = semver_1.default.satisfies(potential, this.nodeInfo.versionSpec); + if (satisfied) { + version = potential; + break; + } + } + if (version) { + core.debug(`matched: ${version}`); + } + else { + core.debug('match not found'); + } + return version; + } findVersionInHostedToolCacheDirectory() { return tc.find('node', this.nodeInfo.versionSpec, this.nodeInfo.arch); } @@ -73319,13 +73281,13 @@ class BaseDistribution { return response.result || []; }); } - getNodejsDistInfo(version, osPlat) { + getNodejsDistInfo(version) { let osArch = this.translateArchToDistUrl(this.nodeInfo.arch); version = semver_1.default.clean(version) || ''; - let fileName = osPlat == 'win32' + let fileName = this.osPlat == 'win32' ? `node-v${version}-win-${osArch}` - : `node-v${version}-${osPlat}-${osArch}`; - let urlFileName = osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; + : `node-v${version}-${this.osPlat}-${osArch}`; + let urlFileName = this.osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; const initialUrl = this.getDistributionUrl(); const url = `${initialUrl}/v${version}/${urlFileName}`; return { @@ -73423,8 +73385,8 @@ class BaseDistribution { return toolPath; }); } - getDistFileName(arch) { - let osArch = this.translateArchToDistUrl(arch); + getDistFileName() { + let osArch = this.translateArchToDistUrl(this.nodeInfo.arch); // node offers a json list of versions let dataFileName; switch (this.osPlat) { @@ -73444,7 +73406,7 @@ class BaseDistribution { } filterVersions(nodeJsVersions) { const versions = []; - const dataFileName = this.getDistFileName(this.nodeInfo.arch); + const dataFileName = this.getDistFileName(); nodeJsVersions.forEach((nodeVersion) => { // ensure this version supports your os and platform if (nodeVersion.files.indexOf(dataFileName) >= 0) { @@ -73476,7 +73438,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getNodejsDistribution = void 0; const nightly_builds_1 = __importDefault(__nccwpck_require__(7127)); const official_builds_1 = __importDefault(__nccwpck_require__(7854)); const rc_builds_1 = __importDefault(__nccwpck_require__(8837)); @@ -73488,31 +73449,22 @@ var Distributions; Distributions["NIGHTLY"] = "nightly"; Distributions["RC"] = "rc"; })(Distributions || (Distributions = {})); -function identifyDistribution(versionSpec) { - let distribution = Distributions.DEFAULT; +function getNodejsDistribution(installerOptions) { + const versionSpec = installerOptions.versionSpec; + let distribution; if (versionSpec.includes(Distributions.NIGHTLY)) { - distribution = Distributions.NIGHTLY; + distribution = new nightly_builds_1.default(installerOptions); } else if (versionSpec.includes(Distributions.CANARY)) { - distribution = Distributions.CANARY; + distribution = new canary_builds_1.default(installerOptions); } else if (versionSpec.includes(Distributions.RC)) { - distribution = Distributions.RC; + distribution = new rc_builds_1.default(installerOptions); } - return distribution; -} -function getNodejsDistribution(installerOptions) { - const distributionName = identifyDistribution(installerOptions.versionSpec); - switch (distributionName) { - case Distributions.NIGHTLY: - return new nightly_builds_1.default(installerOptions); - case Distributions.CANARY: - return new canary_builds_1.default(installerOptions); - case Distributions.RC: - return new rc_builds_1.default(installerOptions); - default: - return new official_builds_1.default(installerOptions); + else { + distribution = new official_builds_1.default(installerOptions); } + return distribution; } exports.getNodejsDistribution = getNodejsDistribution; @@ -73524,23 +73476,11 @@ exports.getNodejsDistribution = getNodejsDistribution; "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); + 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) { @@ -73626,25 +73566,6 @@ exports["default"] = NightlyNodejs; "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) { @@ -73654,14 +73575,19 @@ 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 })); const core = __importStar(__nccwpck_require__(2186)); const tc = __importStar(__nccwpck_require__(7784)); -const semver = __importStar(__nccwpck_require__(5911)); -const os_1 = __importDefault(__nccwpck_require__(2037)); const path_1 = __importDefault(__nccwpck_require__(1017)); const base_distribution_1 = __importDefault(__nccwpck_require__(7)); class OfficialBuilds extends base_distribution_1.default { @@ -73735,7 +73661,7 @@ class OfficialBuilds extends base_distribution_1.default { 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, this.osPlat); + const toolName = this.getNodejsDistInfo(evaluatedVersion); toolPath = yield this.downloadNodejs(toolName); } } @@ -73751,20 +73677,7 @@ class OfficialBuilds extends base_distribution_1.default { core.info(`getting latest node version...`); return versions[0]; } - core.debug(`evaluating ${versions.length} versions`); - for (let potential of versions) { - const satisfied = semver.satisfies(potential, this.nodeInfo.versionSpec); - if (satisfied) { - version = potential; - break; - } - } - if (version) { - core.debug(`matched: ${version}`); - } - else { - core.debug('match not found'); - } + version = super.evaluateVersions(versions); return version; } getDistributionUrl() { @@ -73811,7 +73724,7 @@ class OfficialBuilds extends base_distribution_1.default { } }); } - getInfoFromManifest(versionSpec, osArch = this.translateArchToDistUrl(os_1.default.arch()), manifest) { + getInfoFromManifest(versionSpec, osArch, manifest) { return __awaiter(this, void 0, void 0, function* () { const stable = true; let info = null; @@ -73847,55 +73760,15 @@ exports["default"] = OfficialBuilds; "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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const core = __importStar(__nccwpck_require__(2186)); -const semver = __importStar(__nccwpck_require__(5911)); const base_distribution_1 = __importDefault(__nccwpck_require__(7)); class RcBuild extends base_distribution_1.default { constructor(nodeInfo) { super(nodeInfo); } - evaluateVersions(versions) { - let version = ''; - core.debug(`evaluating ${versions.length} versions`); - for (let i = 0; i < versions.length; i++) { - const potential = versions[i]; - const satisfied = semver.satisfies(potential, this.nodeInfo.versionSpec); - if (satisfied) { - version = potential; - break; - } - } - if (version) { - core.debug(`matched: ${version}`); - } - else { - core.debug('match not found'); - } - return version; - } getDistributionUrl() { return 'https://nodejs.org/download/rc'; } @@ -73910,23 +73783,11 @@ exports["default"] = RcBuild; "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); + 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) { @@ -74012,25 +73873,6 @@ exports["default"] = CanaryBuild; "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) { @@ -74040,11 +73882,17 @@ 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 fs_1 = __importDefault(__nccwpck_require__(7147)); const os_1 = __importDefault(__nccwpck_require__(2037)); @@ -74134,25 +73982,6 @@ function resolveVersionInput() { "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) { @@ -74162,8 +73991,14 @@ 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.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0; const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); function parseNodeVersionFile(contents) { diff --git a/src/distributions/base-distribution.ts b/src/distributions/base-distribution.ts index 06e06a86c..b567fd83e 100644 --- a/src/distributions/base-distribution.ts +++ b/src/distributions/base-distribution.ts @@ -24,7 +24,6 @@ export default abstract class BaseDistribution { } protected abstract getDistributionUrl(): string; - protected abstract evaluateVersions(nodeVersions: string[]): string; public async setupNodeJs() { let nodeJsVersions: INodeVersion[] | undefined; @@ -50,7 +49,7 @@ export default abstract class BaseDistribution { `Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.` ); } - const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); + const toolName = this.getNodejsDistInfo(evaluatedVersion); toolPath = await this.downloadNodejs(toolName); } @@ -61,6 +60,31 @@ export default abstract class BaseDistribution { core.addPath(toolPath); } + protected evaluateVersions(versions: string[]) { + let version = ''; + + core.debug(`evaluating ${versions.length} versions`); + + for (let potential of versions) { + const satisfied: boolean = semver.satisfies( + potential, + this.nodeInfo.versionSpec + ); + 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); } @@ -73,15 +97,15 @@ export default abstract class BaseDistribution { return response.result || []; } - protected getNodejsDistInfo(version: string, osPlat: string) { + protected getNodejsDistInfo(version: string) { let osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch); version = semver.clean(version) || ''; let fileName: string = - osPlat == 'win32' + this.osPlat == 'win32' ? `node-v${version}-win-${osArch}` - : `node-v${version}-${osPlat}-${osArch}`; + : `node-v${version}-${this.osPlat}-${osArch}`; let urlFileName: string = - osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; + this.osPlat == 'win32' ? `${fileName}.7z` : `${fileName}.tar.gz`; const initialUrl = this.getDistributionUrl(); const url = `${initialUrl}/v${version}/${urlFileName}`; @@ -205,8 +229,8 @@ export default abstract class BaseDistribution { return toolPath; } - protected getDistFileName(arch: string): string { - let osArch: string = this.translateArchToDistUrl(arch); + protected getDistFileName(): string { + let osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch); // node offers a json list of versions let dataFileName: string; @@ -230,7 +254,7 @@ export default abstract class BaseDistribution { protected filterVersions(nodeJsVersions: INodeVersion[]) { const versions: string[] = []; - const dataFileName = this.getDistFileName(this.nodeInfo.arch); + const dataFileName = this.getDistFileName(); nodeJsVersions.forEach((nodeVersion: INodeVersion) => { // ensure this version supports your os and platform diff --git a/src/distributions/installer-factory.ts b/src/distributions/installer-factory.ts index 7106f5dbb..6f4c7e8fe 100644 --- a/src/distributions/installer-factory.ts +++ b/src/distributions/installer-factory.ts @@ -12,31 +12,20 @@ enum Distributions { RC = 'rc' } -function identifyDistribution(versionSpec: string) { - let distribution = Distributions.DEFAULT; +export function getNodejsDistribution( + installerOptions: INodejs +): BaseDistribution { + const versionSpec = installerOptions.versionSpec; + let distribution: BaseDistribution; if (versionSpec.includes(Distributions.NIGHTLY)) { - distribution = Distributions.NIGHTLY; + distribution = new NightlyNodejs(installerOptions); } else if (versionSpec.includes(Distributions.CANARY)) { - distribution = Distributions.CANARY; + distribution = new CanaryBuild(installerOptions); } else if (versionSpec.includes(Distributions.RC)) { - distribution = Distributions.RC; + distribution = new RcBuild(installerOptions); + } else { + distribution = new OfficialBuilds(installerOptions); } return distribution; } - -export function getNodejsDistribution( - installerOptions: INodejs -): BaseDistribution { - const distributionName = identifyDistribution(installerOptions.versionSpec); - switch (distributionName) { - case Distributions.NIGHTLY: - return new NightlyNodejs(installerOptions); - case Distributions.CANARY: - return new CanaryBuild(installerOptions); - case Distributions.RC: - return new RcBuild(installerOptions); - default: - return new OfficialBuilds(installerOptions); - } -} diff --git a/src/distributions/official_builds/official_builds.ts b/src/distributions/official_builds/official_builds.ts index 91d6fe0c9..53d7e9103 100644 --- a/src/distributions/official_builds/official_builds.ts +++ b/src/distributions/official_builds/official_builds.ts @@ -1,7 +1,5 @@ import * as core from '@actions/core'; import * as tc from '@actions/tool-cache'; -import * as semver from 'semver'; -import os from 'os'; import path from 'path'; import BaseDistribution from '../base-distribution'; @@ -115,7 +113,7 @@ export default class OfficialBuilds extends BaseDistribution { `Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.` ); } - const toolName = this.getNodejsDistInfo(evaluatedVersion, this.osPlat); + const toolName = this.getNodejsDistInfo(evaluatedVersion); toolPath = await this.downloadNodejs(toolName); } } @@ -135,24 +133,7 @@ export default class OfficialBuilds extends BaseDistribution { return versions[0]; } - core.debug(`evaluating ${versions.length} versions`); - - for (let potential of versions) { - const satisfied: boolean = semver.satisfies( - potential, - this.nodeInfo.versionSpec - ); - if (satisfied) { - version = potential; - break; - } - } - - if (version) { - core.debug(`matched: ${version}`); - } else { - core.debug('match not found'); - } + version = super.evaluateVersions(versions); return version; } @@ -235,7 +216,7 @@ export default class OfficialBuilds extends BaseDistribution { private async getInfoFromManifest( versionSpec: string, - osArch: string = this.translateArchToDistUrl(os.arch()), + osArch: string, manifest: tc.IToolRelease[] | undefined ): Promise { const stable = true; diff --git a/src/distributions/rc/rc_builds.ts b/src/distributions/rc/rc_builds.ts index 3387a93ff..dd57ef820 100644 --- a/src/distributions/rc/rc_builds.ts +++ b/src/distributions/rc/rc_builds.ts @@ -1,7 +1,3 @@ -import * as core from '@actions/core'; - -import * as semver from 'semver'; - import BaseDistribution from '../base-distribution'; import {INodejs} from '../base-models'; @@ -10,32 +6,6 @@ export default class RcBuild extends BaseDistribution { super(nodeInfo); } - protected evaluateVersions(versions: string[]): string { - let version = ''; - - core.debug(`evaluating ${versions.length} versions`); - - for (let i = 0; i < versions.length; i++) { - const potential: string = versions[i]; - const satisfied: boolean = semver.satisfies( - potential, - this.nodeInfo.versionSpec - ); - if (satisfied) { - version = potential; - break; - } - } - - if (version) { - core.debug(`matched: ${version}`); - } else { - core.debug('match not found'); - } - - return version; - } - getDistributionUrl(): string { return 'https://nodejs.org/download/rc'; } From 363785e8f4ddb58af87e75fb8787ce5dc2a5db4d Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 27 Dec 2022 20:58:46 +0100 Subject: [PATCH 44/51] remove changing prerelease --- dist/setup/index.js | 64 ++++---------------- src/distributions/base-distribution.ts | 17 ++++-- src/distributions/nightly/nightly_builds.ts | 38 +----------- src/distributions/v8-canary/canary_builds.ts | 38 +----------- 4 files changed, 29 insertions(+), 128 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 54a6aab94..59655926c 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73254,9 +73254,10 @@ class BaseDistribution { } evaluateVersions(versions) { let version = ''; + const { range, options } = this.validRange(this.nodeInfo.versionSpec); core.debug(`evaluating ${versions.length} versions`); for (let potential of versions) { - const satisfied = semver_1.default.satisfies(potential, this.nodeInfo.versionSpec); + const satisfied = semver_1.default.satisfies(potential, range, options); if (satisfied) { version = potential; break; @@ -73315,6 +73316,13 @@ class BaseDistribution { return toolPath; }); } + validRange(versionSpec) { + var _a; + let options; + const c = semver_1.default.clean(versionSpec) || ''; + const valid = (_a = semver_1.default.valid(c)) !== null && _a !== void 0 ? _a : versionSpec; + return { range: valid, options }; + } acquireNodeFromFallbackLocation(version, arch = os_1.default.arch()) { return __awaiter(this, void 0, void 0, function* () { const initialUrl = this.getDistributionUrl(); @@ -73487,7 +73495,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const core = __importStar(__nccwpck_require__(2186)); const tc = __importStar(__nccwpck_require__(7784)); const semver_1 = __importDefault(__nccwpck_require__(5911)); const base_distribution_1 = __importDefault(__nccwpck_require__(7)); @@ -73514,32 +73521,10 @@ class NightlyNodejs extends base_distribution_1.default { } return toolPath; } - evaluateVersions(versions) { - let version = ''; - core.debug(`evaluating ${versions.length} versions`); - const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec); - for (let i = 0; i < versions.length; i++) { - const potential = versions[i]; - const satisfied = semver_1.default.satisfies(potential.replace(this.distribution, `${this.distribution}.`), range, { - includePrerelease: includePrerelease - }); - if (satisfied) { - version = potential; - break; - } - } - if (version) { - core.debug(`matched: ${version}`); - } - else { - core.debug('match not found'); - } - return version; - } getDistributionUrl() { return 'https://nodejs.org/download/nightly'; } - createRangePreRelease(versionSpec) { + validRange(versionSpec) { let range; const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver_1.default.valid(raw); @@ -73550,7 +73535,7 @@ class NightlyNodejs extends base_distribution_1.default { else { range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } - return { range, includePrerelease: !isValidVersion }; + return { range, options: { includePrerelease: !isValidVersion } }; } splitVersionSpec(versionSpec) { return versionSpec.split(/-(.*)/s); @@ -73794,7 +73779,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const core = __importStar(__nccwpck_require__(2186)); const tc = __importStar(__nccwpck_require__(7784)); const semver_1 = __importDefault(__nccwpck_require__(5911)); const base_distribution_1 = __importDefault(__nccwpck_require__(7)); @@ -73824,29 +73808,7 @@ class CanaryBuild extends base_distribution_1.default { getDistributionUrl() { return 'https://nodejs.org/download/v8-canary'; } - evaluateVersions(versions) { - let version = ''; - core.debug(`evaluating ${versions.length} versions`); - const { includePrerelease, range } = this.createRangePreRelease(this.nodeInfo.versionSpec); - for (let i = 0; i < versions.length; i++) { - const potential = versions[i]; - const satisfied = semver_1.default.satisfies(potential.replace(this.distribution, `${this.distribution}.`), range, { - includePrerelease: includePrerelease - }); - if (satisfied) { - version = potential; - break; - } - } - if (version) { - core.debug(`matched: ${version}`); - } - else { - core.debug('match not found'); - } - return version; - } - createRangePreRelease(versionSpec) { + validRange(versionSpec) { let range; const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver_1.default.valid(raw); @@ -73857,7 +73819,7 @@ class CanaryBuild extends base_distribution_1.default { else { range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } - return { range, includePrerelease: !isValidVersion }; + return { range, options: { includePrerelease: !isValidVersion } }; } splitVersionSpec(versionSpec) { return versionSpec.split(/-(.*)/s); diff --git a/src/distributions/base-distribution.ts b/src/distributions/base-distribution.ts index b567fd83e..c1d2601f6 100644 --- a/src/distributions/base-distribution.ts +++ b/src/distributions/base-distribution.ts @@ -60,16 +60,15 @@ export default abstract class BaseDistribution { core.addPath(toolPath); } - protected evaluateVersions(versions: string[]) { + 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, - this.nodeInfo.versionSpec - ); + const satisfied: boolean = semver.satisfies(potential, range, options); if (satisfied) { version = potential; break; @@ -141,6 +140,14 @@ export default abstract class BaseDistribution { 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() diff --git a/src/distributions/nightly/nightly_builds.ts b/src/distributions/nightly/nightly_builds.ts index bf3692e99..a1837ee4e 100644 --- a/src/distributions/nightly/nightly_builds.ts +++ b/src/distributions/nightly/nightly_builds.ts @@ -1,4 +1,3 @@ -import * as core from '@actions/core'; import * as tc from '@actions/tool-cache'; import semver from 'semver'; @@ -33,44 +32,11 @@ export default class NightlyNodejs extends BaseDistribution { return toolPath; } - protected evaluateVersions(versions: string[]): string { - let version = ''; - - core.debug(`evaluating ${versions.length} versions`); - - const {includePrerelease, range} = this.createRangePreRelease( - this.nodeInfo.versionSpec - ); - - for (let i = 0; i < versions.length; i++) { - const potential: string = versions[i]; - const satisfied: boolean = semver.satisfies( - potential.replace(this.distribution, `${this.distribution}.`), - range, - { - includePrerelease: includePrerelease - } - ); - if (satisfied) { - version = potential; - break; - } - } - - if (version) { - core.debug(`matched: ${version}`); - } else { - core.debug('match not found'); - } - - return version; - } - protected getDistributionUrl(): string { return 'https://nodejs.org/download/nightly'; } - protected createRangePreRelease(versionSpec: string) { + protected validRange(versionSpec: string) { let range: string; const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver.valid(raw); @@ -85,7 +51,7 @@ export default class NightlyNodejs extends BaseDistribution { range = `${semver.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } - return {range, includePrerelease: !isValidVersion}; + return {range, options: {includePrerelease: !isValidVersion}}; } protected splitVersionSpec(versionSpec: string) { diff --git a/src/distributions/v8-canary/canary_builds.ts b/src/distributions/v8-canary/canary_builds.ts index 678f7d24a..673ab1e25 100644 --- a/src/distributions/v8-canary/canary_builds.ts +++ b/src/distributions/v8-canary/canary_builds.ts @@ -1,4 +1,3 @@ -import * as core from '@actions/core'; import * as tc from '@actions/tool-cache'; import semver from 'semver'; @@ -37,40 +36,7 @@ export default class CanaryBuild extends BaseDistribution { return 'https://nodejs.org/download/v8-canary'; } - protected evaluateVersions(versions: string[]): string { - let version = ''; - - core.debug(`evaluating ${versions.length} versions`); - - const {includePrerelease, range} = this.createRangePreRelease( - this.nodeInfo.versionSpec - ); - - for (let i = 0; i < versions.length; i++) { - const potential: string = versions[i]; - const satisfied: boolean = semver.satisfies( - potential.replace(this.distribution, `${this.distribution}.`), - range, - { - includePrerelease: includePrerelease - } - ); - if (satisfied) { - version = potential; - break; - } - } - - if (version) { - core.debug(`matched: ${version}`); - } else { - core.debug('match not found'); - } - - return version; - } - - protected createRangePreRelease(versionSpec: string) { + protected validRange(versionSpec: string) { let range: string; const [raw, prerelease] = this.splitVersionSpec(versionSpec); const isValidVersion = semver.valid(raw); @@ -85,7 +51,7 @@ export default class CanaryBuild extends BaseDistribution { range = `${semver.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } - return {range, includePrerelease: !isValidVersion}; + return {range, options: {includePrerelease: !isValidVersion}}; } protected splitVersionSpec(versionSpec: string) { From 68fd79d66219a4ecd2aee7e9cde044d3ff79b255 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 27 Dec 2022 21:20:23 +0100 Subject: [PATCH 45/51] minor fix --- dist/setup/index.js | 4 ++-- src/distributions/nightly/nightly_builds.ts | 5 +---- src/distributions/v8-canary/canary_builds.ts | 5 +---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 59655926c..ceebcf515 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73530,7 +73530,7 @@ class NightlyNodejs extends base_distribution_1.default { const isValidVersion = semver_1.default.valid(raw); const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); if (prerelease !== this.distribution) { - range = `${rawVersion}-${prerelease.replace(this.distribution, `${this.distribution}.`)}`; + range = versionSpec; } else { range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; @@ -73814,7 +73814,7 @@ class CanaryBuild extends base_distribution_1.default { const isValidVersion = semver_1.default.valid(raw); const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); if (prerelease !== this.distribution) { - range = `${rawVersion}-${prerelease.replace(this.distribution, `${this.distribution}.`)}`; + range = versionSpec; } else { range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; diff --git a/src/distributions/nightly/nightly_builds.ts b/src/distributions/nightly/nightly_builds.ts index a1837ee4e..0c4a23dcb 100644 --- a/src/distributions/nightly/nightly_builds.ts +++ b/src/distributions/nightly/nightly_builds.ts @@ -43,10 +43,7 @@ export default class NightlyNodejs extends BaseDistribution { const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; if (prerelease !== this.distribution) { - range = `${rawVersion}-${prerelease.replace( - this.distribution, - `${this.distribution}.` - )}`; + range = versionSpec; } else { range = `${semver.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } diff --git a/src/distributions/v8-canary/canary_builds.ts b/src/distributions/v8-canary/canary_builds.ts index 673ab1e25..f78305431 100644 --- a/src/distributions/v8-canary/canary_builds.ts +++ b/src/distributions/v8-canary/canary_builds.ts @@ -43,10 +43,7 @@ export default class CanaryBuild extends BaseDistribution { const rawVersion = (isValidVersion ? raw : semver.coerce(raw))!; if (prerelease !== this.distribution) { - range = `${rawVersion}-${prerelease.replace( - this.distribution, - `${this.distribution}.` - )}`; + range = versionSpec; } else { range = `${semver.validRange(`^${rawVersion}-${this.distribution}`)}-0`; } From a4584e0572a296c25b9db4911be731450d7bf9bb Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 27 Dec 2022 21:26:11 +0100 Subject: [PATCH 46/51] regenerate dist --- dist/setup/index.js | 223 +++++++++++++++++++++++++++++++++----------- 1 file changed, 171 insertions(+), 52 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index ceebcf515..a79bcd6dd 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -72915,14 +72915,27 @@ function wrappy (fn, cb) { "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 (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + 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; }; Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.configAuthentication = void 0; const fs = __importStar(__nccwpck_require__(7147)); const os = __importStar(__nccwpck_require__(2037)); const path = __importStar(__nccwpck_require__(1017)); @@ -72977,6 +72990,25 @@ function writeRegistryToFile(registryUrl, fileLocation, alwaysAuth) { "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) { @@ -72986,17 +73018,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.restoreCache = void 0; const cache = __importStar(__nccwpck_require__(7799)); const core = __importStar(__nccwpck_require__(2186)); const glob = __importStar(__nccwpck_require__(8090)); @@ -73004,7 +73030,7 @@ const path_1 = __importDefault(__nccwpck_require__(1017)); const fs_1 = __importDefault(__nccwpck_require__(7147)); const constants_1 = __nccwpck_require__(9042); const cache_utils_1 = __nccwpck_require__(1678); -exports.restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { +const restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () { const packageManagerInfo = yield cache_utils_1.getPackageManagerInfo(packageManager); if (!packageManagerInfo) { throw new Error(`Caching for '${packageManager}' is not supported`); @@ -73030,6 +73056,7 @@ exports.restoreCache = (packageManager, cacheDependencyPath) => __awaiter(void 0 core.saveState(constants_1.State.CacheMatchedKey, cacheKey); core.info(`Cache restored from key: ${cacheKey}`); }); +exports.restoreCache = restoreCache; const findLockFile = (packageManager) => { let lockFiles = packageManager.lockFilePatterns; const workspace = process.env.GITHUB_WORKSPACE; @@ -73049,6 +73076,25 @@ const findLockFile = (packageManager) => { "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) { @@ -73058,14 +73104,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)); @@ -73087,7 +73127,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() @@ -73097,6 +73137,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) { @@ -73104,7 +73145,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; } @@ -73125,7 +73166,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}`); @@ -73133,6 +73175,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'; @@ -73159,6 +73202,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"; @@ -73183,6 +73227,25 @@ var Outputs; "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) { @@ -73192,13 +73255,6 @@ 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 }; }; @@ -73446,6 +73502,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getNodejsDistribution = void 0; const nightly_builds_1 = __importDefault(__nccwpck_require__(7127)); const official_builds_1 = __importDefault(__nccwpck_require__(7854)); const rc_builds_1 = __importDefault(__nccwpck_require__(8837)); @@ -73484,11 +73541,23 @@ exports.getNodejsDistribution = getNodejsDistribution; "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 (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + 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 __importDefault = (this && this.__importDefault) || function (mod) { @@ -73551,6 +73620,25 @@ exports["default"] = NightlyNodejs; "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) { @@ -73560,13 +73648,6 @@ 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 }; }; @@ -73768,11 +73849,23 @@ exports["default"] = RcBuild; "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 (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + 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 __importDefault = (this && this.__importDefault) || function (mod) { @@ -73835,6 +73928,25 @@ exports["default"] = CanaryBuild; "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) { @@ -73844,17 +73956,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 fs_1 = __importDefault(__nccwpck_require__(7147)); const os_1 = __importDefault(__nccwpck_require__(2037)); @@ -73944,6 +74050,25 @@ function resolveVersionInput() { "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) { @@ -73953,14 +74078,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.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0; const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); function parseNodeVersionFile(contents) { From 8dfba60365b8bda94b1179332a07966a62c8c050 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 27 Dec 2022 21:31:43 +0100 Subject: [PATCH 47/51] fix dist --- dist/cache-save/index.js | 64 +++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index d099eecba..92b5418f9 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -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"; From 166e53bba8f9f9720c3172308ef3f46278638aa2 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Tue, 27 Dec 2022 23:53:35 +0100 Subject: [PATCH 48/51] simplify code --- dist/setup/index.js | 59 +------------------- src/distributions/v8-canary/canary_builds.ts | 50 +---------------- 2 files changed, 5 insertions(+), 104 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index a79bcd6dd..0409f3bf5 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73849,74 +73849,19 @@ exports["default"] = RcBuild; "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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const tc = __importStar(__nccwpck_require__(7784)); -const semver_1 = __importDefault(__nccwpck_require__(5911)); -const base_distribution_1 = __importDefault(__nccwpck_require__(7)); -class CanaryBuild extends base_distribution_1.default { +const nightly_builds_1 = __importDefault(__nccwpck_require__(7127)); +class CanaryBuild extends nightly_builds_1.default { constructor(nodeInfo) { super(nodeInfo); this.distribution = 'v8-canary'; } - findVersionInHostedToolCacheDirectory() { - let toolPath = ''; - const localVersionPaths = tc - .findAllVersions('node', this.nodeInfo.arch) - .filter(i => { - const prerelease = semver_1.default.prerelease(i); - if (!prerelease) { - return false; - } - return prerelease[0].includes(this.distribution); - }); - localVersionPaths.sort(semver_1.default.rcompare); - const localVersion = this.evaluateVersions(localVersionPaths); - if (localVersion) { - toolPath = tc.find('node', localVersion, this.nodeInfo.arch); - } - return toolPath; - } getDistributionUrl() { return 'https://nodejs.org/download/v8-canary'; } - validRange(versionSpec) { - let range; - const [raw, prerelease] = this.splitVersionSpec(versionSpec); - const isValidVersion = semver_1.default.valid(raw); - const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); - if (prerelease !== this.distribution) { - range = versionSpec; - } - else { - range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; - } - return { range, options: { includePrerelease: !isValidVersion } }; - } - splitVersionSpec(versionSpec) { - return versionSpec.split(/-(.*)/s); - } } exports["default"] = CanaryBuild; diff --git a/src/distributions/v8-canary/canary_builds.ts b/src/distributions/v8-canary/canary_builds.ts index f78305431..f7656796a 100644 --- a/src/distributions/v8-canary/canary_builds.ts +++ b/src/distributions/v8-canary/canary_builds.ts @@ -1,57 +1,13 @@ -import * as tc from '@actions/tool-cache'; - -import semver from 'semver'; - -import BaseDistribution from '../base-distribution'; import {INodejs} from '../base-models'; +import NightlyNodejs from '../nightly/nightly_builds'; -export default class CanaryBuild extends BaseDistribution { - protected distribution = 'v8-canary'; +export default class CanaryBuild extends NightlyNodejs { constructor(nodeInfo: INodejs) { 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; + this.distribution = 'v8-canary'; } protected getDistributionUrl(): string { return 'https://nodejs.org/download/v8-canary'; } - - 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); - } } From eec2a7e0d86ff7bdda3cbaf671ac70bb52ed246e Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Wed, 28 Dec 2022 15:36:07 +0100 Subject: [PATCH 49/51] minor changes --- dist/setup/index.js | 166 ++++++++++-------- .../base-distribution-prerelease.ts | 53 ++++++ src/distributions/base-distribution.ts | 37 ++-- src/distributions/base-models.ts | 2 +- src/distributions/installer-factory.ts | 4 +- src/distributions/nightly/nightly_builds.ts | 52 +----- .../official_builds/official_builds.ts | 4 +- src/distributions/rc/rc_builds.ts | 4 +- src/distributions/v8-canary/canary_builds.ts | 10 +- 9 files changed, 184 insertions(+), 148 deletions(-) create mode 100644 src/distributions/base-distribution-prerelease.ts diff --git a/dist/setup/index.js b/dist/setup/index.js index 0409f3bf5..4c01ab525 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73220,6 +73220,81 @@ var Outputs; })(Outputs = exports.Outputs || (exports.Outputs = {})); +/***/ }), + +/***/ 957: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const tc = __importStar(__nccwpck_require__(7784)); +const semver_1 = __importDefault(__nccwpck_require__(5911)); +const base_distribution_1 = __importDefault(__nccwpck_require__(7)); +class BasePrereleaseNodejs extends base_distribution_1.default { + constructor(nodeInfo) { + super(nodeInfo); + } + findVersionInHostedToolCacheDirectory() { + let toolPath = ''; + const localVersionPaths = tc + .findAllVersions('node', this.nodeInfo.arch) + .filter(i => { + const prerelease = semver_1.default.prerelease(i); + if (!prerelease) { + return false; + } + return prerelease[0].includes(this.distribution); + }); + localVersionPaths.sort(semver_1.default.rcompare); + const localVersion = this.evaluateVersions(localVersionPaths); + if (localVersion) { + toolPath = tc.find('node', localVersion, this.nodeInfo.arch); + } + return toolPath; + } + validRange(versionSpec) { + let range; + const [raw, prerelease] = this.splitVersionSpec(versionSpec); + const isValidVersion = semver_1.default.valid(raw); + const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); + if (prerelease !== this.distribution) { + range = versionSpec; + } + else { + range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; + } + return { range, options: { includePrerelease: !isValidVersion } }; + } + splitVersionSpec(versionSpec) { + return versionSpec.split(/-(.*)/s); + } +} +exports["default"] = BasePrereleaseNodejs; + + /***/ }), /***/ 7: @@ -73281,24 +73356,15 @@ class BaseDistribution { return __awaiter(this, void 0, void 0, function* () { let nodeJsVersions; if (this.nodeInfo.checkLatest) { - nodeJsVersions = yield this.getNodeJsVersions(); - const versions = this.filterVersions(nodeJsVersions); - const evaluatedVersion = this.evaluateVersions(versions); - if (evaluatedVersion) { - this.nodeInfo.versionSpec = evaluatedVersion; - } + const evaluatedVersion = yield this.findVersionInDist(nodeJsVersions); + this.nodeInfo.versionSpec = evaluatedVersion; } let toolPath = this.findVersionInHostedToolCacheDirectory(); if (toolPath) { core.info(`Found in cache @ ${toolPath}`); } else { - nodeJsVersions = nodeJsVersions !== null && nodeJsVersions !== void 0 ? nodeJsVersions : (yield 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 evaluatedVersion = yield this.findVersionInDist(nodeJsVersions); const toolName = this.getNodejsDistInfo(evaluatedVersion); toolPath = yield this.downloadNodejs(toolName); } @@ -73308,6 +73374,19 @@ class BaseDistribution { core.addPath(toolPath); }); } + findVersionInDist(nodeJsVersions) { + return __awaiter(this, void 0, void 0, function* () { + if (!nodeJsVersions) { + nodeJsVersions = yield 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; + }); + } evaluateVersions(versions) { let version = ''; const { range, options } = this.validRange(this.nodeInfo.versionSpec); @@ -73541,74 +73620,19 @@ exports.getNodejsDistribution = getNodejsDistribution; "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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const tc = __importStar(__nccwpck_require__(7784)); -const semver_1 = __importDefault(__nccwpck_require__(5911)); -const base_distribution_1 = __importDefault(__nccwpck_require__(7)); -class NightlyNodejs extends base_distribution_1.default { +const base_distribution_prerelease_1 = __importDefault(__nccwpck_require__(957)); +class NightlyNodejs extends base_distribution_prerelease_1.default { constructor(nodeInfo) { super(nodeInfo); this.distribution = 'nightly'; } - findVersionInHostedToolCacheDirectory() { - let toolPath = ''; - const localVersionPaths = tc - .findAllVersions('node', this.nodeInfo.arch) - .filter(i => { - const prerelease = semver_1.default.prerelease(i); - if (!prerelease) { - return false; - } - return prerelease[0].includes(this.distribution); - }); - localVersionPaths.sort(semver_1.default.rcompare); - const localVersion = this.evaluateVersions(localVersionPaths); - if (localVersion) { - toolPath = tc.find('node', localVersion, this.nodeInfo.arch); - } - return toolPath; - } getDistributionUrl() { return 'https://nodejs.org/download/nightly'; } - validRange(versionSpec) { - let range; - const [raw, prerelease] = this.splitVersionSpec(versionSpec); - const isValidVersion = semver_1.default.valid(raw); - const rawVersion = (isValidVersion ? raw : semver_1.default.coerce(raw)); - if (prerelease !== this.distribution) { - range = versionSpec; - } - else { - range = `${semver_1.default.validRange(`^${rawVersion}-${this.distribution}`)}-0`; - } - return { range, options: { includePrerelease: !isValidVersion } }; - } - splitVersionSpec(versionSpec) { - return versionSpec.split(/-(.*)/s); - } } exports["default"] = NightlyNodejs; @@ -73853,8 +73877,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const nightly_builds_1 = __importDefault(__nccwpck_require__(7127)); -class CanaryBuild extends nightly_builds_1.default { +const base_distribution_prerelease_1 = __importDefault(__nccwpck_require__(957)); +class CanaryBuild extends base_distribution_prerelease_1.default { constructor(nodeInfo) { super(nodeInfo); this.distribution = 'v8-canary'; diff --git a/src/distributions/base-distribution-prerelease.ts b/src/distributions/base-distribution-prerelease.ts new file mode 100644 index 000000000..f3214af01 --- /dev/null +++ b/src/distributions/base-distribution-prerelease.ts @@ -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); + } +} diff --git a/src/distributions/base-distribution.ts b/src/distributions/base-distribution.ts index c1d2601f6..d214d4062 100644 --- a/src/distributions/base-distribution.ts +++ b/src/distributions/base-distribution.ts @@ -10,13 +10,13 @@ import * as path from 'path'; import os from 'os'; import fs from 'fs'; -import {INodejs, INodeVersion, INodeVersionInfo} from './base-models'; +import {NodeInputs, INodeVersion, INodeVersionInfo} from './base-models'; export default abstract class BaseDistribution { protected httpClient: hc.HttpClient; protected osPlat = os.platform(); - constructor(protected nodeInfo: INodejs) { + constructor(protected nodeInfo: NodeInputs) { this.httpClient = new hc.HttpClient('setup-node', [], { allowRetries: true, maxRetries: 3 @@ -28,27 +28,15 @@ export default abstract class BaseDistribution { public async setupNodeJs() { let nodeJsVersions: INodeVersion[] | undefined; if (this.nodeInfo.checkLatest) { - nodeJsVersions = await this.getNodeJsVersions(); - const versions = this.filterVersions(nodeJsVersions); - const evaluatedVersion = this.evaluateVersions(versions); - - if (evaluatedVersion) { - this.nodeInfo.versionSpec = evaluatedVersion; - } + const evaluatedVersion = await this.findVersionInDist(nodeJsVersions); + this.nodeInfo.versionSpec = evaluatedVersion; } let toolPath = this.findVersionInHostedToolCacheDirectory(); if (toolPath) { core.info(`Found in cache @ ${toolPath}`); } else { - 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}.` - ); - } + const evaluatedVersion = await this.findVersionInDist(nodeJsVersions); const toolName = this.getNodejsDistInfo(evaluatedVersion); toolPath = await this.downloadNodejs(toolName); } @@ -60,6 +48,21 @@ export default abstract class BaseDistribution { 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 = ''; diff --git a/src/distributions/base-models.ts b/src/distributions/base-models.ts index 300461bb0..3304ba7cd 100644 --- a/src/distributions/base-models.ts +++ b/src/distributions/base-models.ts @@ -1,4 +1,4 @@ -export interface INodejs { +export interface NodeInputs { versionSpec: string; arch: string; auth?: string; diff --git a/src/distributions/installer-factory.ts b/src/distributions/installer-factory.ts index 6f4c7e8fe..01438cce4 100644 --- a/src/distributions/installer-factory.ts +++ b/src/distributions/installer-factory.ts @@ -1,5 +1,5 @@ import BaseDistribution from './base-distribution'; -import {INodejs} from './base-models'; +import {NodeInputs} from './base-models'; import NightlyNodejs from './nightly/nightly_builds'; import OfficialBuilds from './official_builds/official_builds'; import RcBuild from './rc/rc_builds'; @@ -13,7 +13,7 @@ enum Distributions { } export function getNodejsDistribution( - installerOptions: INodejs + installerOptions: NodeInputs ): BaseDistribution { const versionSpec = installerOptions.versionSpec; let distribution: BaseDistribution; diff --git a/src/distributions/nightly/nightly_builds.ts b/src/distributions/nightly/nightly_builds.ts index 0c4a23dcb..86a89eed9 100644 --- a/src/distributions/nightly/nightly_builds.ts +++ b/src/distributions/nightly/nightly_builds.ts @@ -1,57 +1,13 @@ -import * as tc from '@actions/tool-cache'; +import BasePrereleaseNodejs from '../base-distribution-prerelease'; +import {NodeInputs} from '../base-models'; -import semver from 'semver'; - -import BaseDistribution from '../base-distribution'; -import {INodejs} from '../base-models'; - -export default class NightlyNodejs extends BaseDistribution { +export default class NightlyNodejs extends BasePrereleaseNodejs { protected distribution = 'nightly'; - constructor(nodeInfo: INodejs) { + 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 getDistributionUrl(): string { return 'https://nodejs.org/download/nightly'; } - - 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); - } } diff --git a/src/distributions/official_builds/official_builds.ts b/src/distributions/official_builds/official_builds.ts index 53d7e9103..fa07dc965 100644 --- a/src/distributions/official_builds/official_builds.ts +++ b/src/distributions/official_builds/official_builds.ts @@ -3,14 +3,14 @@ import * as tc from '@actions/tool-cache'; import path from 'path'; import BaseDistribution from '../base-distribution'; -import {INodejs, INodeVersion, INodeVersionInfo} from '../base-models'; +import {NodeInputs, INodeVersion, INodeVersionInfo} from '../base-models'; interface INodeRelease extends tc.IToolRelease { lts?: string; } export default class OfficialBuilds extends BaseDistribution { - constructor(nodeInfo: INodejs) { + constructor(nodeInfo: NodeInputs) { super(nodeInfo); } diff --git a/src/distributions/rc/rc_builds.ts b/src/distributions/rc/rc_builds.ts index dd57ef820..40cdb192a 100644 --- a/src/distributions/rc/rc_builds.ts +++ b/src/distributions/rc/rc_builds.ts @@ -1,8 +1,8 @@ import BaseDistribution from '../base-distribution'; -import {INodejs} from '../base-models'; +import {NodeInputs} from '../base-models'; export default class RcBuild extends BaseDistribution { - constructor(nodeInfo: INodejs) { + constructor(nodeInfo: NodeInputs) { super(nodeInfo); } diff --git a/src/distributions/v8-canary/canary_builds.ts b/src/distributions/v8-canary/canary_builds.ts index f7656796a..257151b45 100644 --- a/src/distributions/v8-canary/canary_builds.ts +++ b/src/distributions/v8-canary/canary_builds.ts @@ -1,10 +1,10 @@ -import {INodejs} from '../base-models'; -import NightlyNodejs from '../nightly/nightly_builds'; +import BasePrereleaseNodejs from '../base-distribution-prerelease'; +import {NodeInputs} from '../base-models'; -export default class CanaryBuild extends NightlyNodejs { - constructor(nodeInfo: INodejs) { +export default class CanaryBuild extends BasePrereleaseNodejs { + protected distribution = 'v8-canary'; + constructor(nodeInfo: NodeInputs) { super(nodeInfo); - this.distribution = 'v8-canary'; } protected getDistributionUrl(): string { From 0631b1d4442d4ebf24e989c3947f878f8216cd45 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 29 Dec 2022 11:17:34 +0100 Subject: [PATCH 50/51] revert some changes --- dist/setup/index.js | 15 ++++++++------- src/distributions/base-models.ts | 1 + .../official_builds/official_builds.ts | 8 ++++++-- src/main.ts | 3 +++ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/dist/setup/index.js b/dist/setup/index.js index 4c01ab525..ff4bec264 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -73693,7 +73693,7 @@ class OfficialBuilds extends base_distribution_1.default { core.info('Attempt to resolve LTS alias from manifest...'); // No try-catch since it's not possible to resolve LTS alias without manifest manifest = yield this.getManifest(); - this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest(this.nodeInfo.versionSpec, true, manifest); + this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, manifest); } if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { nodeJsVersions = yield this.getNodeJsVersions(); @@ -73703,7 +73703,7 @@ class OfficialBuilds extends base_distribution_1.default { } if (this.nodeInfo.checkLatest) { core.info('Attempt to resolve the latest version from manifest...'); - const resolvedVersion = yield this.resolveVersionFromManifest(this.nodeInfo.versionSpec, osArch, manifest); + const resolvedVersion = yield this.resolveVersionFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, osArch, manifest); if (resolvedVersion) { this.nodeInfo.versionSpec = resolvedVersion; core.info(`Resolved as '${resolvedVersion}'`); @@ -73720,7 +73720,7 @@ class OfficialBuilds extends base_distribution_1.default { let downloadPath = ''; try { core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); - const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, osArch, manifest); + const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, osArch, manifest); if (versionInfo) { core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`); downloadPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.auth); @@ -73802,10 +73802,10 @@ class OfficialBuilds extends base_distribution_1.default { core.debug(`Found LTS release '${release.version}' for Node version '${versionSpec}'`); return release.version.split('.')[0]; } - resolveVersionFromManifest(versionSpec, osArch, manifest) { + resolveVersionFromManifest(versionSpec, stable, osArch, manifest) { return __awaiter(this, void 0, void 0, function* () { try { - const info = yield this.getInfoFromManifest(versionSpec, osArch, manifest); + const info = yield this.getInfoFromManifest(versionSpec, stable, osArch, manifest); return info === null || info === void 0 ? void 0 : info.resolvedVersion; } catch (err) { @@ -73814,9 +73814,8 @@ class OfficialBuilds extends base_distribution_1.default { } }); } - getInfoFromManifest(versionSpec, osArch, manifest) { + getInfoFromManifest(versionSpec, stable, osArch, manifest) { return __awaiter(this, void 0, void 0, function* () { - const stable = true; let info = null; if (!manifest) { core.debug('No manifest cached'); @@ -73960,11 +73959,13 @@ function run() { if (version) { const token = core.getInput('token'); const auth = !token ? undefined : `token ${token}`; + const stable = (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; const nodejsInfo = { versionSpec: version, checkLatest, auth, + stable, arch }; const nodeDistribution = installer_factory_1.getNodejsDistribution(nodejsInfo); diff --git a/src/distributions/base-models.ts b/src/distributions/base-models.ts index 3304ba7cd..0be93b635 100644 --- a/src/distributions/base-models.ts +++ b/src/distributions/base-models.ts @@ -3,6 +3,7 @@ export interface NodeInputs { arch: string; auth?: string; checkLatest: boolean; + stable: boolean; } export interface INodeVersionInfo { diff --git a/src/distributions/official_builds/official_builds.ts b/src/distributions/official_builds/official_builds.ts index fa07dc965..42b1979ce 100644 --- a/src/distributions/official_builds/official_builds.ts +++ b/src/distributions/official_builds/official_builds.ts @@ -26,7 +26,7 @@ export default class OfficialBuilds extends BaseDistribution { this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest( this.nodeInfo.versionSpec, - true, + this.nodeInfo.stable, manifest ); } @@ -43,6 +43,7 @@ export default class OfficialBuilds extends BaseDistribution { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = await this.resolveVersionFromManifest( this.nodeInfo.versionSpec, + this.nodeInfo.stable, osArch, manifest ); @@ -67,6 +68,7 @@ export default class OfficialBuilds extends BaseDistribution { const versionInfo = await this.getInfoFromManifest( this.nodeInfo.versionSpec, + this.nodeInfo.stable, osArch, manifest ); @@ -198,12 +200,14 @@ export default class OfficialBuilds extends BaseDistribution { private async resolveVersionFromManifest( versionSpec: string, + stable: boolean, osArch: string, manifest: tc.IToolRelease[] | undefined ): Promise { try { const info = await this.getInfoFromManifest( versionSpec, + stable, osArch, manifest ); @@ -216,10 +220,10 @@ export default class OfficialBuilds extends BaseDistribution { private async getInfoFromManifest( versionSpec: string, + stable: boolean, osArch: string, manifest: tc.IToolRelease[] | undefined ): Promise { - const stable = true; let info: INodeVersionInfo | null = null; if (!manifest) { core.debug('No manifest cached'); diff --git a/src/main.ts b/src/main.ts index 0b29faace..90cd1d9d9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -36,12 +36,15 @@ export async function run() { if (version) { const token = core.getInput('token'); const auth = !token ? undefined : `token ${token}`; + const stable = + (core.getInput('stable') || 'true').toUpperCase() === 'TRUE'; const checkLatest = (core.getInput('check-latest') || 'false').toUpperCase() === 'TRUE'; const nodejsInfo = { versionSpec: version, checkLatest, auth, + stable, arch }; const nodeDistribution = getNodejsDistribution(nodejsInfo); From bcd8fae10ec82a64569f87ce542b84e303541251 Mon Sep 17 00:00:00 2001 From: Dmitry Shibanov Date: Thu, 29 Dec 2022 11:55:53 +0100 Subject: [PATCH 51/51] npm audit --- package-lock.json | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index c10ee29e2..45b55661a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", @@ -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",