Skip to content

Release

Release #61

Workflow file for this run

name: Release
on:
workflow_dispatch:
inputs:
bump:
description: "Release type"
required: true
type: choice
options:
- patch
- minor
- major
concurrency:
group: release
cancel-in-progress: false
jobs:
ci:
uses: ./.github/workflows/ci.yml
release:
needs: ci
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
pull-requests: write
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
with:
go-version-file: go.mod
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
with:
# Pin to the maintained v2.x line. cosign v3 auto-loads a signing
# config and forces the new single-file bundle format, which breaks
# the classic detached .sig/.pem signing that install.sh and
# install.ps1 verify. See the signs block in .goreleaser.yml.
cosign-release: v2.6.4
- uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
- name: Compute next version
id: version
run: |
# Get the latest semver tag, default to v0.0.0 if none exists
LATEST=$(git tag --list 'v*' --sort=-v:refname | head -n1)
if [ -z "$LATEST" ]; then
LATEST="v0.0.0"
fi
# Strip the leading 'v'
CURRENT="${LATEST#v}"
# Split into major.minor.patch
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
# Bump based on input
case "${{ inputs.bump }}" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
esac
NEXT="${MAJOR}.${MINOR}.${PATCH}"
echo "version=${NEXT}" >> "$GITHUB_OUTPUT"
echo "Bumping ${CURRENT} -> ${NEXT} (${{ inputs.bump }})"
- name: Generate contributor notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
NEW_TAG="v${{ steps.version.outputs.version }}"
# Generate release contributor notes
# Use HEAD instead of $NEW_TAG because the tag hasn't been created yet
if [ -n "$PREV_TAG" ]; then
go run ./cmd/contributors/ --release "$PREV_TAG" HEAD > contrib-notes.md
else
go run ./cmd/contributors/ --release "" HEAD > contrib-notes.md
fi
# Update CONTRIBUTORS.md with all-time contributors
go run ./cmd/contributors/ --all
# Commit updated CONTRIBUTORS.md if changed — open a PR instead of pushing directly to main
if ! git diff --quiet CONTRIBUTORS.md; then
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
CONTRIB_BRANCH="auto/contributors-${NEW_TAG}"
git checkout -b "$CONTRIB_BRANCH"
git add CONTRIBUTORS.md
git commit -m "docs: update CONTRIBUTORS.md for $NEW_TAG"
git push origin "$CONTRIB_BRANCH" --force
gh pr create \
--base main \
--head "$CONTRIB_BRANCH" \
--title "docs: update CONTRIBUTORS.md for $NEW_TAG" \
--body "Auto-generated contributor update for release $NEW_TAG." || echo "::warning::Could not create contributor PR — merge the branch manually"
git checkout main
fi
# Move contrib-notes to temp dir so GoReleaser sees a clean git state
mv contrib-notes.md "$RUNNER_TEMP/contrib-notes.md" 2>/dev/null || true
- name: Verify changelog entry
env:
RELEASE_VERSION: v${{ steps.version.outputs.version }}
run: |
if ! grep -q "## \[${RELEASE_VERSION}\]" CHANGELOG.md; then
echo "::error::CHANGELOG.md has no entry for ${RELEASE_VERSION} -- add one before releasing"
exit 1
fi
echo "Found changelog entry for ${RELEASE_VERSION}"
- name: Create and push tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "v${{ steps.version.outputs.version }}" -m "v${{ steps.version.outputs.version }}"
git push origin "v${{ steps.version.outputs.version }}"
- uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
with:
version: "v2.16.0"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Add contributor notes to release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
TAG="v${{ steps.version.outputs.version }}"
if [ -f "$RUNNER_TEMP/contrib-notes.md" ] && [ -s "$RUNNER_TEMP/contrib-notes.md" ]; then
# Get current release body
CURRENT_BODY=$(gh release view "$TAG" --json body --jq '.body')
# Append contributor notes via stdin to avoid ARG_MAX limits (CWE-400)
{
printf '%s\n\n' "$CURRENT_BODY"
cat "$RUNNER_TEMP/contrib-notes.md"
} | gh release edit "$TAG" --notes-file -
fi
pages:
needs: release
uses: ./.github/workflows/pages.yml
permissions:
contents: read
pages: write
id-token: write