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:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user