From 9e956a555c2c3d534ac93f57280063bfa7c63468 Mon Sep 17 00:00:00 2001 From: Nikolai Laevskii Date: Thu, 19 Oct 2023 13:43:56 +0200 Subject: [PATCH] Add notice about binaries not being updated yet --- __tests__/official-installer.test.ts | 35 +++++ .../official_builds/official_builds.ts | 138 +++++++++++------- 2 files changed, 120 insertions(+), 53 deletions(-) diff --git a/__tests__/official-installer.test.ts b/__tests__/official-installer.test.ts index 474fb5b98..f86ef7b02 100644 --- a/__tests__/official-installer.test.ts +++ b/__tests__/official-installer.test.ts @@ -357,6 +357,41 @@ describe('setup-node', () => { expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`); }); + it('reports when download failed but version exists', async () => { + os.platform = 'linux'; + os.arch = 'x64'; + + // a version which is not in the manifest but is in node dist + const versionSpec = '11.15.0'; + + inputs['node-version'] = versionSpec; + inputs['always-auth'] = false; + inputs['token'] = 'faketoken'; + + // ... but not in the local cache + findSpy.mockImplementation(() => ''); + + dlSpy.mockImplementationOnce(async () => { + throw new tc.HTTPError(404); + }); + + await main.run(); + + expect(getManifestSpy).toHaveBeenCalled(); + expect(logSpy).toHaveBeenCalledWith( + `Attempting to download ${versionSpec}...` + ); + expect(logSpy).toHaveBeenCalledWith( + 'Not found in manifest. Falling back to download directly from Node' + ); + expect(dlSpy).toHaveBeenCalled(); + expect(logSpy).toHaveBeenCalledWith( + `Node version ${versionSpec} for platform ${os.platform} and architecture ${os.arch} was found but failed to download. ` + + 'This usually happens when downloadable binaries are not fully updated at https://nodejs.org/. ' + + 'To resolve this issue you may either fall back to the older version or try again later.' + ); + }); + it('acquires specified architecture of node', async () => { for (const {arch, version, osSpec} of [ {arch: 'x86', version: '12.16.2', osSpec: 'win32'}, diff --git a/src/distributions/official_builds/official_builds.ts b/src/distributions/official_builds/official_builds.ts index 222d341ec..68827880f 100644 --- a/src/distributions/official_builds/official_builds.ts +++ b/src/distributions/official_builds/official_builds.ts @@ -18,6 +18,7 @@ export default class OfficialBuilds extends BaseDistribution { let manifest: tc.IToolRelease[] | undefined; let nodeJsVersions: INodeVersion[] | undefined; const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); + if (this.isLtsAlias(this.nodeInfo.versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); @@ -61,65 +62,67 @@ 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 versionInfo = await this.getInfoFromManifest( - this.nodeInfo.versionSpec, - this.nodeInfo.stable, - osArch, - manifest + this.addToolPath(toolPath); + return; + } + + let downloadPath = ''; + try { + core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); + + const versionInfo = await this.getInfoFromManifest( + this.nodeInfo.versionSpec, + this.nodeInfo.stable, + osArch, + manifest + ); + + if (versionInfo) { + core.info( + `Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}` + ); + downloadPath = await tc.downloadTool( + versionInfo.downloadUrl, + undefined, + this.nodeInfo.auth ); - if (versionInfo) { - core.info( - `Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}` - ); - downloadPath = await tc.downloadTool( - versionInfo.downloadUrl, - undefined, - this.nodeInfo.auth - ); - - if (downloadPath) { - toolPath = await this.extractArchive(downloadPath, versionInfo); - } - } else { - core.info( - 'Not found in manifest. Falling back to download directly from Node' - ); - } - } catch (err) { - // Rate limit? - if ( - err instanceof tc.HTTPError && - (err.httpStatusCode === 403 || err.httpStatusCode === 429) - ) { - core.info( - `Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded` - ); - } else { - core.info((err as Error).message); - } - core.debug((err as Error).stack ?? 'empty stack'); - core.info('Falling back to download directly from Node'); - } - if (!toolPath) { - const nodeJsVersions = await this.getNodeJsVersions(); - const versions = this.filterVersions(nodeJsVersions); - const evaluatedVersion = this.evaluateVersions(versions); - if (!evaluatedVersion) { - throw new Error( - `Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.` - ); + if (downloadPath) { + toolPath = await this.extractArchive(downloadPath, versionInfo); } - const toolName = this.getNodejsDistInfo(evaluatedVersion); - toolPath = await this.downloadNodejs(toolName); + } 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 as Error).message); } + core.debug((err as Error).stack ?? 'empty stack'); + core.info('Falling back to download directly from Node'); } + if (!toolPath) { + toolPath = await this.downloadDirectlyFromNode(); + } + + if (this.osPlat != 'win32') { + toolPath = path.join(toolPath, 'bin'); + } + + core.addPath(toolPath); + } + + protected addToolPath(toolPath: string) { if (this.osPlat != 'win32') { toolPath = path.join(toolPath, 'bin'); } @@ -127,6 +130,35 @@ export default class OfficialBuilds extends BaseDistribution { core.addPath(toolPath); } + protected async downloadDirectlyFromNode() { + const nodeJsVersions = await this.getNodeJsVersions(); + const versions = this.filterVersions(nodeJsVersions); + const evaluatedVersion = this.evaluateVersions(versions); + + if (!evaluatedVersion) { + throw new Error( + `Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch}.` + ); + } + + const toolName = this.getNodejsDistInfo(evaluatedVersion); + + try { + const toolPath = await this.downloadNodejs(toolName); + return toolPath; + } catch (error) { + if (error instanceof tc.HTTPError && error.httpStatusCode === 404) { + core.info( + `Node version ${this.nodeInfo.versionSpec} for platform ${this.osPlat} and architecture ${this.nodeInfo.arch} was found but failed to download. ` + + 'This usually happens when downloadable binaries are not fully updated at https://nodejs.org/. ' + + 'To resolve this issue you may either fall back to the older version or try again later.' + ); + } + + throw error; + } + } + protected evaluateVersions(versions: string[]): string { let version = '';