Skip to content
Merged
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
52 changes: 43 additions & 9 deletions .github/workflows/semver-label.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,32 @@ name: Semver Label
# It is wired as a required status check on main separately (branch ruleset,
# managed in dataviking-infra) — this file only defines the check.
#
# `labeled` / `unlabeled` are in the trigger list so the check re-evaluates
# immediately when labels change; the event payload's label set reflects the
# state after the change.
# Two design constraints, both forced by auto-tag.yml's "Verify CI checks
# passed" step, which refuses to tag while ANY non-green check run sits on
# the merged head SHA:
#
# 1. Labels are fetched fresh from the API, not read from the event
# payload. Label events don't move the head SHA, and reruns replay the
# original payload — a payload-based run that failed before the label
# was added could never be rerun to green, permanently poisoning the
# SHA for auto-tag.
#
# 2. Once the check passes, it re-runs any superseded non-green runs of
# itself on the same SHA (e.g. the `opened` run that correctly failed
# before the label existed, moments later). Thanks to (1), those
# reruns re-fetch the labels and flip green, leaving the SHA clean.
#
# No concurrency/cancel-in-progress: a cancelled run is just another
# non-green conclusion parked on the SHA (this exact failure blocked the
# v1.6.0 recovery), and runs here take ~2 seconds anyway.

on:
pull_request:
types: [opened, reopened, synchronize, labeled, unlabeled]

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
actions: write # rerun superseded runs of this workflow (step 2)

jobs:
semver-label:
Expand All @@ -32,10 +44,12 @@ jobs:
steps:
- name: Require exactly one semver label
env:
LABELS_JSON: ${{ toJSON(github.event.pull_request.labels.*.name) }}
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
set -euo pipefail
echo "PR labels: ${LABELS_JSON}"
LABELS_JSON=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels?per_page=100" --jq '[.[].name]')
echo "PR labels (fresh fetch): ${LABELS_JSON}"

SEMVER_LABELS=$(echo "$LABELS_JSON" | jq -r '.[] | select(startswith("semver:"))')
COUNT=$(echo "$SEMVER_LABELS" | grep -c . || true)
Expand All @@ -59,3 +73,23 @@ jobs:
exit 1
;;
esac

- name: Flip superseded non-green runs of this check green
env:
GH_TOKEN: ${{ github.token }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -euo pipefail
RUN_IDS=$(gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/semver-label.yml/runs?head_sha=${HEAD_SHA}&per_page=100" \
--jq ".workflow_runs[] | select(.status == \"completed\" and .conclusion != \"success\" and .id != ${GITHUB_RUN_ID}) | .id")

if [ -z "$RUN_IDS" ]; then
echo "No superseded non-green runs on ${HEAD_SHA} — nothing to heal."
exit 0
fi

for id in $RUN_IDS; do
echo "Re-running superseded run ${id} so it re-fetches labels and goes green"
gh api -X POST "repos/${GITHUB_REPOSITORY}/actions/runs/${id}/rerun" \
|| echo "::warning::Could not re-run ${id} (fork PR token lacks actions:write?). Re-run it manually before merge, or Auto Semver Tag will refuse to tag this SHA."
done
Loading