distribute: add WinGet spam-safeguards (pre-flight + watchdog)

Sami's winget-pkgs submission bot has been firing one PR per release.
Three of them (#391151/391368/391388) were generated with a buggy path
format and accumulated PullRequest-Error / Needs-Author-Feedback labels
before Sami noticed. That pattern reads as spam to winget-pkgs moderators
and risks the maintainer goodwill we've built with stephengillie.

Two new safeguards:

1. Pre-flight check (distribute.yml, winget job):
   - Before opening a PR, scan existing SamiAhmed7777 PRs on
     microsoft/winget-pkgs for PullRequest-Error or
     Needs-Author-Feedback labels
   - If any are found, abort this submission with a clear error
   - Also skip if a PR for this exact version is already open

2. New winget-watchdog.yml workflow (cron */30 * * * *):
   - Every 30 min, scan open SamiAhmed7777 PRs
   - For each one, inspect wingetbot comments for validation result
   - If a PR has automatic-validation failure comments, post a
     summary comment + close the PR automatically
   - This prevents 'broken PR opened, forgotten for 24h' pattern
     that creates the spam appearance

Both changes keep the existing tag-triggered release flow intact.
This commit is contained in:
Krystie
2026-06-22 20:36:06 -07:00
parent 7f309800e5
commit 5d9a0f47f9
2 changed files with 103 additions and 1 deletions
+34 -1
View File
@@ -488,6 +488,29 @@ jobs:
echo "sha=$SHA" >> $GITHUB_OUTPUT
echo "WinGet installer SHA256: $SHA"
- name: "Pre-flight check for existing failed WinGet PRs"
if: env.WINGET_TOKEN != ''
env:
GH_TOKEN: ${{ secrets.WINGET_TOKEN }}
run: |
set -e
# Don't pile up PRs if previous ones still have author-action-needed flags.
# winget-pkgs moderators can read repeated unfixed failures as spam.
# Skip the PR for this release if any existing SamiAhmed7777 PR against
# microsoft/winget-pkgs has a blocker label.
echo "Checking existing open PRs from SamiAhmed7777 on microsoft/winget-pkgs..."
BLOCKING=$(gh api -X GET \
'repos/microsoft/winget-pkgs/issues?state=open&labels=PullRequest-Error,Needs-Author-Feedback&per_page=30' \
--jq '.[] | select(.user.login=="SamiAhmed7777") | "#\(.number) [\(.state)] \(.title)"' \
|| echo "")
if [ -n "$BLOCKING" ]; then
echo "::error::Existing WinGet PR(s) with blocker labels — fix or close those first:"
echo "$BLOCKING"
echo "::error::Aborting this WinGet submission to avoid piling up failed PRs."
exit 1
fi
echo "✓ No blocker-labelled PRs found — safe to submit."
- name: Fork + update WinGet manifest + open PR
if: env.WINGET_TOKEN != ''
env:
@@ -501,7 +524,17 @@ jobs:
set -e
# Install gh + jq if missing
which gh >/dev/null 2>&1 || (curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list >/dev/null && sudo apt update && sudo apt install -y gh jq)
# Skip if a PR for THIS version already exists (avoid duplicate submissions).
echo "Checking for existing PR for version ${VERSION}..."
if gh api 'repos/microsoft/winget-pkgs/pulls?state=open&per_page=30' \
--jq ".[] | select(.head.ref | startswith(\"triangles-${VERSION}-\")) | .number" \
| grep -q .; then
echo "::notice::PR for v${VERSION} already exists — skipping to avoid duplicate."
exit 0
fi
echo "✓ No existing PR for v${VERSION}."
VERSION="$VERSION"
# Path convention (winget-pkgs): lowercase first letter of publisher,
# then publisher folder (PascalCase), then short package folder name.
+69
View File
@@ -0,0 +1,69 @@
name: WinGet PR watchdog
# Catches failing WinGet submissions within an hour of opening them.
# Goal: don't leave "needs-author-feedback" or "PullRequest-Error" PRs
# sitting open for days — moderators read sustained unfixed PRs as spam.
#
# Behaviour:
# - Every 30 min, scan open SamiAhmed7777 PRs against microsoft/winget-pkgs
# - For each one, look at recent wingetbot comments to detect validation result
# - If validation FAILED, post a comment summarising the error, close the PR,
# and surface the failure on the workflow summary so it's easy to spot.
on:
schedule:
- cron: '*/30 * * * *'
workflow_dispatch:
permissions:
contents: read
jobs:
watchdog:
name: Scan + auto-close failed WinGet PRs
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install gh CLI
run: |
which gh >/dev/null 2>&1 || (curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list >/dev/null && sudo apt update && sudo apt install -y gh jq)
- name: Scan + auto-close
env:
GH_TOKEN: ${{ secrets.WINGET_TOKEN }}
run: |
set -e
if [ -z "$GH_TOKEN" ]; then
echo "::warning::WINGET_TOKEN not set — watchdog can scan but cannot close PRs."
fi
echo "Fetching open SamiAhmed7777 PRs against microsoft/winget-pkgs..."
PRS=$(gh api 'repos/microsoft/winget-pkgs/pulls?state=open&per_page=30' --jq '.[] | select(.user.login=="SamiAhmed7777") | "\(.number)|\(.head.ref)|\(.title)|\(.created_at)"')
if [ -z "$PRS" ]; then
echo "OK no open SamiAhmed7777 PRs."
exit 0
fi
echo "$PRS" | while IFS='|' read -r NUM BRANCH TITLE CREATED; do
echo ""
echo "--- PR #$NUM: $TITLE (branch $BRANCH, created $CREATED) ---"
LAST_VALIDATION=$(gh api "repos/microsoft/winget-pkgs/issues/$NUM/comments?per_page=20" --jq '[.[] | select(.user.login=="wingetbot" or .user.login=="stephengillie") | select(.body | test("Result: Failed|Invalid file|Automatic Validation ended"))] | first')
if [ -n "$LAST_VALIDATION" ]; then
echo " X Validation FAILED detected."
SUMMARY=$(echo "$LAST_VALIDATION" | jq -r '.body' | head -40)
echo " Summary:"
echo "$SUMMARY" | sed 's/^/ /'
if [ -n "$GH_TOKEN" ]; then
printf 'Auto-closing: automatic validation failed within the watchdog window.\n\n```\n%s\n```\n\nThe watchdog (winget-watchdog.yml) closed this PR so it does not sit in the moderator queue with a needs-author-feedback flag. Reopen after fixing the issue, or open a fresh PR for a known-good version.\n' "$SUMMARY" > /tmp/watchdog-comment.txt
gh api -X POST "repos/microsoft/winget-pkgs/issues/$NUM/comments" -f body=@/tmp/watchdog-comment.txt || echo " (comment failed, continuing)"
gh api -X PATCH "repos/microsoft/winget-pkgs/pulls/$NUM" -f state=closed || echo " (close failed, continuing)"
echo " OK Closed PR #$NUM"
echo "::warning::Closed failing PR #$NUM -- $TITLE"
else
echo " (no WINGET_TOKEN, skipping close)"
fi
elif gh api "repos/microsoft/winget-pkgs/issues/$NUM/comments?per_page=20" --jq '[.[] | select(.user.login=="wingetbot") | select(.body | test("Validation Pipeline Run"))] | first' | grep -q .; then
echo " ? Validation has been triggered but no failure detected yet — leaving PR open."
else
echo " ? No validation result yet — leaving PR open."
fi
done