Vendor clean pgstencil with kysely as a Hosted peer, and fail on unmet peers - #742
Conversation
pgstencil now shares kysely and hono with the application as peers instead of pinning its own copies, so Hosted declares kysely and Renovate updates the one copy both sides use. The refresh also brings in pgstencil's Microsoft signing-key fix and quieter expected-rejection diagnostics. The sync script packs a committed revision in a temporary worktree, so the recorded provenance is clean and production preflight accepts it; --working-tree packs an unfinished checkout for local experiments. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A Renovate bump that leaves pgstencil's kysely or hono peer out of range now goes red in its own PR instead of installing with a warning. The workspace has no peer issues today; deliberate widenings stay in peerDependencyRules. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Deploying mouseterm with
|
| Latest commit: |
9e95f83
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://07cb089d.mouseterm.pages.dev |
| Branch Preview URL: | https://pgstencil-peers.mouseterm.pages.dev |
dormouse-bot
left a comment
There was a problem hiding this comment.
Feedback on work in progress, not a merge verdict — mark the PR ready when you want a full review.
The new peer-declaration rule is not enforced by anything. strictPeerDependencies: true catches an out-of-range peer, which is what the pnpm-workspace.yaml comment claims for it. It does not catch a peer the consumer stops declaring: pnpm auto-installs the missing peer into its own copy and the install goes green. So if a later edit drops kysely: ^0.29.5 from hosted/package.json, Hosted silently returns to the duplicate-copy state this PR exists to remove — Renovate stops seeing the version, and nothing goes red.
That also makes the section's closing line read wider than it is: Pinned by hosted/server/tests/artifacts.test.ts now sits under a rule that test does not check — it verifies the archive hashes and the two file: specifiers only. Its second test (both pinned specifiers name the recorded archives) already reads hosted/package.json's dependencies and the first already untars both archives, so asserting that every key of each archive's peerDependencies appears in dependencies would pin the rule, and would track pgstencil's peer list on its own rather than hardcoding kysely and hono.
How the pnpm behaviour was checked
Minimal workspace under pnpm 11.27.0 (the pinned packageManager): a file: tarball declaring peerDependencies: { kysely: "^0.29.5" }, strictPeerDependencies: true in pnpm-workspace.yaml, consumer declaring no kysely.
- Consumer declares nothing: install exits 0,
Packages: +2— pnpm resolved the peer itself. - Consumer declares
kysely@0.28.7: install fails withERR_PNPM_PEER_DEP_ISSUES—unmet peer kysely / Installed: 0.28.7 / Wanted: ^0.29.5.
One smaller point inline, on the new option parsing.
strictPeerDependencies only rejects an out-of-range peer; pnpm resolves an undeclared one itself. The artifacts test now requires every peer of each vendored archive in hosted/package.json. A mistyped sync flag used to fall back to a clean sync of HEAD and overwrite the archives; it now prints the usage instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
dormouse-bot
left a comment
There was a problem hiding this comment.
Feedback on work in progress, not a merge verdict — mark the PR ready when you want a full review.
Both earlier points are addressed: the test now derives each archive's peer list instead of hardcoding one, and a mistyped flag fails rather than quietly syncing HEAD.
--working-tree on a clean checkout records the same provenance as a worktree sync. dirty is workingTree && !!git("status", "--porcelain"), so a checkout with nothing uncommitted writes dirty: false against a real commit — and that is also the path that skips pnpm install --frozen-lockfile, since the install is gated on !workingTree. git status --porcelain says nothing about ignored paths, so the archives can be packed against whatever node_modules the developer happens to have and from build output the repo ignores, and verifyPackages takes them: assert.equal(manifest.dirty, false, ...) in hosted/scripts/production.mjs is its only check on how they were built. Recording which path produced them — a workingTree field asserted false beside dirty — is what makes the isolation the rewrite buys visible to the preflight.
The two pin checks still run after the install and the pack. They read hosted/package.json, the workspace overrides, and packages/*/package.json from the checkout, all available as soon as git worktree add returns, so a pgstencil version bump you forgot to mirror into hosted/package.json costs a full cold install in the temp worktree before it errors. Hoisting them above the pnpm install also closes the window where the first copyFileSync has already overwritten vendor/pgstencil-0.1.0.tgz and the second iteration throws, leaving build.json recording the old hash.
One inline suggestion on the spec line.
… dirty The version and override checks now read pgstencil's manifests from the requested commit before the temporary install, so a forgotten bump fails at once and cannot leave one archive replaced. A --working-tree build depends on the local install and ignored build output even when git status is clean, so it is always recorded dirty and production preflight refuses it. The spec rule names every archive peer instead of listing them, since the artifacts test derives the list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
dormouse-bot
left a comment
There was a problem hiding this comment.
Feedback on work in progress, not a merge verdict — mark the PR ready when you want a full review.
The earlier points are addressed: the pins are checked before the install and before any archive is overwritten, and --working-tree can no longer launder a clean-looking provenance.
dirty changed meaning, and docs/specs/hosted.md is the one place that still describes the old one. const dirty = workingTree records how the archives were built, not whether the source tree had uncommitted changes — a clean --working-tree checkout now gets dirty: true against a real commit. The source comment and hosted/README.md both carry the new meaning; the spec's only sentence on vendor/build.json still calls it "dirty state", so a reader who hits that dirty: true finds nothing in the spec saying it should be there. The same sentence is also where the production gate would belong — verifyPackages asserting dirty === false is the entire reason the field exists, and no spec states it today.
Suggestion inline; it fits the 1100-word budget as it stands (1068 now, 1078 after).
…spec Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Depends on diffplug/pgstencil#8, and vendors that PR's commit
297edf6.Vendor a clean pgstencil with kysely as a Hosted peer
kyselyandhonowith the app as peer dependencies instead of pinning its own copies. That split is what broke type-the-rhythm#355.hosted/package.jsonnow declareskysely: ^0.29.5, so Renovate updates the single copy both sides use;honowas already declared.c14097c. This refresh adds pgstencil Setup our deployment pipeline #6 (expected auth rejections are no longer reported as server failures) and Add auto-update for the standalone app #7 (Microsoft signing keys withoutalg). Add auto-update for the standalone app #7 is the fix type-the-rhythm needed for Microsoft login, which Hosted also offers.scripts/sync-pgstencil.mjspacks a committed pgstencil revision in a temporary clean worktree, sovendor/build.jsonnow recordsdirty: false.verifyPackagesinhosted/scripts/production.mjsrejected the old dirty build and accepts this one, so production releases are no longer blocked on this.--working-treereplaces--packedfor trying unfinished pgstencil changes; production refuses the dirty result.docs/specs/hosted.mdgets a peer-dependency rule, and its word budget goes from 1050 to 1100 via--ratchet.hosted/README.mdis updated to match.Fail installs on unmet peer dependencies
strictPeerDependencies: trueinpnpm-workspace.yaml. The workspace has no peer issues today (pnpm peers check). I checked that an out-of-rangekysely(0.28.11) now fails the install. Deliberate widenings stay inpeerDependencyRules.Testing
On a fresh install with strict peers:
dormouse-hostedbuild and tests (18 passed)verifyPackages🤖 Generated with Claude Code