Skip to content

chore: migrate to Yarn 4 and bump dev-deps to current majors#1742

Open
oliverlaz wants to merge 8 commits into
masterfrom
migrate-to-yarn4
Open

chore: migrate to Yarn 4 and bump dev-deps to current majors#1742
oliverlaz wants to merge 8 commits into
masterfrom
migrate-to-yarn4

Conversation

@oliverlaz
Copy link
Copy Markdown
Member

@oliverlaz oliverlaz commented May 13, 2026

CLA

  • I have signed the Stream CLA (required).
  • Code changes are tested

Description of the changes, What, Why and How?

What

  • Migrate the package manager from Yarn Classic (v1) to Yarn 4.14.1 (Berry), with the binary committed under .yarn/releases/ so no Corepack bootstrap is required.
  • Bump several dev-dep majors that had been deferred — TypeScript 5.8 → 6.0, Vitest 3.1 → 4.1 (+ @vitest/coverage-v8), @commitlint/{cli,config-conventional} 19 → 21, conventional-changelog-conventionalcommits 8 → 9, esbuild 0.25 → 0.28, globals 16 → 17, lint-staged 15 → 17 — with minor bumps to eslint, typescript-eslint, prettier, semantic-release, concurrently, eslint-plugin-import, and @types/*.
  • Update CI to install via yarn install --immutable and cache .yarn/cache + install-state.gz instead of node_modules.
  • Drop the dead testwatch script and the redundant @types/base64-js stub (base64-js ships its own types since 1.5.0).
  • Add CLAUDE.md documenting toolchain, build pipeline, architecture, and contributor conventions for agents working in this repo.

Why

  • Yarn 1 is EOL. Yarn 4 brings hardened mode (HTTPS-only registries, install-script allowlisting via dependenciesMeta, configurable npm age gate), built-in provenance support, and the modern Berry resolver. The committed binary keeps installs deterministic across machines and CI without Corepack churn.
  • The dev-dep majors had been piling up and starting to block each other. Pulling them in as one bundled bump (with the few code adjustments they require) keeps lockfile churn down and unblocks future upgrades.

oliverlaz added 6 commits May 13, 2026 00:54
Commits the Yarn 4.14.1 release binary, a fully hardened
.yarnrc.yml (node-modules linker, hardened mode, scripts off,
hardlinks-global, 3-day npm age gate, provenance opt-in,
telemetry off), and the in-place Berry-format migration of
yarn.lock produced by `yarn install`. Yarn 4 detected the v1
lockfile and converted it (YN0087), preserving resolved
versions where the existing resolutions still satisfied the
manifest ranges.

Whitelists esbuild and husky install scripts via
dependenciesMeta -- the only deps with build hooks the
project actually depends on. Splits the prior `prepare`
script into `postinstall: husky` (Berry runs postinstall on
every install but NOT prepare) and `prepare: yarn run build`
(still fires before semantic-release's npm publish).

The `browser` block was alphabetized as a side-effect of
Yarn 4's package.json normalization -- functionally
identical to the prior order.

No workspaces added -- single-package repo. The foundation
and lockfile migration were combined into a single commit
because the pre-commit hook (yarn run lint-staged) can't run
on a v1 lockfile under hardened mode -- separating them
would require either skipping hooks (forbidden) or leaving
the working tree in an unusable state.
- Composite action: cache .yarn/cache + install-state.gz
  instead of node_modules; use `yarn install --immutable`
  (Berry equivalent of --frozen-lockfile).
- release.yml: opt into npm sigstore provenance via
  NPM_CONFIG_PROVENANCE (id-token: write was already in
  the permissions block, so no perms change needed).
  Note: this is the env var the npm CLI honors -- the
  .yarnrc.yml npmPublishProvenance setting is a no-op for
  this repo's actual publish path (semantic-release calls
  `npm publish`, not `yarn npm publish`).
- size.yml: drop YARN_IGNORE_ENGINES (Yarn 1-only env var).
- Replaces `yarn install --frozen-lockfile --ignore-engines`
  with `yarn install --immutable`.
- Notes that the Yarn 4 binary is committed to .yarn/releases
  and Corepack is not required.
Major bumps: typescript 5.8 -> 6.0, vitest 3.1 -> 4.1,
@vitest/coverage-v8 3.1 -> 4.1, @commitlint/{cli,config-conventional}
19 -> 21, conventional-changelog-conventionalcommits 8 -> 9, esbuild
0.25 -> 0.28, globals 16 -> 17, lint-staged 15 -> 17. Plus minor
bumps to eslint, typescript-eslint, prettier, semantic-release,
concurrently, @types/* and eslint-plugin-import.

Adjustments required by the bumps:

- tsconfig.json: TypeScript 6 no longer infers `rootDir` from
  inputs (TS5011). Set it explicitly to `./src`.

- vite.config.ts: vitest 4 made `vi.spyOn` return the same
  persistent spy on repeated calls to the same target, so call
  counts accumulate across tests (broke retry-count assertions
  in channel_manager.test.ts and addInfo assertions in
  poll.test.js). Enable `restoreMocks: true` to restore the
  vitest 3 / Jest-conventional default these tests were written
  against.

- pollComposer.test.ts: vitest 4 no longer wraps arrow functions
  passed to `vi.fn().mockImplementation(...)` to be constructable
  (arrow functions can't be constructors). Switched the two
  PollComposer*MiddlewareExecutor mocks to function expressions
  so `new ...()` works again.

- eslint.config.mjs: added `.yarn`, `coverage`, `.claude` to the
  ignores. After the Yarn 4 migration, the committed Yarn binary
  in .yarn/releases was being picked up by ESLint's discovery;
  same for vitest's coverage output.
…n prettier ignores

- Removed the `testwatch` script -- it referenced mocha,
  nodemon, test-entry.js and test/test.js, none of which
  exist in the repo. Tests have been on vitest for a while.

- Removed @types/base64-js. The base64-js package has shipped
  its own type declarations (index.d.ts) since 1.5.0, so the
  separate @types stub is redundant. Only src/base64.ts uses
  the package; type resolution still works.

- Extended .prettierignore with /.yarn, /.claude, and
  /coverage. After the Yarn 4 migration these directories
  exist in the working tree and were polluting local
  `yarn prettier` output with 100+ false warnings.

- Auto-fixed pre-existing whitespace in
  test/unit/MessageComposer/attachmentManager.test.ts that
  the .claude/ noise was previously masking (prettier 3.8
  wants extra parens around a comma-sequence in an
  assignment). No semantic change.
Comment thread .github/actions/setup-node/action.yml Outdated
Comment thread .github/actions/setup-node/action.yml Outdated
Comment thread .github/actions/setup-node/action.yml Outdated
oliverlaz and others added 2 commits May 13, 2026 10:37
…node cache

- size.yml: restore YARN_IGNORE_ENGINES. The compressed-size action
  installs both the PR head and the base branch. Master is still on
  Yarn 1 (which enforces engines), and master's semantic-release@25.0.2
  requires Node >= 22.14 while the action's runner uses Node 20. The
  env var is a Yarn-1-only knob and a no-op under Yarn 4 -- safe to
  drop in a follow-up once master is on Yarn 4.

- setup-node composite: drop the explicit actions/cache@v5 step and
  rely on actions/setup-node@v6's built-in `cache: 'yarn'`. v6 detects
  Berry via package.json#packageManager and caches `.yarn/cache`
  natively with a yarn.lock-derived key, so the hand-rolled cache step
  was redundant.
Co-authored-by: Anton Arnautov <43254280+arnautov-anton@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants