chore: add release verification scripts

This commit is contained in:
Peter Steinberger 2025-12-31 20:15:56 +01:00
parent ac8cfe23fe
commit 6a17462eab
3 changed files with 166 additions and 0 deletions

View File

@ -8,6 +8,12 @@ This playbook mirrors the Homebrew + GitHub flow used in `../camsnap`.
Always do **all** steps below (CI + changelog + tag + GitHub release artifacts + tap update + Homebrew sanity install). No partial releases.
Shortcut scripts (preferred, keep notes non-empty):
```sh
scripts/release.sh X.Y.Z
scripts/verify-release.sh X.Y.Z
```
Assumptions:
- Repo: `steipete/gogcli`
- Tap repo: `../homebrew-tap` (tap: `steipete/tap`)
@ -55,6 +61,8 @@ gh run list -L 5 --workflow release.yml
gh release view vX.Y.Z
```
Ensure GitHub release notes are not empty (mirror the changelog section).
If the workflow needs a rerun:
```sh
gh workflow run release.yml -f tag=vX.Y.Z

62
scripts/release.sh Executable file
View File

@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail
version="${1:-}"
if [[ -z "$version" ]]; then
echo "usage: scripts/release.sh X.Y.Z" >&2
exit 2
fi
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$root"
branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ "$branch" != "main" ]]; then
echo "expected branch main (got $branch)" >&2
exit 2
fi
if [[ -n "$(git status --porcelain)" ]]; then
echo "working tree not clean" >&2
exit 2
fi
changelog="CHANGELOG.md"
if ! rg -q "^## ${version} - " "$changelog"; then
echo "missing changelog section for $version" >&2
exit 2
fi
if rg -q "^## ${version} - Unreleased" "$changelog"; then
echo "changelog section still Unreleased for $version" >&2
exit 2
fi
notes_file="$(mktemp "/tmp/gogcli-release-notes.XXXXXX.md")"
awk -v ver="$version" '
$0 ~ "^## "ver" " {print "## "ver; in=1; next}
in && /^## / {exit}
in {print}
' "$changelog" | sed '/^$/d' > "$notes_file"
if [[ ! -s "$notes_file" ]]; then
echo "release notes empty for $version" >&2
exit 2
fi
make ci
if git rev-parse "v$version" >/dev/null 2>&1; then
echo "tag v$version already exists"
else
git tag -a "v$version" -m "Release $version"
git push origin main --tags
fi
if gh release view "v$version" >/dev/null 2>&1; then
gh release edit "v$version" --notes-file "$notes_file"
else
gh release create "v$version" --notes-file "$notes_file"
fi
rm -f "$notes_file"
echo "Release notes updated. Next: scripts/verify-release.sh $version"

96
scripts/verify-release.sh Executable file
View File

@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -euo pipefail
version="${1:-}"
if [[ -z "$version" ]]; then
echo "usage: scripts/verify-release.sh X.Y.Z" >&2
exit 2
fi
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$root"
changelog="CHANGELOG.md"
if ! rg -q "^## ${version} - " "$changelog"; then
echo "missing changelog section for $version" >&2
exit 2
fi
if rg -q "^## ${version} - Unreleased" "$changelog"; then
echo "changelog section still Unreleased for $version" >&2
exit 2
fi
notes_file="$(mktemp "/tmp/gogcli-release-notes.XXXXXX.md")"
awk -v ver="$version" '
$0 ~ "^## "ver" " {print "## "ver; in=1; next}
in && /^## / {exit}
in {print}
' "$changelog" | sed '/^$/d' > "$notes_file"
if [[ ! -s "$notes_file" ]]; then
echo "release notes empty for $version" >&2
exit 2
fi
release_body="$(gh release view "v$version" --json body -q .body)"
if [[ -z "$release_body" ]]; then
echo "GitHub release notes empty for v$version" >&2
exit 2
fi
assets_count="$(gh release view "v$version" --json assets -q '.assets | length')"
if [[ "$assets_count" -eq 0 ]]; then
echo "no GitHub release assets for v$version" >&2
exit 2
fi
release_run_id="$(gh run list -L 20 --workflow release.yml --json databaseId,conclusion,headBranch -q ".[] | select(.headBranch==\"v$version\") | select(.conclusion==\"success\") | .databaseId" | head -n1)"
if [[ -z "$release_run_id" ]]; then
echo "release workflow not green for v$version" >&2
exit 2
fi
ci_ok="$(gh run list -L 1 --workflow ci --branch main --json conclusion -q '.[0].conclusion')"
if [[ "$ci_ok" != "success" ]]; then
echo "CI not green for main" >&2
exit 2
fi
make ci
sha_url="https://github.com/steipete/gogcli/archive/refs/tags/v${version}.tar.gz"
sha_file="/tmp/gogcli-${version}.tar.gz"
rm -f "$sha_file"
curl -L -o "$sha_file" "$sha_url"
sha256="$(shasum -a 256 "$sha_file" | awk '{print $1}')"
formula_path="../homebrew-tap/Formula/gogcli.rb"
if [[ ! -f "$formula_path" ]]; then
echo "missing formula at $formula_path" >&2
exit 2
fi
formula_url="$(rg -n '^\s*url ' "$formula_path" | sed -E 's/\s*url "([^"]+)"/\1/')"
formula_sha="$(rg -n '^\s*sha256 ' "$formula_path" | sed -E 's/\s*sha256 "([^"]+)"/\1/')"
if [[ "$formula_url" != "$sha_url" ]]; then
echo "formula url mismatch: $formula_url" >&2
exit 2
fi
if [[ "$formula_sha" != "$sha256" ]]; then
echo "formula sha mismatch: $formula_sha (expected $sha256)" >&2
exit 2
fi
brew update
brew uninstall gogcli || true
brew untap steipete/tap || true
brew tap steipete/tap
brew install steipete/tap/gogcli
brew test steipete/tap/gogcli
gog --help
rm -f "$notes_file" "$sha_file"
echo "Release v$version verified (CI, GitHub release notes/assets, Homebrew install/test)."