Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 94 additions & 118 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,136 +1,112 @@
name: Release

# Cut an arcade release: bump the tag, cross-compile, publish archives with
# checksums and build provenance.
#
# The tag is a PLAIN v0.0.1, not a prefixed one. This repository is the Go
# module, so `go run github.com/aviorstudio/termcade@v0.0.2`
# only resolves if the tag is exactly that. A prefixed tag would publish a
# release nobody could install by version, and `@latest` would go on
# resolving to a pseudo-version of whatever main happened to be.
#
# The sdk module has its own tags (sdk/v*) and its own workflow: an arcade
# release does not imply an SDK contract change, and vice versa.

on:
'on':
workflow_dispatch:
inputs:
bump:
description: Version bump
required: true
type: choice
options:
- patch
- minor
- major

- patch
- minor
- major
permissions: {}

concurrency: release-${{ github.repository }}

jobs:
release:
name: "Release"
name: Release
runs-on: ubuntu-24.04
env:
MISE_GITHUB_TOKEN: ${{ github.token }}
# Bounded, so a step that hangs fails here rather than sitting until the
# runner's own timeout hours later.
timeout-minutes: 20
permissions:
contents: write # create the tag and the release
id-token: write # OIDC identity for build provenance
attestations: write # record the provenance attestation
contents: read
id-token: write
attestations: write
steps:
- name: "Check out source"
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: Determine release version
id: release
env:
BUMP: ${{ inputs.bump }}
run: |
set -euo pipefail
if [ "$GITHUB_REF" != "refs/heads/main" ]; then
echo 'Run releases from the main branch.' >&2
exit 1
fi
git fetch --tags --force
latest="$(git tag --list 'v[0-9]*' | sed -E 's/^v//' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1 || true)"
if [ -z "$latest" ]; then
version="0.0.1"
else
IFS=. read -r major minor patch <<< "$latest"
case "$BUMP" in
major) major=$((major + 1)); minor=0; patch=0 ;;
minor) minor=$((minor + 1)); patch=0 ;;
patch) patch=$((patch + 1)) ;;
*) echo "Unsupported bump: $BUMP" >&2; exit 1 ;;
esac
version="${major}.${minor}.${patch}"
fi
tag="v${version}"
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
echo "Tag already exists: $tag" >&2
exit 1
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "tag=$tag" >> "$GITHUB_OUTPUT"

- name: "Set up tools"
uses: nicodes/komizo/setup@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
env:
GH_TOKEN: ${{ github.token }}
- name: Install pinned build and validation tools
uses: nicodes/komizo/run@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
with:
target: install

# Verify the exact versioned artifacts before attestation and publication.
- name: Check project
uses: nicodes/komizo/run@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
with:
target: check
env:
VERSION: ${{ steps.release.outputs.tag }}


- name: Verify released binary version
env:
ARCHIVE: dist/termcade_Linux_x86_64.tar.gz
EXPECTED: termcade v${{ steps.release.outputs.version }}
run: .github/scripts/verify-release-archive.sh "$ARCHIVE" "$EXPECTED"

# Installed games run sandboxed, but the arcade itself runs with the
# player's full permissions — worth tying the archives to this workflow,
# this repository and this commit.
- name: Attest build provenance
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: |
dist/*.tar.gz
dist/*.zip

- name: Create the release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.release.outputs.tag }}
run: |
set -euo pipefail
cat > dist/notes.md <<NOTES
termcade $TAG

\`\`\`sh
go run github.com/aviorstudio/termcade@$TAG
\`\`\`

Or take an archive below and verify it:

\`\`\`sh
gh attestation verify termcade_Linux_x86_64.tar.gz --repo $GITHUB_REPOSITORY
\`\`\`
NOTES
gh release create "$TAG" dist/*.tar.gz dist/*.zip dist/checksums.txt \
--target "$GITHUB_SHA" --title "$TAG" --notes-file dist/notes.md
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
fetch-depth: 0
persist-credentials: false
- name: Determine release version
id: release
env:
BUMP: ${{ inputs.bump }}
run: |
set -euo pipefail
if [ "$GITHUB_REF" != "refs/heads/main" ]; then
echo 'Run releases from the main branch.' >&2
exit 1
fi
git fetch --tags --force
latest="$(git tag --list 'v[0-9]*' | sed -E 's/^v//' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1 || true)"
if [ -z "$latest" ]; then
version="0.0.1"
else
IFS=. read -r major minor patch <<< "$latest"
case "$BUMP" in
major) major=$((major + 1)); minor=0; patch=0 ;;
minor) minor=$((minor + 1)); patch=0 ;;
patch) patch=$((patch + 1)) ;;
*) echo "Unsupported bump: $BUMP" >&2; exit 1 ;;
esac
version="${major}.${minor}.${patch}"
fi
tag="v${version}"
if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then
echo "Tag already exists: $tag" >&2
exit 1
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
- name: Set up tools
uses: nicodes/komizo/setup@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
env:
GH_TOKEN: ${{ github.token }}
- name: Install pinned build and validation tools
uses: nicodes/komizo/run@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
with:
target: install
- name: Check project
uses: nicodes/komizo/run@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
with:
target: check
env:
VERSION: ${{ steps.release.outputs.tag }}
- name: Verify released binary version
env:
ARCHIVE: dist/termcade_Linux_x86_64.tar.gz
EXPECTED: termcade v${{ steps.release.outputs.version }}
run: .github/scripts/verify-release-archive.sh "$ARCHIVE" "$EXPECTED"
- name: Attest build provenance
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8
with:
subject-path: |
dist/*.tar.gz
dist/*.zip
- name: Upload accepted release artifacts
id: accepted
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9
with:
name: accepted-cli-${{ github.sha }}-${{ github.run_attempt }}
path: |-
dist/*.tar.gz
dist/*.zip
dist/checksums.txt
if-no-files-found: error
retention-days: 7
outputs:
tag: ${{ steps.release.outputs.tag }}
artifact-id: ${{ steps.accepted.outputs.artifact-id }}
publish:
name: Publish release
needs: release
uses: nicodes/tools/.github/workflows/cli-publish.yml@0276991861118d6e70a92cd11432dd664d3b030f
permissions:
contents: write
with:
tools-ref: '0276991861118d6e70a92cd11432dd664d3b030f'
binary: termcade
tag: ${{ needs.release.outputs.tag }}
artifact-id: ${{ needs.release.outputs.artifact-id }}