원클릭으로
release
Prep and publish a VoidReader release — version bump, CHANGELOG, house-style notes, tag, and edit the release body after CI publishes
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Prep and publish a VoidReader release — version bump, CHANGELOG, house-style notes, tag, and edit the release body after CI publishes
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | release |
| description | Prep and publish a VoidReader release — version bump, CHANGELOG, house-style notes, tag, and edit the release body after CI publishes |
| disable-model-invocation | true |
| user-invocable | true |
| arguments | ["version"] |
The full pipeline for $version. A human pushes a v$version tag; GitHub's release.yml does the build / sign / notarize / GitHub-release / Homebrew-cask work automatically. Everything before the tag is prep; the nice release body is edited in after CI publishes.
.github/workflows/release.yml triggers on any v* tag push and, on a macOS runner:
project.yml's version (both generated Info.plists) == the tag, or fails before building.make dmg-signed; Apple creds are CI secrets)..app's CFBundleShortVersionString == the tag, or refuses to publish.--generate-notes).lazypower/homebrew-tap (version + SHA256).Two consequences: the tag is the trigger, the version gate is strict (drift fails the job), and the good release body is not written by CI — you replace the auto notes in Step 7.
Remotes: github is where releases live (the workflow is GitHub-only); origin (gitea) only runs the test/perf CI. The release tag must reach github to fire the workflow.
x.y.Z): fixes, hardening, packaging, cleanup — no new user-facing feature. However chonky. (1.2.1 "Trust Issues" was ~30 fixes and is still a patch.)x.Y.0): a genuine new capability shipped.Don't inflate a fixes release to a minor because it's big.
main, clean tree, the release work merged.HEAD.git log $(git describe --tags --abbrev=0)..HEAD --onelineSet CFBundleShortVersionString to $version in both targets in project.yml:
VoidReader (~line 54)VoidReaderQuickLook (~line 100)Both must match the tag or the release job fails the version gate (pre-build and post-build). make project regenerates the Info.plists if you want to verify locally with PlistBuddy.
Add a top entry to CHANGELOG.md (just below the intro ---), newest-first, in house format:
## [$version] - YYYY-MM-DD
### The "<Name>" Release
<one-line tagline>
#### Fixed
- ...
#### Added / Performance / Housekeeping (as applicable)
- ...
#### The Numbers (optional, for big releases)
- ...
Reality check first. .gitea/workflows/test-perf-lab.yml is path-gated — it only runs when scripts/perf/**, PERFORMANCE.md, or its fixtures change. A normal fixes/hardening release touches none of those, so there's usually no fresh perf run on the release commit (0 test-perf-lab runs in the last 50 pushes, as of 1.2.1). Don't document numbers that don't exist.
workflow_dispatch, so trigger it first: run Performance Lab → "Run workflow" in the Gitea Actions UI (or dispatch via API), wait for it to complete, then pull:# most recent COMPLETED perf-lab run (widen the window; it's rare)
tea api --login gitea.wabash.place "repos/chuck/VoidReader/actions/runs?limit=50" | python3 -c "
import json,sys
for r in json.load(sys.stdin).get('workflow_runs',[]):
if r.get('path','').split('@')[0]=='test-perf-lab.yml' and r['status']=='completed':
print(r['id']); break"
# jobs, then the '=== window ===' summaries
tea api --login gitea.wabash.place repos/chuck/VoidReader/actions/runs/<RUN_ID>/jobs
tea api --login gitea.wabash.place repos/chuck/VoidReader/actions/jobs/<JOB_ID>/logs | grep -A20 '=== window ==='
Scenarios: open-large, scroll-to-bottom, search-navigate, edit-toggle. Summarize samples, idle-vs-work ratio, top app frames for the notes table.
House voice — self-aware, cheeky, technically grounded:
VoidReader X.Y.Z — "Subtitle"Save it to a file (e.g. scratchpad/RELEASE_NOTES_$version.md) for Step 7.
git add project.yml CHANGELOG.md
git commit -m "release: v$version"
git push github main # 1) commits first
git tag v$version
git push github v$version # 2) tag SEPARATELY — THIS fires release.yml
Push commits and the tag as separate pushes (a combined push can miss the tag trigger). Then keep gitea in sync: git push origin main (and git push origin v$version to mirror the tag if you like — gitea won't publish, it just keeps history aligned).
CI created the release with --generate-notes. Swap in the real body:
gh release edit v$version --repo lazypower/VoidReader --notes-file scratchpad/RELEASE_NOTES_$version.md
Verify:
gh release view v$version --repo lazypower/VoidReader # body + DMG asset attached
# confirm the cask bumped: check lazypower/homebrew-tap Casks/voidreader.rb
project.yml targets, then re-tag:
git push github :v$version && git tag -d v$version → fix → re-tag → push tag again.make dmg-signed needs your Developer ID + notarization credentials and won't match CI's artifact.github.