Skip to content

Per-package atomic publish: metas travel with bytes, ref registers last#52

Merged
fengmk2 merged 2 commits into
mainfrom
fix/atomic-per-package-publish
Jul 2, 2026
Merged

Per-package atomic publish: metas travel with bytes, ref registers last#52
fengmk2 merged 2 commits into
mainfrom
fix/atomic-per-package-publish

Conversation

@fengmk2

@fengmk2 fengmk2 commented Jul 2, 2026

Copy link
Copy Markdown
Member

Incident (2026-07-02, sha 0fecc75a)

A publish run was cancelled mid-way (re-running a workflow auto-cancels the in-flight attempt). It had already overwritten the R2 tarballs for vite-plus/core with new bytes, but never reached the single end-of-run /-/publish, so for ~20 minutes the packument advertised metas that no longer matched the served bytes. Every install in the window failed with ERR_PNPM_TARBALL_INTEGRITY, and the mixed state got captured by CDN edge caches (immutable, deployment-scoped) and pnpm client metadata caches, both of which outlived the server-side self-heal.

Fix

  • /-/publish accepts register: false (store metas only, ref stays unregistered/invisible) and a final packages: [] register-only call. The old single-call protocol is unchanged.
  • The publish action now uploads each tarball and immediately publishes that package's meta, then registers the ref once at the end. Bytes and meta can no longer diverge beyond a single package's upload, and a cancelled run strands only invisible artifacts instead of serving mixed state.
  • The worker's on-demand rebuild (buildAndStore) now updates the meta-index alongside the per-version meta. Previously it skipped the index, leaving two disagreeing meta sources: the packument flapped between them (workerd's gzip output never matches CI's Node gzip, so a stale index integrity was unsatisfiable by the rebuilt bytes).

Test plan

  • New failing-first tests: two-phase publish protocol (meta-only invisible, register-only flips visible) and on-demand-rebuild index consistency
  • pnpm test 81/81, pnpm typecheck
  • Action bundle rebuilt (pnpm build:action)

Follow-ups (separate)

  • Content-keyed tarball paths in dist.tarball so a poisoned edge/client cache can never outlive a fix (CDN ignores query strings, so it must be path-based)
  • vite-plus workflow: reconsider continue-on-error: true on the register step and cancellation of in-flight publishes

fengmk2 added 2 commits July 2, 2026 09:37
A publish run cancelled mid-way (re-runs auto-cancel in-flight attempts)
left R2 tarballs overwritten with new bytes while the packument kept serving
the previous metas for ~20 minutes, failing every install in the window with
ERR_PNPM_TARBALL_INTEGRITY and poisoning CDN edge caches and pnpm client
metadata caches with the mixed state (2026-07-02 incident, sha 0fecc75a).

The action now publishes each package's meta (a new register:false mode of
/-/publish) immediately after uploading its tarball, so bytes and meta can
never diverge for longer than one package's upload, and registers the ref in
one final packages-empty call so a new version flips visible atomically. The
old single-call protocol still works unchanged.

Also fix the on-demand rebuild writing only the per-version meta: it now
updates the meta-index too, so the packument cannot flap between two meta
sources that disagree (an in-worker workerd gzip never matches CI's Node
gzip byte-for-byte, so a divergent stale index entry advertised an integrity
the served bytes could no longer satisfy).
Without a deadline, a hung connection stalls up to undici's ~5-minute
defaults, and 4 retry attempts across ~11 packages can zombie a publish for
tens of minutes (the incident's cancelled attempt ran 21 minutes mid-publish,
which is what made mid-publish cancellation likely in the first place).
Transfers (pkg.pr.new download, tarball PUT, up to ~19MB) get 120s per
attempt; the small register/publish POST gets 30s.
@fengmk2 fengmk2 merged commit a8dc053 into main Jul 2, 2026
4 checks passed
@fengmk2 fengmk2 deleted the fix/atomic-per-package-publish branch July 2, 2026 01:44
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.

1 participant