ci: verify the binary builds before tagging a release - #20
Merged
Conversation
Lint, typecheck, and tests all pass on code that `bun build --compile` cannot bundle, so a compile break could previously merge undetected. Add a build step to PR CI so that failure surfaces before merge instead of during the release run.
Previously the version job pushed both the bump commit and the tag before build even ran, so a compile failure left a bumped main and an orphan tag with no release attached -- brew install would 404 for that version. The version job now pushes only the bump commit and outputs its SHA; build and release check out that SHA; the tag is created and pushed by the release job after all five binaries have built and been packaged. Tagging is the first irreversible act, so it now happens last. Also add just build to the version job's Verify step, so a compile break fails before the bump commit is even pushed. Two recovery paths introduced by this restructure: - If a run pushes the bump but fails before tagging, the version files on main are already correct on the next run, so the commit step now detects an empty stage, reuses the existing commit, and proceeds instead of dying and wedging releases permanently. - The tag step is idempotent, so a re-run after a partial failure completes instead of dying on an already-existing tag.
Replace bun-version: latest with 1.4.0 in all three setup-bun steps. latest already resolves to 1.4.0, so this changes nothing today, but it makes the build reproducible: an upstream Bun release can no longer break CI or a release run with no change on our side. Bump actions to clear Node 20 deprecation warnings: checkout v4 to v7, upload-artifact v4 to v7, download-artifact v4 to v8, action-gh-release v2 to v3, setup-just v2 to v4. Breaking changes were checked against our actual usage: download-artifact v5's path change only affects downloads by artifact ID (we download all artifacts, so unaffected), and v8's digest-mismatch-errors and skip-decompress changes don't affect our flow. Also tighten engines.bun from >=1.0.0 to >=1.3.0 in package.json to match the pinned version.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
bun build --compilebreak fails review instead of merging silentlyCloses #18
The problem
Nothing verified that the CLI binary compiles until after a version bump and tag were already pushed.
auto-release.yml'sversionjob pushed the bump and tag (git push origin main --follow-tags), and only then didbuildrun.ci.ymlnever built at all -- just lint, typecheck, tests. So a change that typechecks and passes tests but breaksbun build --compilecould merge, bump the version, push a tag, and only then fail, leaving a bumped main, an orphan tag, and no release assets -- meaningbrew install llbbl/tap/upkeep404s for that version. This nearly bit us on the TypeScript 7 upgrade (#15), caught only becausebuild:allwas run locally by hand.The fix, three layers of defense
bun run build, so a compile break fails review before merge.Verifystep now also runsjust build, so a break fails before the bump commit is even pushed.versionjob.versionpushes only the bump commit and outputs its SHA;buildandreleasecheck out that SHA; the tag is created and pushed by thereleasejob after all five binaries are built and packaged. Tagging is the first irreversible act, so it now happens last.Recovery paths added
Both matter because the restructure introduced these failure modes:
git commitwould be empty and fail -- permanently wedging releases. The commit step now detects an empty stage, reuses the existing commit, and proceeds.Changes
CI
Build binarystep (bun run build) after testsversionpushes only the bump commit and outputs its SHA (steps.bump.outputs.sha);buildandreleasecheck out that SHA instead of the tag;releasecreates and pushes the tag only after all binaries are packaged;version'sVerifystep also runsjust build; commit step tolerates an empty stage; tag step is idempotentPins
bun-version: latestreplaced with1.4.0in all threesetup-bunsteps --latestalready resolves to1.4.0, so this changes nothing today but makes the build reproducible. Actions bumped to clear Node 20 deprecation warnings:actions/checkoutv4 to v7,actions/upload-artifactv4 to v7,actions/download-artifactv4 to v8,softprops/action-gh-releasev2 to v3,extractions/setup-justv2 to v4. Breaking changes were checked against actual usage:download-artifactv5's path change only affects downloads by artifact ID (we download all artifacts, so unaffected), and v8's digest-mismatch-errors and skip-decompress changes don't affect our flowengines.buntightened from>=1.0.0to>=1.3.0Verification
actionlintclean on both workflows (also validates the newneeds.version.outputs.shaexpression references)just checkpasses locally (lint, typecheck, 405 tests)just build-- the newly added CI step -- succeeds locallyNote for the reviewer
The restructured release path cannot be fully exercised until the next real release runs. The first merge to main after this lands will be its live test.
Test plan
Build binarystepactionlintclean on both workflows