Draft releases cannot create tags via the GitHub API, resulting in
'untagged-xxx' releases. Fixed by creating the tag first, then
creating the draft release pointing to it.
See: https://github.com/cli/cli/issues/11589
- Preflight builds multi-arch images to staging tags on GHCR
- Publish workflow just retags staging → final (no rebuild)
- Reduces publish time from ~10min to ~1min
Docker images now build only after release is published, not during
the draft creation phase. This prevents users from getting updates
before the release is reviewed and approved.
Scripts like install.sh and install-sensor-proxy.sh are now attached
as release assets and downloaded from releases/latest/download/ URLs.
This ensures users always get scripts compatible with their installed
version, even while development continues on main.
Changes:
- build-release.sh: copy install scripts to release directory
- create-release.yml: upload scripts as release assets
- Updated all documentation and code references to use release URLs
- Scripts reference each other via release URLs for consistency
GitHub's API has a quirk: if you POST to /releases with a tag_name
that already exists as a git tag, it creates an 'untagged' release
instead of attaching to the existing tag.
The fix is to let the API create both tag and release together.
gh release create doesn't work properly when the tag already exists -
it creates an 'untagged' release instead of attaching to the existing tag.
Using the API directly with POST to /releases fixes this.
gh release create with --target was still creating untagged releases.
The fix is to create and push the git tag explicitly first, then
create the release which will properly attach to the existing tag.
The workflow was broken because it expected a tag to exist but the
documented process never created one. This caused gh release create
to fail with 'untagged' releases.
Changes:
- Workflow now creates the tag using --target flag
- Simplified release creation logic (no retry loops needed)
- Removed confusing comment about 'tag already exists'
This fixes the fundamental issue where the workflow and documented
process were out of sync.
Back to the working pattern:
- Claude generates release notes
- Passes them directly to workflow via workflow_dispatch input
- No tag annotation reading complexity
- Simple: gh workflow run -f version=X.Y.Z -f release_notes="..."
This is what you wanted and what actually works reliably.
Tag push triggers in GitHub Actions are unreliable (known issue).
Major projects don't actually use automatic tag triggers - they use
workflow_dispatch or other manual triggers.
Changes:
- Remove tag push trigger
- Use workflow_dispatch with version input
- Workflow validates that annotated tag already exists
- Tag still stores LLM changelog in annotation
- Manual trigger: gh workflow run release.yml -f version=X.Y.Z
This is the pattern that actually works reliably.
GitHub Actions has a known issue where tag pushes sometimes don't
trigger workflows. Add workflow_dispatch as a backup trigger that
accepts a tag parameter.
This allows manual triggering if automatic tag push trigger fails.
Preflight tests improvements:
- Add npm cache for frontend dependencies (saves ~30-60s)
- Add Go module cache (saves ~20-40s)
- Add Playwright browser cache (saves ~40-60s)
- Remove excessive diagnostic output (saves ~10-20s)
- Total preflight savings: ~2-3 minutes
Docker build improvements:
- Enable Docker layer caching via registry (saves ~2-4 min per build)
- Cache stored in GHCR as :buildcache tags
- Reuses unchanged layers across releases
- First build same time, subsequent builds much faster
- Total Docker savings: ~4-8 minutes on releases with few changes
Expected total time reduction: 6-11 minutes on typical releases
No functionality sacrificed - all tests and validations remain.
Remove GitHub auto-generation fallback. Tags MUST be annotated
with Claude-written release notes.
Why:
- LLMs write semantic, user-focused changelogs
- Filters out dev/internal commits
- Explains features in terms users understand
- GitHub's auto-gen is just raw commit dumps
Workflow now fails fast with clear error if tag lacks annotation.
Workflow now checks for annotated tags and uses the annotation
as release notes. If no annotation exists, falls back to GitHub's
auto-generation.
This allows Claude to write formatted release notes when creating
releases, stored directly in git history as part of the tag.