Skip to content
Open
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
47 changes: 47 additions & 0 deletions .github/workflows/move-major-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Move Major Tag

# Callers reference this repo as @v2, a moving tag that must be repointed at
# every release. Doing that by hand is easy to forget: v2 sat on the pre-#12
# commit for two days after the fix merged, so every consumer kept running the
# broken auto-review gate. This job moves it automatically.
#
# Push v2.3.2 -> v2 is force-updated to the same commit.
# Pre-release tags (v2.4.0-rc1) are ignored; they should not move v2.
#
# A first release on a new major (v3.0.0) creates v3; nothing here is specific
# to v2. The tag filter deliberately avoids the `+` glob operator: if it were
# ever treated as a literal, this workflow would silently never fire, which is
# the same quiet staleness it exists to prevent. `[0-9]*` needs only plain
# glob semantics.

on:
push:
tags:
- 'v[0-9]*.[0-9]*.[0-9]*'

jobs:
move-major-tag:
name: Move Major Tag
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4

- name: Move major tag to this release
env:
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail

# v2.3.2-rc1 -> skip. Only finished releases move the major tag.
case "$TAG" in
*-*) echo "::notice::$TAG is a pre-release; leaving the major tag alone."; exit 0 ;;
esac

major="${TAG%%.*}" # v2.3.2 -> v2

git tag -f "$major" "$GITHUB_SHA"
git push -f origin "$major"

echo "::notice::Moved $major to $GITHUB_SHA ($TAG)."
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,27 @@ v2 callers should set `permissions: { contents: read, actions: read }`. The `con
- Adding inputs with backward-compatible defaults is minor/patch
- Pin to a specific SHA (e.g., `@abc1234`) for strict reproducibility

### Releasing

Tag the merge commit with a full version and push it. Nothing else is needed — `.github/workflows/move-major-tag.yml` force-moves the major tag (`v2`) to match.

```bash
git tag v2.3.2 <sha>
git push origin v2.3.2
```

The full version tag is the only one you create by hand. Never create or move a major tag (`v2`, `v3`) yourself — that is the job's whole purpose, and doing it manually is what gets forgotten.

`@v2` is a moving tag, so a release reaches every caller on their next PR event with no change on their side. That only works if `v2` actually moves: when it is left behind, callers keep running the older workflow and there is no signal that anything is stale. Pre-release tags (`v2.4.0-rc1`) do not move `v2`.

#### Starting a new major

Nothing extra to do. Push `v3.0.0` and the job creates `v3` at that commit — creating and moving a major tag are the same operation, so there is no special first release. `v3` is usable by callers immediately; you do not need to ship a patch to bring it into existence.

Two things the job does *not* do on a major bump: update the `@v2` references in this README and in `examples/`, and tell existing callers. `@v2` callers stay on v2 by design and only move when they edit their own workflow.

Note that a tag push runs the workflow file as it exists *on the tagged commit*. Tagging a commit from before this job was added does nothing at all.

## Security

The following guards are hardcoded in the reusable workflow and **cannot be overridden** by callers:
Expand Down