Prepare for v0.2.0: close out the changelog (#10) #6
Workflow file for this run
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
| # Dormant until a v* tag is pushed. Nothing here runs on ordinary commits. | |
| name: Release | |
| on: | |
| push: | |
| tags: ["v*"] | |
| permissions: | |
| contents: read | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| # Job-level so the tap step's `if` can see it. A step's own `env:` block is | |
| # not in scope for that step's `if`, which would make the step skip always. | |
| env: | |
| HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| permissions: | |
| # Create the release and upload archives. | |
| contents: write | |
| # Mint build provenance so a downloaded binary can be verified with | |
| # `gh attestation verify <file> --repo jonascript/ike`. | |
| id-token: write | |
| attestations: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| # goreleaser builds the changelog from git history. | |
| fetch-depth: 0 | |
| - uses: actions/setup-go@v7 | |
| with: | |
| # Stable, deliberately not go-version-file. go.mod declares the | |
| # minimum a user may build with (currently 1.25.0); binaries we | |
| # publish must be compiled with a toolchain that has current stdlib | |
| # security fixes. Building releases from the floor would ship known | |
| # CVEs to everyone who downloads them. | |
| go-version: stable | |
| # Never publish a release that would not have passed CI. | |
| - name: Verify before releasing | |
| run: | | |
| go vet ./... | |
| go test -race -count=1 ./... | |
| - uses: goreleaser/goreleaser-action@v7 | |
| with: | |
| version: "~> v2" | |
| args: release --clean | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Skipped while the repository is private: GitHub does not offer the | |
| # attestation API for user-owned private repos, and an unconditional step | |
| # fails the whole job after goreleaser has already published — which also | |
| # skips the tap update below. Found by rehearsing a tag before going | |
| # public. Once public this runs, and a download can be checked with | |
| # `gh attestation verify <file> --repo jonascript/ike`. | |
| - name: Attest build provenance | |
| if: ${{ !github.event.repository.private }} | |
| uses: actions/attest-build-provenance@v4 | |
| with: | |
| subject-path: | | |
| dist/*.tar.gz | |
| dist/checksums.txt | |
| # The Homebrew formula builds from the tag tarball, so it needs that | |
| # tarball's sha256 — which only exists once the tag is pushed. This is | |
| # deliberately a separate, manual-ish step rather than goreleaser's | |
| # deprecated `brews:` support. | |
| # | |
| # Requires HOMEBREW_TAP_TOKEN: a fine-grained PAT scoped to the tap repo | |
| # alone with Contents: read/write. The default GITHUB_TOKEN cannot write | |
| # to another repository. Until that secret exists this step is skipped, | |
| # so the release itself still succeeds. | |
| # Also gated on the repository being public, for a reason that is not | |
| # obvious: the checksum has to come from the exact URL the formula points | |
| # at, and github.com's /archive/ endpoint does not accept the Actions | |
| # GITHUB_TOKEN, so on a private repo it 404s. api.github.com's tarball | |
| # endpoint *would* authenticate, but it returns a different archive — | |
| # verified: prefix `jonascript-ike-<sha>/` instead of `ike-<version>/`, | |
| # and a different sha256 — so its checksum would not match what Homebrew | |
| # downloads, producing a formula that fails to install. A token that works | |
| # against /archive/ would have to be a broad PAT, which is not worth | |
| # carrying for the sake of a private-repo rehearsal. So this step runs for | |
| # real once the repository is public, where the anonymous fetch below just | |
| # works. | |
| - name: Update the Homebrew tap | |
| if: ${{ env.HOMEBREW_TAP_TOKEN != '' && !github.event.repository.private }} | |
| env: | |
| TAG: ${{ github.ref_name }} | |
| TAP: jonascript/homebrew-tap | |
| run: | | |
| set -euo pipefail | |
| version="${TAG#v}" | |
| url="https://github.com/${GITHUB_REPOSITORY}/archive/refs/tags/${TAG}.tar.gz" | |
| # The exact URL the formula points at, fetched the same anonymous way | |
| # Homebrew will, so the checksum cannot disagree with what it verifies. | |
| curl -fsSL -o source.tar.gz "$url" | |
| sha=$(sha256sum source.tar.gz | cut -d' ' -f1) | |
| echo "tag=$TAG version=$version sha256=$sha" | |
| git clone --depth 1 \ | |
| "https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/${TAP}.git" tap | |
| # A tap created by `gh repo create` has no Formula directory, and only | |
| # `brew tap-new` makes one, so do not assume it exists. | |
| mkdir -p tap/Formula | |
| cp packaging/ike.rb tap/Formula/ike.rb | |
| cd tap | |
| sed -i -E "s|^ url \".*\"| url \"${url}\"|" Formula/ike.rb | |
| sed -i -E "s|^ sha256 \".*\"| sha256 \"${sha}\"|" Formula/ike.rb | |
| # Fail loudly rather than pushing a formula still holding a | |
| # placeholder checksum. | |
| grep -q "$sha" Formula/ike.rb | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add Formula/ike.rb | |
| if git diff --cached --quiet; then | |
| echo "formula already current" | |
| exit 0 | |
| fi | |
| git commit -m "ike ${version}" | |
| git push |