caddy/.github/scripts/previous-release.sh

42 lines
1.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Prints the tag of the highest published (non-draft) GitHub release whose
# version is lower than the given one, or nothing if there is none.
#
# Usage: previous-release.sh <version>
#
# Release changelogs should cover everything since the last release users
# actually received. "The last tag" is not good enough:
#
# - When a release attempt is abandoned after tagging, the Go module proxy
# has usually cached the tag, so it can't be deleted and reused, and the
# next attempt gets a new patch number. Those abandoned tags never get a
# published release, so they are skipped here.
# - Releases can be cut from maintenance branches (e.g. 2.11), so the
# previous release isn't necessarily an ancestor of the new one. Picking
# by version means 2.12.0 compares against the latest 2.11.x, and a 2.11.x
# released after 2.12.0 compares against the previous 2.11.x.
#
# Requires GH_TOKEN and GITHUB_REPOSITORY in the environment.
set -euo pipefail
version=${1:?usage: $0 <version>}
# sort -V orders "2.12.0-beta.1" after "2.12.0", but with the prerelease
# separator replaced by "~" (which sorts before everything, even the end of
# the string) it orders like semver.
sort_key() {
printf '%s' "${1#v}" | sed 's/-/~/'
}
tags=$(gh api --paginate "repos/${GITHUB_REPOSITORY}/releases" --jq '.[] | select(.draft | not) | .tag_name')
{
# The new version itself, marked by an empty tag column.
printf '%s\t\n' "$(sort_key "$version")"
grep -E '^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$' <<< "$tags" | while IFS= read -r tag; do
if [ "$tag" != "$version" ]; then
printf '%s\t%s\n' "$(sort_key "$tag")" "$tag"
fi
done
} | sort -t $'\t' -k1,1V | awk -F '\t' '$2 == "" { print prev; exit } { prev = $2 }'