Tag last when cutting a release - #48
Merged
Merged
Conversation
The release workflow triggered on `release: created`, so the tag already
existed when the job started. It built the xcframework, uploaded it to
that release, then pushed the Package.swift URL/checksum update to main
afterwards. The tag never moved, so every tagged commit referenced the
*previous* release's artifact:
0.32 -> download/0.31/
0.33 -> download/0.32/
0.34 -> download/0.33/
0.35 -> download/0.34/
That stayed harmless while the N-1 binary happened to export everything
the Swift wrapper called. 0.35 broke it: the same release added
lyte_program_has_entry_point to both lyte.h and Lyte.swift, and since
CLyte is a pure binaryTarget the header comes from the downloaded
xcframework. Tag 0.35 downloads the 0.34 artifact, whose header predates
the symbol, so the package fails to build for anyone resolving by
version rather than by branch (issue #37).
Cut releases via workflow_dispatch instead, and create the tag last:
build -> update Package.swift on main -> create the release and tag at
that commit -> verify.
Also:
- Fail fast if the version is malformed or the tag/release already
exists, rather than after a ~30 minute LLVM build.
- Check both sed rewrites landed; a silently non-matching pattern would
otherwise tag a Package.swift pointing at the wrong artifact.
- Retry the push with a rebase, since main can move during the build.
- Verify by cloning the fresh tag and running swift build against it.
That is the consumer's build path, so an issue #37 style mismatch now
fails the release job instead of reaching users.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DeNzkFkzMbdH3XPzitDmVa
The README told you to cut a release with `gh release create`, which no longer triggers anything — it would produce a release with no xcframework attached. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeNzkFkzMbdH3XPzitDmVa
Code review of the reordering found that it fixed the tag but broke the branch. The Package.swift commit naming .../download/$TAG/... was pushed to main *before* `gh release create` uploaded the asset, so a failure between the two left main pointing at a 404 — and consumers resolving by branch, which is how Audulus consumes this package, would fail to resolve until someone reverted by hand. Verification also ran after the release was already public, so the step whose entire purpose is to fail would fail with a broken release published and the version burned. Stage the Package.swift commit on a release/<version> branch instead. The release and tag are created there, the published tag is verified, and only then is main fast-forwarded onto it. If publishing or verification fails, the release and tag are deleted so the version can be re-run; main was never touched. A failure to fast-forward main leaves a good release alone. Also verify before publishing, not only after: build the package against the freshly built xcframework via a local binaryTarget path. Against a stale artifact this reproduces the issue #37 error exactly ("cannot find 'lyte_program_has_entry_point' in scope"), now with nothing published. Also: - Abort if main moved during the build instead of rebasing onto it. The rebase would tag sources newer than the binary, which is the issue #37 shape: merge a PR adding an FFI symbol mid-build and the tag ships a wrapper calling a symbol its artifact's header lacks. - Require the version to look like 0.36 or 0.36.1. The old check only rejected empty and non-[0-9.] input, so a typo'd "036" would have produced a real tag and an unresolvable URL. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeNzkFkzMbdH3XPzitDmVa
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.
Fixes #37.
The bug
The release workflow triggered on
release: created, so the tag already existed when the job started. It built the xcframework, uploaded it to that release, then pushed thePackage.swiftURL/checksum update tomainafterwards. The tag never moved, so every tagged commit references the previous release's artifact:b4b8b2f "Update Package.swift for release 0.35"is not an ancestor of tag0.35— it is the commit right after it, onmainonly.This stayed harmless for many releases because the N-1 binary happened to export everything the Swift wrapper called. 0.35 broke it: #35 added
lyte_program_has_entry_pointto bothSources/CLyte/include/lyte.handSources/Lyte/Lyte.swift:127in the same release.CLyteis a purebinaryTarget, so the header the Swift target compiles against comes from the downloaded xcframework, not fromSources/CLyte/include. Tag 0.35 downloads the 0.34 xcframework, whose header predates the symbol.Consumers resolving by branch (as Audulus does) never saw this, because
mainalways has the correctedPackage.swift. The reporter is the first to pin by version.The fix
Cut releases via
workflow_dispatchwith a version input instead of by creating a release in the UI, and create the tag last:build -> update
Package.swiftonmain->gh release create "$TAG" --target <that commit sha>-> verifygh release create --targetcreates the tag, the release, and uploads the asset at the commit that already names the right URL and checksum.Guards
sedrewrites are verified withgrep -q. A silently non-matching pattern would otherwise tag aPackage.swiftpointing at the wrong artifact.pull --rebase(3x), sincemaincan move during the build. The commit is skipped entirely ifPackage.swiftis already correct.swift build. That is exactly the consumer's build path, so an issue Lyte 0.35 Swift package fails to build: missing lyte_program_has_entry_point in bundled CLyte artifact #37 class mismatch now fails the release job instead of reaching users.Note
This only fixes future releases. Tag 0.35 stays broken for version-pinned consumers; cutting 0.36 from
main(the first run of this workflow) unblocks them, and its verify step would prove the tag is good.🤖 Generated with Claude Code
https://claude.ai/code/session_01DeNzkFkzMbdH3XPzitDmVa