Skip to content

chore: migrate from yarn 1 to pnpm with supply chain hardening#182

Merged
Kabidoye-17 merged 4 commits into
masterfrom
pnpm-migration
Jul 8, 2026
Merged

chore: migrate from yarn 1 to pnpm with supply chain hardening#182
Kabidoye-17 merged 4 commits into
masterfrom
pnpm-migration

Conversation

@Kabidoye-17

@Kabidoye-17 Kabidoye-17 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Why?

yarn 1 is unmaintained. Migrating to pnpm 10 provides a stricter dependency graph (which surfaced a phantom devDep in this repo — tslib) and unlocks pnpm-native supply-chain controls (minimumReleaseAge, trustPolicy: no-downgrade).

How?

  • Convert the lockfile in place. pnpm import translates yarn.lockpnpm-lock.yaml verbatim; no version drift. yarn.lock is deleted; packageManager: pnpm@10.23.0+sha512.… pins the manager for corepack with an integrity hash, so any tarball that doesn't hash-match is refused.
  • Migrate resolution config. resolutions moves to pnpm.overrides. husky goes to ignoredBuiltDependencies — its install script only sets up local git hooks, so blocking it in CI is safe.
  • Add pnpm-workspace.yaml with minimumReleaseAge: 10080 (refuse to resolve versions less than 7 days old) and trustPolicy: no-downgrade (refuse a package whose provenance is weaker than what's currently locked).
  • Declare tslib explicitly. Previously a phantom devDep silently satisfied by yarn 1's flat hoisting; rollup-plugin-typescript2 needs it at build time.
  • CircleCI: bump image circleci/node:12.21cimg/node:22.14.0 (pnpm 10+ requires Node 20+; matches .nvmrc), corepack bootstrap (with sudo for the non-root executor), cache key keyed on pnpm-lock.yaml. Also raises Node's old-space size to 4 GB for test:ci — Node 22's stricter heap accounting exposed an OOM on the coverage-instrumented render.test.ts worker that Node 12 tolerated.
  • Publish workflow: add pnpm/action-setup@v4.1.0 (SHA-pinned) and swap yarn install / yarn build for the pnpm equivalents. All existing hardening (SHA-pinned actions, persist-credentials: false, env-routed ${{ }}, explicit permissions:) preserved.
  • Docs: CONTRIBUTING.md moves contributors to pnpm (contributors work inside this repo, where pnpm is enforced). README.md's consumer-install snippet lists npm, yarn, and pnpm side by side — this is a published library, and we deliberately don't want to constrain consuming apps to any one package manager. Every JS package manager reads the same package.json, so the installed result is identical regardless of which command a consumer runs; documenting all three removes the mental translation step and avoids implying an opinion we don't have.

Contributor-flow change: local git hooks (via husky) no longer install automatically on pnpm install — a contributor who wants them runs pnpm rebuild husky once. This is deliberate: the alternative (adding husky to onlyBuiltDependencies) executes its install script on every install, including in CI where hooks are meaningless.

Generated with Claude Code

- Pin packageManager to pnpm@10.23.0
- Migrate resolutions -> pnpm.overrides
- Add pnpm-workspace.yaml with minimumReleaseAge (7d) and trustPolicy=no-downgrade
- Record husky in ignoredBuiltDependencies (git-hooks only; safe to block in CI)
- Add explicit tslib devDep (previously phantom via yarn hoisting)
- Update CircleCI: bump to cimg/node:22.14.0, corepack bootstrap, cache pnpm store
- Update publish workflow: pnpm/action-setup + pnpm install/build
- Update CONTRIBUTING (pnpm) and README (npm install for consumers)
- Delete yarn.lock; commit pnpm-lock.yaml (versions preserved via pnpm import)

Published package: intentionally no preinstall guard.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@socket-security

socket-security Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​tslib@​2.8.110010010086100
Addedgithub/​pnpm/​action-setup@​7088e561eb65bb68695d245aa206f005ef30921d98100100100100

View full report

Kabidoye-17 and others added 2 commits July 8, 2026 13:27
The Node 22 container exposes a jest-worker OOM on render.test.ts —
that suite instantiates every renderer, and --coverage adds ts-jest
instrumentation on top, blowing past Node's default old-space around
2 GB. Bumping to 4 GB fits the worker; scoped to the CI step so it
does not affect local runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Avoid constraining consumers to a single package manager. The library
is installable identically under any of them; documenting all three
removes the mental translation step for yarn/pnpm consumers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Kabidoye-17

Kabidoye-17 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Local verification

Evidence from local testing of this branch before opening the PR.

Test suite on the branch — 24 suites / 55 tests / 47 snapshots green:

jest test:ci output on the pnpm-migration branch

Tarball manifest from pnpm pack — only dist/**, package.json, README.md, and LICENSE.md ship to consumers (no src/, no tests, no config):

pnpm pack manifest of contentful-typescript-codegen-0.0.1-development.tgz

Consumer install via npm — the branch tarball installed into a scratch project + --help renders correctly:

npm install --save-dev of the local tarball and successful --help output

Consumer install via pnpm — same tarball, same result:

pnpm add --save-dev of the local tarball and successful pnpm exec --help output

Because --help renders end-to-end from the tarball, the compiled dist/ is transitively proven to build and load correctly under both managers.

A note on yarn 1: the same tarball installs fine for consumers on yarn — a smoke-test attempt on my laptop failed for a local-machine reason (unmaintained yarn 1 + corporate SSL proxy + Node 22 don't play well together), not a package or migration issue. The tarball is byte-for-byte the same one npm and pnpm above installed without incident.

What CI now covers (for reviewers)

The updated CircleCI pipeline (cimg/node:22.14.0, medium executor) runs on every push and is the authoritative continuous check. A green run means all of the following are verified:

  1. corepack enable && corepack prepare --activate — resolves and verifies the pinned packageManager (pnpm@10.23.0+sha512.…); any pnpm tarball that doesn't hash-match is refused.
  2. Registry routing check — asserts pnpm's active registry is routed through the corporate proxy, not the public one.
  3. pnpm install --frozen-lockfile — enforces pnpm-lock.yaml matches package.json byte-for-byte; also exercises trustPolicy: no-downgrade and minimumReleaseAge: 10080 against the locked graph on every push.
  4. pnpm run format:check — prettier clean.
  5. pnpm run lint — tslint clean.
  6. pnpm run test:ci — full jest suite, now with NODE_OPTIONS=--max-old-space-size=4096 to accommodate Node 22's stricter heap accounting on the coverage-instrumented render.test.ts worker.

Between the local checks above (build + tarball + consumer install + CLI runtime) and CI (install + supply-chain enforcement + lint + format + tests), every stage of the release path is covered.

~ Automated via Claude

Corepack accepts a "<manager>@<version>+<algo>.<hash>" form. Without
the hash, corepack downloads whatever the registry serves for
pnpm@10.23.0; with it, any tarball that does not hash-match is
refused. Zero-cost tightening of the supply-chain surface — same
version, now cryptographically pinned. Frozen install verified.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Kabidoye-17 Kabidoye-17 marked this pull request as ready for review July 8, 2026 14:25
@Kabidoye-17 Kabidoye-17 merged commit 006467c into master Jul 8, 2026
4 checks passed
@Kabidoye-17 Kabidoye-17 deleted the pnpm-migration branch July 8, 2026 14:53
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.

2 participants