CI: cut releases by hand instead of on every merge to main #79

Merged
jknapp merged 2 commits from ci/release-gate into main 2026-11-14 23:16:38 +00:00
Owner

Merging to main now ships nothing. A release happens only when someone runs the release workflow on main.

Before: every merge to main touching app/ published a signed release for all three platforms, and every merge touching container/ moved :latest, which every installed app pulls. Phased work like the AWS host couldn't land without each step shipping.

After:

  • build-app.yml runs only by hand (Actions → Build App → Run workflow).
    • Run on main, it cuts a release: Gitea and GitHub releases, the version tag, the Linux update channel, then the container images.
    • Run on any other branch, it's a dry run that builds, signs and verifies, as before.
  • Release tags are pinned to the dispatched commit (target_commitish), so a merge during a ~30 min release run can't move them. create-tag now fails if the tag points anywhere else, where before it swallowed errors.
  • build.yml / build-stt.yml:
    • A push to main publishes only :edge and :<sha>.
    • :latest moves only when the release dispatches them with its tag. They build exactly that tag.
    • The weekly sandbox security rebuild now rebuilds the newest release tag instead of main.
  • CLAUDE.md gains a "Releases are cut by hand" section.

Merging this PR doesn't release either: the merged build-app.yml has no push trigger, and the container push publishes only :edge/:<sha>.

Checked:

  • actionlint is clean on all three files (with gitea. mapped to github.).
  • The tag-picking script was run locally for each event:
    • schedule → newest release v0.4.43 as :latest;
    • dispatch with v0.4.40 → that commit;
    • a malformed tag is rejected;
    • push → :edge.
  • The Gitea dispatch endpoint and the tag API response shape were checked against the live server.

Not yet exercised: a real release run, which will happen the first time you cut one.

🤖 Generated with Claude Code

Merging to main now ships nothing. A release happens only when someone runs the release workflow on main. **Before:** every merge to main touching `app/` published a signed release for all three platforms, and every merge touching `container/` moved `:latest`, which every installed app pulls. Phased work like the AWS host couldn't land without each step shipping. **After:** - `build-app.yml` runs only by hand (Actions → Build App → Run workflow). - Run on `main`, it cuts a release: Gitea and GitHub releases, the version tag, the Linux update channel, then the container images. - Run on any other branch, it's a dry run that builds, signs and verifies, as before. - Release tags are pinned to the dispatched commit (`target_commitish`), so a merge during a ~30 min release run can't move them. `create-tag` now fails if the tag points anywhere else, where before it swallowed errors. - `build.yml` / `build-stt.yml`: - A push to main publishes only `:edge` and `:<sha>`. - `:latest` moves only when the release dispatches them with its tag. They build exactly that tag. - The weekly sandbox security rebuild now rebuilds the newest release tag instead of main. - `CLAUDE.md` gains a "Releases are cut by hand" section. **Merging this PR doesn't release either:** the merged `build-app.yml` has no push trigger, and the container push publishes only `:edge`/`:<sha>`. **Checked:** - actionlint is clean on all three files (with `gitea.` mapped to `github.`). - The tag-picking script was run locally for each event: - schedule → newest release `v0.4.43` as `:latest`; - dispatch with `v0.4.40` → that commit; - a malformed tag is rejected; - push → `:edge`. - The Gitea dispatch endpoint and the tag API response shape were checked against the live server. **Not yet exercised:** a real release run, which will happen the first time you cut one. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jknapp added 1 commit 2026-11-14 22:55:04 +00:00
CI: cut releases by hand instead of on every merge to main
Secret Scan / scan (push) Successful in 25s
Secret Scan / scan (pull_request) Successful in 10s
Build Container / build-container (pull_request) Successful in 1m57s
Build STT Container / build-stt-container (pull_request) Successful in 4m12s
8787f39a38
Every merge to main that touched app/ published a signed release, and every
merge touching container/ moved :latest, the image installed apps pull. That
made it impossible to land phased work (the AWS host) on main without
shipping each step.

- build-app.yml runs only on workflow_dispatch. Dispatched on main it
  releases; on any other branch it stays a build/sign/verify dry run.
- Release tags are pinned to the dispatched commit (target_commitish), and
  create-tag now fails if the tag points anywhere else.
- After tagging, the release dispatches build.yml and build-stt.yml with the
  tag. They build that tag and move :latest.
- Pushes to main publish containers as :edge and :<sha> only. The weekly
  security rebuild rebuilds the newest release tag, not main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jknapp added 1 commit 2026-11-14 22:56:41 +00:00
CI: only main publishes :latest, and only from a tag on main
Secret Scan / scan (pull_request) Successful in 12s
Secret Scan / scan (push) Successful in 5s
Build STT Container / build-stt-container (pull_request) Successful in 2m33s
Build Container / build-container (pull_request) Successful in 18m56s
bd0a52269b
A dispatch from another branch, or a v* tag cut on a branch, could otherwise
become the image every user pulls. An older tag on main is still accepted
so a rollback works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jknapp merged commit b6e59154cc into main 2026-11-14 23:16:38 +00:00
jknapp deleted branch ci/release-gate 2026-11-14 23:16:41 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: CyberCoveLLC/Triple-C#79