diff --git a/.github/workflows/major-version-tag.yml b/.github/workflows/major-version-tag.yml index 6f59e7e..02e6dc0 100644 --- a/.github/workflows/major-version-tag.yml +++ b/.github/workflows/major-version-tag.yml @@ -1,13 +1,23 @@ name: "Maintain major version tag" # When a semver release tag (vX.Y.Z) is pushed, move the floating major tag -# (vX) to point at it. Consumers pin `@vX` (e.g. tests.yml@v1) and thus track -# the latest vX.Y.Z automatically, while exact pins (@vX.Y.Z) stay immutable. +# (vX) to point at it, so consumers pinning `@vX` (e.g. tests.yml@v1) track the +# latest vX.Y.Z automatically while exact pins (@vX.Y.Z) stay immutable. +# +# Also runnable manually (workflow_dispatch) as a fallback when the tag-push +# event doesn't fire (e.g. a stuck/again-needed run): it points the major tag +# at the given release tag, or the latest vX.Y.Z if none is given. on: push: tags: - 'v[0-9]+.[0-9]+.[0-9]+' + workflow_dispatch: + inputs: + tag: + description: "Release tag to point the major tag at (e.g. v1.3.0). Empty = latest vX.Y.Z." + required: false + default: "" permissions: contents: write @@ -17,14 +27,33 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 + with: + fetch-depth: 0 + fetch-tags: true - - name: "Point the major tag at this release" + - name: "Point the major tag at the release" + env: + EVENT_NAME: ${{ github.event_name }} + REF_NAME: ${{ github.ref_name }} + INPUT_TAG: ${{ inputs.tag }} run: | set -euo pipefail - full="${GITHUB_REF_NAME}" # e.g. v1.2.3 + if [ "$EVENT_NAME" = "push" ]; then + full="$REF_NAME" # e.g. v1.2.3 + else + full="$INPUT_TAG" + if [ -z "$full" ]; then + full="$(git tag -l 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n1)" + fi + fi + if [ -z "$full" ]; then + echo "No release tag to act on." >&2 + exit 1 + fi major="v$(printf '%s' "${full#v}" | cut -d. -f1)" # -> v1 - echo "Moving ${major} -> ${full} (${GITHUB_SHA})" + sha="$(git rev-list -n1 "$full")" # deref annotated tags to a commit + echo "Moving ${major} -> ${full} (${sha})" git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git tag -f "${major}" "${GITHUB_SHA}" + git tag -f "${major}" "${sha}" git push -f origin "refs/tags/${major}" diff --git a/README.md b/README.md index 37a3d31..56ecd98 100644 --- a/README.md +++ b/README.md @@ -579,7 +579,8 @@ jobs: ## Releasing changes to these workflows Merge to `master`, then tag a semver release; `major-version-tag.yml` moves -`@v1` for you. Full process in [`RELEASING.md`](RELEASING.md). Breaking changes +`@v1` for you (or run it manually via `workflow_dispatch` if a tag-push run +doesn't fire). Full process in [`RELEASING.md`](RELEASING.md). Breaking changes get a new major (`v2.0.0`) so `@v1` consumers aren't disrupted. --- diff --git a/RELEASING.md b/RELEASING.md index 4aab22d..ddb5174 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -24,6 +24,17 @@ Repos that want to pin exactly can use `@v1.2.3` (immutable). 3. The `Maintain major version tag` workflow automatically moves `v1` to the new release commit. Nothing else to do — every `@v1` consumer now gets it. + **If `v1` didn't move** (e.g. the tag-push run was stuck/failed), run the + workflow manually: Actions → "Maintain major version tag" → "Run workflow", + optionally passing the release tag (defaults to the latest `vX.Y.Z`). It + re-points `vX` at that release. You can also do it by hand: + + ```bash + git fetch --tags + git tag -f v1 "$(git rev-list -n1 v1.3.0)" + git push -f origin refs/tags/v1 + ``` + - **Bug/feature, backward compatible:** bump patch/minor (`v1.x.y`); `v1` moves. - **Breaking change** (e.g. dropping an input, switching the formatter): tag `v2.0.0`. `@v1` consumers are unaffected; they opt in by changing to `@v2`