Skip to content

Release

Release #19

Workflow file for this run

name: Release
on:
workflow_run:
workflows: [CI]
branches: [main]
types:
- completed
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
defaults:
run:
shell: bash
env:
# go-semantic-release/action (SHA-pinned below) is a thin wrapper: at
# runtime it downloads a `semantic-release` executable and runs it with
# this job's `contents: write` permission. Pinning the action's SHA does
# NOT pin that executable — by default the action fetches whatever is
# currently "latest" from registry.go-semantic-release.xyz. We instead
# download a specific, checksummed release ourselves and hand the action
# that binary via its `bin` input, so nothing here floats.
#
# To bump: pick the new tag from
# https://github.com/go-semantic-release/semantic-release/releases, then
# copy the `linux_amd64` line out of that release's own
# `semantic-release_<version>_checksums.txt` asset.
SEMREL_VERSION: v2.31.0
SEMREL_SHA256: b8f518b1aeb1d1742f4e6e91a179b707cea4309a64fe3854f465bf724f04f6d3
jobs:
release:
name: Create Release
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
# The changelog promote opens a PR instead of pushing to main, which the
# branch ruleset forbids.
pull-requests: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: true
- name: Fetch and verify semantic-release binary
id: semrel-bin
run: |
set -euo pipefail
asset="semantic-release_${SEMREL_VERSION}_linux_amd64"
url="https://github.com/go-semantic-release/semantic-release/releases/download/${SEMREL_VERSION}/${asset}"
dest="${RUNNER_TEMP}/${asset}"
curl --fail --silent --show-error --location -o "$dest" "$url"
echo "${SEMREL_SHA256} ${dest}" | sha256sum -c -
chmod +x "$dest"
echo "path=${dest}" >> "$GITHUB_OUTPUT"
- name: Create Release
id: release
uses: go-semantic-release/action@2e9dc4247a6004f8377781bef4cb9dad273a741f # v1.24.1
with:
hooks: goreleaser
# Throwaway path for the goreleaser hook — never committed. The
# real CHANGELOG.md is promoted by hand below, since `prepend`
# writes above the file's H1 and intro prose, and this action
# never commits the file back to the repo regardless.
changelog-file: .release-notes.md
allow-initial-development-versions: true
prepend: true
bin: ${{ steps.semrel-bin.outputs.path }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Promote Unreleased changelog section
# steps.release.outputs.version is only set when a new version was
# actually released (go-semantic-release/action returns early,
# without calling setOutput, when there's nothing to release).
#
# This opens a PR rather than pushing to main. The main ruleset requires
# a pull request and 5 status checks with no bypass actors, so the direct
# push this used to do was rejected outright (GH013) — the tag and the
# GitHub Release were created and only the changelog commit was lost, so
# the job failed AFTER releasing and the drift was silent. Granting the
# bot a bypass would have fixed it by letting every workflow in the repo
# push to main unreviewed, which is a poor trade for a docs commit.
if: steps.release.outputs.version != ''
env:
RELEASE_VERSION: ${{ steps.release.outputs.version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
date="$(date -u +%Y-%m-%d)"
.github/scripts/promote-changelog.sh "$RELEASE_VERSION" "$date"
if git diff --quiet -- CHANGELOG.md; then
echo "CHANGELOG.md unchanged — nothing to promote."
exit 0
fi
branch="chore/changelog-v${RELEASE_VERSION}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git checkout -b "$branch"
git add CHANGELOG.md
git commit -m "docs: promote Unreleased to v${RELEASE_VERSION} in CHANGELOG.md"
git push origin "$branch"
# --fill would reuse the commit message; the body is worth spelling
# out because whoever sees this PR did not run the release. Built with
# printf so the text is not indented by this block's YAML indentation.
body="$(printf '%s\n' \
"Automated by the Release workflow after cutting v${RELEASE_VERSION}." \
"" \
"Moves the \`## Unreleased\` section under a \`## v${RELEASE_VERSION}\` heading." \
"The tag and GitHub Release already exist; this only records them in" \
"the changelog, so merging is safe whenever convenient.")"
gh pr create \
--base main \
--head "$branch" \
--title "docs: promote Unreleased to v${RELEASE_VERSION} in CHANGELOG.md" \
--body "$body"
# Auto-merge so the changelog does not drift while PRs queue up. It
# merges once the required checks pass; if auto-merge is disabled on
# the repo, say so and leave the PR open rather than failing a release
# that has already succeeded.
gh pr merge "$branch" --squash --auto \
|| echo "::warning::Could not enable auto-merge; merge the changelog PR by hand."