ci(release): derive canary version from git tags (single source of truth)
Every release workflow hardcoded a canary base version (0.5.0 in
Apple/Android/rpm/flatpak/deb, 0.3 in windows-msix/windows-host/decky) that
had to be hand-bumped on each stable release and wasn't. With stable at
v0.6.0, every canary was a version *behind* stable — e.g. the Apple canary
showed up on TestFlight as 0.5.0 while 0.6.0 was already published.
Add scripts/ci/pf-version.{sh,ps1} (bash + pwsh twin) as the single source of
truth: stable = the vX.Y.Z tag; canary = latest stable tag with minor+1,
patch 0 (v0.6.0 -> 0.7.0), so canary is always exactly one minor ahead of the
newest release with zero maintenance. Falls back to the workspace Cargo.toml
version when no tag is fetchable. All workflows now eval/call it and format
their own channel suffix off $PF_BASE; only the canary branch changed, stable
branches and per-channel suffixes are untouched. channels.md drops the old
manual "bump the canary base" release step.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# shellcheck shell=bash
|
||||
# Single source of truth for punktfunk release/canary version numbers (Linux + macOS runners).
|
||||
#
|
||||
# WHY THIS EXISTS: every release workflow used to hardcode a canary base version
|
||||
# (`0.5.0`, `0.3`, …). Those magic numbers had to be hand-bumped on every stable release
|
||||
# and nobody did — so canary channels silently fell *behind* stable (a canary showed up on
|
||||
# TestFlight as 0.5.0 while 0.6.0 was already published). This script computes the base
|
||||
# version DETERMINISTICALLY from the git tags instead, so there is nothing to hand-edit and
|
||||
# no future agent can get it wrong.
|
||||
#
|
||||
# THE RULE (chosen 2026-07-03):
|
||||
# * stable (a `vX.Y.Z` tag push) → PF_BASE = X.Y.Z (the tag, minus any -rc/+meta suffix).
|
||||
# * canary (a main push) → PF_BASE = <latest stable tag with minor+1, patch 0>.
|
||||
# i.e. latest release v0.6.0 → canary base 0.7.0. Cutting v0.7.0 auto-advances canary to
|
||||
# 0.8.0. Canary is therefore ALWAYS exactly one minor ahead of the newest stable release.
|
||||
#
|
||||
# USAGE (bash workflows) — eval it, then format your channel's suffix off $PF_BASE:
|
||||
# eval "$(bash scripts/ci/pf-version.sh)"
|
||||
# case "$GITHUB_REF" in
|
||||
# refs/tags/v*) V="${GITHUB_REF_NAME#v}" ;; # stable
|
||||
# *) V="${PF_BASE}-ci${GITHUB_RUN_NUMBER}" ;; # canary suffix is per-channel
|
||||
# esac
|
||||
#
|
||||
# It prints `KEY=VALUE` lines (eval-able) to stdout and — when $GITHUB_ENV is set — also
|
||||
# appends them there for later steps. Exports:
|
||||
# PF_CHANNEL stable | canary
|
||||
# PF_BASE the base semver X.Y.Z (see THE RULE)
|
||||
# PF_MAJOR/MINOR/PATCH the components of PF_BASE (numeric-version channels build
|
||||
# `<MAJOR>.<MINOR>.<run>` from these — MSIX/decky need monotonic ints)
|
||||
# PF_STABLE_TAG the latest stable release version the canary base was derived from (for logs)
|
||||
#
|
||||
# The pwsh twin scripts/ci/pf-version.ps1 implements the identical rule for the Windows runners.
|
||||
set -euo pipefail
|
||||
|
||||
_root="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/../.." && pwd)"
|
||||
|
||||
# actions/checkout is shallow and fetches NO tags by default — canary needs the full tag list
|
||||
# to find the latest stable. Best-effort fetch; the Cargo.toml fallback below covers a fresh
|
||||
# repo with no tags at all.
|
||||
git -C "$_root" fetch --tags --force --quiet 2>/dev/null || true
|
||||
|
||||
# Latest stable release = highest strict vX.Y.Z tag (pre-releases like v0.7.0-rc1 are ignored).
|
||||
_stable="$(
|
||||
git -C "$_root" tag -l 'v*' \
|
||||
| sed -n 's/^v\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)$/\1/p' \
|
||||
| sort -V | tail -n1
|
||||
)"
|
||||
if [ -z "${_stable:-}" ]; then
|
||||
# No tags yet — seed from the workspace Cargo.toml version so canary still has a base.
|
||||
_stable="$(sed -n 's/^version = "\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)".*/\1/p' "$_root/Cargo.toml" | head -n1)"
|
||||
fi
|
||||
_stable="${_stable:-0.0.0}"
|
||||
|
||||
case "${GITHUB_REF:-}" in
|
||||
refs/tags/v*)
|
||||
_channel="stable"
|
||||
_base="${GITHUB_REF_NAME#v}"
|
||||
_base="${_base%%-*}" # drop -rc / pre-release for the numeric marketing/package version
|
||||
_base="${_base%%+*}" # drop +build metadata
|
||||
;;
|
||||
*)
|
||||
_channel="canary"
|
||||
_maj="${_stable%%.*}"; _rest="${_stable#*.}"; _min="${_rest%%.*}"
|
||||
_base="${_maj}.$((_min + 1)).0"
|
||||
;;
|
||||
esac
|
||||
|
||||
_pf_major="${_base%%.*}"; _pf_rest="${_base#*.}"; _pf_minor="${_pf_rest%%.*}"; _pf_patch="${_pf_rest##*.}"
|
||||
|
||||
_emit() {
|
||||
printf '%s=%s\n' "$1" "$2"
|
||||
if [ -n "${GITHUB_ENV:-}" ]; then printf '%s=%s\n' "$1" "$2" >> "$GITHUB_ENV"; fi
|
||||
}
|
||||
_emit PF_CHANNEL "$_channel"
|
||||
_emit PF_BASE "$_base"
|
||||
_emit PF_MAJOR "$_pf_major"
|
||||
_emit PF_MINOR "$_pf_minor"
|
||||
_emit PF_PATCH "$_pf_patch"
|
||||
_emit PF_STABLE_TAG "$_stable"
|
||||
Reference in New Issue
Block a user