From 2936fe8cda9cf52952329ff4ac173c5d916a0ac1 Mon Sep 17 00:00:00 2001 From: "Jacob Parish (JP250552)" <75643994+JP250552@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:02:28 -0600 Subject: [PATCH 01/12] Added option to enable corepack (#1) Co-authored-by: Steven Co-authored-by: Sayak Mukhopadhyay Co-authored-by: Jacob Parish --- README.md | 23 ++++++++++---------- __tests__/official-installer.test.ts | 32 ++++++++++++++++++++++++++++ action.yml | 5 ++++- dist/cache-save/index.js | 17 ++++++++++++++- dist/setup/index.js | 19 ++++++++++++++++- docs/advanced-usage.md | 29 +++++++++++++++++++++++++ src/main.ts | 9 +++++++- src/util.ts | 13 +++++++++++ 8 files changed, 132 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 20d23405..613100fe 100644 --- a/README.md +++ b/README.md @@ -26,22 +26,22 @@ See [action.yml](action.yml) node-version: '' # File containing the version Spec of the version to use. Examples: .nvmrc, .node-version, .tool-versions. - # If node-version and node-version-file are both provided the action will use version from node-version. + # If node-version and node-version-file are both provided the action will use version from node-version. node-version-file: '' - # Set this option if you want the action to check for the latest available version + # Set this option if you want the action to check for the latest available version # that satisfies the version spec. - # It will only get affect for lts Nodejs versions (12.x, >=10.15.0, lts/Hydrogen). + # It will only get affect for lts Nodejs versions (12.x, >=10.15.0, lts/Hydrogen). # Default: false check-latest: false # Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default. - # Default: ''. The action use system architecture by default + # Default: ''. The action use system architecture by default architecture: '' - # Used to pull node distributions from https://github.com/actions/node-versions. - # Since there's a default, this is typically not supplied by the user. - # When running this action on github.com, the default value is sufficient. + # Used to pull node distributions from https://github.com/actions/node-versions. + # Since there's a default, this is typically not supplied by the user. + # When running this action on github.com, the default value is sufficient. # When running on GHES, you can pass a personal access token for github.com if you are experiencing rate limiting. # # We recommend using a service account with the least permissions necessary. Also @@ -57,18 +57,18 @@ See [action.yml](action.yml) # Default: '' cache: '' - # Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. - # It will generate hash from the target file for primary key. It works only If cache is specified. + # Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. + # It will generate hash from the target file for primary key. It works only If cache is specified. # Supports wildcards or a list of file names for caching multiple dependencies. # Default: '' cache-dependency-path: '' - # Optional registry to set up for auth. Will set the registry in a project level .npmrc and .yarnrc file, + # Optional registry to set up for auth. Will set the registry in a project level .npmrc and .yarnrc file, # and set up auth to read in from env.NODE_AUTH_TOKEN. # Default: '' registry-url: '' - # Optional scope for authenticating against scoped registries. + # Optional scope for authenticating against scoped registries. # Will fall back to the repository owner when using the GitHub Packages registry (https://npm.pkg.github.com/). # Default: '' scope: '' @@ -203,6 +203,7 @@ If the runner is not able to access github.com, any Nodejs versions requested du - [Publishing to npmjs and GPR with npm](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-npm) - [Publishing to npmjs and GPR with yarn](docs/advanced-usage.md#publish-to-npmjs-and-gpr-with-yarn) - [Using private packages](docs/advanced-usage.md#use-private-packages) + - [Enabling Corepack](docs/advanced-usage.md#enabling-corepack) ## License diff --git a/__tests__/official-installer.test.ts b/__tests__/official-installer.test.ts index 2d36c19c..778b5196 100644 --- a/__tests__/official-installer.test.ts +++ b/__tests__/official-installer.test.ts @@ -825,4 +825,36 @@ describe('setup-node', () => { } ); }); + + describe('corepack flag', () => { + it('use corepack if specified', async () => { + inputs['corepack'] = 'true'; + await main.run(); + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'corepack', + ['enable'], + expect.anything() + ); + }); + + it('use corepack with given package manager', async () => { + inputs['corepack'] = 'npm'; + await main.run(); + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'corepack', + ['enable', 'npm'], + expect.anything() + ); + }); + + it('use corepack with multiple package managers', async () => { + inputs['corepack'] = 'npm yarn'; + await main.run(); + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'corepack', + ['enable', 'npm', 'yarn'], + expect.anything() + ); + }); + }); }); diff --git a/action.yml b/action.yml index 40af8838..689afa35 100644 --- a/action.yml +++ b/action.yml @@ -25,10 +25,13 @@ inputs: description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.' cache-dependency-path: description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.' + corepack: + description: 'Used to specify whether to enable Corepack. Set to true to enable all package managers or set it to one or more package manager names separated by a space. Supported package manager names: npm, yarn, pnpm.' + default: 'false' # TODO: add input to control forcing to pull from cloud or dist. # escape valve for someone having issues or needing the absolute latest which isn't cached yet outputs: - cache-hit: + cache-hit: description: 'A boolean value to indicate if a cache was hit.' node-version: description: 'The installed node version.' diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index 0b7060e5..05f3e582 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -83321,7 +83321,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.unique = exports.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0; +exports.enableCorepack = exports.unique = exports.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0; const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); function parseNodeVersionFile(contents) { @@ -83393,6 +83393,21 @@ const unique = () => { }; }; exports.unique = unique; +function enableCorepack(input) { + return __awaiter(this, void 0, void 0, function* () { + const corepackArgs = ['enable']; + if (input.length > 0 && input !== 'false') { + if (input !== 'true') { + const packageManagers = input.split(' '); + corepackArgs.push(...packageManagers); + } + yield exec.getExecOutput('corepack', corepackArgs, { + ignoreReturnCode: true + }); + } + }); +} +exports.enableCorepack = enableCorepack; /***/ }), diff --git a/dist/setup/index.js b/dist/setup/index.js index 0512f3a7..4c58b1d7 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -93698,6 +93698,8 @@ function run() { if (registryUrl) { auth.configAuthentication(registryUrl, alwaysAuth); } + const corepack = core.getInput('corepack') || 'false'; + yield (0, util_1.enableCorepack)(corepack); if (cache && (0, cache_utils_1.isCacheFeatureAvailable)()) { core.saveState(constants_1.State.CachePackageManager, cache); const cacheDependencyPath = core.getInput('cache-dependency-path'); @@ -93775,7 +93777,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.unique = exports.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0; +exports.enableCorepack = exports.unique = exports.printEnvDetailsAndSetOutput = exports.parseNodeVersionFile = void 0; const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); function parseNodeVersionFile(contents) { @@ -93847,6 +93849,21 @@ const unique = () => { }; }; exports.unique = unique; +function enableCorepack(input) { + return __awaiter(this, void 0, void 0, function* () { + const corepackArgs = ['enable']; + if (input.length > 0 && input !== 'false') { + if (input !== 'true') { + const packageManagers = input.split(' '); + corepackArgs.push(...packageManagers); + } + yield exec.getExecOutput('corepack', corepackArgs, { + ignoreReturnCode: true + }); + } + }); +} +exports.enableCorepack = enableCorepack; /***/ }), diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 079b8bfa..0d1ddf4e 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -416,3 +416,32 @@ Please refer to the [Ensuring workflow access to your package - Configuring a pa ### always-auth input The always-auth input sets `always-auth=true` in .npmrc file. With this option set [npm](https://docs.npmjs.com/cli/v6/using-npm/config#always-auth)/yarn sends the authentication credentials when making a request to the registries. + +## Enabling Corepack +You can enable [Corepack](https://github.com/nodejs/corepack) by using the `corepack` input. You can then use `pnpm` and `yarn` commands in your project. + +```yaml +steps: +- uses: actions/checkout@v3 +- uses: actions/setup-node@v3 + with: + node-version: '16.x' + corepack: true +- name: Install dependencies + run: yarn install --immutable +``` + +You can also pass package manager names separated by a space to enable corepack for specific package managers only. + +```yaml +steps: +- uses: actions/checkout@v3 +- uses: actions/setup-node@v3 + with: + node-version: '16.x' + corepack: yarn pnpm +- name: Install dependencies + run: yarn install --immutable +``` + +This option by default is `false` as Corepack is still in experimental phase. diff --git a/src/main.ts b/src/main.ts index ac051766..082815a7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,7 +8,11 @@ import * as path from 'path'; import {restoreCache} from './cache-restore'; import {isCacheFeatureAvailable} from './cache-utils'; import {getNodejsDistribution} from './distributions/installer-factory'; -import {parseNodeVersionFile, printEnvDetailsAndSetOutput} from './util'; +import { + parseNodeVersionFile, + printEnvDetailsAndSetOutput, + enableCorepack +} from './util'; import {State} from './constants'; export async function run() { @@ -60,6 +64,9 @@ export async function run() { auth.configAuthentication(registryUrl, alwaysAuth); } + const corepack = core.getInput('corepack') || 'false'; + await enableCorepack(corepack); + if (cache && isCacheFeatureAvailable()) { core.saveState(State.CachePackageManager, cache); const cacheDependencyPath = core.getInput('cache-dependency-path'); diff --git a/src/util.ts b/src/util.ts index 3ae94a2d..d0b417ad 100644 --- a/src/util.ts +++ b/src/util.ts @@ -70,3 +70,16 @@ export const unique = () => { return true; }; }; + +export async function enableCorepack(input: string): Promise { + const corepackArgs = ['enable']; + if (input.length > 0 && input !== 'false') { + if (input !== 'true') { + const packageManagers = input.split(' '); + corepackArgs.push(...packageManagers); + } + await exec.getExecOutput('corepack', corepackArgs, { + ignoreReturnCode: true + }); + } +} From 7c0fdd03f544655a07e8bf1ab1f0873d1306a784 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 21 Nov 2023 13:31:24 -0600 Subject: [PATCH 02/12] test: updated tests --- __tests__/main.test.ts | 52 ++++++++++++++++++++++++++++ __tests__/official-installer.test.ts | 32 ----------------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index b5724875..e7d92a51 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -300,4 +300,56 @@ describe('main tests', () => { ); }); }); + + describe('corepack flag', () => { + it('should not enable corepack when no input', async () => { + inputs['corepack'] = ''; + await main.run(); + expect(getExecOutputSpy).not.toHaveBeenCalledWith( + 'corepack', + expect.anything(), + expect.anything() + ); + }); + + it('should not enable corepack when input is "false"', async () => { + inputs['corepack'] = 'false'; + await main.run(); + expect(getExecOutputSpy).not.toHaveBeenCalledWith( + 'corepack', + expect.anything(), + expect.anything() + ); + }); + + it('should enable corepack when input is "true"', async () => { + inputs['corepack'] = 'true'; + await main.run(); + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'corepack', + ['enable'], + expect.anything() + ); + }); + + it('should enable corepack with a single package manager', async () => { + inputs['corepack'] = 'npm'; + await main.run(); + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'corepack', + ['enable', 'npm'], + expect.anything() + ); + }); + + it('should enable corepack with multiple package managers', async () => { + inputs['corepack'] = 'npm yarn'; + await main.run(); + expect(getExecOutputSpy).toHaveBeenCalledWith( + 'corepack', + ['enable', 'npm', 'yarn'], + expect.anything() + ); + }); + }); }); diff --git a/__tests__/official-installer.test.ts b/__tests__/official-installer.test.ts index 778b5196..2d36c19c 100644 --- a/__tests__/official-installer.test.ts +++ b/__tests__/official-installer.test.ts @@ -825,36 +825,4 @@ describe('setup-node', () => { } ); }); - - describe('corepack flag', () => { - it('use corepack if specified', async () => { - inputs['corepack'] = 'true'; - await main.run(); - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'corepack', - ['enable'], - expect.anything() - ); - }); - - it('use corepack with given package manager', async () => { - inputs['corepack'] = 'npm'; - await main.run(); - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'corepack', - ['enable', 'npm'], - expect.anything() - ); - }); - - it('use corepack with multiple package managers', async () => { - inputs['corepack'] = 'npm yarn'; - await main.run(); - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'corepack', - ['enable', 'npm', 'yarn'], - expect.anything() - ); - }); - }); }); From f9532b258e7ddfc36a3f549c77f42ea4ddc4db64 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 21 Nov 2023 13:46:39 -0600 Subject: [PATCH 03/12] docs: node version --- docs/advanced-usage.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 0d1ddf4e..057434c7 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -157,7 +157,7 @@ jobs: ## Nightly versions -You can specify a nightly version to download it from https://nodejs.org/download/nightly. +You can specify a nightly version to download it from https://nodejs.org/download/nightly. ### Install the nightly build for a major version @@ -265,7 +265,7 @@ steps: - run: pnpm test ``` -> **Note**: By default `--frozen-lockfile` option is passed starting from pnpm `6.10.x`. It will be automatically added if you run it on [CI](https://pnpm.io/cli/install#--frozen-lockfile). +> **Note**: By default `--frozen-lockfile` option is passed starting from pnpm `6.10.x`. It will be automatically added if you run it on [CI](https://pnpm.io/cli/install#--frozen-lockfile). > If the `pnpm-lock.yaml` file changes then pass `--frozen-lockfile` option. @@ -425,7 +425,7 @@ steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: '16.x' + node-version: '18.x' corepack: true - name: Install dependencies run: yarn install --immutable @@ -438,7 +438,7 @@ steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: '16.x' + node-version: '18.x' corepack: yarn pnpm - name: Install dependencies run: yarn install --immutable From 28c91a3bbc8c3f744ebc5b02f54ca99d68047620 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 21 Nov 2023 13:47:29 -0600 Subject: [PATCH 04/12] docs: actions versions --- docs/advanced-usage.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 057434c7..0b2e82ae 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -422,8 +422,8 @@ You can enable [Corepack](https://github.com/nodejs/corepack) by using the `core ```yaml steps: -- uses: actions/checkout@v3 -- uses: actions/setup-node@v3 +- uses: actions/checkout@v4 +- uses: actions/setup-node@v4 with: node-version: '18.x' corepack: true @@ -435,8 +435,8 @@ You can also pass package manager names separated by a space to enable corepack ```yaml steps: -- uses: actions/checkout@v3 -- uses: actions/setup-node@v3 +- uses: actions/checkout@v4 +- uses: actions/setup-node@v4 with: node-version: '18.x' corepack: yarn pnpm From d8a8b93089a020a119d54ba91b6fa4553389aba4 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 21 Nov 2023 13:49:41 -0600 Subject: [PATCH 05/12] docs: remove reference to experimental --- docs/advanced-usage.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index 0b2e82ae..7739c08c 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -443,5 +443,3 @@ steps: - name: Install dependencies run: yarn install --immutable ``` - -This option by default is `false` as Corepack is still in experimental phase. From c73bf9098a639e60a138e5caf34368347ba22106 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 6 Feb 2024 09:27:54 -0600 Subject: [PATCH 06/12] fix: pr review adjustments --- __tests__/main.test.ts | 33 +++++++++------------------------ dist/cache-save/index.js | 9 ++++----- dist/setup/index.js | 9 ++++----- src/util.ts | 9 ++++----- 4 files changed, 21 insertions(+), 39 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 41310ab0..97883cff 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -11,6 +11,7 @@ import each from 'jest-each'; import * as main from '../src/main'; import * as util from '../src/util'; +import * as cacheUtil from '../src/cache-utils'; import OfficialBuilds from '../src/distributions/official_builds/official_builds'; describe('main tests', () => { @@ -25,6 +26,7 @@ describe('main tests', () => { let endGroupSpy: jest.SpyInstance; let getExecOutputSpy: jest.SpyInstance; + let getCommandOutputSpy: jest.SpyInstance; let getNodeVersionFromFileSpy: jest.SpyInstance; let cnSpy: jest.SpyInstance; @@ -56,6 +58,7 @@ describe('main tests', () => { inSpy.mockImplementation(name => inputs[name]); getExecOutputSpy = jest.spyOn(exec, 'getExecOutput'); + getCommandOutputSpy = jest.spyOn(cacheUtil, 'getCommandOutput'); findSpy = jest.spyOn(tc, 'find'); @@ -274,50 +277,32 @@ describe('main tests', () => { it('should not enable corepack when no input', async () => { inputs['corepack'] = ''; await main.run(); - expect(getExecOutputSpy).not.toHaveBeenCalledWith( - 'corepack', - expect.anything(), - expect.anything() - ); + expect(getCommandOutputSpy).not.toHaveBeenCalledWith('corepack'); }); it('should not enable corepack when input is "false"', async () => { inputs['corepack'] = 'false'; await main.run(); - expect(getExecOutputSpy).not.toHaveBeenCalledWith( - 'corepack', - expect.anything(), - expect.anything() - ); + expect(getCommandOutputSpy).not.toHaveBeenCalledWith('corepack'); }); it('should enable corepack when input is "true"', async () => { inputs['corepack'] = 'true'; await main.run(); - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'corepack', - ['enable'], - expect.anything() - ); + expect(getCommandOutputSpy).toHaveBeenCalledWith('corepack enable'); }); it('should enable corepack with a single package manager', async () => { inputs['corepack'] = 'npm'; await main.run(); - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'corepack', - ['enable', 'npm'], - expect.anything() - ); + expect(getCommandOutputSpy).toHaveBeenCalledWith('corepack enable npm'); }); it('should enable corepack with multiple package managers', async () => { inputs['corepack'] = 'npm yarn'; await main.run(); - expect(getExecOutputSpy).toHaveBeenCalledWith( - 'corepack', - ['enable', 'npm', 'yarn'], - expect.anything() + expect(getCommandOutputSpy).toHaveBeenCalledWith( + 'corepack enable npm yarn' ); }); }); diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index dda290fb..00385962 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -83338,6 +83338,7 @@ const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); const fs_1 = __importDefault(__nccwpck_require__(7147)); const path_1 = __importDefault(__nccwpck_require__(1017)); +const cache_utils_1 = __nccwpck_require__(1678); function getNodeVersionFromFile(versionFilePath) { var _a, _b, _c, _d, _e; if (!fs_1.default.existsSync(versionFilePath)) { @@ -83431,15 +83432,13 @@ const unique = () => { exports.unique = unique; function enableCorepack(input) { return __awaiter(this, void 0, void 0, function* () { - const corepackArgs = ['enable']; - if (input.length > 0 && input !== 'false') { + if (input.length && input !== 'false') { + const corepackArgs = ['enable']; if (input !== 'true') { const packageManagers = input.split(' '); corepackArgs.push(...packageManagers); } - yield exec.getExecOutput('corepack', corepackArgs, { - ignoreReturnCode: true - }); + yield (0, cache_utils_1.getCommandOutput)(`corepack ${corepackArgs.join(' ')}`); } }); } diff --git a/dist/setup/index.js b/dist/setup/index.js index 31947aba..ccc9d2aa 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -93787,6 +93787,7 @@ const core = __importStar(__nccwpck_require__(2186)); const exec = __importStar(__nccwpck_require__(1514)); const fs_1 = __importDefault(__nccwpck_require__(7147)); const path_1 = __importDefault(__nccwpck_require__(1017)); +const cache_utils_1 = __nccwpck_require__(1678); function getNodeVersionFromFile(versionFilePath) { var _a, _b, _c, _d, _e; if (!fs_1.default.existsSync(versionFilePath)) { @@ -93880,15 +93881,13 @@ const unique = () => { exports.unique = unique; function enableCorepack(input) { return __awaiter(this, void 0, void 0, function* () { - const corepackArgs = ['enable']; - if (input.length > 0 && input !== 'false') { + if (input.length && input !== 'false') { + const corepackArgs = ['enable']; if (input !== 'true') { const packageManagers = input.split(' '); corepackArgs.push(...packageManagers); } - yield exec.getExecOutput('corepack', corepackArgs, { - ignoreReturnCode: true - }); + yield (0, cache_utils_1.getCommandOutput)(`corepack ${corepackArgs.join(' ')}`); } }); } diff --git a/src/util.ts b/src/util.ts index acfab3f6..00872a10 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,6 +3,7 @@ import * as exec from '@actions/exec'; import fs from 'fs'; import path from 'path'; +import {getCommandOutput} from './cache-utils'; export function getNodeVersionFromFile(versionFilePath: string): string | null { if (!fs.existsSync(versionFilePath)) { @@ -107,14 +108,12 @@ export const unique = () => { }; export async function enableCorepack(input: string): Promise { - const corepackArgs = ['enable']; - if (input.length > 0 && input !== 'false') { + if (input.length && input !== 'false') { + const corepackArgs = ['enable']; if (input !== 'true') { const packageManagers = input.split(' '); corepackArgs.push(...packageManagers); } - await exec.getExecOutput('corepack', corepackArgs, { - ignoreReturnCode: true - }); + await getCommandOutput(`corepack ${corepackArgs.join(' ')}`); } } From 0c618ceb2e48275dc06e86901822fd966ce75ba2 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 6 Feb 2024 09:46:03 -0600 Subject: [PATCH 07/12] test: added e2e test, improved unit test --- .github/workflows/e2e-cache.yml | 38 +++++++++++++++++++++++++++++++++ __tests__/main.test.ts | 4 ++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/.github/workflows/e2e-cache.yml b/.github/workflows/e2e-cache.yml index a0f20639..424dcaf4 100644 --- a/.github/workflows/e2e-cache.yml +++ b/.github/workflows/e2e-cache.yml @@ -135,6 +135,44 @@ jobs: run: __tests__/verify-node.sh "${{ matrix.node-version }}" shell: bash + node-yarn4-corepack-dependencies-caching: + name: Test yarn 4 (Node ${{ matrix.node-version}}, ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + env: + YARN_ENABLE_IMMUTABLE_INSTALLS: false + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + node-version: [18, 20] + steps: + - uses: actions/checkout@v4 + - name: Update yarn + run: yarn set version 4.1.0 + - name: Yarn version + run: yarn --version + - name: Generate simple .yarnrc.yml + run: | + echo "nodeLinker: node-modules" >> .yarnrc.yml + - name: Generate yarn file + run: yarn install + - name: Remove dependencies + shell: pwsh + run: Remove-Item node_modules -Force -Recurse + - name: Clean global cache + run: yarn cache clean --all + - name: Setup Node + uses: ./ + with: + node-version: ${{ matrix.node-version }} + cache: 'yarn' + corepack: true + - name: Install dependencies + run: yarn install + - name: Verify node and yarn + run: __tests__/verify-node.sh "${{ matrix.node-version }}" + shell: bash + yarn-subprojects: name: Test yarn subprojects strategy: diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 97883cff..da025ce3 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -277,13 +277,13 @@ describe('main tests', () => { it('should not enable corepack when no input', async () => { inputs['corepack'] = ''; await main.run(); - expect(getCommandOutputSpy).not.toHaveBeenCalledWith('corepack'); + expect(getCommandOutputSpy).not.toHaveBeenCalledWith(expect.stringContaining('corepack')); }); it('should not enable corepack when input is "false"', async () => { inputs['corepack'] = 'false'; await main.run(); - expect(getCommandOutputSpy).not.toHaveBeenCalledWith('corepack'); + expect(getCommandOutputSpy).not.toHaveBeenCalledWith(expect.stringContaining('corepack')); }); it('should enable corepack when input is "true"', async () => { From 4c2fa5a76f57e2c029c999a12be8a08e05df96e0 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 25 Mar 2025 09:53:39 -0500 Subject: [PATCH 08/12] feat: install corepack before enabling --- __tests__/main.test.ts | 11 +++++-- dist/cache-save/index.js | 62 +++++++++++++++++++++------------------- dist/setup/index.js | 58 +++++++++++++++++++------------------ src/util.ts | 1 + 4 files changed, 72 insertions(+), 60 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 9aed769c..076870eb 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -288,30 +288,37 @@ describe('main tests', () => { it('should not enable corepack when no input', async () => { inputs['corepack'] = ''; await main.run(); - expect(getCommandOutputSpy).not.toHaveBeenCalledWith(expect.stringContaining('corepack')); + expect(getCommandOutputSpy).not.toHaveBeenCalledWith( + expect.stringContaining('corepack') + ); }); it('should not enable corepack when input is "false"', async () => { inputs['corepack'] = 'false'; await main.run(); - expect(getCommandOutputSpy).not.toHaveBeenCalledWith(expect.stringContaining('corepack')); + expect(getCommandOutputSpy).not.toHaveBeenCalledWith( + expect.stringContaining('corepack') + ); }); it('should enable corepack when input is "true"', async () => { inputs['corepack'] = 'true'; await main.run(); + expect(getCommandOutputSpy).toHaveBeenCalledWith('npm i -g corepack'); expect(getCommandOutputSpy).toHaveBeenCalledWith('corepack enable'); }); it('should enable corepack with a single package manager', async () => { inputs['corepack'] = 'npm'; await main.run(); + expect(getCommandOutputSpy).toHaveBeenCalledWith('npm i -g corepack'); expect(getCommandOutputSpy).toHaveBeenCalledWith('corepack enable npm'); }); it('should enable corepack with multiple package managers', async () => { inputs['corepack'] = 'npm yarn'; await main.run(); + expect(getCommandOutputSpy).toHaveBeenCalledWith('npm i -g corepack'); expect(getCommandOutputSpy).toHaveBeenCalledWith( 'corepack enable npm yarn' ); diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index b45cd2b8..9f982d98 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -2151,7 +2151,7 @@ function retry(name, method, getStatusCode, maxAttempts = constants_1.DefaultRet exports.retry = retry; function retryTypedResponse(name, method, maxAttempts = constants_1.DefaultRetryAttempts, delay = constants_1.DefaultRetryDelay) { return __awaiter(this, void 0, void 0, function* () { - return yield retry(name, method, (response) => response.statusCode, maxAttempts, delay, + return yield retry(name, method, (response) => response.statusCode, maxAttempts, delay, // If the error object contains the statusCode property, extract it and return // an TypedResponse so it can be processed by the retry logic. (error) => { @@ -6305,8 +6305,8 @@ class OidcClient { const res = yield httpclient .getJson(id_token_url) .catch(error => { - throw new Error(`Failed to get ID Token. \n - Error Code : ${error.statusCode}\n + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n Error Message: ${error.message}`); }); const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; @@ -11102,7 +11102,7 @@ class Serializer { /** * The provided model mapper. */ - modelMappers = {}, + modelMappers = {}, /** * Whether the contents are XML or not. */ @@ -13218,7 +13218,7 @@ class NodeFetchHttpClient { body = uploadReportStream; } const platformSpecificRequestInit = await this.prepareRequest(httpRequest); - const requestInit = Object.assign({ body: body, headers: httpRequest.headers.rawHeaders(), method: httpRequest.method, + const requestInit = Object.assign({ body: body, headers: httpRequest.headers.rawHeaders(), method: httpRequest.method, // the types for RequestInit are from the browser, which expects AbortSignal to // have `reason` and `throwIfAborted`, but these don't exist on our polyfill // for Node. @@ -13417,7 +13417,7 @@ class BaseRequestPolicy { /** * The next policy in the pipeline. Each policy is responsible for executing the next one if the request is to continue through the pipeline. */ - _nextPolicy, + _nextPolicy, /** * The options that can be passed to a given request policy. */ @@ -14395,7 +14395,7 @@ function createTokenCycler(credential, scopes, tokenCyclerOptions) { const tryGetAccessToken = () => credential.getToken(scopes, getTokenOptions); // Take advantage of promise chaining to insert an assignment to `token` // before the refresh can be considered done. - refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, + refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, // If we don't have a token, then we should timeout immediately (_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : Date.now()) .then((_token) => { @@ -15202,7 +15202,7 @@ class ServiceClient { * @param credentials - The credentials used for authentication with the service. * @param options - The service client options that govern the behavior of the client. */ - constructor(credentials, + constructor(credentials, /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options */ options) { if (!options) { @@ -34182,7 +34182,7 @@ function createTokenCycler(credential, scopes, tokenCyclerOptions) { const tryGetAccessToken = () => credential.getToken(scopes, getTokenOptions); // Take advantage of promise chaining to insert an assignment to `token` // before the refresh can be considered done. - refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, + refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, // If we don't have a token, then we should timeout immediately (_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : Date.now()) .then((_token) => { @@ -38602,7 +38602,7 @@ const fsCreateReadStream = fs__namespace.createReadStream; * append blob, or page blob. */ class BlobClient extends StorageClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -39650,7 +39650,7 @@ class BlobClient extends StorageClient { * AppendBlobClient defines a set of operations applicable to append blobs. */ class AppendBlobClient extends BlobClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -39906,7 +39906,7 @@ class AppendBlobClient extends BlobClient { * BlockBlobClient defines a set of operations applicable to block blobs. */ class BlockBlobClient extends BlobClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -40535,7 +40535,7 @@ class BlockBlobClient extends BlobClient { if (options.onProgress) { options.onProgress({ loadedBytes: transferProgress }); } - }, + }, // concurrency should set a smaller value than maxConcurrency, which is helpful to // reduce the possibility when a outgoing handler waits for stream data, in // this situation, outgoing handlers are blocked. @@ -40560,7 +40560,7 @@ class BlockBlobClient extends BlobClient { * PageBlobClient defines a set of operations applicable to page blobs. */ class PageBlobClient extends BlobClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -41818,7 +41818,7 @@ class BatchHeaderFilterPolicyFactory { * @see https://docs.microsoft.com/en-us/rest/api/storageservices/blob-batch */ class BlobBatchClient { - constructor(url, credentialOrPipeline, + constructor(url, credentialOrPipeline, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -41850,7 +41850,7 @@ class BlobBatchClient { createBatch() { return new BlobBatch(); } - async deleteBlobs(urlsOrBlobClients, credentialOrOptions, + async deleteBlobs(urlsOrBlobClients, credentialOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -41865,7 +41865,7 @@ class BlobBatchClient { } return this.submitBatch(batch); } - async setBlobsAccessTier(urlsOrBlobClients, credentialOrTier, tierOrOptions, + async setBlobsAccessTier(urlsOrBlobClients, credentialOrTier, tierOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -41957,7 +41957,7 @@ class BlobBatchClient { * A ContainerClient represents a URL to the Azure Storage container allowing you to manipulate its blobs. */ class ContainerClient extends StorageClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -43669,7 +43669,7 @@ function generateAccountSASQueryParameters(accountSASSignatureValues, sharedKeyC * to manipulate blob containers. */ class BlobServiceClient extends StorageClient { - constructor(url, credentialOrPipeline, + constructor(url, credentialOrPipeline, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -43701,7 +43701,7 @@ class BlobServiceClient extends StorageClient { * `BlobEndpoint=https://myaccount.blob.core.windows.net/;QueueEndpoint=https://myaccount.queue.core.windows.net/;FileEndpoint=https://myaccount.file.core.windows.net/;TableEndpoint=https://myaccount.table.core.windows.net/;SharedAccessSignature=sasString` * @param options - Optional. Options to configure the HTTP pipeline. */ - static fromConnectionString(connectionString, + static fromConnectionString(connectionString, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -49137,7 +49137,7 @@ class BinaryWriter { * Write a `sint64` value, a signed, zig-zag-encoded 64-bit varint. */ sint64(value) { - let long = pb_long_1.PbLong.from(value), + let long = pb_long_1.PbLong.from(value), // zigzag encode sign = long.hi >> 31, lo = (long.lo << 1) ^ sign, hi = ((long.hi << 1) | (long.lo >>> 31)) ^ sign; goog_varint_1.varint64write(lo, hi, this.buf); @@ -88239,12 +88239,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.unique = exports.printEnvDetailsAndSetOutput = exports.getNodeVersionFromFile = void 0; +exports.enableCorepack = exports.unique = exports.printEnvDetailsAndSetOutput = exports.getNodeVersionFromFile = void 0; const core = __importStar(__nccwpck_require__(7484)); const exec = __importStar(__nccwpck_require__(5236)); const io = __importStar(__nccwpck_require__(4994)); const fs_1 = __importDefault(__nccwpck_require__(9896)); const path_1 = __importDefault(__nccwpck_require__(6928)); +const cache_utils_1 = __nccwpck_require__(4673); function getNodeVersionFromFile(versionFilePath) { var _a, _b, _c, _d, _e; if (!fs_1.default.existsSync(versionFilePath)) { @@ -88345,6 +88346,7 @@ function enableCorepack(input) { const packageManagers = input.split(' '); corepackArgs.push(...packageManagers); } + yield (0, cache_utils_1.getCommandOutput)('npm i -g corepack'); yield (0, cache_utils_1.getCommandOutput)(`corepack ${corepackArgs.join(' ')}`); } }); @@ -90271,7 +90273,7 @@ module.exports = /*#__PURE__*/JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45 /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; -/******/ +/******/ /******/ // The require function /******/ function __nccwpck_require__(moduleId) { /******/ // Check if module is in cache @@ -90285,7 +90287,7 @@ module.exports = /*#__PURE__*/JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45 /******/ // no module.loaded needed /******/ exports: {} /******/ }; -/******/ +/******/ /******/ // Execute the module function /******/ var threw = true; /******/ try { @@ -90294,23 +90296,23 @@ module.exports = /*#__PURE__*/JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45 /******/ } finally { /******/ if(threw) delete __webpack_module_cache__[moduleId]; /******/ } -/******/ +/******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } -/******/ +/******/ /************************************************************************/ /******/ /* webpack/runtime/compat */ -/******/ +/******/ /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; -/******/ +/******/ /************************************************************************/ -/******/ +/******/ /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined /******/ var __webpack_exports__ = __nccwpck_require__(3579); /******/ module.exports = __webpack_exports__; -/******/ +/******/ /******/ })() ; \ No newline at end of file diff --git a/dist/setup/index.js b/dist/setup/index.js index d9d09531..499239be 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -2151,7 +2151,7 @@ function retry(name, method, getStatusCode, maxAttempts = constants_1.DefaultRet exports.retry = retry; function retryTypedResponse(name, method, maxAttempts = constants_1.DefaultRetryAttempts, delay = constants_1.DefaultRetryDelay) { return __awaiter(this, void 0, void 0, function* () { - return yield retry(name, method, (response) => response.statusCode, maxAttempts, delay, + return yield retry(name, method, (response) => response.statusCode, maxAttempts, delay, // If the error object contains the statusCode property, extract it and return // an TypedResponse so it can be processed by the retry logic. (error) => { @@ -6305,8 +6305,8 @@ class OidcClient { const res = yield httpclient .getJson(id_token_url) .catch(error => { - throw new Error(`Failed to get ID Token. \n - Error Code : ${error.statusCode}\n + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n Error Message: ${error.message}`); }); const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; @@ -13871,7 +13871,7 @@ class Serializer { /** * The provided model mapper. */ - modelMappers = {}, + modelMappers = {}, /** * Whether the contents are XML or not. */ @@ -15987,7 +15987,7 @@ class NodeFetchHttpClient { body = uploadReportStream; } const platformSpecificRequestInit = await this.prepareRequest(httpRequest); - const requestInit = Object.assign({ body: body, headers: httpRequest.headers.rawHeaders(), method: httpRequest.method, + const requestInit = Object.assign({ body: body, headers: httpRequest.headers.rawHeaders(), method: httpRequest.method, // the types for RequestInit are from the browser, which expects AbortSignal to // have `reason` and `throwIfAborted`, but these don't exist on our polyfill // for Node. @@ -16186,7 +16186,7 @@ class BaseRequestPolicy { /** * The next policy in the pipeline. Each policy is responsible for executing the next one if the request is to continue through the pipeline. */ - _nextPolicy, + _nextPolicy, /** * The options that can be passed to a given request policy. */ @@ -17164,7 +17164,7 @@ function createTokenCycler(credential, scopes, tokenCyclerOptions) { const tryGetAccessToken = () => credential.getToken(scopes, getTokenOptions); // Take advantage of promise chaining to insert an assignment to `token` // before the refresh can be considered done. - refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, + refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, // If we don't have a token, then we should timeout immediately (_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : Date.now()) .then((_token) => { @@ -17971,7 +17971,7 @@ class ServiceClient { * @param credentials - The credentials used for authentication with the service. * @param options - The service client options that govern the behavior of the client. */ - constructor(credentials, + constructor(credentials, /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options */ options) { if (!options) { @@ -36951,7 +36951,7 @@ function createTokenCycler(credential, scopes, tokenCyclerOptions) { const tryGetAccessToken = () => credential.getToken(scopes, getTokenOptions); // Take advantage of promise chaining to insert an assignment to `token` // before the refresh can be considered done. - refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, + refreshWorker = beginRefresh(tryGetAccessToken, options.retryIntervalInMs, // If we don't have a token, then we should timeout immediately (_a = token === null || token === void 0 ? void 0 : token.expiresOnTimestamp) !== null && _a !== void 0 ? _a : Date.now()) .then((_token) => { @@ -41371,7 +41371,7 @@ const fsCreateReadStream = fs__namespace.createReadStream; * append blob, or page blob. */ class BlobClient extends StorageClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -42419,7 +42419,7 @@ class BlobClient extends StorageClient { * AppendBlobClient defines a set of operations applicable to append blobs. */ class AppendBlobClient extends BlobClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -42675,7 +42675,7 @@ class AppendBlobClient extends BlobClient { * BlockBlobClient defines a set of operations applicable to block blobs. */ class BlockBlobClient extends BlobClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -43304,7 +43304,7 @@ class BlockBlobClient extends BlobClient { if (options.onProgress) { options.onProgress({ loadedBytes: transferProgress }); } - }, + }, // concurrency should set a smaller value than maxConcurrency, which is helpful to // reduce the possibility when a outgoing handler waits for stream data, in // this situation, outgoing handlers are blocked. @@ -43329,7 +43329,7 @@ class BlockBlobClient extends BlobClient { * PageBlobClient defines a set of operations applicable to page blobs. */ class PageBlobClient extends BlobClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, blobNameOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -44587,7 +44587,7 @@ class BatchHeaderFilterPolicyFactory { * @see https://docs.microsoft.com/en-us/rest/api/storageservices/blob-batch */ class BlobBatchClient { - constructor(url, credentialOrPipeline, + constructor(url, credentialOrPipeline, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -44619,7 +44619,7 @@ class BlobBatchClient { createBatch() { return new BlobBatch(); } - async deleteBlobs(urlsOrBlobClients, credentialOrOptions, + async deleteBlobs(urlsOrBlobClients, credentialOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -44634,7 +44634,7 @@ class BlobBatchClient { } return this.submitBatch(batch); } - async setBlobsAccessTier(urlsOrBlobClients, credentialOrTier, tierOrOptions, + async setBlobsAccessTier(urlsOrBlobClients, credentialOrTier, tierOrOptions, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -44726,7 +44726,7 @@ class BlobBatchClient { * A ContainerClient represents a URL to the Azure Storage container allowing you to manipulate its blobs. */ class ContainerClient extends StorageClient { - constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, + constructor(urlOrConnectionString, credentialOrPipelineOrContainerName, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -46438,7 +46438,7 @@ function generateAccountSASQueryParameters(accountSASSignatureValues, sharedKeyC * to manipulate blob containers. */ class BlobServiceClient extends StorageClient { - constructor(url, credentialOrPipeline, + constructor(url, credentialOrPipeline, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -46470,7 +46470,7 @@ class BlobServiceClient extends StorageClient { * `BlobEndpoint=https://myaccount.blob.core.windows.net/;QueueEndpoint=https://myaccount.queue.core.windows.net/;FileEndpoint=https://myaccount.file.core.windows.net/;TableEndpoint=https://myaccount.table.core.windows.net/;SharedAccessSignature=sasString` * @param options - Optional. Options to configure the HTTP pipeline. */ - static fromConnectionString(connectionString, + static fromConnectionString(connectionString, // Legacy, no fix for eslint error without breaking. Disable it for this interface. /* eslint-disable-next-line @azure/azure-sdk/ts-naming-options*/ options) { @@ -54272,7 +54272,7 @@ class BinaryWriter { * Write a `sint64` value, a signed, zig-zag-encoded 64-bit varint. */ sint64(value) { - let long = pb_long_1.PbLong.from(value), + let long = pb_long_1.PbLong.from(value), // zigzag encode sign = long.hi >> 31, lo = (long.lo << 1) ^ sign, hi = ((long.hi << 1) | (long.lo >>> 31)) ^ sign; goog_varint_1.varint64write(lo, hi, this.buf); @@ -97917,12 +97917,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.unique = exports.printEnvDetailsAndSetOutput = exports.getNodeVersionFromFile = void 0; +exports.enableCorepack = exports.unique = exports.printEnvDetailsAndSetOutput = exports.getNodeVersionFromFile = void 0; const core = __importStar(__nccwpck_require__(7484)); const exec = __importStar(__nccwpck_require__(5236)); const io = __importStar(__nccwpck_require__(4994)); const fs_1 = __importDefault(__nccwpck_require__(9896)); const path_1 = __importDefault(__nccwpck_require__(6928)); +const cache_utils_1 = __nccwpck_require__(4673); function getNodeVersionFromFile(versionFilePath) { var _a, _b, _c, _d, _e; if (!fs_1.default.existsSync(versionFilePath)) { @@ -98023,6 +98024,7 @@ function enableCorepack(input) { const packageManagers = input.split(' '); corepackArgs.push(...packageManagers); } + yield (0, cache_utils_1.getCommandOutput)('npm i -g corepack'); yield (0, cache_utils_1.getCommandOutput)(`corepack ${corepackArgs.join(' ')}`); } }); @@ -99949,7 +99951,7 @@ module.exports = /*#__PURE__*/JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45 /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; -/******/ +/******/ /******/ // The require function /******/ function __nccwpck_require__(moduleId) { /******/ // Check if module is in cache @@ -99963,7 +99965,7 @@ module.exports = /*#__PURE__*/JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45 /******/ // no module.loaded needed /******/ exports: {} /******/ }; -/******/ +/******/ /******/ // Execute the module function /******/ var threw = true; /******/ try { @@ -99972,16 +99974,16 @@ module.exports = /*#__PURE__*/JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45 /******/ } finally { /******/ if(threw) delete __webpack_module_cache__[moduleId]; /******/ } -/******/ +/******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } -/******/ +/******/ /************************************************************************/ /******/ /* webpack/runtime/compat */ -/******/ +/******/ /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; -/******/ +/******/ /************************************************************************/ var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be in strict mode. diff --git a/src/util.ts b/src/util.ts index af8f903a..6aef3651 100644 --- a/src/util.ts +++ b/src/util.ts @@ -115,6 +115,7 @@ export async function enableCorepack(input: string): Promise { const packageManagers = input.split(' '); corepackArgs.push(...packageManagers); } + await getCommandOutput('npm i -g corepack'); await getCommandOutput(`corepack ${corepackArgs.join(' ')}`); } } From 108e90108c402eb6bc48f93e904bd444066cd438 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 25 Mar 2025 10:02:05 -0500 Subject: [PATCH 09/12] fix: removed extra corepack commands --- __tests__/main.test.ts | 17 ----------------- action.yml | 2 +- dist/cache-save/index.js | 6 ------ dist/setup/index.js | 6 ------ docs/advanced-usage.md | 15 +-------------- src/util.ts | 6 ------ 6 files changed, 2 insertions(+), 50 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 076870eb..dd814ce5 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -305,23 +305,6 @@ describe('main tests', () => { inputs['corepack'] = 'true'; await main.run(); expect(getCommandOutputSpy).toHaveBeenCalledWith('npm i -g corepack'); - expect(getCommandOutputSpy).toHaveBeenCalledWith('corepack enable'); - }); - - it('should enable corepack with a single package manager', async () => { - inputs['corepack'] = 'npm'; - await main.run(); - expect(getCommandOutputSpy).toHaveBeenCalledWith('npm i -g corepack'); - expect(getCommandOutputSpy).toHaveBeenCalledWith('corepack enable npm'); - }); - - it('should enable corepack with multiple package managers', async () => { - inputs['corepack'] = 'npm yarn'; - await main.run(); - expect(getCommandOutputSpy).toHaveBeenCalledWith('npm i -g corepack'); - expect(getCommandOutputSpy).toHaveBeenCalledWith( - 'corepack enable npm yarn' - ); }); }); }); diff --git a/action.yml b/action.yml index 78fbfbbb..16d58835 100644 --- a/action.yml +++ b/action.yml @@ -26,7 +26,7 @@ inputs: cache-dependency-path: description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.' corepack: - description: 'Used to specify whether to enable Corepack. Set to true to enable all package managers or set it to one or more package manager names separated by a space. Supported package manager names: npm, yarn, pnpm.' + description: 'Used to specify whether to enable Corepack.' default: 'false' # TODO: add input to control forcing to pull from cloud or dist. # escape valve for someone having issues or needing the absolute latest which isn't cached yet diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index 9f982d98..dd2f9fb4 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -88341,13 +88341,7 @@ exports.unique = unique; function enableCorepack(input) { return __awaiter(this, void 0, void 0, function* () { if (input.length && input !== 'false') { - const corepackArgs = ['enable']; - if (input !== 'true') { - const packageManagers = input.split(' '); - corepackArgs.push(...packageManagers); - } yield (0, cache_utils_1.getCommandOutput)('npm i -g corepack'); - yield (0, cache_utils_1.getCommandOutput)(`corepack ${corepackArgs.join(' ')}`); } }); } diff --git a/dist/setup/index.js b/dist/setup/index.js index 499239be..c5ea08da 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -98019,13 +98019,7 @@ exports.unique = unique; function enableCorepack(input) { return __awaiter(this, void 0, void 0, function* () { if (input.length && input !== 'false') { - const corepackArgs = ['enable']; - if (input !== 'true') { - const packageManagers = input.split(' '); - corepackArgs.push(...packageManagers); - } yield (0, cache_utils_1.getCommandOutput)('npm i -g corepack'); - yield (0, cache_utils_1.getCommandOutput)(`corepack ${corepackArgs.join(' ')}`); } }); } diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index a1e947cd..cf84d0fd 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -427,21 +427,8 @@ steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: '18.x' + node-version: '22.x' corepack: true - name: Install dependencies run: yarn install --immutable ``` - -You can also pass package manager names separated by a space to enable corepack for specific package managers only. - -```yaml -steps: -- uses: actions/checkout@v4 -- uses: actions/setup-node@v4 - with: - node-version: '18.x' - corepack: yarn pnpm -- name: Install dependencies - run: yarn install --immutable -``` diff --git a/src/util.ts b/src/util.ts index 6aef3651..e5621aca 100644 --- a/src/util.ts +++ b/src/util.ts @@ -110,12 +110,6 @@ export const unique = () => { export async function enableCorepack(input: string): Promise { if (input.length && input !== 'false') { - const corepackArgs = ['enable']; - if (input !== 'true') { - const packageManagers = input.split(' '); - corepackArgs.push(...packageManagers); - } await getCommandOutput('npm i -g corepack'); - await getCommandOutput(`corepack ${corepackArgs.join(' ')}`); } } From 788fa93aab76868da2797f81e82d3dbf6375d503 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 25 Mar 2025 10:03:25 -0500 Subject: [PATCH 10/12] test: updated e2e test --- .github/workflows/e2e-cache.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-cache.yml b/.github/workflows/e2e-cache.yml index 9674fe4c..672318a4 100644 --- a/.github/workflows/e2e-cache.yml +++ b/.github/workflows/e2e-cache.yml @@ -144,7 +144,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - node-version: [18, 20] + node-version: [18, 20, 22] steps: - uses: actions/checkout@v4 - name: Update yarn From 4478bd47024b3eae8425bf7fed57d49db8282d3e Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 25 Mar 2025 10:10:32 -0500 Subject: [PATCH 11/12] docs: update wording --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 16d58835..3876806c 100644 --- a/action.yml +++ b/action.yml @@ -26,7 +26,7 @@ inputs: cache-dependency-path: description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.' corepack: - description: 'Used to specify whether to enable Corepack.' + description: 'Enables Corepack which allows the use of other package managers.' default: 'false' # TODO: add input to control forcing to pull from cloud or dist. # escape valve for someone having issues or needing the absolute latest which isn't cached yet From aa9724272b8a9ea9fca3d51295a2cc4707e35ec2 Mon Sep 17 00:00:00 2001 From: Jacob Parish Date: Tue, 25 Mar 2025 11:13:23 -0500 Subject: [PATCH 12/12] feat: allow specifying a version --- __tests__/main.test.ts | 22 ++++++++++++++++++++-- action.yml | 2 +- dist/cache-save/index.js | 3 ++- dist/setup/index.js | 3 ++- docs/advanced-usage.md | 13 +++++++++++++ src/util.ts | 3 ++- 6 files changed, 40 insertions(+), 6 deletions(-) diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index dd814ce5..1b80b79b 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -301,10 +301,28 @@ describe('main tests', () => { ); }); - it('should enable corepack when input is "true"', async () => { + it('should install latest corepack when input is "true"', async () => { inputs['corepack'] = 'true'; await main.run(); - expect(getCommandOutputSpy).toHaveBeenCalledWith('npm i -g corepack'); + expect(getCommandOutputSpy).toHaveBeenCalledWith( + 'npm i -g corepack@latest' + ); + }); + + it('should install latest corepack when input is "latest"', async () => { + inputs['corepack'] = 'latest'; + await main.run(); + expect(getCommandOutputSpy).toHaveBeenCalledWith( + 'npm i -g corepack@latest' + ); + }); + + it('should install a specific version of corepack when specified', async () => { + inputs['corepack'] = '0.32.0'; + await main.run(); + expect(getCommandOutputSpy).toHaveBeenCalledWith( + 'npm i -g corepack@0.32.0' + ); }); }); }); diff --git a/action.yml b/action.yml index 3876806c..b97744f8 100644 --- a/action.yml +++ b/action.yml @@ -26,7 +26,7 @@ inputs: cache-dependency-path: description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.' corepack: - description: 'Enables Corepack which allows the use of other package managers.' + description: 'Enables Corepack which allows the use of other package managers. Can provide a version string to install a specific version.' default: 'false' # TODO: add input to control forcing to pull from cloud or dist. # escape valve for someone having issues or needing the absolute latest which isn't cached yet diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js index dd2f9fb4..488b3e0d 100644 --- a/dist/cache-save/index.js +++ b/dist/cache-save/index.js @@ -88341,7 +88341,8 @@ exports.unique = unique; function enableCorepack(input) { return __awaiter(this, void 0, void 0, function* () { if (input.length && input !== 'false') { - yield (0, cache_utils_1.getCommandOutput)('npm i -g corepack'); + const version = input === 'true' ? 'latest' : input; + yield (0, cache_utils_1.getCommandOutput)(`npm i -g corepack@${version}`); } }); } diff --git a/dist/setup/index.js b/dist/setup/index.js index c5ea08da..9f7d342c 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -98019,7 +98019,8 @@ exports.unique = unique; function enableCorepack(input) { return __awaiter(this, void 0, void 0, function* () { if (input.length && input !== 'false') { - yield (0, cache_utils_1.getCommandOutput)('npm i -g corepack'); + const version = input === 'true' ? 'latest' : input; + yield (0, cache_utils_1.getCommandOutput)(`npm i -g corepack@${version}`); } }); } diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index cf84d0fd..42f1c945 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -432,3 +432,16 @@ steps: - name: Install dependencies run: yarn install --immutable ``` + +You can also pass a version string to install a specific version of corepack. + +```yaml +steps: +- uses: actions/checkout@v4 +- uses: actions/setup-node@v4 + with: + node-version: '18.x' + corepack: '0.32.0' +- name: Install dependencies + run: yarn install --immutable +``` diff --git a/src/util.ts b/src/util.ts index e5621aca..dc546abc 100644 --- a/src/util.ts +++ b/src/util.ts @@ -110,6 +110,7 @@ export const unique = () => { export async function enableCorepack(input: string): Promise { if (input.length && input !== 'false') { - await getCommandOutput('npm i -g corepack'); + const version = input === 'true' ? 'latest' : input; + await getCommandOutput(`npm i -g corepack@${version}`); } }