Closed general

pkg publish onto a release-born version row reports ok but attaches no tarball and does not move latest (pup-bridge 2.0.398)

John Lauer · 1mo ago ·closed by Colby Knox

Measured today while shipping pup-bridge 2.0.398 (tools/ship.sh: release create + release upload of the bridge zip, THEN pkg publish --org adom of the skills package, same version):

  • pkg publish --org adom --json answers status: ok, published: adom/pup-bridge, version: 2.0.398, sha256: sha256-bc3947c9... (so the tarball was accepted).
  • pkg info adom/pup-bridge --json afterwards: the 2.0.398 version row has type: null, integrity: null, size_bytes: null, published_at: "2026-09-05 12:29:49" (the space-separated timestamp format of a release-born row), and dist_tags.latest still points at 2.0.397. Repeating the publish changes nothing.
  • 2.0.397 (yesterday's flow, where the release row did not pre-exist at publish time) shows type: app, integrity: sha256-60972ab..., ISO timestamp, and became latest.

So when a version row was created by a release before the package publish, the publish reports success but never attaches the tarball to that row nor moves latest. This is the pup-bridge#66 family (a release-only top row breaks pkg install <ref>@<ver>); pkg install adom/pup-bridge still works only because latest stayed on 2.0.397.

Asks:

  1. pkg publish onto an existing release-born row should attach the tarball (type, integrity, size) and move latest, or fail loudly instead of answering ok.
  2. Please attach the accepted 2.0.398 tarball (sha256-bc3947c9fc77b9cefc3b0838cb2d7727bff47032178e23b40fa99e09b9e1e799) to the row, or tell me to republish.

Workaround on my side from now on: ship.sh publishes the package BEFORE creating the release, so the row is born as a package row.

4 Replies

John Lauer · 1mo ago

Workaround confirmed on the next ship: publishing the package BEFORE creating the release (pup-bridge 2.0.399) produced a proper row (type app, integrity, size) and moved latest. Ask 2 (attach the accepted 2.0.398 tarball to its release-born row) still stands, low priority since latest has moved past it.

John Lauer · 1mo ago

New evidence, 2.0.400 (2026-09-05 16:29): this time pkg publish --org adom ran BEFORE release create, and still: publish answered status: ok, version: 2.0.400, sha256: sha256-3762f99f..., but pkg info shows the 2.0.400 row with type: null, integrity: null and dist_tags.latest stayed on 2.0.399. A second publish right after (no release in between) reported ok with the same sha and changed nothing. So it is not the release-born row alone: for some versions the publish reports success and never attaches the tarball. 2.0.399 worked with the identical flow 30 minutes earlier. Both accepted sha256 values (2.0.398: sha256-bc3947c9..., 2.0.400: sha256-3762f99f...) are in the server's hands; please check what happened to those uploads server-side.

Colby Knox · 1mo ago

Root cause found, and it was the server, not your flow. On 2026-09-04 the registry gained a storage rule: a version bump whose files are byte-identical to the previous version stores nothing and answers ok (PUBLISH_UNCHANGED). It was built for the generated component catalogue, where a republish pass used to add a full tarball set for no change. Your skills package rides in lockstep with every bridge release, so whenever the skill files did not change between two bridge builds, the publish was answered ok and stored nothing; release create then made an empty release-born row for that version, and latest stayed put. That is exactly 2.0.398, 2.0.400 and 2.0.442 (no manifest snapshot exists for any of them), while every version whose skills changed went through normally.

Fixed on prod (git-wiki 2e01ee2, rolled out 2026-09-08 ~14:55 UTC):

  • The no-op is scoped to component/hardware packages only. App, skill and bootstrap bumps always store a real version and move latest, identical files or not.
  • It never fires for a version whose release row already exists: the publish attaches to the empty release-born row (the ghost-reclaim path) instead of skipping it. Either order of release create and pkg publish now yields a full row.
  • When it does fire (catalogue pages), the answer says published: false, unchanged: true, requested_version, so a script cannot read it as a publish.

Ask 2: the accepted sha256 values were content hashes of the members, not stored tarballs, so there is nothing server-side to attach. Re-run pkg publish for 2.0.398, 2.0.400 and 2.0.442 with the same manifests whenever convenient: the empty rows accept the publish now (ghost reclaim) and get type, integrity and size. Your ship.sh order can stay as it is.

Sorry for the detour this cost you; the regression test (publish-lockstep) pins both the app-bump case and the release-first case.

Colby Knox · 28d ago

Closing as shipped: the lockstep fix has been on prod since 2026-09-08 (git-wiki f7084b2 + 2e01ee2). App, skill and bootstrap bumps always store a real version and move latest even when the files are byte-identical; a publish onto an existing release-born row attaches to it in either order; the component-only no-op answers published:false, unchanged:true so scripts cannot misread it. The three ghost rows (2.0.398, 2.0.400, 2.0.442) needed a re-run of pkg publish for each, which was yours to do; reopen if any of them is still empty and you want them reclaimed.

Log in to reply.