From 24265e14d4c566d4523518a70afc685aafa8754e Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Fri, 21 May 2021 18:16:14 +0300 Subject: [PATCH 01/24] Create 0000-caching-dependencies.md --- docs/adrs/0000-caching-dependencies.md | 59 ++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/adrs/0000-caching-dependencies.md diff --git a/docs/adrs/0000-caching-dependencies.md b/docs/adrs/0000-caching-dependencies.md new file mode 100644 index 000000000..4f9429b6a --- /dev/null +++ b/docs/adrs/0000-caching-dependencies.md @@ -0,0 +1,59 @@ +# 0. Caching dependencies +Date: 2021-05-21 + +Status: Proposed + +# Context +`actions/setup-node` is the 2nd most popular action in GitHub Actions. A lot of customers use it in conjunction with [actions/cache](https://github.com/actions/cache) to speed up dependencies installation. +See more examples on proper usage in [actions/cache documentation](https://github.com/actions/cache/blob/main/examples.md#node---npm). + +# Goals & Anti-Goals +Integration of caching functionality into `actions/setup-node` action will bring the following benefits for action users: +- Decrease the entry threshold for using the cache for Node.js dependencies and simplify initial configuration +- Simplify YAML pipelines because no need additional steps to enable caching + +As a result, more users will use the cache for Node.js builds and will be happy with fast builds. +As the first stage, we will add support for NPM dependencies caching. We can consider adding the same functionality for Yarn later. + +We don't persue the goal to provide wide customization of caching in scope of `actions/setup-node` action. The purpose of this integration is covering ~90% of basic use-cases. If user needs flexible customization, we should advice them to use `actions/cache` directly. + +# Decision +- Add `cache` input parameter to `actions/setup-node`. For now, input will accept the following values: + - `npm` - enable caching for npm dependencies + - `''` - disable caching (default value) + - Potentially, we will be able to extend this input to support Yarn +- Cache feature will be disabled by default to make sure that we don't break existing customers. We will consider enabling cache by default in next major release (`v3`) +- Add optional input `package-lock-path` that will allow to specify path to `package.lock.json` file path: + - If input is not defined, action will try to search `package.lock.json` or `yarn.lock` (npm 7.x supports `yarn.lock` files) files in the repository root and throw error if no one is found + - If input contains file path, action will use the specified file + - If input contains folder path, action will try to search `package.lock.json` file in the specified folder + - if input contains wildcards (like `**/package-lock.json`), hash of multiple files will be used +- The hash of file provided in `package-lock-path` input will be used as cache key (the same approach like [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) recommends) +- The following key cache will be used `${{ runner.os }}-npm-${{ hashFiles('') }}` + +# Example of real use-cases +Default use case when `package.lock.json` or `yarn.lock` are located in repository root: +```yml +steps: +- uses: actions/checkout@v2 +- uses: actions/setup-node@v2 + with: + node-version: '14' + cache: npm +``` + +More flexible solution for monorepos: +```yml +steps: +- uses: actions/checkout@v2 +- uses: actions/setup-node@v2 + with: + node-version: '14' + cache: npm + package-lock-path: service1/yarn.lock +``` + +# Release process + +As soon as functionality is implemented, we will release minor update of action. No need to bump major version since there are no breaking changes for existing users. +After that, we will update [starter-workflows](https://github.com/actions/starter-workflows/blob/main/ci/node.js.yml) and [GitHub Action documentation](https://docs.github.com/en/actions/guides/building-and-testing-nodejs#example-caching-dependencies). \ No newline at end of file From 8c35c6c880f88b29b6448c27ed295bc8578256e7 Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Fri, 21 May 2021 18:28:06 +0300 Subject: [PATCH 02/24] Update 0000-caching-dependencies.md --- docs/adrs/0000-caching-dependencies.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/adrs/0000-caching-dependencies.md b/docs/adrs/0000-caching-dependencies.md index 4f9429b6a..c8c24c552 100644 --- a/docs/adrs/0000-caching-dependencies.md +++ b/docs/adrs/0000-caching-dependencies.md @@ -11,8 +11,8 @@ See more examples on proper usage in [actions/cache documentation](https://githu Integration of caching functionality into `actions/setup-node` action will bring the following benefits for action users: - Decrease the entry threshold for using the cache for Node.js dependencies and simplify initial configuration - Simplify YAML pipelines because no need additional steps to enable caching +- More users will use cache for Node.js so more customers will have fast builds! -As a result, more users will use the cache for Node.js builds and will be happy with fast builds. As the first stage, we will add support for NPM dependencies caching. We can consider adding the same functionality for Yarn later. We don't persue the goal to provide wide customization of caching in scope of `actions/setup-node` action. The purpose of this integration is covering ~90% of basic use-cases. If user needs flexible customization, we should advice them to use `actions/cache` directly. @@ -23,16 +23,16 @@ We don't persue the goal to provide wide customization of caching in scope of `a - `''` - disable caching (default value) - Potentially, we will be able to extend this input to support Yarn - Cache feature will be disabled by default to make sure that we don't break existing customers. We will consider enabling cache by default in next major release (`v3`) -- Add optional input `package-lock-path` that will allow to specify path to `package.lock.json` file path: - - If input is not defined, action will try to search `package.lock.json` or `yarn.lock` (npm 7.x supports `yarn.lock` files) files in the repository root and throw error if no one is found +- Add optional input `package-lock-path` that will allow to specify path to `package-lock.json` file path: + - If input is not defined, action will try to search `package-lock.json` or `yarn.lock` (npm 7.x supports `yarn.lock` files) files in the repository root and throw error if no one is found - If input contains file path, action will use the specified file - - If input contains folder path, action will try to search `package.lock.json` file in the specified folder + - If input contains folder path, action will try to search `package-lock.json` file in the specified folder - if input contains wildcards (like `**/package-lock.json`), hash of multiple files will be used - The hash of file provided in `package-lock-path` input will be used as cache key (the same approach like [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) recommends) - The following key cache will be used `${{ runner.os }}-npm-${{ hashFiles('') }}` # Example of real use-cases -Default use case when `package.lock.json` or `yarn.lock` are located in repository root: +Default use case when `package-lock.json` or `yarn.lock` are located in repository root: ```yml steps: - uses: actions/checkout@v2 From 5fddb2d5101a1d50d5a55586ac2fded054bf56e7 Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Mon, 24 May 2021 17:35:10 +0300 Subject: [PATCH 03/24] Update 0000-caching-dependencies.md --- docs/adrs/0000-caching-dependencies.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/adrs/0000-caching-dependencies.md b/docs/adrs/0000-caching-dependencies.md index c8c24c552..16193f710 100644 --- a/docs/adrs/0000-caching-dependencies.md +++ b/docs/adrs/0000-caching-dependencies.md @@ -30,6 +30,7 @@ We don't persue the goal to provide wide customization of caching in scope of `a - if input contains wildcards (like `**/package-lock.json`), hash of multiple files will be used - The hash of file provided in `package-lock-path` input will be used as cache key (the same approach like [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) recommends) - The following key cache will be used `${{ runner.os }}-npm-${{ hashFiles('') }}` +- Action will cache global npm cache directory (retrieved via `npm config get cache`) # Example of real use-cases Default use case when `package-lock.json` or `yarn.lock` are located in repository root: From ae26aaf1b56fb80d170677751f3399908c8eb107 Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Wed, 26 May 2021 17:27:14 +0300 Subject: [PATCH 04/24] Update 0000-caching-dependencies.md --- docs/adrs/0000-caching-dependencies.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/adrs/0000-caching-dependencies.md b/docs/adrs/0000-caching-dependencies.md index 16193f710..641bf838a 100644 --- a/docs/adrs/0000-caching-dependencies.md +++ b/docs/adrs/0000-caching-dependencies.md @@ -26,7 +26,6 @@ We don't persue the goal to provide wide customization of caching in scope of `a - Add optional input `package-lock-path` that will allow to specify path to `package-lock.json` file path: - If input is not defined, action will try to search `package-lock.json` or `yarn.lock` (npm 7.x supports `yarn.lock` files) files in the repository root and throw error if no one is found - If input contains file path, action will use the specified file - - If input contains folder path, action will try to search `package-lock.json` file in the specified folder - if input contains wildcards (like `**/package-lock.json`), hash of multiple files will be used - The hash of file provided in `package-lock-path` input will be used as cache key (the same approach like [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) recommends) - The following key cache will be used `${{ runner.os }}-npm-${{ hashFiles('') }}` From 1bf30534fd920341a18c11e3fcfad5da2494039a Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Wed, 26 May 2021 17:29:27 +0300 Subject: [PATCH 05/24] Update docs/adrs/0000-caching-dependencies.md Co-authored-by: Alejandro Pauly --- docs/adrs/0000-caching-dependencies.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/adrs/0000-caching-dependencies.md b/docs/adrs/0000-caching-dependencies.md index 641bf838a..5a8829286 100644 --- a/docs/adrs/0000-caching-dependencies.md +++ b/docs/adrs/0000-caching-dependencies.md @@ -15,7 +15,7 @@ Integration of caching functionality into `actions/setup-node` action will bring As the first stage, we will add support for NPM dependencies caching. We can consider adding the same functionality for Yarn later. -We don't persue the goal to provide wide customization of caching in scope of `actions/setup-node` action. The purpose of this integration is covering ~90% of basic use-cases. If user needs flexible customization, we should advice them to use `actions/cache` directly. +We don't pursue the goal to provide wide customization of caching in scope of `actions/setup-node` action. The purpose of this integration is covering ~90% of basic use-cases. If user needs flexible customization, we should advice them to use `actions/cache` directly. # Decision - Add `cache` input parameter to `actions/setup-node`. For now, input will accept the following values: @@ -56,4 +56,4 @@ steps: # Release process As soon as functionality is implemented, we will release minor update of action. No need to bump major version since there are no breaking changes for existing users. -After that, we will update [starter-workflows](https://github.com/actions/starter-workflows/blob/main/ci/node.js.yml) and [GitHub Action documentation](https://docs.github.com/en/actions/guides/building-and-testing-nodejs#example-caching-dependencies). \ No newline at end of file +After that, we will update [starter-workflows](https://github.com/actions/starter-workflows/blob/main/ci/node.js.yml) and [GitHub Action documentation](https://docs.github.com/en/actions/guides/building-and-testing-nodejs#example-caching-dependencies). From 59294710198cfb7f55d398c98de60d13e53d11cb Mon Sep 17 00:00:00 2001 From: Maxim Lobanov Date: Wed, 2 Jun 2021 15:52:17 +0300 Subject: [PATCH 06/24] Update 0000-caching-dependencies.md --- docs/adrs/0000-caching-dependencies.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/adrs/0000-caching-dependencies.md b/docs/adrs/0000-caching-dependencies.md index 5a8829286..99a6932e7 100644 --- a/docs/adrs/0000-caching-dependencies.md +++ b/docs/adrs/0000-caching-dependencies.md @@ -13,26 +13,27 @@ Integration of caching functionality into `actions/setup-node` action will bring - Simplify YAML pipelines because no need additional steps to enable caching - More users will use cache for Node.js so more customers will have fast builds! -As the first stage, we will add support for NPM dependencies caching. We can consider adding the same functionality for Yarn later. +We will add support for NPM and Yarn dependencies caching. +As the first stage, we won't support custom locations for `package-lock.json`, `yarn.lock` files and action will work only when files are located in repository root. We don't pursue the goal to provide wide customization of caching in scope of `actions/setup-node` action. The purpose of this integration is covering ~90% of basic use-cases. If user needs flexible customization, we should advice them to use `actions/cache` directly. # Decision - Add `cache` input parameter to `actions/setup-node`. For now, input will accept the following values: - `npm` - enable caching for npm dependencies + - `yarn` - enable caching for yarn dependencies - `''` - disable caching (default value) - - Potentially, we will be able to extend this input to support Yarn - Cache feature will be disabled by default to make sure that we don't break existing customers. We will consider enabling cache by default in next major release (`v3`) -- Add optional input `package-lock-path` that will allow to specify path to `package-lock.json` file path: - - If input is not defined, action will try to search `package-lock.json` or `yarn.lock` (npm 7.x supports `yarn.lock` files) files in the repository root and throw error if no one is found - - If input contains file path, action will use the specified file - - if input contains wildcards (like `**/package-lock.json`), hash of multiple files will be used -- The hash of file provided in `package-lock-path` input will be used as cache key (the same approach like [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) recommends) +- Action will try to search `package-lock.json` or `yarn.lock` (npm 7.x supports `yarn.lock` files) files in the repository root and throw error if no one is found +- The hash of found file will be used as cache key (the same approach like [actions/cache](https://github.com/actions/cache/blob/main/examples.md#node---npm) recommends) - The following key cache will be used `${{ runner.os }}-npm-${{ hashFiles('') }}` -- Action will cache global npm cache directory (retrieved via `npm config get cache`) +- Action will cache global cache: + - Npm (retrieved via `npm config get cache`) + - Yarn 1 (retrieved via `yarn cache dir`) + - Yarn 2 (retrieved via `yarn config get cacheFolder`) # Example of real use-cases -Default use case when `package-lock.json` or `yarn.lock` are located in repository root: +Npm package manager: ```yml steps: - uses: actions/checkout@v2 @@ -42,15 +43,14 @@ steps: cache: npm ``` -More flexible solution for monorepos: +Yarn package manager: ```yml steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: node-version: '14' - cache: npm - package-lock-path: service1/yarn.lock + cache: yarn ``` # Release process From 88d5bfde3141931c4d6926ff20c837c589f97662 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Thu, 17 Jun 2021 17:51:02 +0200 Subject: [PATCH 07/24] Support LTS aliases --- __tests__/data/versions-manifest.json | 5 +++ __tests__/installer.test.ts | 64 +++++++++++++++++++++++++++ src/installer.ts | 38 ++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/__tests__/data/versions-manifest.json b/__tests__/data/versions-manifest.json index d313b16bb..4cf2ccee6 100644 --- a/__tests__/data/versions-manifest.json +++ b/__tests__/data/versions-manifest.json @@ -2,6 +2,7 @@ { "version": "14.0.0", "stable": true, + "lts": "Fermium", "release_url": "https://github.com/actions/node-versions/releases/tag/14.0.0-20200423.30", "files": [ { @@ -52,6 +53,7 @@ { "version": "12.16.2", "stable": true, + "lts": "Erbium", "release_url": "https://github.com/actions/node-versions/releases/tag/12.16.2-20200423.28", "files": [ { @@ -77,6 +79,7 @@ { "version": "10.20.1", "stable": true, + "lts": "Dubnium", "release_url": "https://github.com/actions/node-versions/releases/tag/10.20.1-20200423.27", "files": [ { @@ -102,6 +105,7 @@ { "version": "8.17.0", "stable": true, + "lts": "Carbon", "release_url": "https://github.com/actions/node-versions/releases/tag/8.17.0-20200423.26", "files": [ { @@ -127,6 +131,7 @@ { "version": "6.17.1", "stable": true, + "lts": "Boron", "release_url": "https://github.com/actions/node-versions/releases/tag/6.17.1-20200423.25", "files": [ { diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 4fe757792..3bcaf5801 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -134,6 +134,7 @@ describe('setup-node', () => { let match = await tc.findFromManifest('12.16.2', true, versions); expect(match).toBeDefined(); expect(match?.version).toBe('12.16.2'); + expect((match as any).lts).toBe('Erbium') }); it('can find 12 from manifest on linux', async () => { @@ -148,6 +149,7 @@ describe('setup-node', () => { let match = await tc.findFromManifest('12.16.2', true, versions); expect(match).toBeDefined(); expect(match?.version).toBe('12.16.2'); + expect((match as any).lts).toBe('Erbium') }); it('can find 10 from manifest on windows', async () => { @@ -162,6 +164,7 @@ describe('setup-node', () => { let match = await tc.findFromManifest('10', true, versions); expect(match).toBeDefined(); expect(match?.version).toBe('10.20.1'); + expect((match as any).lts).toBe('Dubnium') }); //-------------------------------------------------- @@ -217,6 +220,10 @@ describe('setup-node', () => { expect(cnSpy).toHaveBeenCalledWith('::error::' + errMsg + osm.EOL); }); + //-------------------------------------------------- + // Manifest tests + //-------------------------------------------------- + it('downloads a version from a manifest match', async () => { os.platform = 'linux'; os.arch = 'x64'; @@ -525,4 +532,61 @@ describe('setup-node', () => { expect(cnSpy).toHaveBeenCalledWith(`::add-path::${expPath}${osm.EOL}`); }); }); + + describe('LTS version', () => { + it('find latest LTS version and resolve it from local cache (lts/erbium)', async () => { + // arrange + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = 'lts/erbium'; + inputs.stable = 'true'; + + const toolPath = path.normalize('/cache/node/12.16.2/x64'); + findSpy.mockReturnValue(toolPath); + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) + expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release 'erbium' for Node version 'lts/erbium'`) + expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); + }); + + it('find latest LTS version and install it from manifest (lts/erbium)', async () => { + // arrange + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = 'lts/erbium'; + inputs.stable = 'true'; + + const toolPath = path.normalize('/cache/node/12.16.2/x64'); + findSpy.mockImplementation(() => ''); + dlSpy.mockImplementation(async () => '/some/temp/path'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + const expectedUrl = 'https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-linux-x64.tar.gz'; + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) + expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release 'erbium' for Node version 'lts/erbium'`) + expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); + expect(logSpy).toHaveBeenCalledWith("Attempting to download 12.16.2..."); + expect(logSpy).toHaveBeenCalledWith(`Acquiring 12.16.2 - ${os.arch} from ${expectedUrl}`); + expect(logSpy).toHaveBeenCalledWith('Extracting ...'); + expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); + expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); + }) + }) }); diff --git a/src/installer.ts b/src/installer.ts index cc45e2248..2351883dd 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -34,6 +34,11 @@ export async function getNode( let osPlat: string = os.platform(); let osArch: string = translateArchToDistUrl(arch); + if (isLts(versionSpec)) { + core.warning('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); + checkLatest = true; + } + if (checkLatest) { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = await resolveVersionFromManifest( @@ -170,6 +175,34 @@ export async function getNode( core.addPath(toolPath); } +function isLts(versionSpec: string): boolean { + return versionSpec.startsWith('lts') +} + +function findLtsVersionFromManifest( + versionSpec: string, + stable: boolean, + candidates: Array +): string { + const alias = versionSpec.split('lts/')[1]?.toLowerCase(); + + if (!alias) { + throw new Error(`Unexpected LTS alias '${alias}' for Node version '${versionSpec}'`); + } + + core.debug(`LTS alias '${alias}' for Node version '${versionSpec}'`); + + const release = candidates.find(x => x.lts?.toLowerCase() === alias && x.stable === stable); + + if (!release) { + throw new Error(`Unable to find LTS release '${alias}' for Node version '${versionSpec}'.`); + } + + core.debug(`Found LTS release '${alias}' for Node version '${versionSpec}'`); + + return release.version.split('.')[0]; +} + async function getInfoFromManifest( versionSpec: string, stable: boolean, @@ -183,6 +216,11 @@ async function getInfoFromManifest( auth, 'main' ); + + if (isLts(versionSpec)) { + versionSpec = findLtsVersionFromManifest(versionSpec, stable, releases); + } + const rel = await tc.findFromManifest(versionSpec, stable, releases, osArch); if (rel && rel.files.length > 0) { From c8889b24a3681f12ac9befb673b9b5b6aef41b33 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Thu, 17 Jun 2021 18:34:09 +0200 Subject: [PATCH 08/24] Support lts/* alias --- __tests__/installer.test.ts | 59 +++++++++++++++++++++++++++++++++++-- src/installer.ts | 6 ++-- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 3bcaf5801..6c7559d9e 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -552,7 +552,7 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) - expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release 'erbium' for Node version 'lts/erbium'`) + expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); @@ -580,7 +580,7 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) - expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release 'erbium' for Node version 'lts/erbium'`) + expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); expect(logSpy).toHaveBeenCalledWith("Attempting to download 12.16.2..."); expect(logSpy).toHaveBeenCalledWith(`Acquiring 12.16.2 - ${os.arch} from ${expectedUrl}`); @@ -588,5 +588,60 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); }) + + it('find latest LTS version and resolve it from local cache (lts/*)', async () => { + // arrange + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = 'lts/*'; + inputs.stable = 'true'; + + const toolPath = path.normalize('/cache/node/14.0.0/x64'); + findSpy.mockReturnValue(toolPath); + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) + expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) + expect(logSpy).toHaveBeenCalledWith("Resolved as '14.0.0'"); + expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); + expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); + }); + + it('find latest LTS version and install it from manifest (lts/*)', async () => { + // arrange + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = 'lts/*'; + inputs.stable = 'true'; + + const toolPath = path.normalize('/cache/node/14.0.0/x64'); + findSpy.mockImplementation(() => ''); + dlSpy.mockImplementation(async () => '/some/temp/path'); + exSpy.mockImplementation(async () => '/some/other/temp/path'); + cacheSpy.mockImplementation(async () => toolPath); + const expectedUrl = 'https://github.com/actions/node-versions/releases/download/14.0.0-20200423.30/node-14.0.0-linux-x64.tar.gz'; + + // act + await main.run(); + + // assert + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) + expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) + expect(logSpy).toHaveBeenCalledWith("Resolved as '14.0.0'"); + expect(logSpy).toHaveBeenCalledWith("Attempting to download 14.0.0..."); + expect(logSpy).toHaveBeenCalledWith(`Acquiring 14.0.0 - ${os.arch} from ${expectedUrl}`); + expect(logSpy).toHaveBeenCalledWith('Extracting ...'); + expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); + expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); + }) }) }); diff --git a/src/installer.ts b/src/installer.ts index 2351883dd..84c57c09a 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -192,13 +192,15 @@ function findLtsVersionFromManifest( core.debug(`LTS alias '${alias}' for Node version '${versionSpec}'`); - const release = candidates.find(x => x.lts?.toLowerCase() === alias && x.stable === stable); + const release = alias === '*' + ? candidates.find(x => !!x.lts && x.stable === stable) + : candidates.find(x => x.lts?.toLowerCase() === alias && x.stable === stable); if (!release) { throw new Error(`Unable to find LTS release '${alias}' for Node version '${versionSpec}'.`); } - core.debug(`Found LTS release '${alias}' for Node version '${versionSpec}'`); + core.debug(`Found LTS release '${release.version}' for Node version '${versionSpec}'`); return release.version.split('.')[0]; } From fa68745dc062afab6c154b4b956c74b5f450ee50 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Thu, 17 Jun 2021 18:53:38 +0200 Subject: [PATCH 09/24] Test coverage for uknown and malformed aliases --- __tests__/installer.test.ts | 53 ++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 6c7559d9e..13a1c55c6 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -549,8 +549,8 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); @@ -577,8 +577,8 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); @@ -604,8 +604,8 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) expect(logSpy).toHaveBeenCalledWith("Resolved as '14.0.0'"); @@ -632,8 +632,8 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) expect(logSpy).toHaveBeenCalledWith("Resolved as '14.0.0'"); @@ -643,5 +643,50 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); }) + + it('fail with unexpected LTS alias (lts/)', async () => { + // arrange + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = 'lts/'; + inputs.stable = 'true'; + + findSpy.mockImplementation(() => ''); + + // act + await main.run(); + + // assert + expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + expect(logSpy).toHaveBeenCalledWith('Unable to resolve version from manifest...'); + expect(dbgSpy).toHaveBeenCalledWith(`Unexpected LTS alias '' for Node version 'lts/'`) + expect(logSpy).toHaveBeenCalledWith('Failed to resolve version lts/ from manifest'); + expect(cnSpy).toHaveBeenCalledWith(`::error::Unable to find Node version 'lts/' for platform linux and architecture x64.${osm.EOL}`); + }); + + it('fail to find LTS version (lts/unknown)', async () => { + // arrange + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = 'lts/unknown'; + inputs.stable = 'true'; + + findSpy.mockImplementation(() => ''); + + // act + await main.run(); + + // assert + expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'unknown' for Node version 'lts/unknown'`) + expect(logSpy).toHaveBeenCalledWith('Unable to resolve version from manifest...'); + expect(dbgSpy).toHaveBeenCalledWith(`Unable to find LTS release 'unknown' for Node version 'lts/unknown'.`) + expect(logSpy).toHaveBeenCalledWith('Failed to resolve version lts/unknown from manifest'); + expect(cnSpy).toHaveBeenCalledWith(`::error::Unable to find Node version 'lts/unknown' for platform linux and architecture x64.${osm.EOL}`); + }); }) }); From c8c6442c742d26063afab708954f283b3998acd7 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Mon, 21 Jun 2021 11:37:06 +0200 Subject: [PATCH 10/24] Add brief comment about supported formats --- src/installer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/installer.ts b/src/installer.ts index 84c57c09a..bc2f99f89 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -192,6 +192,7 @@ function findLtsVersionFromManifest( core.debug(`LTS alias '${alias}' for Node version '${versionSpec}'`); + // Supported formats are `lts/` and `lts/*`. Where asterisk means highest possible LTS. const release = alias === '*' ? candidates.find(x => !!x.lts && x.stable === stable) : candidates.find(x => x.lts?.toLowerCase() === alias && x.stable === stable); From e761a7024e7c9202ccf7e64cfe33cbc8d4190bee Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Mon, 21 Jun 2021 11:37:50 +0200 Subject: [PATCH 11/24] Interface extraction --- src/installer.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/installer.ts b/src/installer.ts index bc2f99f89..0afcaa62e 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -24,6 +24,10 @@ interface INodeVersionInfo { fileName: string; } +interface INodeRelease extends tc.IToolRelease { + lts?: string; +} + export async function getNode( versionSpec: string, stable: boolean, @@ -182,7 +186,7 @@ function isLts(versionSpec: string): boolean { function findLtsVersionFromManifest( versionSpec: string, stable: boolean, - candidates: Array + candidates: INodeRelease[] ): string { const alias = versionSpec.split('lts/')[1]?.toLowerCase(); From 0ec4841e4b4a8aef0c86a18ed294669513661cdd Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Mon, 21 Jun 2021 11:39:00 +0200 Subject: [PATCH 12/24] Function renaming --- src/installer.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/installer.ts b/src/installer.ts index 0afcaa62e..2df2e13ee 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -38,7 +38,7 @@ export async function getNode( let osPlat: string = os.platform(); let osArch: string = translateArchToDistUrl(arch); - if (isLts(versionSpec)) { + if (isLtsVersion(versionSpec)) { core.warning('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); checkLatest = true; } @@ -179,7 +179,7 @@ export async function getNode( core.addPath(toolPath); } -function isLts(versionSpec: string): boolean { +function isLtsVersion(versionSpec: string): boolean { return versionSpec.startsWith('lts') } @@ -224,7 +224,7 @@ async function getInfoFromManifest( 'main' ); - if (isLts(versionSpec)) { + if (isLtsVersion(versionSpec)) { versionSpec = findLtsVersionFromManifest(versionSpec, stable, releases); } From bcdcde00c0fc83717dcc05a8e0d9ea352513fe05 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Mon, 21 Jun 2021 11:40:55 +0200 Subject: [PATCH 13/24] Stage dist files --- dist/index.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/dist/index.js b/dist/index.js index 800d35a9c..d2c35be11 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13107,6 +13107,10 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { return __awaiter(this, void 0, void 0, function* () { let osPlat = os.platform(); let osArch = translateArchToDistUrl(arch); + if (isLtsVersion(versionSpec)) { + core.warning('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); + checkLatest = true; + } if (checkLatest) { core.info('Attempt to resolve the latest version from manifest...'); const resolvedVersion = yield resolveVersionFromManifest(versionSpec, stable, auth, osArch); @@ -13216,10 +13220,33 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { }); } exports.getNode = getNode; +function isLtsVersion(versionSpec) { + return versionSpec.startsWith('lts'); +} +function findLtsVersionFromManifest(versionSpec, stable, candidates) { + var _a; + const alias = (_a = versionSpec.split('lts/')[1]) === null || _a === void 0 ? void 0 : _a.toLowerCase(); + if (!alias) { + throw new Error(`Unexpected LTS alias '${alias}' for Node version '${versionSpec}'`); + } + core.debug(`LTS alias '${alias}' for Node version '${versionSpec}'`); + // Supported formats are `lts/` and `lts/*`. Where asterisk means highest possible LTS. + const release = alias === '*' + ? candidates.find(x => !!x.lts && x.stable === stable) + : candidates.find(x => { var _a; return ((_a = x.lts) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === alias && x.stable === stable; }); + 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]; +} function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os.arch())) { return __awaiter(this, void 0, void 0, function* () { let info = null; const releases = yield tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); + if (isLtsVersion(versionSpec)) { + versionSpec = findLtsVersionFromManifest(versionSpec, stable, releases); + } const rel = yield tc.findFromManifest(versionSpec, stable, releases, osArch); if (rel && rel.files.length > 0) { info = {}; From 36d2ce149ef6fea8601c6ee9636d1a3dcbf09ad6 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Mon, 21 Jun 2021 14:33:27 +0200 Subject: [PATCH 14/24] Switch warning to info logging --- __tests__/installer.test.ts | 12 ++++++------ dist/index.js | 2 +- src/installer.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 13a1c55c6..12805972d 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -549,7 +549,7 @@ describe('setup-node', () => { await main.run(); // assert - expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) @@ -577,7 +577,7 @@ describe('setup-node', () => { await main.run(); // assert - expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) @@ -604,7 +604,7 @@ describe('setup-node', () => { await main.run(); // assert - expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) @@ -632,7 +632,7 @@ describe('setup-node', () => { await main.run(); // assert - expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) @@ -658,7 +658,7 @@ describe('setup-node', () => { await main.run(); // assert - expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(logSpy).toHaveBeenCalledWith('Unable to resolve version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`Unexpected LTS alias '' for Node version 'lts/'`) @@ -680,7 +680,7 @@ describe('setup-node', () => { await main.run(); // assert - expect(warningSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') + expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'unknown' for Node version 'lts/unknown'`) expect(logSpy).toHaveBeenCalledWith('Unable to resolve version from manifest...'); diff --git a/dist/index.js b/dist/index.js index d2c35be11..915200f03 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13108,7 +13108,7 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { let osPlat = os.platform(); let osArch = translateArchToDistUrl(arch); if (isLtsVersion(versionSpec)) { - core.warning('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); + core.info('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); checkLatest = true; } if (checkLatest) { diff --git a/src/installer.ts b/src/installer.ts index 2df2e13ee..284b8b5e1 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -39,7 +39,7 @@ export async function getNode( let osArch: string = translateArchToDistUrl(arch); if (isLtsVersion(versionSpec)) { - core.warning('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); + core.info('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); checkLatest = true; } From c62861c1e7c9af33f6d2343356f2c691c4eb4cbf Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Tue, 22 Jun 2021 13:10:16 +0200 Subject: [PATCH 15/24] Rename --- dist/index.js | 14 +++++++------- src/installer.ts | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dist/index.js b/dist/index.js index 915200f03..dcbb152b1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13107,7 +13107,7 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { return __awaiter(this, void 0, void 0, function* () { let osPlat = os.platform(); let osArch = translateArchToDistUrl(arch); - if (isLtsVersion(versionSpec)) { + if (isLtsAlias(versionSpec)) { core.info('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); checkLatest = true; } @@ -13220,10 +13220,10 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { }); } exports.getNode = getNode; -function isLtsVersion(versionSpec) { +function isLtsAlias(versionSpec) { return versionSpec.startsWith('lts'); } -function findLtsVersionFromManifest(versionSpec, stable, candidates) { +function resolveLtsAliasFromManifest(versionSpec, stable, manifest) { var _a; const alias = (_a = versionSpec.split('lts/')[1]) === null || _a === void 0 ? void 0 : _a.toLowerCase(); if (!alias) { @@ -13232,8 +13232,8 @@ function findLtsVersionFromManifest(versionSpec, stable, candidates) { core.debug(`LTS alias '${alias}' for Node version '${versionSpec}'`); // Supported formats are `lts/` and `lts/*`. Where asterisk means highest possible LTS. const release = alias === '*' - ? candidates.find(x => !!x.lts && x.stable === stable) - : candidates.find(x => { var _a; return ((_a = x.lts) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === alias && x.stable === stable; }); + ? manifest.find(x => !!x.lts && x.stable === stable) + : manifest.find(x => { var _a; return ((_a = x.lts) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === alias && x.stable === stable; }); if (!release) { throw new Error(`Unable to find LTS release '${alias}' for Node version '${versionSpec}'.`); } @@ -13244,8 +13244,8 @@ function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchTo return __awaiter(this, void 0, void 0, function* () { let info = null; const releases = yield tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); - if (isLtsVersion(versionSpec)) { - versionSpec = findLtsVersionFromManifest(versionSpec, stable, releases); + if (isLtsAlias(versionSpec)) { + versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, releases); } const rel = yield tc.findFromManifest(versionSpec, stable, releases, osArch); if (rel && rel.files.length > 0) { diff --git a/src/installer.ts b/src/installer.ts index 284b8b5e1..7a19a257d 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -38,7 +38,7 @@ export async function getNode( let osPlat: string = os.platform(); let osArch: string = translateArchToDistUrl(arch); - if (isLtsVersion(versionSpec)) { + if (isLtsAlias(versionSpec)) { core.info('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); checkLatest = true; } @@ -179,14 +179,14 @@ export async function getNode( core.addPath(toolPath); } -function isLtsVersion(versionSpec: string): boolean { +function isLtsAlias(versionSpec: string): boolean { return versionSpec.startsWith('lts') } -function findLtsVersionFromManifest( +function resolveLtsAliasFromManifest( versionSpec: string, stable: boolean, - candidates: INodeRelease[] + manifest: INodeRelease[] ): string { const alias = versionSpec.split('lts/')[1]?.toLowerCase(); @@ -198,8 +198,8 @@ function findLtsVersionFromManifest( // Supported formats are `lts/` and `lts/*`. Where asterisk means highest possible LTS. const release = alias === '*' - ? candidates.find(x => !!x.lts && x.stable === stable) - : candidates.find(x => x.lts?.toLowerCase() === alias && x.stable === stable); + ? manifest.find(x => !!x.lts && x.stable === stable) + : manifest.find(x => x.lts?.toLowerCase() === alias && x.stable === stable); if (!release) { throw new Error(`Unable to find LTS release '${alias}' for Node version '${versionSpec}'.`); @@ -224,8 +224,8 @@ async function getInfoFromManifest( 'main' ); - if (isLtsVersion(versionSpec)) { - versionSpec = findLtsVersionFromManifest(versionSpec, stable, releases); + if (isLtsAlias(versionSpec)) { + versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, releases); } const rel = await tc.findFromManifest(versionSpec, stable, releases, osArch); From 92722aec8cf5360a51b6b050870d1c9344b95798 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Tue, 22 Jun 2021 15:45:25 +0200 Subject: [PATCH 16/24] Logic remastered to not force check-latest --- __tests__/installer.test.ts | 74 ++++++++++++++++++++++++------------- dist/index.js | 27 ++++++++------ src/installer.ts | 40 ++++++++++++-------- 3 files changed, 88 insertions(+), 53 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 12805972d..6a77c213e 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -399,6 +399,7 @@ describe('setup-node', () => { expect(logSpy).not.toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached, getting manifest from actions/node-versions@main') }); it('check latest version and resolve it from local cache', async () => { @@ -419,6 +420,7 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached, getting manifest from actions/node-versions@main') expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); }); @@ -443,6 +445,7 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached, 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}` @@ -479,6 +482,7 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached, getting manifest from actions/node-versions@main') expect(logSpy).toHaveBeenCalledWith( `Failed to resolve version ${versionSpec} from manifest` ); @@ -522,6 +526,7 @@ describe('setup-node', () => { ); expect(logSpy).toHaveBeenCalledWith( 'Unable to resolve version from manifest...' + // 'Unable to get manifest...' ); expect(logSpy).toHaveBeenCalledWith( `Failed to resolve version ${versionSpec} from manifest` @@ -549,11 +554,11 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + 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, getting manifest from actions/node-versions@main') expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) - expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); }); @@ -577,12 +582,12 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + 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, getting manifest from actions/node-versions@main') expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) - expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); - expect(logSpy).toHaveBeenCalledWith("Attempting to download 12.16.2..."); + expect(logSpy).toHaveBeenCalledWith("Attempting to download 12..."); expect(logSpy).toHaveBeenCalledWith(`Acquiring 12.16.2 - ${os.arch} from ${expectedUrl}`); expect(logSpy).toHaveBeenCalledWith('Extracting ...'); expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); @@ -604,11 +609,11 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + 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, getting manifest from actions/node-versions@main') expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) - expect(logSpy).toHaveBeenCalledWith("Resolved as '14.0.0'"); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); }); @@ -632,12 +637,12 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + 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, getting manifest from actions/node-versions@main') expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) - expect(logSpy).toHaveBeenCalledWith("Resolved as '14.0.0'"); - expect(logSpy).toHaveBeenCalledWith("Attempting to download 14.0.0..."); + expect(logSpy).toHaveBeenCalledWith("Attempting to download 14..."); expect(logSpy).toHaveBeenCalledWith(`Acquiring 14.0.0 - ${os.arch} from ${expectedUrl}`); expect(logSpy).toHaveBeenCalledWith('Extracting ...'); expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); @@ -658,12 +663,9 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); - expect(logSpy).toHaveBeenCalledWith('Unable to resolve version from manifest...'); - expect(dbgSpy).toHaveBeenCalledWith(`Unexpected LTS alias '' for Node version 'lts/'`) - expect(logSpy).toHaveBeenCalledWith('Failed to resolve version lts/ from manifest'); - expect(cnSpy).toHaveBeenCalledWith(`::error::Unable to find Node version 'lts/' for platform linux and architecture x64.${osm.EOL}`); + expect(logSpy).toHaveBeenCalledWith('Attempt to resolve LTS alias from manifest...') + expect(dbgSpy).toHaveBeenCalledWith('Getting manifest from actions/node-versions@main') + expect(cnSpy).toHaveBeenCalledWith(`::error::Unexpected LTS alias '' for Node version 'lts/'${osm.EOL}`) }); it('fail to find LTS version (lts/unknown)', async () => { @@ -680,13 +682,33 @@ describe('setup-node', () => { await main.run(); // assert - expect(logSpy).toHaveBeenCalledWith('LTS version is provided. For LTS versions `check-latest` will be automatically set to true') - expect(logSpy).toHaveBeenCalledWith('Attempt to resolve the latest version from manifest...'); + 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(logSpy).toHaveBeenCalledWith('Unable to resolve version from manifest...'); - expect(dbgSpy).toHaveBeenCalledWith(`Unable to find LTS release 'unknown' for Node version 'lts/unknown'.`) - expect(logSpy).toHaveBeenCalledWith('Failed to resolve version lts/unknown from manifest'); - expect(cnSpy).toHaveBeenCalledWith(`::error::Unable to find Node version 'lts/unknown' for platform linux and architecture x64.${osm.EOL}`); + 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 + os.platform = 'linux'; + os.arch = 'x64'; + + inputs['node-version'] = 'lts/erbium'; + inputs.stable = 'true'; + + // ... 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}`) + }) }) }); diff --git a/dist/index.js b/dist/index.js index dcbb152b1..a1f7f053a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13105,15 +13105,20 @@ const semver = __importStar(__webpack_require__(280)); const fs = __webpack_require__(747); function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { return __awaiter(this, void 0, void 0, function* () { + // Store manifest data to avoid multiple calls + let manifest; let osPlat = os.platform(); let osArch = translateArchToDistUrl(arch); if (isLtsAlias(versionSpec)) { - core.info('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); - checkLatest = true; + core.info('Attempt to resolve LTS alias from manifest...'); + core.debug('Getting manifest from actions/node-versions@main'); + // No try-catch since it's not possible to resolve LTS alias without manifest + manifest = yield tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); + versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } if (checkLatest) { core.info('Attempt to resolve the latest version from manifest...'); - const resolvedVersion = yield resolveVersionFromManifest(versionSpec, stable, auth, osArch); + const resolvedVersion = yield resolveVersionFromManifest(versionSpec, stable, auth, osArch, manifest); if (resolvedVersion) { versionSpec = resolvedVersion; core.info(`Resolved as '${versionSpec}'`); @@ -13137,7 +13142,7 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { // Try download from internal distribution (popular versions only) // try { - info = yield getInfoFromManifest(versionSpec, stable, auth, osArch); + 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); @@ -13240,14 +13245,14 @@ function resolveLtsAliasFromManifest(versionSpec, stable, manifest) { core.debug(`Found LTS release '${release.version}' for Node version '${versionSpec}'`); return release.version.split('.')[0]; } -function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os.arch())) { +function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os.arch()), manifest) { return __awaiter(this, void 0, void 0, function* () { let info = null; - const releases = yield tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); - if (isLtsAlias(versionSpec)) { - versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, releases); + if (!manifest) { + core.debug('No manifest cached, getting manifest from actions/node-versions@main'); + manifest = yield tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); } - const rel = yield tc.findFromManifest(versionSpec, stable, releases, osArch); + const rel = yield tc.findFromManifest(versionSpec, stable, manifest, osArch); if (rel && rel.files.length > 0) { info = {}; info.resolvedVersion = rel.version; @@ -13284,10 +13289,10 @@ function getInfoFromDist(versionSpec, arch = os.arch()) { }; }); } -function resolveVersionFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os.arch())) { +function resolveVersionFromManifest(versionSpec, stable, auth, osArch = translateArchToDistUrl(os.arch()), manifest) { return __awaiter(this, void 0, void 0, function* () { try { - const info = yield getInfoFromManifest(versionSpec, stable, auth, osArch); + const info = yield getInfoFromManifest(versionSpec, stable, auth, osArch, manifest); return info === null || info === void 0 ? void 0 : info.resolvedVersion; } catch (err) { diff --git a/src/installer.ts b/src/installer.ts index 7a19a257d..ac7be1c7b 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -35,12 +35,17 @@ export async function getNode( auth: string | undefined, arch: string = os.arch() ) { + // Store manifest data to avoid multiple calls + let manifest: INodeRelease[] | undefined; let osPlat: string = os.platform(); let osArch: string = translateArchToDistUrl(arch); if (isLtsAlias(versionSpec)) { - core.info('LTS version is provided. For LTS versions `check-latest` will be automatically set to true'); - checkLatest = true; + core.info('Attempt to resolve LTS alias from manifest...'); + core.debug('Getting manifest from actions/node-versions@main') + // No try-catch since it's not possible to resolve LTS alias without manifest + manifest = await tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); + versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } if (checkLatest) { @@ -49,7 +54,8 @@ export async function getNode( versionSpec, stable, auth, - osArch + osArch, + manifest ); if (resolvedVersion) { versionSpec = resolvedVersion; @@ -75,7 +81,7 @@ export async function getNode( // Try download from internal distribution (popular versions only) // try { - info = await getInfoFromManifest(versionSpec, stable, auth, osArch); + info = await getInfoFromManifest(versionSpec, stable, auth, osArch, manifest); if (info) { core.info( `Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}` @@ -214,21 +220,22 @@ async function getInfoFromManifest( versionSpec: string, stable: boolean, auth: string | undefined, - osArch: string = translateArchToDistUrl(os.arch()) + osArch: string = translateArchToDistUrl(os.arch()), + manifest: tc.IToolRelease[] | undefined ): Promise { let info: INodeVersionInfo | null = null; - const releases = await tc.getManifestFromRepo( - 'actions', - 'node-versions', - auth, - 'main' - ); + if (!manifest) { + core.debug('No manifest cached, getting manifest from actions/node-versions@main') - if (isLtsAlias(versionSpec)) { - versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, releases); + manifest = await tc.getManifestFromRepo( + 'actions', + 'node-versions', + auth, + 'main' + ); } - const rel = await tc.findFromManifest(versionSpec, stable, releases, osArch); + const rel = await tc.findFromManifest(versionSpec, stable, manifest, osArch); if (rel && rel.files.length > 0) { info = {}; @@ -279,10 +286,11 @@ async function resolveVersionFromManifest( versionSpec: string, stable: boolean, auth: string | undefined, - osArch: string = translateArchToDistUrl(os.arch()) + osArch: string = translateArchToDistUrl(os.arch()), + manifest: tc.IToolRelease[] | undefined ): Promise { try { - const info = await getInfoFromManifest(versionSpec, stable, auth, osArch); + const info = await getInfoFromManifest(versionSpec, stable, auth, osArch, manifest); return info?.resolvedVersion; } catch (err) { core.info('Unable to resolve version from manifest...'); From 56c3db9ddab4bfd2b952bdfed6259e78a05c099a Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Tue, 22 Jun 2021 15:51:57 +0200 Subject: [PATCH 17/24] Cleanup redundant leftover --- __tests__/installer.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 6a77c213e..100050c92 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -526,7 +526,6 @@ describe('setup-node', () => { ); expect(logSpy).toHaveBeenCalledWith( 'Unable to resolve version from manifest...' - // 'Unable to get manifest...' ); expect(logSpy).toHaveBeenCalledWith( `Failed to resolve version ${versionSpec} from manifest` From d9ce83b637cfedc635fce2626d990276d3dc49bb Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Tue, 22 Jun 2021 16:11:44 +0200 Subject: [PATCH 18/24] Formatter --- __tests__/installer.test.ts | 184 ++++++++++++++++++++++++++---------- src/installer.ts | 52 +++++++--- 2 files changed, 173 insertions(+), 63 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 100050c92..2fc88d633 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -134,7 +134,7 @@ describe('setup-node', () => { let match = await tc.findFromManifest('12.16.2', true, versions); expect(match).toBeDefined(); expect(match?.version).toBe('12.16.2'); - expect((match as any).lts).toBe('Erbium') + expect((match as any).lts).toBe('Erbium'); }); it('can find 12 from manifest on linux', async () => { @@ -149,7 +149,7 @@ describe('setup-node', () => { let match = await tc.findFromManifest('12.16.2', true, versions); expect(match).toBeDefined(); expect(match?.version).toBe('12.16.2'); - expect((match as any).lts).toBe('Erbium') + expect((match as any).lts).toBe('Erbium'); }); it('can find 10 from manifest on windows', async () => { @@ -164,7 +164,7 @@ describe('setup-node', () => { let match = await tc.findFromManifest('10', true, versions); expect(match).toBeDefined(); expect(match?.version).toBe('10.20.1'); - expect((match as any).lts).toBe('Dubnium') + expect((match as any).lts).toBe('Dubnium'); }); //-------------------------------------------------- @@ -399,7 +399,9 @@ describe('setup-node', () => { expect(logSpy).not.toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); - expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached, getting manifest from actions/node-versions@main') + expect(dbgSpy).not.toHaveBeenCalledWith( + 'No manifest cached, getting manifest from actions/node-versions@main' + ); }); it('check latest version and resolve it from local cache', async () => { @@ -420,7 +422,9 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); - expect(dbgSpy).toHaveBeenCalledWith('No manifest cached, getting manifest from actions/node-versions@main') + expect(dbgSpy).toHaveBeenCalledWith( + 'No manifest cached, getting manifest from actions/node-versions@main' + ); expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); }); @@ -445,7 +449,9 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); - expect(dbgSpy).toHaveBeenCalledWith('No manifest cached, getting manifest from actions/node-versions@main') + expect(dbgSpy).toHaveBeenCalledWith( + 'No manifest cached, 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}` @@ -482,7 +488,9 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); - expect(dbgSpy).toHaveBeenCalledWith('No manifest cached, getting manifest from actions/node-versions@main') + expect(dbgSpy).toHaveBeenCalledWith( + 'No manifest cached, getting manifest from actions/node-versions@main' + ); expect(logSpy).toHaveBeenCalledWith( `Failed to resolve version ${versionSpec} from manifest` ); @@ -553,13 +561,25 @@ describe('setup-node', () => { 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, getting manifest from actions/node-versions@main') - expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) - expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) + 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, getting manifest from actions/node-versions@main' + ); + expect(dbgSpy).toHaveBeenCalledWith( + `LTS alias 'erbium' for Node version 'lts/erbium'` + ); + expect(dbgSpy).toHaveBeenCalledWith( + `Found LTS release '12.16.2' for Node version 'lts/erbium'` + ); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); - expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); + expect(cnSpy).toHaveBeenCalledWith( + `::add-path::${toolPath}/bin${osm.EOL}` + ); }); it('find latest LTS version and install it from manifest (lts/erbium)', async () => { @@ -575,23 +595,38 @@ describe('setup-node', () => { dlSpy.mockImplementation(async () => '/some/temp/path'); exSpy.mockImplementation(async () => '/some/other/temp/path'); cacheSpy.mockImplementation(async () => toolPath); - const expectedUrl = 'https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-linux-x64.tar.gz'; + const expectedUrl = + 'https://github.com/actions/node-versions/releases/download/12.16.2-20200423.28/node-12.16.2-linux-x64.tar.gz'; // 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, getting manifest from actions/node-versions@main') - expect(dbgSpy).toHaveBeenCalledWith(`LTS alias 'erbium' for Node version 'lts/erbium'`) - expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '12.16.2' for Node version 'lts/erbium'`) - expect(logSpy).toHaveBeenCalledWith("Attempting to download 12..."); - expect(logSpy).toHaveBeenCalledWith(`Acquiring 12.16.2 - ${os.arch} from ${expectedUrl}`); + 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, getting manifest from actions/node-versions@main' + ); + expect(dbgSpy).toHaveBeenCalledWith( + `LTS alias 'erbium' for Node version 'lts/erbium'` + ); + expect(dbgSpy).toHaveBeenCalledWith( + `Found LTS release '12.16.2' for Node version 'lts/erbium'` + ); + expect(logSpy).toHaveBeenCalledWith('Attempting to download 12...'); + expect(logSpy).toHaveBeenCalledWith( + `Acquiring 12.16.2 - ${os.arch} from ${expectedUrl}` + ); expect(logSpy).toHaveBeenCalledWith('Extracting ...'); expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); - expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); - }) + expect(cnSpy).toHaveBeenCalledWith( + `::add-path::${toolPath}/bin${osm.EOL}` + ); + }); it('find latest LTS version and resolve it from local cache (lts/*)', async () => { // arrange @@ -608,13 +643,25 @@ describe('setup-node', () => { 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, getting manifest from actions/node-versions@main') - expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) - expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) + 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, getting manifest from actions/node-versions@main' + ); + expect(dbgSpy).toHaveBeenCalledWith( + `LTS alias '*' for Node version 'lts/*'` + ); + expect(dbgSpy).toHaveBeenCalledWith( + `Found LTS release '14.0.0' for Node version 'lts/*'` + ); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); - expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); + expect(cnSpy).toHaveBeenCalledWith( + `::add-path::${toolPath}/bin${osm.EOL}` + ); }); it('find latest LTS version and install it from manifest (lts/*)', async () => { @@ -630,23 +677,38 @@ describe('setup-node', () => { dlSpy.mockImplementation(async () => '/some/temp/path'); exSpy.mockImplementation(async () => '/some/other/temp/path'); cacheSpy.mockImplementation(async () => toolPath); - const expectedUrl = 'https://github.com/actions/node-versions/releases/download/14.0.0-20200423.30/node-14.0.0-linux-x64.tar.gz'; + const expectedUrl = + 'https://github.com/actions/node-versions/releases/download/14.0.0-20200423.30/node-14.0.0-linux-x64.tar.gz'; // 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, getting manifest from actions/node-versions@main') - expect(dbgSpy).toHaveBeenCalledWith(`LTS alias '*' for Node version 'lts/*'`) - expect(dbgSpy).toHaveBeenCalledWith(`Found LTS release '14.0.0' for Node version 'lts/*'`) - expect(logSpy).toHaveBeenCalledWith("Attempting to download 14..."); - expect(logSpy).toHaveBeenCalledWith(`Acquiring 14.0.0 - ${os.arch} from ${expectedUrl}`); + 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, getting manifest from actions/node-versions@main' + ); + expect(dbgSpy).toHaveBeenCalledWith( + `LTS alias '*' for Node version 'lts/*'` + ); + expect(dbgSpy).toHaveBeenCalledWith( + `Found LTS release '14.0.0' for Node version 'lts/*'` + ); + expect(logSpy).toHaveBeenCalledWith('Attempting to download 14...'); + expect(logSpy).toHaveBeenCalledWith( + `Acquiring 14.0.0 - ${os.arch} from ${expectedUrl}` + ); expect(logSpy).toHaveBeenCalledWith('Extracting ...'); expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); - expect(cnSpy).toHaveBeenCalledWith(`::add-path::${toolPath}/bin${osm.EOL}`); - }) + expect(cnSpy).toHaveBeenCalledWith( + `::add-path::${toolPath}/bin${osm.EOL}` + ); + }); it('fail with unexpected LTS alias (lts/)', async () => { // arrange @@ -662,9 +724,15 @@ describe('setup-node', () => { 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::Unexpected LTS alias '' for Node version 'lts/'${osm.EOL}`) + expect(logSpy).toHaveBeenCalledWith( + 'Attempt to resolve LTS alias from manifest...' + ); + expect(dbgSpy).toHaveBeenCalledWith( + 'Getting manifest from actions/node-versions@main' + ); + expect(cnSpy).toHaveBeenCalledWith( + `::error::Unexpected LTS alias '' for Node version 'lts/'${osm.EOL}` + ); }); it('fail to find LTS version (lts/unknown)', async () => { @@ -681,10 +749,18 @@ describe('setup-node', () => { 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}`) + 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 () => { @@ -705,9 +781,15 @@ describe('setup-node', () => { 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}`) - }) - }) + 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}` + ); + }); + }); }); diff --git a/src/installer.ts b/src/installer.ts index ac7be1c7b..2001f4d79 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -42,9 +42,14 @@ export async function getNode( if (isLtsAlias(versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); - core.debug('Getting manifest from actions/node-versions@main') + core.debug('Getting manifest from actions/node-versions@main'); // No try-catch since it's not possible to resolve LTS alias without manifest - manifest = await tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); + manifest = await tc.getManifestFromRepo( + 'actions', + 'node-versions', + auth, + 'main' + ); versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } @@ -81,7 +86,13 @@ export async function getNode( // Try download from internal distribution (popular versions only) // try { - info = await getInfoFromManifest(versionSpec, stable, auth, osArch, manifest); + info = await getInfoFromManifest( + versionSpec, + stable, + auth, + osArch, + manifest + ); if (info) { core.info( `Acquiring ${info.resolvedVersion} - ${info.arch} from ${info.downloadUrl}` @@ -186,7 +197,7 @@ export async function getNode( } function isLtsAlias(versionSpec: string): boolean { - return versionSpec.startsWith('lts') + return versionSpec.startsWith('lts'); } function resolveLtsAliasFromManifest( @@ -197,21 +208,30 @@ function resolveLtsAliasFromManifest( const alias = versionSpec.split('lts/')[1]?.toLowerCase(); if (!alias) { - throw new Error(`Unexpected LTS alias '${alias}' for Node version '${versionSpec}'`); + throw new Error( + `Unexpected LTS alias '${alias}' for Node version '${versionSpec}'` + ); } core.debug(`LTS alias '${alias}' for Node version '${versionSpec}'`); // Supported formats are `lts/` and `lts/*`. Where asterisk means highest possible LTS. - const release = alias === '*' - ? manifest.find(x => !!x.lts && x.stable === stable) - : manifest.find(x => x.lts?.toLowerCase() === alias && x.stable === stable); + const release = + alias === '*' + ? manifest.find(x => !!x.lts && x.stable === stable) + : manifest.find( + x => x.lts?.toLowerCase() === alias && x.stable === stable + ); if (!release) { - throw new Error(`Unable to find LTS release '${alias}' for Node version '${versionSpec}'.`); + throw new Error( + `Unable to find LTS release '${alias}' for Node version '${versionSpec}'.` + ); } - core.debug(`Found LTS release '${release.version}' for Node version '${versionSpec}'`); + core.debug( + `Found LTS release '${release.version}' for Node version '${versionSpec}'` + ); return release.version.split('.')[0]; } @@ -225,7 +245,9 @@ async function getInfoFromManifest( ): Promise { let info: INodeVersionInfo | null = null; if (!manifest) { - core.debug('No manifest cached, getting manifest from actions/node-versions@main') + core.debug( + 'No manifest cached, getting manifest from actions/node-versions@main' + ); manifest = await tc.getManifestFromRepo( 'actions', @@ -290,7 +312,13 @@ async function resolveVersionFromManifest( manifest: tc.IToolRelease[] | undefined ): Promise { try { - const info = await getInfoFromManifest(versionSpec, stable, auth, osArch, manifest); + const info = await getInfoFromManifest( + versionSpec, + stable, + auth, + osArch, + manifest + ); return info?.resolvedVersion; } catch (err) { core.info('Unable to resolve version from manifest...'); From c2dfe2df9884bf1033e0ee352d86309105ea6cf0 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Tue, 22 Jun 2021 17:52:06 +0200 Subject: [PATCH 19/24] Reuse manifest code --- __tests__/installer.test.ts | 28 ++++++++++++---------------- dist/index.js | 11 +++++++---- src/installer.ts | 27 ++++++++++----------------- 3 files changed, 29 insertions(+), 37 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 2fc88d633..a6907c4cd 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -399,8 +399,9 @@ describe('setup-node', () => { expect(logSpy).not.toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); expect(dbgSpy).not.toHaveBeenCalledWith( - 'No manifest cached, getting manifest from actions/node-versions@main' + 'Getting manifest from actions/node-versions@main' ); }); @@ -422,8 +423,9 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); expect(dbgSpy).toHaveBeenCalledWith( - 'No manifest cached, getting manifest from actions/node-versions@main' + 'Getting manifest from actions/node-versions@main' ); expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); @@ -449,8 +451,9 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); expect(dbgSpy).toHaveBeenCalledWith( - 'No manifest cached, getting manifest from actions/node-versions@main' + 'Getting manifest from actions/node-versions@main' ); expect(logSpy).toHaveBeenCalledWith("Resolved as '12.16.2'"); expect(logSpy).toHaveBeenCalledWith( @@ -488,8 +491,9 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith( 'Attempt to resolve the latest version from manifest...' ); + expect(dbgSpy).toHaveBeenCalledWith('No manifest cached'); expect(dbgSpy).toHaveBeenCalledWith( - 'No manifest cached, getting manifest from actions/node-versions@main' + 'Getting manifest from actions/node-versions@main' ); expect(logSpy).toHaveBeenCalledWith( `Failed to resolve version ${versionSpec} from manifest` @@ -567,9 +571,7 @@ describe('setup-node', () => { expect(dbgSpy).toHaveBeenCalledWith( 'Getting manifest from actions/node-versions@main' ); - expect(dbgSpy).not.toHaveBeenCalledWith( - 'No manifest cached, getting manifest from actions/node-versions@main' - ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); expect(dbgSpy).toHaveBeenCalledWith( `LTS alias 'erbium' for Node version 'lts/erbium'` ); @@ -608,9 +610,7 @@ describe('setup-node', () => { expect(dbgSpy).toHaveBeenCalledWith( 'Getting manifest from actions/node-versions@main' ); - expect(dbgSpy).not.toHaveBeenCalledWith( - 'No manifest cached, getting manifest from actions/node-versions@main' - ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); expect(dbgSpy).toHaveBeenCalledWith( `LTS alias 'erbium' for Node version 'lts/erbium'` ); @@ -649,9 +649,7 @@ describe('setup-node', () => { expect(dbgSpy).toHaveBeenCalledWith( 'Getting manifest from actions/node-versions@main' ); - expect(dbgSpy).not.toHaveBeenCalledWith( - 'No manifest cached, getting manifest from actions/node-versions@main' - ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); expect(dbgSpy).toHaveBeenCalledWith( `LTS alias '*' for Node version 'lts/*'` ); @@ -690,9 +688,7 @@ describe('setup-node', () => { expect(dbgSpy).toHaveBeenCalledWith( 'Getting manifest from actions/node-versions@main' ); - expect(dbgSpy).not.toHaveBeenCalledWith( - 'No manifest cached, getting manifest from actions/node-versions@main' - ); + expect(dbgSpy).not.toHaveBeenCalledWith('No manifest cached'); expect(dbgSpy).toHaveBeenCalledWith( `LTS alias '*' for Node version 'lts/*'` ); diff --git a/dist/index.js b/dist/index.js index a1f7f053a..170f8279c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13111,9 +13111,8 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { let osArch = translateArchToDistUrl(arch); if (isLtsAlias(versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); - core.debug('Getting manifest from actions/node-versions@main'); // No try-catch since it's not possible to resolve LTS alias without manifest - manifest = yield tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); + manifest = yield getManifest(auth); versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } if (checkLatest) { @@ -13228,6 +13227,10 @@ exports.getNode = getNode; function isLtsAlias(versionSpec) { return versionSpec.startsWith('lts'); } +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(); @@ -13249,8 +13252,8 @@ function getInfoFromManifest(versionSpec, stable, auth, osArch = translateArchTo return __awaiter(this, void 0, void 0, function* () { let info = null; if (!manifest) { - core.debug('No manifest cached, getting manifest from actions/node-versions@main'); - manifest = yield tc.getManifestFromRepo('actions', 'node-versions', auth, 'main'); + core.debug('No manifest cached'); + manifest = yield getManifest(auth); } const rel = yield tc.findFromManifest(versionSpec, stable, manifest, osArch); if (rel && rel.files.length > 0) { diff --git a/src/installer.ts b/src/installer.ts index 2001f4d79..47d24c930 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -42,14 +42,10 @@ export async function getNode( if (isLtsAlias(versionSpec)) { core.info('Attempt to resolve LTS alias from manifest...'); - core.debug('Getting manifest from actions/node-versions@main'); + // No try-catch since it's not possible to resolve LTS alias without manifest - manifest = await tc.getManifestFromRepo( - 'actions', - 'node-versions', - auth, - 'main' - ); + manifest = await getManifest(auth); + versionSpec = resolveLtsAliasFromManifest(versionSpec, stable, manifest); } @@ -200,6 +196,11 @@ 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'); +} + function resolveLtsAliasFromManifest( versionSpec: string, stable: boolean, @@ -245,16 +246,8 @@ async function getInfoFromManifest( ): Promise { let info: INodeVersionInfo | null = null; if (!manifest) { - core.debug( - 'No manifest cached, getting manifest from actions/node-versions@main' - ); - - manifest = await tc.getManifestFromRepo( - 'actions', - 'node-versions', - auth, - 'main' - ); + core.debug('No manifest cached'); + manifest = await getManifest(auth); } const rel = await tc.findFromManifest(versionSpec, stable, manifest, osArch); From 9b447f0b81b0095ab8349f9ea321f6d07b174b0b Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Fri, 25 Jun 2021 11:48:41 +0200 Subject: [PATCH 20/24] Fix paths for windows tests --- __tests__/installer.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index a6907c4cd..0376761e3 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -580,7 +580,7 @@ describe('setup-node', () => { ); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); expect(cnSpy).toHaveBeenCalledWith( - `::add-path::${toolPath}/bin${osm.EOL}` + `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` ); }); @@ -624,7 +624,7 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith('Extracting ...'); expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); expect(cnSpy).toHaveBeenCalledWith( - `::add-path::${toolPath}/bin${osm.EOL}` + `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` ); }); @@ -658,7 +658,7 @@ describe('setup-node', () => { ); expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); expect(cnSpy).toHaveBeenCalledWith( - `::add-path::${toolPath}/bin${osm.EOL}` + `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` ); }); @@ -702,7 +702,7 @@ describe('setup-node', () => { expect(logSpy).toHaveBeenCalledWith('Extracting ...'); expect(logSpy).toHaveBeenCalledWith('Adding to the cache ...'); expect(cnSpy).toHaveBeenCalledWith( - `::add-path::${toolPath}/bin${osm.EOL}` + `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` ); }); From 4bef829942f19576d693e96c710bcfdc93352956 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Fri, 25 Jun 2021 11:56:15 +0200 Subject: [PATCH 21/24] Add e2e test for lts-syntax --- .github/workflows/versions.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index 2058b0223..6ea1e404f 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -29,6 +29,23 @@ jobs: run: __tests__/verify-node.sh "${{ matrix.node-version }}" shell: bash + lts-syntax: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + node-version: [lts/dubnium, lts/erbium, lts/fermium, lts/*] + steps: + - uses: actions/checkout@v2 + - name: Setup Node + uses: ./ + with: + node-version: ${{ matrix.node-version }} + - name: Verify node and npm + run: __tests__/verify-node.sh "${{ matrix.node-version }}" + shell: bash + manifest: runs-on: ${{ matrix.os }} strategy: From 57b9c8c424ced4e02e087acbad689bd982229567 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Fri, 25 Jun 2021 12:13:33 +0200 Subject: [PATCH 22/24] Don't run verify check on lts syntax --- .github/workflows/versions.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/versions.yml b/.github/workflows/versions.yml index 6ea1e404f..4dc5c312f 100644 --- a/.github/workflows/versions.yml +++ b/.github/workflows/versions.yml @@ -42,9 +42,6 @@ jobs: uses: ./ with: node-version: ${{ matrix.node-version }} - - name: Verify node and npm - run: __tests__/verify-node.sh "${{ matrix.node-version }}" - shell: bash manifest: runs-on: ${{ matrix.os }} From 8624ddbdce6443553a7b456fd5f0b66ae19ee70f Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Wed, 30 Jun 2021 09:27:49 +0200 Subject: [PATCH 23/24] Extract common setup logic to hook --- __tests__/installer.test.ts | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 0376761e3..59fc97982 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -550,13 +550,15 @@ describe('setup-node', () => { }); describe('LTS version', () => { - it('find latest LTS version and resolve it from local cache (lts/erbium)', async () => { - // arrange + beforeEach(() => { os.platform = 'linux'; os.arch = 'x64'; + inputs.stable = 'true'; + }); + it('find latest LTS version and resolve it from local cache (lts/erbium)', async () => { + // arrange inputs['node-version'] = 'lts/erbium'; - inputs.stable = 'true'; const toolPath = path.normalize('/cache/node/12.16.2/x64'); findSpy.mockReturnValue(toolPath); @@ -586,11 +588,7 @@ describe('setup-node', () => { it('find latest LTS version and install it from manifest (lts/erbium)', async () => { // arrange - os.platform = 'linux'; - os.arch = 'x64'; - inputs['node-version'] = 'lts/erbium'; - inputs.stable = 'true'; const toolPath = path.normalize('/cache/node/12.16.2/x64'); findSpy.mockImplementation(() => ''); @@ -630,11 +628,7 @@ describe('setup-node', () => { it('find latest LTS version and resolve it from local cache (lts/*)', async () => { // arrange - os.platform = 'linux'; - os.arch = 'x64'; - inputs['node-version'] = 'lts/*'; - inputs.stable = 'true'; const toolPath = path.normalize('/cache/node/14.0.0/x64'); findSpy.mockReturnValue(toolPath); @@ -664,11 +658,7 @@ describe('setup-node', () => { it('find latest LTS version and install it from manifest (lts/*)', async () => { // arrange - os.platform = 'linux'; - os.arch = 'x64'; - inputs['node-version'] = 'lts/*'; - inputs.stable = 'true'; const toolPath = path.normalize('/cache/node/14.0.0/x64'); findSpy.mockImplementation(() => ''); @@ -708,11 +698,7 @@ describe('setup-node', () => { it('fail with unexpected LTS alias (lts/)', async () => { // arrange - os.platform = 'linux'; - os.arch = 'x64'; - inputs['node-version'] = 'lts/'; - inputs.stable = 'true'; findSpy.mockImplementation(() => ''); @@ -733,11 +719,7 @@ describe('setup-node', () => { it('fail to find LTS version (lts/unknown)', async () => { // arrange - os.platform = 'linux'; - os.arch = 'x64'; - inputs['node-version'] = 'lts/unknown'; - inputs.stable = 'true'; findSpy.mockImplementation(() => ''); @@ -761,11 +743,7 @@ describe('setup-node', () => { it('fail if manifest is not available', async () => { // arrange - os.platform = 'linux'; - os.arch = 'x64'; - inputs['node-version'] = 'lts/erbium'; - inputs.stable = 'true'; // ... but not in the local cache findSpy.mockImplementation(() => ''); From 48042628a6db42682e77501e473361c6da26bbb0 Mon Sep 17 00:00:00 2001 From: Gordey Doronin Date: Wed, 30 Jun 2021 09:34:42 +0200 Subject: [PATCH 24/24] Stricter check and cleaner messaging --- __tests__/installer.test.ts | 4 ++-- dist/index.js | 4 ++-- src/installer.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 59fc97982..994892365 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -696,7 +696,7 @@ describe('setup-node', () => { ); }); - it('fail with unexpected LTS alias (lts/)', async () => { + it('fail with unable to parse LTS alias (lts/)', async () => { // arrange inputs['node-version'] = 'lts/'; @@ -713,7 +713,7 @@ describe('setup-node', () => { 'Getting manifest from actions/node-versions@main' ); expect(cnSpy).toHaveBeenCalledWith( - `::error::Unexpected LTS alias '' for Node version 'lts/'${osm.EOL}` + `::error::Unable to parse LTS alias for Node version 'lts/'${osm.EOL}` ); }); diff --git a/dist/index.js b/dist/index.js index 170f8279c..1c614cd83 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13225,7 +13225,7 @@ function getNode(versionSpec, stable, checkLatest, auth, arch = os.arch()) { } exports.getNode = getNode; function isLtsAlias(versionSpec) { - return versionSpec.startsWith('lts'); + return versionSpec.startsWith('lts/'); } function getManifest(auth) { core.debug('Getting manifest from actions/node-versions@main'); @@ -13235,7 +13235,7 @@ 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(`Unexpected LTS alias '${alias}' for Node version '${versionSpec}'`); + 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/` and `lts/*`. Where asterisk means highest possible LTS. diff --git a/src/installer.ts b/src/installer.ts index 47d24c930..b43e5448c 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -193,7 +193,7 @@ export async function getNode( } function isLtsAlias(versionSpec: string): boolean { - return versionSpec.startsWith('lts'); + return versionSpec.startsWith('lts/'); } function getManifest(auth: string | undefined): Promise { @@ -210,7 +210,7 @@ function resolveLtsAliasFromManifest( if (!alias) { throw new Error( - `Unexpected LTS alias '${alias}' for Node version '${versionSpec}'` + `Unable to parse LTS alias for Node version '${versionSpec}'` ); }