From 6e7c20c59c9039c4779eb6aa38357267d094f8f9 Mon Sep 17 00:00:00 2001 From: purian23 Date: Sun, 12 Jul 2026 15:58:17 -0400 Subject: [PATCH] feat(release): add issue notification script for retesting on new releases Port 1.5 --- .github/workflows/release.yml | 16 ++++++++++ scripts/notify-issues.sh | 55 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100755 scripts/notify-issues.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 96605f6b5..228e814d6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,6 +11,7 @@ on: permissions: contents: write actions: write + issues: write concurrency: group: release-${{ inputs.tag }} @@ -427,3 +428,18 @@ jobs: prerelease: ${{ contains(env.TAG, '-') }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Ask reporters on still-open "related/fixes #N" issues to retest. + # Skipped for prereleases; --dry-run locally: scripts/notify-issues.sh --dry-run + - name: Notify open issues to retest + if: ${{ !contains(env.TAG, '-') }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true) + if [ -z "$PREVIOUS_TAG" ]; then + echo "no previous tag; skipping issue notify" + exit 0 + fi + bash scripts/notify-issues.sh "$PREVIOUS_TAG" "$TAG" diff --git a/scripts/notify-issues.sh b/scripts/notify-issues.sh new file mode 100755 index 000000000..c900ece59 --- /dev/null +++ b/scripts/notify-issues.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Comment on open issues referenced by commits shipped in a release, +# asking reporters to retest. +# +# Usage: notify-issues.sh [--dry-run] +# +# Scans commit messages in .. for "related/fixes/closes/ +# resolves/ref #N", keeps refs that are open issues (PRs and closed issues +# are skipped), and posts one comment per issue linking the release. +# Re-runs are safe: issues already carrying a comment that mentions the +# tag are skipped. Requires gh auth (GH_TOKEN). +set -euo pipefail + +PREV="${1:?usage: notify-issues.sh [--dry-run]}" +TAG="${2:?usage: notify-issues.sh [--dry-run]}" +DRY=0 +[ "${3:-}" = "--dry-run" ] && DRY=1 + +REPO="${GITHUB_REPOSITORY:-$(gh repo view --json nameWithOwner --jq .nameWithOwner)}" +RELEASE_URL="https://github.com/${REPO}/releases/tag/${TAG}" + +# Allow "related #N", "related: #N", "fixes #N", "Closes #N", etc. +refs=$(git log --no-merges --format=%B "${PREV}..${TAG}" | + { grep -oiE '(related([ -]to)?|ref(erence[sd]?)?|fix(es|ed)?|close[sd]?|resolve[sd]?|see)[-: ]*#[0-9]+' || true; } | + grep -oE '[0-9]+' | sort -un) + +[ -n "$refs" ] || { echo "no issue references found in ${PREV}..${TAG}"; exit 0; } + +for n in $refs; do + info=$(gh api "repos/${REPO}/issues/${n}" \ + --jq '{state: .state, pr: (.pull_request != null), title: .title}' 2>/dev/null) || { + echo "skip #${n}: not found"; continue; } + [ "$(jq -r .pr <<<"$info")" = "false" ] || { echo "skip #${n}: is a PR"; continue; } + [ "$(jq -r .state <<<"$info")" = "open" ] || { echo "skip #${n}: closed"; continue; } + + # don't double-post if a comment for this tag already exists + if gh api "repos/${REPO}/issues/${n}/comments" --paginate \ + --jq ".[].body" 2>/dev/null | grep -q "$TAG"; then + echo "skip #${n}: already notified for ${TAG}" + continue + fi + + title=$(jq -r .title <<<"$info") + if [ "$DRY" = 1 ]; then + echo "DRY-RUN: would comment on #${n} — ${title}" + continue + fi + gh issue comment "$n" --repo "$REPO" --body "$(cat <