Release and packaging runbook
State: release preparation authorized (Sep 2, 2026). An earlier v0.3.0 tag attempt triggered nothing (fork Actions quirk) and was deleted; zero releases exist. The working tree is now version 0.4.0 in Cargo.toml. After the release workflow lands on main and its branch smoke run passes, run this top to bottom with that version.
0. Cut, verify, and publish the release
git tag v0.4.0 && git push origin v0.4.0Then verify a run appeared (gh run list --repo kreatzzz/woofer). A tag push runs the complete build and verification matrix but does not publish a GitHub release. The workflow also accepts a manual dispatch: a branch run is an isolated smoke build named 0.4.0-dev.<run-number>, while a dispatch from the release tag can publish only when the publish input is explicitly set to true.
After the tag run is green, start the publish pass from that same tag:
gh workflow run Release --repo kreatzzz/woofer --ref v0.4.0 -f publish=trueThe assemble job validates every name, archive path, and checksum before the publish job uploads anything. Each successful build contains:
- Linux x86_64 and arm64 portable
.tar.gzarchives plus AppImages, built with pinned, SHA-256-verified AppImage tools; - Windows x86_64 and arm64 portable
.ziparchives plus per-user Inno Setup installers; - one universal macOS DMG; and
- a sorted
checksums.txtcovering every asset.
Windows Authenticode signing is optional, enabled only when both documented certificate secrets exist. macOS signing and notarization are optional too, but require the complete six-secret Apple contract; otherwise the DMG is ad-hoc/unsigned and needs the usual first-open approval. Tag-push smoke runs never receive signing secrets.
1. Homebrew tap (~10 min, fully scriptable)
gh repo create kreatzzz/homebrew-tap --public --clone=false
git clone https://github.com/kreatzzz/homebrew-tap /tmp/tap && cd /tmp/tap
mkdir -p CasksCasks/woofer.rb:
cask "woofer" do
version "0.4.0"
sha256 "SHA256_OF_THE_DMG" # from the release's checksums.txt
url "https://github.com/kreatzzz/woofer/releases/download/v#{version}/woofer-v#{version}-macos-universal.dmg"
name "Woofer"
desc "Fast, lightweight, native Spotify client"
homepage "https://github.com/kreatzzz/woofer"
livecheck do
url :url
strategy :github_latest
end
app "Woofer.app"
endCommit, push. Users: brew install kreatzzz/tap/woofer. Every future release: bump version + sha256 in one tap commit. If the first DMG is unsigned, put the first-open note in the README: right-click → Open, or xattr -cr /Applications/Woofer.app. Add the direct release URL only after the explicit publish pass has created a public asset.
2. AUR (~20 min, needs the user's aur.archlinux.org account + SSH key)
Two packages, each pushed to aur@aur.archlinux.org:<pkg>.git:
woofer (release tarball, x86_64):
pkgname=woofer
pkgver=0.4.0
pkgrel=1
pkgdesc="Fast, lightweight, native Spotify client built with Rust and egui"
arch=('x86_64')
url="https://github.com/kreatzzz/woofer"
license=('MIT')
depends=('alsa-lib' 'libpulse' 'wayland' 'libxkbcommon')
conflicts=('woofer-git')
source=("$pkgname-$pkgver.tar.gz::$url/releases/download/v$pkgver/woofer-v$pkgver-x86_64-unknown-linux-gnu.tar.gz")
sha256sums=('FILL_FROM_checksums.txt')
package() {
cd "$srcdir/$pkgname-v$pkgver-x86_64-unknown-linux-gnu"
install -Dm755 woofer "$pkgdir/usr/bin/woofer"
install -Dm644 packaging/applications/woofer.desktop \
"$pkgdir/usr/share/applications/woofer.desktop"
install -Dm644 packaging/icons/woofer.svg \
"$pkgdir/usr/share/icons/hicolor/scalable/apps/woofer.svg"
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/woofer/LICENSE"
}Validate with makepkg -f (or namcap), then git init && git add . && git commit && git push aur:woofer.git. Test with yay -S woofer in a clean chroot if possible.
woofer-git: same shape, makedepends=('cargo' 'git'), source=("$pkgname::git+$url.git"), pkgver() from git describe, build with cargo build --release --locked, same package() installs.
3. winget (Windows; the bureaucratic one)
- Fork
microsoft/winget-pkgsunderkreatzzz, shallow-clone it. - Add
manifests/k/kreatzzz/Woofer/0.4.0/with three YAML files:kreatzzz.Woofer.yaml—PackageIdentifier: kreatzzz.Woofer,PackageVersion: 0.4.0,PackageLocale,Publisher: kreatzzz,PackageName: Woofer,License: MIT,ShortDescription,Moniker: woofer.kreatzzz.Woofer.installer.yaml—InstallerType: inno, both architectures pointing at the GitHub…-setup.exeURLs, each with its sha256 fromchecksums.txt, andInstallerSwitches: { Silent: /VERYSILENT /SUPPRESSMSGBOXES /NORESTART, SilentWithProgress: /SILENT },AppsAndFeaturesEntrieswithProductCodeif the .iss declares one.kreatzzz.Woofer.locale.en-US.yaml— description, tags, homepage.
- Validate locally with
winget validate(on Windows) or thewinget-pkgsCI, then open the PR with their template. The bot verifies the URLs and hashes; a human reviews (1-3 days). First-time submitters need a seasoned GitHub account — having the tap and AUR package public first helps the review.
Future versions: a new version folder per release.
After the first release
- Bump the tap (version + sha256) — one commit.
docs/_guide/download.mdrecords the paused release state and the source install path; add direct package links there when Homebrew/AUR/winget are live.- The update checker (
src/updates.rs) watcheskreatzzz/woofer/releases/latest— it starts working from the first real release.