Skip to content
Merged
Show file tree
Hide file tree
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
121 changes: 121 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
name: Release

on:
push:
tags:
- 'v*.*.*'

permissions:
contents: write

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
release:
name: Validate and publish Glaze
runs-on: ubuntu-latest
timeout-minutes: 20

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true

- name: Validate annotated tag and main provenance
shell: bash
run: |
set -euo pipefail
if [[ "$(git cat-file -t "$GITHUB_REF_NAME")" != "tag" ]]; then
echo "release tag must be annotated" >&2
exit 1
fi
git fetch origin main
if ! git merge-base --is-ancestor HEAD origin/main; then
echo "release commit must be part of origin/main" >&2
exit 1
fi

- name: Install Racket
uses: Bogdanp/setup-racket@v1.11
with:
version: '8.12'

- name: Validate release metadata
shell: bash
run: |
set -euo pipefail
if [[ ! "$GITHUB_REF_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "release tag must be vMAJOR.MINOR.PATCH" >&2
exit 1
fi
tag_version="${GITHUB_REF_NAME#v}"
package_version="$(sed -n 's/^(define version "\([^"]*\)")/\1/p' info.rkt)"
release_version="$(sed -n 's/^(define release-version "\([^"]*\)")/\1/p' info.rkt)"
if ! racket -e '(require version/utils) (exit (if (valid-version? (vector-ref (current-command-line-arguments) 0)) 0 1))' "$package_version"; then
echo "info.rkt version $package_version is not a valid Racket package version" >&2
exit 1
fi
if [[ "$tag_version" != "$release_version" ]]; then
echo "tag version $tag_version does not match release-version $release_version" >&2
exit 1
fi
if ! grep -Eq "^## \\[$release_version\\]( |$)" CHANGELOG.md; then
echo "CHANGELOG.md has no $release_version section" >&2
exit 1
fi
echo "GLAZE_VERSION=$release_version" >> "$GITHUB_ENV"

- name: Install and test Glaze
shell: bash
run: |
set -euo pipefail
raco pkg install --auto --no-docs --name glaze --link "$PWD"
raco test --package glaze
raco scribble ++xref-in setup/xref load-collections-xref \
--htmls --dest "$RUNNER_TEMP/glaze-doc" \
glaze-doc/scribblings/glaze.scrbl

- name: Build source package and release notes
shell: bash
run: |
set -euo pipefail
mkdir -p dist
raco pkg create --from-dir --source --format zip --dest dist "$PWD"
archive="$(find dist -maxdepth 1 -type f -name '*.zip' -print -quit)"
destination="dist/glaze-${GLAZE_VERSION}.zip"
mv "$archive" "$destination"
sha256sum "$destination" > "${destination}.sha256"
awk -v version="$GLAZE_VERSION" '
$0 ~ ("^## \\[" version "\\]") { capture = 1; next }
capture && /^## / { exit }
capture { print }
' CHANGELOG.md > dist/release-notes.md
test -s dist/release-notes.md

- name: Smoke-test exact source package
shell: bash
run: |
set -euo pipefail
smoke_root="$(mktemp -d)"
PLTUSERHOME="$smoke_root/racket-user" \
raco pkg install --auto --no-docs --name glaze \
"$PWD/dist/glaze-${GLAZE_VERSION}.zip"
PLTUSERHOME="$smoke_root/racket-user" \
racket -e '(require glaze glaze/server glaze/events)'
PLTUSERHOME="$smoke_root/racket-user" raco glaze help >/dev/null

- name: Publish GitHub Release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
gh release create "$GITHUB_REF_NAME" \
"dist/glaze-${GLAZE_VERSION}.zip" \
"dist/glaze-${GLAZE_VERSION}.zip.sha256" \
--verify-tag \
--title "Glaze ${GLAZE_VERSION}" \
--notes-file dist/release-notes.md
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ All notable changes to Glaze will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]
## [0.7.0] - 2026-09-29

### Fixed
- Build the Scribble reference manual in CI and group modules that share a
Expand Down
15 changes: 15 additions & 0 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Releasing Glaze

Glaze uses two equivalent version forms: `info.rkt` carries the canonical
Racket package version (for example `0.7`), while `release-version`, Git tags,
the changelog, and GitHub Releases use three-component SemVer (`0.7.0`).

1. Move the pending changelog entries into a dated release section.
2. Update both version bindings and the README release badges.
3. Merge the fully green release-preparation pull request into `main`.
4. Create and push an annotated `vMAJOR.MINOR.PATCH` tag on that exact commit.

The tag workflow verifies that the commit belongs to `main`, runs the complete
package test suite, builds the Scribble manual, creates the Racket source ZIP,
installs that exact ZIP into a fresh package scope, and publishes the archive,
checksum, and changelog notes as a GitHub Release.
1 change: 1 addition & 0 deletions info.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
;; NOTE: Racket's `valid-version?` rejects a trailing ".0" component
;; ("0.7.0" is invalid; "0.7" is the same release).
(define version "0.7")
(define release-version "0.7.0")

;; `raco test --package` otherwise executes every backend implementation as a
;; standalone test module. The dispatcher and platform CI exercise these
Expand Down
Loading