docs: the finish-the-release runbook and the approved release notes #441
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
| # AsyncAO CI: lint + race tests + alloc-gated benchmarks, then binary builds | |
| # for every platform. Pull requests get downloadable binaries as artifacts. | |
| # | |
| # Each platform builds TWICE via a `variant` matrix: the full default binary | |
| # (Discord Rich Presence bundled — pure stdlib IPC, no DLL, off by default; voice | |
| # chat included) and a lean `-tags "nodiscord novoice"` binary with BOTH the | |
| # Discord integration and the LemmyAO/Nyathena voice chat compiled out entirely. | |
| # Neither is ever a forced dependency; the second artifact exists for anyone who | |
| # wants a binary with zero Discord and zero voice code at all. | |
| name: CI | |
| on: | |
| push: | |
| branches: ["**"] | |
| pull_request: | |
| workflow_dispatch: | |
| env: | |
| GO_VERSION: "1.24" | |
| jobs: | |
| test: | |
| name: Lint & race tests (Linux) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install SDL2 + libwebp + libavif dev packages | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libavif-dev libopus-dev | |
| - name: go vet | |
| run: go vet ./... | |
| - name: staticcheck | |
| uses: dominikh/staticcheck-action@v1 | |
| with: | |
| version: "latest" | |
| install-go: false | |
| - name: Tests (race detector — §17.8 gate) | |
| run: go test -race -timeout 600s -count=1 ./... | |
| - name: "Tests (lean build — Discord + voice compiled out; nodiscord+novoice stubs must build & pass)" | |
| run: go test -tags "nodiscord novoice" -timeout 600s -count=1 ./... | |
| - name: Benchmarks (alloc gates — §15) | |
| run: | | |
| go test -run=NONE -bench=. -benchmem -benchtime=200ms -count=1 ./... | tee bench.txt | |
| # Gate: the learned resolver path must stay ≤ 1 alloc/op and the | |
| # cache hits + render frame at 0 allocs/op. | |
| ! grep -E "BenchmarkBuildCandidates_Learned.* *[2-9] allocs/op" bench.txt | |
| ! grep -E "BenchmarkCacheHit_T[12].* *[1-9] allocs/op" bench.txt | |
| ! grep -E "BenchmarkRenderFrame.* *[1-9] allocs/op" bench.txt | |
| - name: Upload benchmark results | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: benchmarks | |
| path: bench.txt | |
| build-linux: | |
| name: Binary (Linux x86_64)${{ matrix.variant.label }} | |
| runs-on: ubuntu-latest | |
| needs: test | |
| strategy: | |
| matrix: | |
| variant: | |
| - { label: "", tags: "", suffix: "" } | |
| - { label: " - Discord-free, no voice", tags: "nodiscord novoice", suffix: "-nodiscord" } | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install SDL2 + libwebp + libavif dev packages | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libavif-dev libopus-dev | |
| - name: Build | |
| run: | | |
| go build -tags "${{ matrix.variant.tags }}" -pgo=auto -trimpath -ldflags "-s -w" -o asyncao ./cmd/asyncao | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: asyncao-linux-x86_64${{ matrix.variant.suffix }} | |
| path: asyncao | |
| build-windows: | |
| name: Binary (Windows x86_64)${{ matrix.variant.label }} | |
| runs-on: windows-latest | |
| needs: test | |
| strategy: | |
| matrix: | |
| variant: | |
| - { label: "", tags: "", suffix: "" } | |
| - { label: " - Discord-free, no voice", tags: "nodiscord novoice", suffix: "-nodiscord" } | |
| defaults: | |
| run: | |
| shell: msys2 {0} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: msys2/setup-msys2@v2 | |
| with: | |
| msystem: UCRT64 | |
| update: true | |
| install: >- | |
| mingw-w64-ucrt-x86_64-gcc | |
| mingw-w64-ucrt-x86_64-pkgconf | |
| mingw-w64-ucrt-x86_64-SDL2 | |
| mingw-w64-ucrt-x86_64-SDL2_ttf | |
| mingw-w64-ucrt-x86_64-SDL2_mixer | |
| mingw-w64-ucrt-x86_64-libwebp | |
| mingw-w64-ucrt-x86_64-libavif | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| # setup-go only edits the *Windows* PATH and no longer exports GOROOT | |
| # (that stopped at Go 1.9), while the msys2 shell rebuilds a minimal | |
| # PATH of its own — so the toolchain is invisible in the build step. | |
| # Publish GOROOT via GITHUB_ENV; non-PATH env vars do cross into MSYS2. | |
| - name: Expose GOROOT to the MSYS2 shell | |
| shell: pwsh | |
| run: | | |
| "GOROOT=$(go env GOROOT)" | Out-File -FilePath $env:GITHUB_ENV -Append | |
| - name: Build + bundle DLLs | |
| run: | | |
| export PATH="$(cygpath -u "$GOROOT")/bin:$PATH" | |
| export CGO_ENABLED=1 | |
| go build -tags "${{ matrix.variant.tags }}" -pgo=auto -trimpath -ldflags "-s -w" -o dist/asyncao.exe ./cmd/asyncao | |
| # Ship the runtime DLLs next to the exe so it runs anywhere. | |
| ldd dist/asyncao.exe | grep -io '/ucrt64/bin/[a-z0-9_.+-]*\.dll' | sort -u | while read -r dll; do | |
| cp "$dll" dist/ | |
| done | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: asyncao-windows-x86_64${{ matrix.variant.suffix }} | |
| path: dist/ | |
| build-macos: | |
| name: Binary (macOS arm64)${{ matrix.variant.label }} | |
| runs-on: macos-latest | |
| needs: test | |
| strategy: | |
| matrix: | |
| variant: | |
| - { label: "", tags: "", suffix: "" } | |
| - { label: " - Discord-free, no voice", tags: "nodiscord novoice", suffix: "-nodiscord" } | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| # dylibbundler is needed by scripts/bundle-macos.sh. Ogg-Opus MUSIC | |
| # decode/seek comes from the opusfile FORMULA, hard-linked into | |
| # libSDL2_mixer by its formula (--enable-music-opus with the shared/dlopen | |
| # path disabled); the bare `opus` formula is only the codec (voice chat) | |
| # and provides no Ogg demuxing/seeking. brew already pulls opusfile as an | |
| # sdl2_mixer dependency — naming it here pins that requirement explicitly | |
| # (release.yml installs the same list — keep them consistent). | |
| - name: Install SDL2 + libwebp + libavif | |
| run: brew install sdl2 sdl2_ttf sdl2_mixer webp libavif opus opusfile pkg-config dylibbundler | |
| - name: Build | |
| run: | | |
| export CGO_ENABLED=1 | |
| go build -tags "${{ matrix.variant.tags }}" -pgo=auto -trimpath -ldflags "-s -w" -o asyncao ./cmd/asyncao | |
| # Run the release-time dylib bundler here too, BLOCKING, purely for its | |
| # built-in otool assertion: if a new dependency ever links against a | |
| # Homebrew path that the bundler can't rewrite, this fails the build and | |
| # catches the "Library not loaded on a clean Mac" regression before release. | |
| - name: Bundle dylibs + assert no Homebrew paths remain | |
| run: | | |
| bash scripts/bundle-macos.sh asyncao macos-stage | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: asyncao-macos-arm64${{ matrix.variant.suffix }} | |
| path: asyncao | |
| # The bare Linux binary above runs only where SDL2/webp/avif are already | |
| # installed. This job packages a self-contained AppImage — one executable that | |
| # bundles the runtime libraries — so non-Windows users get a download that | |
| # "just works" like the Windows DLL bundle does. (Default variant; the | |
| # Discord-free flavor remains available as the bare binary artifact.) | |
| appimage-linux: | |
| name: AppImage (Linux x86_64)${{ matrix.variant.label }} | |
| runs-on: ubuntu-latest | |
| needs: test | |
| strategy: | |
| matrix: | |
| variant: | |
| - { label: "", tags: "", suffix: "", output: "AsyncAO-x86_64.AppImage" } | |
| - { label: " - Discord-free, no voice", tags: "nodiscord novoice", suffix: "-nodiscord", output: "AsyncAO-nodiscord-x86_64.AppImage" } | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install SDL2 + libwebp + libavif dev packages + AppImage tooling | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libwebp-dev libavif-dev libopus-dev \ | |
| patchelf desktop-file-utils | |
| - name: Build the binary | |
| run: | | |
| export CGO_ENABLED=1 | |
| go build -tags "${{ matrix.variant.tags }}" -pgo=auto -trimpath -ldflags "-s -w" -o asyncao ./cmd/asyncao | |
| - name: Package the AppImage | |
| run: | | |
| chmod +x scripts/build-appimage.sh | |
| APPIMAGE_OUTPUT="${{ matrix.variant.output }}" scripts/build-appimage.sh ./asyncao | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: asyncao-linux-x86_64-AppImage${{ matrix.variant.suffix }} | |
| path: dist/${{ matrix.variant.output }} |