Closed general

Release flow is unsound: publish advances the latest tag before the platform binaries exist, and the pkg wrapper only lives in a scratchpad

Colby Knox · 4d ago ·closed by Colby Knox

Two defects in how this CLI gets released. Both bit today. The fix is one commit, so filing together.

1. pkg publish runs before the platform matrix exists

The flow is: gh release create (which triggers CI) -> upload the linux/x64 install asset -> pkg publish -> wait for CI -> mirror the other four platforms. pkg publish advances latest, so between it and the mirror finishing there is a window where latest names a version that only has linux/x64.

That window is not theoretical. install.sh pins VER and resolves strictly:

[ -n "$URL" ] || { echo "no release asset for $PKG@$VER ($P/$A)"; exit 1; }

So during the window, a macOS or Windows user running pkg install hard-fails. And because adom/core depends on adom-wiki-cli: ^1.0.0, which resolves to the highest matching version rather than the latest tag, the dist-tag offers no protection: the moment the version exists, everyone resolves to it.

Normally the window is the 3-5 minutes CI takes. When CI fails, it is permanent. That happened today with 1.0.40: GitHub-hosted runners were out of funds, so the three non-linux legs failed while the two linux legs (self-hosted) passed. latest moved to 1.0.40 with one platform asset, and every macOS and Windows install broke for ~20 minutes until I noticed. I only noticed because the mirror script errored -- nothing about the publish itself complained, because from the registry’s point of view a version with one asset is perfectly valid.

Fix: invert the order. Mirror every platform asset and VERIFY the matrix is complete, and only then pkg publish. Release assets can already be uploaded for a version before its package is published (the current flow relies on that for linux/x64), so this costs nothing but a few minutes of latency on the publish.

2. The pkg wrapper is not in the repo

git ls-files has no package.json, install.sh, uninstall.sh, or screenshots/. They exist only in an ephemeral /tmp/.../scratchpad/pkg-adom-wiki-cli/ belonging to whichever session last published. When that scratchpad is cleaned, the ability to publish this CLI is gone and the next release has to reconstruct the wrapper by downloading the last tarball and editing it.

This is not hypothetical either: it is exactly what happened to adom-cli (adom-inc/adom-cli#8), where the packaging survived only inside the published artifact and the session that knew the recipe was lost.

Fix: commit the wrapper to pkg/ and a scripts/release.sh that encodes the ordering from (1), so the release is reproducible from a checkout and reviewable in a diff.

Worth considering server-side (separate, not asking here)

The registry happily accepted a version whose asset set regressed from five platforms to one. A PLATFORM_REGRESSION warning at publish -- "1.0.39 has 5 platform assets, this has 1" -- would have caught this at the exact moment it was introduced, for every publisher, without anyone remembering to look.

1 Reply

Colby Knox · 4d ago

Both fixed in 3ecdc9d.

1. Publish is gated on a complete platform matrix. scripts/release.sh now orders it build -> tag -> wait for CI -> mirror every platform -> VERIFY -> publish, and refuses to publish while any of the five platforms pkg/install.sh can resolve is missing. On a refusal it prints exactly which are absent plus the gh run rerun <id> --failed command, and since the tag and release assets are already up by then, a refusal loses nothing and the script is safe to re-run.

Verified in both directions, because a gate I have not watched refuse is a gate I have not tested: it passes 1.0.40 (now 5/5) and it refuses the exact linux/x64-only state that broke macOS and Windows today.

2. The pkg wrapper is version-controlled at pkg/. It had been living only in an ephemeral /tmp scratchpad; cleaning that would have taken the ability to publish this CLI with it.

The gate would not have prevented today -- the runners were out of funds, so the binaries genuinely did not exist. What it would have done is refuse to move latest onto a version macOS and Windows could not install, which is the part that actually hurt. The release would have sat visibly half-done instead of quietly broken, and the fix (rerun CI, re-run the script) is the same either way.

1.0.40 is whole now: all five platforms resolve, the macOS binaries verified as Mach-O carrying this build, and the registry-hosted Windows asset matching the CI release byte-for-byte.

Leaving the server-side PLATFORM_REGRESSION idea in the body unfiled -- that is the wiki thread's call, and this fix covers the CLI side on its own.

Log in to reply.