feat: build the .deb and draft a GitHub release on tag push - #102
Merged
Conversation
Every release from v1.0.0 to v1.8.0 was built and uploaded by hand, and
v1.9.0 was tagged on 2026-08-08 without one: the tag pushed, CI went
green, and nothing produced an artifact, because the repo has only ever
had ci.yml and version-sync.yml. Neither builds anything.
Add .github/workflows/release.yml, triggered by a vX.Y.Z tag push or by
workflow_dispatch with a tag input. The dispatch path exists so tags that
predate this workflow (v1.9.0 among them) can be shipped without deleting
and re-pushing a tag. The job checks the tag against gmrs_tty.__version__
before it spends ten minutes on wheels, which finally gives
check_version_sync.check_tag_matches() a caller -- it reads GITHUB_REF and
has never run under a tag ref until now.
Building on a runner needed two gaps closed. Models/ and Voices/ are both
gitignored but build-deb.sh hard-fails without them: the STT side already
had bootstrap_models.py, the voices side had nothing, so add
scripts/voices.txt as the manifest of what ships and scripts/fetch-voices.sh
to download it. The script is idempotent and writes through a .part file,
so an interrupted run cannot leave a truncated voice that the next run
skips. build-deb.sh now honors a PYTHON override, since a runner has
neither a .venv nor a python3.13 on PATH.
The workflow drafts the release rather than publishing it. Release titles
here are hand-written ("v1.9.0 - Tabbed settings, ..."), so it does the
slow mechanical half and leaves the title and notes to a human.
A size guard fails the build past 1.9 GiB. build-deb.sh leans on
--extra-index-url .../whl/cpu winning on PEP 440 local-version ordering to
keep torch CPU-only; if a version skew between the indexes ever pulls the
nvidia-* wheels instead, that is a loud CI failure rather than a release
asset that silently blows the 2 GB limit.
Also drop two stale claims the deb outgrew several releases ago: the
header comment saying the models are NOT bundled, and the control
Description advertising a speaker-identification model that no source file
references. tests/unit/test_voices_manifest.py validates the manifest
offline and pins both fixes against drifting back.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Why
v1.9.0was tagged and pushed on 2026-08-08. Both CI workflows passed, and no release exists and no.debwas ever produced — because the repo has never had release automation..github/workflows/holds onlyci.ymlandversion-sync.yml; neither builds an artifact. Every release from v1.0.0 through v1.8.0 was built locally and uploaded by hand.The intent was already half there:
scripts/check_version_sync.pydefinescheck_tag_matches(), which readsGITHUB_REFand fails when arefs/tags/vX.Y.Zref disagrees withgmrs_tty.__version__. Nothing has ever run it under a tag ref. This gives it a caller.What
.github/workflows/release.yml— on av*tag push (orworkflow_dispatchwith ataginput), a singleubuntu-latestjob checks the tag against the tree, fetches the Whisper model and the Piper voices, builds the deb, checks it against the asset budget, and opens a draft release with the deb attached.workflow_dispatchis howv1.9.0gets shipped: the tag already exists, and re-pushing it to trigger a build would rewrite release history.Draft, not published. Release titles here are hand-written (
v1.9.0 — Tabbed settings, ...). The workflow does the slow mechanical half; the title and notes stay human.scripts/voices.txt+scripts/fetch-voices.sh—Models/andVoices/are both gitignored, butbuild-deb.shhard-fails without them, and a runner starts with neither. The STT side already hadbootstrap_models.py; the voices side had nothing. The manifest is now the single source of truth for what ships, and the fetch script downloads it intoVoices/. It skips files already present, so it is safe to run locally, and it downloads through a.partfile so an interrupted run cannot leave a truncated voice that the next run happily skips.scripts/build-deb.sh— honors aPYTHONenv override ahead of the.venv/python3.13/python3fallbacks, since a runner has neither a.venvnor apython3.13onPATH. Also drops two stale claims the deb outgrew several releases ago: the header comment saying the models are NOT bundled (sections 2c/2d have bundled both for a while) and the controlDescriptionadvertising a speaker-identification model that no source file references.tests/unit/test_voices_manifest.py— offline, no network. Validates the manifest shape and no duplicate basenames, checks the fetch script is executable and reads the manifest, and pins the two comment fixes against drifting back.Verification
Run locally on this branch:
flake8 gmrs_tty tests scripts bootstrap_models.pyclean;pytest1129 passedcheck_version_sync.pywithGITHUB_REF=refs/tags/v1.9.0exits 0; withrefs/tags/v1.8.0exits 1 —tag v1.8.0 does not match gmrs_tty.__version__ 1.9.0fetch-voices.shagainst the existingVoices/skips all 10 files, exit 0. Against an empty directory it fetches all 5 pairs non-empty. All five.onnxURLs return HTTP 206 on a ranged probe.PYTHON=.venv/bin/python ./scripts/build-deb.shproducesgmrs-tty_1.9.0_amd64.deb, 1,632,666,144 bytes (1.52 GiB).dpkg-deb -IshowsVersion: 1.9.0and the corrected Description.Size context: 1.63 GB against v1.8.0's 1.61 GB, so torch is still resolving CPU-only.
Risks
build-deb.shrelies on--extra-index-url .../whl/cpuwinning because2.x.y+cpusorts above PyPI's2.x.yunder PEP 440 local-version ordering. That has held, but a version skew between the two indexes would silently pull ~2 GB ofnvidia-*wheels. The 1.9 GiB size guard turns that into a loud CI failure instead of a release asset that blows the 2 GB per-asset limit. If it fires, the fix is a+cpuconstraints file. The other lever on asset size is trimmingscripts/voices.txt.After merge
gh workflow run release.yml -f tag=v1.9.0, then edit the draft's title to the usualv1.9.0 — <highlights>form and publish. Untested on CI until this lands onmain—workflow_dispatchneeds the workflow file on the default branch.🤖 Generated with Claude Code