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
25 changes: 25 additions & 0 deletions .github/workflows/semantic-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,31 @@ jobs:
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Mirror prerelease tags as semver
run: |
# Prerelease tags use PEP 440 (v3.0.0b1) to match the published
# package version, but semantic-release only understands semver and
# silently ignores tags it cannot parse. Without this, every run
# reports the first prerelease of the channel as the next version.
# Mirror each PEP 440 prerelease tag onto its semver equivalent
# (v3.0.0-beta.1). These are local to the run and are never pushed;
# the PEP 440 tags remain the only real ones. The channel notes the
# Version workflow records against the tagged commit apply to the
# mirrored tag too, since notes attach to commits, not tags.
for tag in $(git tag --list 'v*'); do
semver="$(
printf '%s' "${tag#v}" | sed -E \
-e 's/^([0-9]+\.[0-9]+\.[0-9]+)a([0-9]+)$/\1-alpha.\2/' \
-e 's/^([0-9]+\.[0-9]+\.[0-9]+)b([0-9]+)$/\1-beta.\2/' \
-e 's/^([0-9]+\.[0-9]+\.[0-9]+)rc([0-9]+)$/\1-rc.\2/'
)"
if [ "$semver" = "${tag#v}" ]; then
continue
fi

git tag --force "v$semver" "$tag^{commit}"
echo "Mirrored $tag as v$semver."
done
- name: Semantic release
id: release
uses: cycjimmy/semantic-release-action@v6
Expand Down
26 changes: 17 additions & 9 deletions .github/workflows/version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,28 @@ jobs:
passphrase: ${{ secrets.GPG_PASSPHRASE }}
- name: Setup
uses: ./.github/actions/setup
# uv normalizes the semver version semantic-release computes
# (3.0.0-beta.1) to PEP 440 (3.0.0b1), which is what gets committed,
# tagged and published. The Semantic Release workflow mirrors that tag
# back to semver so it can pick up where the last prerelease left off.
- name: Cut ${{ github.event.inputs.version }} version
run: |
uv version "${{ github.event.inputs.version }}"
just version
# semantic-release only treats a prerelease tag as released when a note
# records the channel it went out on, so record it here, once the release
# exists. The note is keyed to the commit rather than the tag, which is
# what lets the mirrored semver tag pick it up.
- name: Record prerelease channel
env:
VERSION: ${{ github.event.inputs.version }}
run: |
case "$VERSION" in
*-*) channel="${VERSION#*-}"; channel="${channel%%.*}" ;;
tag="v$(uv version --short)"
case "$(uv version --short)" in
*.*.*a[0-9]*) channel=alpha ;;
*.*.*b[0-9]*) channel=beta ;;
*.*.*rc[0-9]*) channel=rc ;;
*) echo "Stable release, no channel note required."; exit 0 ;;
esac
git fetch origin "+refs/notes/semantic-release:refs/notes/semantic-release" || true
git notes --ref semantic-release add --force \
--message "{\"channels\":[\"$channel\"]}" "v$VERSION^{commit}"
git push origin refs/notes/semantic-release
echo "Recorded v$VERSION on the '$channel' channel."
git notes --ref "semantic-release-$tag" add --force \
--message "{\"channels\":[\"$channel\"]}" "$tag^{commit}"
git push origin "refs/notes/semantic-release-$tag"
echo "Recorded $tag on the '$channel' channel."
Loading