Skip to content

Commit cdf5bb2

Browse files
scripts: de-duplicate and harden the close_pull_requests_with_*.sh backlog jobs
Extract the five byte-for-byte-identical backlog-closing scripts into one parameterized close_pull_requests_with_label.sh and make each named script a thin wrapper. Addresses the recommendations from #15168: - Correctness: filter by label server-side (gh pr list --label) instead of listing all ~900 open PRs and matching client-side, so no PR is skipped by an arbitrary --limit cap. - De-duplication: one implementation removes the drift between copies (some had sleep 2, one had it commented out, two had none). - Throttling: a single, deliberate SLEEP (default 2s) between closes. - Safety rails: set -euo pipefail, explicit --repo, and a DRY_RUN=1 preview mode that prints what would close before a maintainer commits. - Machine-readable summary (CLOSED_COUNT/CLOSED_PRS) so the Hacktoberfest tracker can be updated from script output. Follow-up to #15081.
1 parent c1ad752 commit cdf5bb2

6 files changed

Lines changed: 93 additions & 103 deletions
Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,7 @@
11
#!/bin/bash
2-
3-
# List all open pull requests
4-
prs=$(gh pr list --state open --json number,title,labels --limit 500)
5-
6-
# Loop through each pull request
7-
echo "$prs" | jq -c '.[]' | while read -r pr; do
8-
pr_number=$(echo "$pr" | jq -r '.number')
9-
pr_title=$(echo "$pr" | jq -r '.title')
10-
pr_labels=$(echo "$pr" | jq -r '.labels')
11-
12-
# Check if the "awaiting changes" label is present
13-
awaiting_changes=$(echo "$pr_labels" | jq -r '.[] | select(.name == "awaiting changes")')
14-
echo "Checking PR #$pr_number $pr_title ($awaiting_changes) ($pr_labels)"
15-
16-
# If awaiting_changes, close the pull request
17-
if [[ -n "$awaiting_changes" ]]; then
18-
echo "Closing PR #$pr_number $pr_title due to awaiting_changes label"
19-
gh pr close "$pr_number" --comment "Closing awaiting_changes PRs to prepare for Hacktoberfest"
20-
sleep 2
21-
fi
22-
done
2+
#
3+
# Close every open pull request labelled "awaiting changes".
4+
# Thin wrapper around close_pull_requests_with_label.sh so all five backlog
5+
# jobs share one implementation. Set DRY_RUN=1 to preview.
6+
set -euo pipefail
7+
exec "$(dirname "$0")/close_pull_requests_with_label.sh" "awaiting changes" "$@"
Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,7 @@
11
#!/bin/bash
2-
3-
# List all open pull requests
4-
prs=$(gh pr list --state open --json number,title,labels --limit 500)
5-
6-
# Loop through each pull request
7-
echo "$prs" | jq -c '.[]' | while read -r pr; do
8-
pr_number=$(echo "$pr" | jq -r '.number')
9-
pr_title=$(echo "$pr" | jq -r '.title')
10-
pr_labels=$(echo "$pr" | jq -r '.labels')
11-
12-
# Check if the "tests are failing" label is present
13-
tests_are_failing=$(echo "$pr_labels" | jq -r '.[] | select(.name == "tests are failing")')
14-
echo "Checking PR #$pr_number $pr_title ($tests_are_failing) ($pr_labels)"
15-
16-
# If there are failing tests, close the pull request
17-
if [[ -n "$tests_are_failing" ]]; then
18-
echo "Closing PR #$pr_number $pr_title due to tests_are_failing label"
19-
gh pr close "$pr_number" --comment "Closing tests_are_failing PRs to prepare for Hacktoberfest"
20-
sleep 2
21-
fi
22-
done
2+
#
3+
# Close every open pull request labelled "tests are failing".
4+
# Thin wrapper around close_pull_requests_with_label.sh so all five backlog
5+
# jobs share one implementation. Set DRY_RUN=1 to preview.
6+
set -euo pipefail
7+
exec "$(dirname "$0")/close_pull_requests_with_label.sh" "tests are failing" "$@"
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/bash
2+
#
3+
# Close every open pull request that carries a given label, leaving an
4+
# explanatory comment. This is used to clear the backlog before Hacktoberfest.
5+
#
6+
# Usage:
7+
# scripts/close_pull_requests_with_label.sh "<label>" ["<comment>"]
8+
#
9+
# Examples:
10+
# scripts/close_pull_requests_with_label.sh "require type hints"
11+
# DRY_RUN=1 scripts/close_pull_requests_with_label.sh "tests are failing"
12+
#
13+
# Environment variables:
14+
# DRY_RUN=1 Print the PRs that would be closed without closing them.
15+
# REPO Target repository (default: TheAlgorithms/Python).
16+
# SLEEP Seconds to wait between closes (default: 2) to avoid tripping
17+
# GitHub's secondary rate limits during bulk closes.
18+
#
19+
# On completion the script prints a machine-readable summary line:
20+
# CLOSED_COUNT=<n> CLOSED_PRS=<comma-separated PR numbers>
21+
# so the Hacktoberfest tracker can be updated from the output.
22+
23+
set -euo pipefail
24+
25+
label="${1:-}"
26+
if [[ -z "$label" ]]; then
27+
echo "error: missing label argument" >&2
28+
echo "usage: $0 \"<label>\" [\"<comment>\"]" >&2
29+
exit 2
30+
fi
31+
32+
repo="${REPO:-TheAlgorithms/Python}"
33+
sleep_seconds="${SLEEP:-2}"
34+
comment="${2:-Closing \"${label}\" PRs to prepare for Hacktoberfest}"
35+
36+
# Filter by label server-side so we never miss PRs beyond an arbitrary --limit
37+
# cap (the repo can have ~900 open PRs). --limit is set high purely as a ceiling.
38+
prs=$(gh pr list --repo "$repo" --state open --label "$label" \
39+
--json number,title --limit 1000)
40+
41+
count=$(echo "$prs" | jq 'length')
42+
echo "Found $count open PR(s) with label \"$label\" in $repo"
43+
44+
closed=()
45+
while read -r pr; do
46+
[[ -z "$pr" ]] && continue
47+
pr_number=$(echo "$pr" | jq -r '.number')
48+
pr_title=$(echo "$pr" | jq -r '.title')
49+
50+
if [[ "${DRY_RUN:-0}" == "1" ]]; then
51+
echo "[dry-run] would close PR #$pr_number: $pr_title"
52+
closed+=("$pr_number")
53+
continue
54+
fi
55+
56+
echo "Closing PR #$pr_number: $pr_title"
57+
gh pr close "$pr_number" --repo "$repo" --comment "$comment"
58+
closed+=("$pr_number")
59+
sleep "$sleep_seconds"
60+
done < <(echo "$prs" | jq -c '.[]')
61+
62+
# Machine-readable summary for the tracker.
63+
IFS=,; echo "CLOSED_COUNT=${#closed[@]} CLOSED_PRS=${closed[*]:-}"
Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,7 @@
11
#!/bin/bash
2-
3-
# List all open pull requests
4-
prs=$(gh pr list --state open --json number,title,labels --limit 500)
5-
6-
# Loop through each pull request
7-
echo "$prs" | jq -c '.[]' | while read -r pr; do
8-
pr_number=$(echo "$pr" | jq -r '.number')
9-
pr_title=$(echo "$pr" | jq -r '.title')
10-
pr_labels=$(echo "$pr" | jq -r '.labels')
11-
12-
# Check if the "require descriptive names" label is present
13-
require_descriptive_names=$(echo "$pr_labels" | jq -r '.[] | select(.name == "require descriptive names")')
14-
echo "Checking PR #$pr_number $pr_title ($require_descriptive_names) ($pr_labels)"
15-
16-
# If there are require_descriptive_names, close the pull request
17-
if [[ -n "$require_descriptive_names" ]]; then
18-
echo "Closing PR #$pr_number $pr_title due to require_descriptive_names label"
19-
gh pr close "$pr_number" --comment "Closing require_descriptive_names PRs to prepare for Hacktoberfest"
20-
fi
21-
done
2+
#
3+
# Close every open pull request labelled "require descriptive names".
4+
# Thin wrapper around close_pull_requests_with_label.sh so all five backlog
5+
# jobs share one implementation. Set DRY_RUN=1 to preview.
6+
set -euo pipefail
7+
exec "$(dirname "$0")/close_pull_requests_with_label.sh" "require descriptive names" "$@"
Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,7 @@
11
#!/bin/bash
2-
3-
# List all open pull requests
4-
prs=$(gh pr list --state open --json number,title,labels --limit 500)
5-
6-
# Loop through each pull request
7-
echo "$prs" | jq -c '.[]' | while read -r pr; do
8-
pr_number=$(echo "$pr" | jq -r '.number')
9-
pr_title=$(echo "$pr" | jq -r '.title')
10-
pr_labels=$(echo "$pr" | jq -r '.labels')
11-
12-
# Check if the "require_tests" label is present
13-
require_tests=$(echo "$pr_labels" | jq -r '.[] | select(.name == "require tests")')
14-
echo "Checking PR #$pr_number $pr_title ($require_tests) ($pr_labels)"
15-
16-
# If there require tests, close the pull request
17-
if [[ -n "$require_tests" ]]; then
18-
echo "Closing PR #$pr_number $pr_title due to require_tests label"
19-
gh pr close "$pr_number" --comment "Closing require_tests PRs to prepare for Hacktoberfest"
20-
# sleep 2
21-
fi
22-
done
2+
#
3+
# Close every open pull request labelled "require tests".
4+
# Thin wrapper around close_pull_requests_with_label.sh so all five backlog
5+
# jobs share one implementation. Set DRY_RUN=1 to preview.
6+
set -euo pipefail
7+
exec "$(dirname "$0")/close_pull_requests_with_label.sh" "require tests" "$@"
Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,7 @@
11
#!/bin/bash
2-
3-
# List all open pull requests
4-
prs=$(gh pr list --state open --json number,title,labels --limit 500)
5-
6-
# Loop through each pull request
7-
echo "$prs" | jq -c '.[]' | while read -r pr; do
8-
pr_number=$(echo "$pr" | jq -r '.number')
9-
pr_title=$(echo "$pr" | jq -r '.title')
10-
pr_labels=$(echo "$pr" | jq -r '.labels')
11-
12-
# Check if the "require type hints" label is present
13-
require_type_hints=$(echo "$pr_labels" | jq -r '.[] | select(.name == "require type hints")')
14-
echo "Checking PR #$pr_number $pr_title ($require_type_hints) ($pr_labels)"
15-
16-
# If require_type_hints, close the pull request
17-
if [[ -n "$require_type_hints" ]]; then
18-
echo "Closing PR #$pr_number $pr_title due to require_type_hints label"
19-
gh pr close "$pr_number" --comment "Closing require_type_hints PRs to prepare for Hacktoberfest"
20-
fi
21-
done
2+
#
3+
# Close every open pull request labelled "require type hints".
4+
# Thin wrapper around close_pull_requests_with_label.sh so all five backlog
5+
# jobs share one implementation. Set DRY_RUN=1 to preview.
6+
set -euo pipefail
7+
exec "$(dirname "$0")/close_pull_requests_with_label.sh" "require type hints" "$@"

0 commit comments

Comments
 (0)