Exercise the release workflow end to end. v0.3.1 was tagged and published by
hand before release.yml existed, so the tag-triggered path has never actually
run; this tag is the first to go through it.
Add docs/releases/v0.3.2.md, which release.yml picks up as the release body
instead of falling back to generated notes. The notes cover the whole v0.2.0
range rather than just this tag, since v0.3.0 through v0.3.2 landed in quick
succession and the F1 to Ctrl+H change is the one thing an upgrader must know.
Also record the measured reproducibility result: with modes, locale and
timezone pinned, ubuntu-latest and a workstation on a different umask, locale
and timezone now produce identical checksums for all five archives.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
release.sh normalized entry order, ownership and mtimes, but not permissions,
so the archives inherited the builder's umask. A host with umask 002 packaged
664/775 while ubuntu-latest packaged 644/755, and the two archives hashed
differently even though every file inside was byte-identical:
CI -rw-r--r-- README.md local -rw-rw-r-- README.md
CI -rwxr-xr-x sshkeeper local -rwxrwxr-x sshkeeper
Force 755 on directories and the program, 644 on everything else. Building the
same commit under umask 002 and umask 022 now yields identical checksums.
Also correct the reproducibility claim in the release docs. What is reproducible
is the binary, given the same commit and Go version; the archive hash still
depends on the host tar and gzip, so the documented verification step now
compares the extracted binary instead.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The repository had no automation at all: every release was packaged and
published by hand, and nothing ran tests on a pull request.
- ci.yml runs gofmt, go vet and go test on Linux and macOS, and cross-builds
all five release targets. macOS is a stated release target but was never
actually exercised, only cross-compiled.
- release.yml publishes on a v* tag. It gates on `make release-check` so a red
suite cannot ship, and builds through release.sh rather than duplicating the
packaging rules, so CI archives stay byte-identical to local ones. A
hand-written docs/releases/<tag>.md becomes the release body when present,
otherwise notes are generated from history.
- nightly.yml rebuilds the tip of main on every push and replaces a rolling
`nightly` prerelease. Prerelease is deliberate: it keeps GitHub's `Latest`
badge on the newest real release rather than on an untested build.
The rolling tag is why version discovery was pinned to v* in the previous
commit; nightly.yml depends on that filter already being in place.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nightly builds will move a rolling `nightly` tag across main. A plain
`git describe --tags` returns whichever tag is nearest, so once that tag exists
every build — including a real release build — would report its version as
"nightly" and lose the release lineage entirely.
Restrict discovery to `v*` so the rolling tag is invisible to versioning:
with a nightly tag ahead of v0.3.1
git describe --tags → nightly
git describe --tags --match 'v*' → v0.3.1-1-gf940087
Land this before the nightly workflow exists, so no build is ever stamped from
the rolling tag.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Complete the final task of the unified TUI shell plan, which had been left
undone: the code dropped F1 in favour of Ctrl+H, but README and the guide
still documented F1 as the full-help key in nine places, and the repository
screenshots still showed the pre-shell UI.
- Replace every F1 reference in README.md and docs/guide.md with Ctrl+H,
including the two ASCII help blocks that mirror runtime output.
- Document the BS/DEL terminal constraint: Ctrl+H is BS (0x08) while xterm
sends DEL (0x7F) for Backspace, so help and text editing do not collide.
- Recapture all five screenshots from the current binary in a real xterm at
120x40, 80x24 and 60x16 using an isolated XDG profile.
Runtime verification in xterm confirms Ctrl+H opens full help while seven
Backspace presses correctly trim typed text, and that every captured screen
carries the header, framed content and bottom-anchored footer.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>