diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d87dab6..eaa3b4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,15 +46,21 @@ jobs: fail-fast: false matrix: node: - - 18 - 20 - 22 - - 23 + - 24 platform: - ubuntu-latest - macos-latest - windows-latest + # Temporarily skipping Node.js 24 under Windows due to issue + # https://github.com/nodejs/corepack/issues/715 + # vitest fails "handle integrity checks" on Windows with Node.js 24.x + exclude: + - node: 24 + platform: windows-latest + name: "${{matrix.platform}} w/ Node.js ${{matrix.node}}.x" runs-on: ${{matrix.platform}} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4f57f18..9c2cc6c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,12 +8,14 @@ env: YARN_ENABLE_GLOBAL_CACHE: false permissions: - contents: write - pull-requests: write + contents: read jobs: release-please: runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write outputs: release_created: ${{ steps.release.outputs.release_created }} release_tag: ${{ steps.release.outputs.tag_name }} @@ -30,6 +32,7 @@ jobs: if: ${{ needs.release-please.outputs.release_created }} runs-on: ubuntu-latest permissions: + contents: write id-token: write steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index ad0bba5..fdf9377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## [0.34.0](https://github.com/nodejs/corepack/compare/v0.33.0...v0.34.0) (2025-07-19) + + +### ⚠ BREAKING CHANGES + +* drop Node.js 18.x and 23.x support + +### Features + +* update package manager versions ([#719](https://github.com/nodejs/corepack/issues/719)) ([7707ea7](https://github.com/nodejs/corepack/commit/7707ea7350c129ad3aae8ca08e9e80fcf164dcb6)) + + +### Miscellaneous Chores + +* remove Node.js 18.x and 23.x usage, add 24.x ([#718](https://github.com/nodejs/corepack/issues/718)) ([783a42f](https://github.com/nodejs/corepack/commit/783a42fbe35371964e9dde75e2263b179f53bc0c)) + +## [0.33.0](https://github.com/nodejs/corepack/compare/v0.32.0...v0.33.0) (2025-06-02) + + +### Features + +* Adds guard to avoid stepping on Yarn's feet ([#714](https://github.com/nodejs/corepack/issues/714)) ([5fc3691](https://github.com/nodejs/corepack/commit/5fc3691354eb5bdeca17a9495b234584353f0151)) +* update package manager versions ([#671](https://github.com/nodejs/corepack/issues/671)) ([b45b3a3](https://github.com/nodejs/corepack/commit/b45b3a3244bacfbaf65188ae8c04209a1e98307d)) + + +### Bug Fixes + +* debug text typo ([#698](https://github.com/nodejs/corepack/issues/698)) ([0b94797](https://github.com/nodejs/corepack/commit/0b94797f96e30e46e466873fe7d437d0471cd92c)) + ## [0.32.0](https://github.com/nodejs/corepack/compare/v0.31.0...v0.32.0) (2025-02-28) diff --git a/README.md b/README.md index 809a9bc..f69cdf6 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ and pnpm without having to install them**. ### Default Installs -Corepack is [distributed by default with all recent Node.js versions](https://nodejs.org/api/corepack.html). +Corepack is distributed with Node.js from version 14.19.0 up to (but not including) 25.0.0. Run `corepack enable` to install the required Yarn and pnpm binaries on your path. ### Manual Installs diff --git a/config.json b/config.json index 9fde440..9392715 100644 --- a/config.json +++ b/config.json @@ -1,7 +1,7 @@ { "definitions": { "npm": { - "default": "11.1.0+sha1.dba08f7d0f5301ebedaf968b4f74b2282f97a750", + "default": "11.4.2+sha1.6f1519a03f7e04023a957a22b812832d0c4a4b33", "fetchLatestFrom": { "type": "npm", "package": "npm" @@ -38,7 +38,7 @@ } }, "pnpm": { - "default": "10.5.2+sha1.ca68c0441df195b7e2992f1d1cb12fb731f82d78", + "default": "10.13.1+sha1.aa8c167c4509c97519542ef77a09e4b8ab59fb6a", "fetchLatestFrom": { "type": "npm", "package": "pnpm" @@ -102,7 +102,7 @@ "package": "yarn" }, "transparent": { - "default": "4.6.0+sha224.acd0786f07ffc6c933940eb65fc1d627131ddf5455bddcc295dc90fd", + "default": "4.9.2+sha224.b8e0b161ae590950fbda696e6f3ca071362768e5280c5fbfdadf064b", "commands": [ [ "yarn", diff --git a/package.json b/package.json index ac6242b..01ceb17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "corepack", - "version": "0.32.0", + "version": "0.34.0", "homepage": "https://github.com/nodejs/corepack#readme", "bugs": { "url": "https://github.com/nodejs/corepack/issues" @@ -10,7 +10,7 @@ "url": "https://github.com/nodejs/corepack.git" }, "engines": { - "node": "^18.17.1 || ^20.10.0 || >=22.11.0" + "node": "^20.10.0 || ^22.11.0 || >=24.0.0" }, "exports": { "./package.json": "./package.json" diff --git a/sources/commands/Disable.ts b/sources/commands/Disable.ts index 204de33..bb184eb 100644 --- a/sources/commands/Disable.ts +++ b/sources/commands/Disable.ts @@ -3,6 +3,7 @@ import fs from 'f import path from 'path'; import which from 'which'; +import * as corepackUtils from '../corepackUtils'; import {Context} from '../main'; import type {NodeError} from '../nodeUtils'; import {isSupportedPackageManager, SupportedPackageManagerSetWithoutNpm} from '../types'; @@ -70,6 +71,11 @@ export class DisableCommand extends Command { async removePosixLink(installDirectory: string, binName: string) { const file = path.join(installDirectory, binName); try { + if (binName.includes(`yarn`) && corepackUtils.isYarnSwitchPath(await fs.promises.realpath(file))) { + console.warn(`${binName} is already installed in ${file} and points to a Yarn Switch install - skipping`); + return; + } + await fs.promises.unlink(file); } catch (err) { if ((err as NodeError).code !== `ENOENT`) { diff --git a/sources/commands/Enable.ts b/sources/commands/Enable.ts index 78b33c0..6a2a584 100644 --- a/sources/commands/Enable.ts +++ b/sources/commands/Enable.ts @@ -4,6 +4,7 @@ import fs from 'f import path from 'path'; import which from 'which'; +import * as corepackUtils from '../corepackUtils'; import {Context} from '../main'; import {isSupportedPackageManager, SupportedPackageManagerSetWithoutNpm} from '../types'; @@ -83,6 +84,12 @@ export class EnableCommand extends Command { if (fs.existsSync(file)) { const currentSymlink = await fs.promises.readlink(file); + + if (binName.includes(`yarn`) && corepackUtils.isYarnSwitchPath(await fs.promises.realpath(file))) { + console.warn(`${binName} is already installed in ${file} and points to a Yarn Switch install - skipping`); + return; + } + if (currentSymlink !== symlink) { await fs.promises.unlink(file); } else { diff --git a/sources/corepackUtils.ts b/sources/corepackUtils.ts index 0592696..3bad373 100644 --- a/sources/corepackUtils.ts +++ b/sources/corepackUtils.ts @@ -19,6 +19,12 @@ import * as npmRegistryUtils from './npmRegist import {RegistrySpec, Descriptor, Locator, PackageManagerSpec} from './types'; import {BinList, BinSpec, InstallSpec, DownloadSpec} from './types'; +const YARN_SWITCH_REGEX = /[/\\]switch[/\\]bin[/\\]/; + +export function isYarnSwitchPath(p: string) { + return YARN_SWITCH_REGEX.test(p); +} + export function getRegistryFromPackageManagerSpec(spec: PackageManagerSpec) { return process.env.COREPACK_NPM_REGISTRY ? spec.npmRegistry ?? spec.registry diff --git a/tests/Disable.test.ts b/tests/Disable.test.ts index e85fd6e..fcea6a6 100644 --- a/tests/Disable.test.ts +++ b/tests/Disable.test.ts @@ -97,4 +97,23 @@ describe(`DisableCommand`, () => { await expect(sortedEntries).resolves.toEqual([...binNames].sort()); }); }); + + it(`shouldn't remove Yarn binaries if they are in a /switch/ folder`, async () => { + await xfs.mktempPromise(async cwd => { + await xfs.mkdirPromise(ppath.join(cwd, `switch/bin`), {recursive: true}); + await xfs.writeFilePromise(ppath.join(cwd, `switch/bin/yarn`), `hello`); + + await xfs.linkPromise( + ppath.join(cwd, `switch/bin/yarn`), + ppath.join(cwd, `yarn`), + ); + + await expect(runCli(cwd, [`disable`])).resolves.toMatchObject({ + exitCode: 0, + }); + + const file = await xfs.readFilePromise(ppath.join(cwd, `yarn`), `utf8`); + expect(file).toBe(`hello`); + }); + }); }); diff --git a/tests/Enable.test.ts b/tests/Enable.test.ts index cb9b1af..a72b5b4 100644 --- a/tests/Enable.test.ts +++ b/tests/Enable.test.ts @@ -1,7 +1,7 @@ import {Filename, ppath, xfs, npath} from '@yarnpkg/fslib'; import {delimiter} from 'node:path'; import process from 'node:process'; -import {describe, beforeEach, it, expect} from 'vitest'; +import {describe, beforeEach, it, expect, test} from 'vitest'; import {Engine} from '../sources/Engine'; import {SupportedPackageManagers, SupportedPackageManagerSetWithoutNpm} from '../sources/types'; @@ -87,4 +87,42 @@ describe(`EnableCommand`, () => { await expect(sortedEntries).resolves.toEqual(expectedEntries.sort()); }); }); + + test.skipIf(process.platform === `win32`)(`should overwrite existing files`, async () => { + await xfs.mktempPromise(async cwd => { + await xfs.writeFilePromise(ppath.join(cwd, `yarn`), `hello`); + + process.env.PATH = `${npath.fromPortablePath(cwd)}${delimiter}${process.env.PATH}`; + await expect(runCli(cwd, [`enable`])).resolves.toMatchObject({ + stdout: ``, + stderr: ``, + exitCode: 0, + }); + + const file = await xfs.readFilePromise(ppath.join(cwd, `yarn`), `utf8`); + expect(file).toBe(`hello`); + }); + }); + + test.skipIf(process.platform === `win32`)(`shouldn't overwrite Yarn files if they are in a /switch/ folder`, async () => { + await xfs.mktempPromise(async cwd => { + await xfs.mkdirPromise(ppath.join(cwd, `switch/bin`), {recursive: true}); + await xfs.writeFilePromise(ppath.join(cwd, `switch/bin/yarn`), `hello`); + + await xfs.linkPromise( + ppath.join(cwd, `switch/bin/yarn`), + ppath.join(cwd, `yarn`), + ); + + process.env.PATH = `${npath.fromPortablePath(cwd)}${delimiter}${process.env.PATH}`; + await expect(runCli(cwd, [`enable`])).resolves.toMatchObject({ + stdout: ``, + stderr: ``, + exitCode: 0, + }); + + const file = await xfs.readFilePromise(ppath.join(cwd, `yarn`), `utf8`); + expect(file).toBe(`hello`); + }); + }); }); diff --git a/tests/nocks.db b/tests/nocks.db index 26c4868..285731a 100644 Binary files a/tests/nocks.db and b/tests/nocks.db differ