Skip to content

Commit f7c352b

Browse files
committed
docs: document release process and pipeline plan
Add a Releases section to the README explaining the tag-to-release flow, and check in the implementation plan for the release pipeline.
1 parent 283f1a5 commit f7c352b

2 files changed

Lines changed: 129 additions & 0 deletions

File tree

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,18 @@ Configure your STT provider (Groq, OpenAI, or any OpenAI-compatible endpoint) vi
2222
- Persistent settings and secure key storage
2323
- Microphone device selection with auto-calibration
2424
- Post-type key support (Enter, Tab, Space, Backspace)
25+
26+
## Releases
27+
28+
Pushing a version tag builds the Windows executable and publishes a GitHub Release
29+
automatically (see `.github/workflows/release.yml`):
30+
31+
```bash
32+
git tag v1.0.0
33+
git push origin v1.0.0
34+
```
35+
36+
The workflow runs the test suite, builds with PyInstaller, and attaches a
37+
`Screamer-v1.0.0-windows-x64.zip` (plus a `.sha256` checksum) to the release.
38+
Tags with a hyphen (e.g. `v1.0.0-rc1`) are published as pre-releases. Download the
39+
zip, extract it, and run `Screamer\Screamer.exe`.

docs/RELEASE_PIPELINE_PLAN.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# Plan — GitHub Release Pipeline
2+
3+
## Goal
4+
On a version tag push, automatically build the Windows `.exe`, package it, and publish a GitHub Release with the artifact attached. No manual build/upload steps.
5+
6+
## Scope
7+
- New workflow file: `.github/workflows/release.yml`.
8+
- Trigger: push of a tag matching `v*` (e.g. `v1.0.0`, `v1.2.0-rc1`).
9+
- Build on `windows-latest` (PyInstaller produces a Windows-native onedir bundle; cannot cross-build).
10+
- Gate the release on the test suite passing first (don't ship a broken build).
11+
- Package `dist\Screamer\` (onedir output) into a versioned zip.
12+
- Publish a GitHub Release using the built-in `gh` CLI (no third-party action — matches project's minimal-dependency ethos).
13+
- Auto-generate release notes from commit history.
14+
- Mark pre-releases automatically when the tag contains a hyphen (`-rc`, `-beta`, etc.).
15+
- Attach a SHA256 checksum file alongside the zip.
16+
17+
Out of scope: code signing (separate concern, needs a cert), auto-bumping version numbers, changelog curation, multi-arch.
18+
19+
## Key facts grounding the design
20+
- `screamer.spec` uses `COLLECT` → output is a **directory** `dist\Screamer\` containing `Screamer.exe` + Qt DLLs. Not a single file. So the artifact must be a **zip of the folder**.
21+
- `build_windows.ps1` creates its own `.venv`. In CI that's wasteful — install deps into the runner's Python directly and call PyInstaller, mirroring the build script's pip + pyinstaller steps.
22+
- Existing `ci.yml` already runs the unittest suite on `windows-latest` with `QT_QPA_PLATFORM=offscreen`. The release workflow reuses that exact invocation as a gate.
23+
- Build deps: `requirements.txt` + `requirements-build.txt` (pins `pyinstaller==6.14.2`).
24+
- Python 3.12 is the target per `docs/PLAN.md`.
25+
26+
## Workflow design (`.github/workflows/release.yml`)
27+
28+
```yaml
29+
name: Release
30+
31+
on:
32+
push:
33+
tags:
34+
- "v*"
35+
36+
permissions:
37+
contents: write # required for gh release create
38+
39+
jobs:
40+
release:
41+
name: build and publish (windows / py3.12)
42+
runs-on: windows-latest
43+
steps:
44+
- uses: actions/checkout@v4
45+
46+
- uses: actions/setup-python@v5
47+
with:
48+
python-version: "3.12"
49+
cache: pip
50+
51+
- name: Install dependencies
52+
run: |
53+
python -m pip install --upgrade pip
54+
pip install -r requirements.txt -r requirements-build.txt
55+
56+
- name: Run tests (gate)
57+
env:
58+
QT_QPA_PLATFORM: offscreen
59+
run: python -m unittest discover -s tests -v
60+
61+
- name: Build executable
62+
run: python -m PyInstaller --noconfirm --clean screamer.spec
63+
64+
- name: Package
65+
shell: pwsh
66+
run: |
67+
$tag = $env:GITHUB_REF_NAME
68+
$zip = "Screamer-$tag-windows-x64.zip"
69+
Compress-Archive -Path dist\Screamer -DestinationPath $zip
70+
$hash = (Get-FileHash $zip -Algorithm SHA256).Hash.ToLower()
71+
"$hash $zip" | Out-File -FilePath "$zip.sha256" -Encoding ascii
72+
"ASSET_ZIP=$zip" | Out-File -FilePath $env:GITHUB_ENV -Append
73+
"ASSET_SHA=$zip.sha256" | Out-File -FilePath $env:GITHUB_ENV -Append
74+
75+
- name: Publish release
76+
env:
77+
GH_TOKEN: ${{ github.token }}
78+
shell: pwsh
79+
run: |
80+
$tag = $env:GITHUB_REF_NAME
81+
$ghArgs = @(
82+
"release", "create", $tag,
83+
$env:ASSET_ZIP, $env:ASSET_SHA,
84+
"--title", $tag,
85+
"--generate-notes"
86+
)
87+
if ($tag -match "-") { $ghArgs += "--prerelease" }
88+
& gh @ghArgs
89+
```
90+
91+
> Review fix: the earlier draft passed `$pre` (possibly an empty string) as a trailing
92+
> positional argument to `gh release create`. On a stable tag (no hyphen) that empty
93+
> string would be parsed as an extra asset path with an empty name and the publish would
94+
> fail. Building an args array and only appending `--prerelease` when needed avoids this.
95+
96+
## Steps to implement
97+
1. Create `.github/workflows/release.yml` with the workflow above.
98+
2. Validate YAML syntax locally (Python `yaml.safe_load`).
99+
3. Document the release process in `README.md` (a short "Releases" section: tag `vX.Y.Z`, push tag, CI builds and publishes).
100+
4. Verify nothing else references release artifacts inconsistently.
101+
102+
## Verification
103+
- YAML parses without error.
104+
- Logic walk-through: tag `v1.0.0` → tests run → PyInstaller builds `dist\Screamer\` → zip created → `gh release create` publishes with notes, non-prerelease. Tag `v1.0.0-rc1` → same but `--prerelease`.
105+
- Cannot fully run end-to-end without pushing a real tag; that is left to the user. The workflow is validated by syntax + the fact that its build/test steps mirror the already-green `ci.yml` and `build_windows.ps1`.
106+
107+
## Risks
108+
- PyInstaller build time on CI (~several min) — acceptable, runs only on tags.
109+
- `gh release create` fails if a release for the tag already exists — acceptable (re-tag or delete release to retry).
110+
- If tests are flaky on CI, releases block — desired behavior (gate).
111+
112+
## Commit split
113+
1. `ci: add release workflow triggered on version tags`
114+
2. `docs: document the release/tagging process in README`

0 commit comments

Comments
 (0)