Release & hotfix process¶
How a Prompt Gate release is cut, what the CI does, and how to ship a hotfix without breaking the trunk. Read alongside the root CHANGELOG.md.
Branch & tag model¶
| Ref | Role |
|---|---|
develop |
Working trunk. Direct push allowed. Everything lands here first. |
main |
Release line. Reserved for release merges + tags. |
config-{e,f,g,h,l} |
Long-lived engine variants. Never merged across configs. |
v{major}.{minor}.{patch} |
Annotated release tags (git tag -a). |
v{x}.{y}.{z}-config-{c} |
Per-config release tags. |
SemVer applies from 1.0.0 onward. The 0.x line was pre-release
iteration where feature releases could break compatibility.
What triggers what¶
| Workflow | Trigger | Produces |
|---|---|---|
release.yml |
push of any v* tag |
agents ×5 platforms, electron dmg/exe/AppImage/deb, extensions (Chrome/FF/Safari), installers, a GitHub Release |
ci.yml |
push to main only |
tests / vet / build gate |
docs.yml |
docs changes | GitHub Pages docs site |
Pushing to
developbuilds nothing. Neither workflow hasworkflow_dispatch— the only way to produce a build is to cut av*tag. CI does not run ondevelop, so runmake testlocally before tagging.
Cutting a normal release¶
- Land everything on
developand confirm green locally: - Finalize the CHANGELOG. Move
[Unreleased]content into a## [x.y.z] — YYYY-MM-DDsection; leave a fresh empty[Unreleased]. - Promote to
main(release line): - Tag (annotated) once CI on
mainis green: - Edit the GitHub Release body.
action-gh-releaseruns withgenerate_release_notes: true(auto commit list); replace/prepend it with the human-written notes (template lives with the release draft). - Smoke the artifacts — download one per OS, install, toggle protection, confirm the agent starts.
The release job runs under GitHub Actions with
contents: write; no personal account is involved. For manual maintainer pushes, ensure yourghaccount has push access to the repo (a 404 on push usually means the active account lacks access — switch withgh auth switch).
Cutting a hotfix (x.y.Z+1)¶
For an urgent fix against an already-released version:
- Branch from the release tag, not from a drifted
develop: - Make the smallest fix. Add/adjust a regression test. Run
make test. - Add a
## [x.y.z+1] — YYYY-MM-DDCHANGELOG section. - Merge the hotfix branch into
main, tagvX.Y.(Z+1), push the tag (triggers the build + Release). - Back-merge into
developso the fix isn't lost on the next release: - Delete the hotfix branch.
A false-positive flood is the most likely launch-day hotfix trigger;
the FP issue template feeds it. Keep the v1.0.1 window pre-planned.
Rolling back a bad release¶
The published binaries can't be un-downloaded, but you can stop new users from getting a broken build:
- Mark the GitHub Release as "pre-release" (or delete it) so it stops being "Latest".
- Delete the bad tag if you'll re-cut the same number, or just move forward to the next patch (preferred — tags are cheap, history is clearer):
- Ship the fix as a new patch via the hotfix flow. Don't reuse a tag that ever had a published Release object.
- Note the bad version in the CHANGELOG ("yanked").
Signing status (gap)¶
Builds from release.yml are currently unsigned — CI reports
"0 valid identities found" and code signing is skipped:
- macOS: Gatekeeper warns; users run
xattr -cr "/Applications/Prompt Gate.app". - Windows: SmartScreen warns until reputation accrues.
To close this, add Developer ID / Authenticode creds as repo secrets
(CSC_LINK, CSC_KEY_PASSWORD, APPLE_ID,
APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID) and wire the electron
signing/notarize step. Until then, every release note must carry the
unsigned-install caveat.
Gotchas the pipeline has already bitten us on¶
| Symptom | Cause | Fix (already in tree) |
|---|---|---|
All 3 electron jobs crash Cannot read properties of null (reading 'channel') |
missing repository field in electron/package.json (electron-updater needs it to resolve a publish channel) |
keep the repository field |
Installer (macos) dies GH_TOKEN is not set |
the make electron path tried to auto-publish on tag |
--publish never pinned in the package script; action-gh-release owns upload |
| Tag pushed but no Release appears | tag didn't match v*, or a build job failed |
check Actions; the release job needs all build jobs |
Lesson: when changing electron-builder config, verify the
make {macos,linux} installer path end-to-end, not just
electron-builder --mac — the installer path differs from the
standalone electron jobs.
Pre-tag checklist¶
The Critical column of the pre-launch checklist must be green before the
first v* tag: signed binaries, CHANGELOG finalized, privacy invariant
CI green on main, telemetry off-by-default verified, release notes
drafted, social-preview image. See the launch tracker for the live list.