Skip to content

Commit 56cc036

Browse files
committed
build: add debug logging to script
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: na - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: passed - task: lint_typescript_declarations status: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 6d63d37 commit 56cc036

File tree

2 files changed

+136
-22
lines changed

2 files changed

+136
-22
lines changed

.github/workflows/check_duplicate_prs.yml

+14-8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ on:
2727

2828
# Allow the workflow to be manually run:
2929
workflow_dispatch:
30+
inputs:
31+
debug:
32+
description: 'Enable debug output'
33+
required: false
34+
default: 'false'
35+
type: choice
36+
options:
37+
- 'true'
38+
- 'false'
3039

3140
# Global permissions:
3241
permissions:
@@ -55,20 +64,17 @@ jobs:
5564
# Pin action to full length commit SHA
5665
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
5766
with:
58-
# Specify whether to remove untracked files before checking out the repository:
59-
clean: false
60-
61-
# Limit clone depth to the most recent commit:
62-
fetch-depth: 1
63-
64-
# Specify whether to download Git-LFS files:
65-
lfs: false
67+
# Ensure we have access to the scripts directory:
68+
sparse-checkout: |
69+
.github/workflows/scripts
70+
sparse-checkout-cone-mode: false
6671
timeout-minutes: 10
6772

6873
# Check for duplicate PRs:
6974
- name: 'Check for duplicate PRs'
7075
env:
7176
GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }}
77+
DEBUG: ${{ inputs.debug || 'false' }}
7278
run: |
7379
. "$GITHUB_WORKSPACE/.github/workflows/scripts/check_duplicate_prs"
7480
timeout-minutes: 15

.github/workflows/scripts/check_duplicate_prs

+122-14
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,26 @@ repo_name="stdlib"
4242
# Label to add/remove for duplicate PRs:
4343
duplicate_label="Potential Duplicate"
4444

45+
# Debug mode controlled by environment variable (defaults to false if not set)
46+
debug="${DEBUG:-false}"
47+
48+
# Configure retries for API calls
49+
max_retries=3
50+
retry_delay=2
51+
4552

4653
# FUNCTIONS #
4754

55+
# Debug logging function
56+
#
57+
# $1 - debug message
58+
debug_log() {
59+
# Only print debug messages if DEBUG environment variable is set to "true"
60+
if [ "$debug" = true ]; then
61+
echo "[DEBUG] $1" >&2
62+
fi
63+
}
64+
4865
# Error handler.
4966
#
5067
# $1 - error status
@@ -67,6 +84,10 @@ github_api() {
6784
local method="$1"
6885
local endpoint="$2"
6986
local data="$3"
87+
local retry_count=0
88+
local response=""
89+
local status_code
90+
local success=false
7091

7192
# Initialize an array to hold curl headers:
7293
local headers=()
@@ -76,26 +97,80 @@ github_api() {
7697
headers+=("-H" "Authorization: token ${GITHUB_TOKEN}")
7798
fi
7899

100+
debug_log "Making API request: ${method} ${endpoint}"
101+
79102
# For POST/PATCH requests, always set the Content-Type header:
80103
if [ "$method" != "GET" ]; then
81104
headers+=("-H" "Content-Type: application/json")
82105
fi
83106

84-
# Make the API request:
85-
if [ -n "${data}" ]; then
86-
curl -s -X "${method}" "${headers[@]}" -d "${data}" "${github_api_url}${endpoint}"
87-
else
88-
curl -s -X "${method}" "${headers[@]}" "${github_api_url}${endpoint}"
107+
# Add retry logic
108+
while [ $retry_count -lt $max_retries ] && [ "$success" = false ]; do
109+
if [ $retry_count -gt 0 ]; then
110+
echo "Retrying request (attempt $((retry_count+1))/${max_retries})..."
111+
sleep $retry_delay
112+
fi
113+
114+
# Make the API request:
115+
if [ -n "${data}" ]; then
116+
response=$(curl -s -w "%{http_code}" -X "${method}" "${headers[@]}" -d "${data}" "${github_api_url}${endpoint}")
117+
else
118+
response=$(curl -s -w "%{http_code}" -X "${method}" "${headers[@]}" "${github_api_url}${endpoint}")
119+
fi
120+
121+
# Extract status code (last 3 digits) and actual response (everything before)
122+
status_code="${response: -3}"
123+
response="${response:0:${#response}-3}"
124+
125+
debug_log "Status code: $status_code"
126+
127+
# Check if we got a successful response
128+
if [[ $status_code -ge 200 && $status_code -lt 300 ]]; then
129+
success=true
130+
else
131+
echo "API request failed with status $status_code: $response" >&2
132+
retry_count=$((retry_count+1))
133+
fi
134+
done
135+
136+
if [ "$success" = false ]; then
137+
echo "Failed to complete API request after $max_retries attempts" >&2
138+
return 1
89139
fi
140+
141+
# Validate that response is valid JSON if expected
142+
if ! echo "$response" | jq -e '.' > /dev/null 2>&1; then
143+
echo "Warning: Response is not valid JSON: ${response}" >&2
144+
# Return empty JSON object as fallback
145+
echo "{}"
146+
return 0
147+
fi
148+
149+
# Return the actual response data (without status code)
150+
echo "$response"
151+
return 0
90152
}
91153

92154
# Extracts issue numbers resolved/closed in PRs for stdlib-js/stdlib.
93155
#
94156
# $1 - PR body text
95157
extract_resolved_issues() {
96158
local body="$1"
97-
echo "$body" | grep -Eio "(resolves|closes|close|fix|fixes|fixed|resolve)[[:space:]]*(#[0-9]+|https?://github\.com/stdlib-js/stdlib/issues/[0-9]+)" |
98-
grep -Eo "([0-9]+)$" | sort -u
159+
160+
debug_log "Extracting resolved issues from PR body of length ${#body} chars"
161+
162+
# Handle empty body case
163+
if [ -z "$body" ]; then
164+
debug_log "PR body is empty, no issues to extract"
165+
return 0
166+
fi
167+
168+
local issues
169+
issues=$(echo "$body" | grep -Eio "(resolves|closes|close|fix|fixes|fixed|resolve)[[:space:]]*(#[0-9]+|https?://github\.com/stdlib-js/stdlib/issues/[0-9]+)" |
170+
grep -Eo "([0-9]+)$" | sort -u)
171+
172+
debug_log "Extracted issues: $issues"
173+
echo "$issues"
99174
}
100175

101176
# Removes a label from a PR.
@@ -119,13 +194,19 @@ main() {
119194

120195
while true; do
121196
# Fetch current page of PRs:
122-
page_data=$(github_api "GET" "/repos/${repo_owner}/${repo_name}/pulls?state=open&per_page=100&page=${page}")
197+
debug_log "Fetching page $page of PRs"
198+
if ! page_data=$(github_api "GET" "/repos/${repo_owner}/${repo_name}/pulls?state=open&per_page=100&page=${page}"); then
199+
echo "Error fetching PRs on page $page, aborting" >&2
200+
exit 1
201+
fi
123202

124203
# Check if we got any results:
125204
page_count=$(echo "$page_data" | jq length)
205+
debug_log "Got $page_count PRs on page $page"
126206

127207
if [ "$page_count" -eq 0 ]; then
128208
# No more results, break the loop
209+
debug_log "No more PRs, breaking pagination loop"
129210
break
130211
fi
131212

@@ -158,23 +239,40 @@ main() {
158239

159240
if ! echo "$labeled_prs_data" | jq -e 'if type=="array" then true else false end' > /dev/null 2>&1; then
160241
echo "Warning: Invalid response when fetching labeled PRs: ${labeled_prs_data}" >&2
242+
debug_log "Full labeled PRs response: $labeled_prs_data"
161243
elif [ -n "$labeled_prs_data" ]; then
162244
while IFS= read -r labeled_pr; do
163245
pr_number=$(echo "$labeled_pr" | jq -r '.number')
164246
labeled_prs_list+=("$pr_number")
247+
debug_log "Found PR #$pr_number with duplicate label"
165248
done < <(echo "$labeled_prs_data" | jq -c '.[]')
166249
fi
167250
echo "Found ${#labeled_prs_list[@]} PRs with duplicate label"
168251

169252
# Process each PR to build issue mappings:
170253
echo "Processing PRs for issue references..."
254+
debug_log "Starting to process $pr_count PRs for issue references"
255+
256+
# Process PRs one by one...
171257
pr_count=0
258+
total_prs=$(echo "$open_prs" | jq length)
172259

173-
total_prs=$(echo "$open_prs" | jq 'length')
174-
for i in $(seq 0 $((total_prs-1))); do
260+
for ((i=0; i<total_prs; i++)); do
175261
pr=$(echo "$open_prs" | jq -c ".[$i]")
262+
263+
if [ -z "$pr" ] || [ "$pr" = "null" ]; then
264+
debug_log "Warning: Empty PR data at index $i"
265+
continue
266+
fi
267+
176268
pr_number=$(echo "$pr" | jq -r '.number')
177-
pr_body=$(echo "$pr" | jq -r '.body')
269+
if [ -z "$pr_number" ] || [ "$pr_number" = "null" ]; then
270+
debug_log "Warning: Could not extract PR number"
271+
continue
272+
fi
273+
274+
debug_log "Processing PR #$pr_number"
275+
pr_body=$(echo "$pr" | jq -r '.body // ""')
178276
resolved_issues=$(extract_resolved_issues "$pr_body")
179277

180278
pr_count=$((pr_count + 1))
@@ -183,6 +281,7 @@ main() {
183281
fi
184282

185283
for issue in $resolved_issues; do
284+
debug_log "PR #$pr_number references issue #$issue"
186285
# Find existing issue index
187286
index=-1
188287
for j in "${!issue_prs_keys[@]}"; do
@@ -192,34 +291,42 @@ main() {
192291
fi
193292
done
194293
if [ "$index" -eq -1 ]; then
294+
debug_log "Creating new entry for issue #$issue with PR #$pr_number"
195295
issue_prs_keys+=("$issue")
196296
issue_prs_values+=("$pr_number")
197297
else
298+
debug_log "Adding PR #$pr_number to existing issue #$issue"
198299
issue_prs_values[index]="${issue_prs_values[index]} $pr_number"
199300
fi
200301
done
201302
done
202303

304+
debug_log "Finished processing all PRs for issue references"
305+
debug_log "Found ${#issue_prs_keys[@]} unique issues referenced in PRs"
306+
203307
# Process the mappings to find duplicates:
204308
declare -a should_be_labeled_list
205309

206310
for i in "${!issue_prs_keys[@]}"; do
207311
read -r -a prs <<< "${issue_prs_values[$i]}"
208312
if [ ${#prs[@]} -gt 1 ]; then
313+
debug_log "Issue #${issue_prs_keys[$i]} has ${#prs[@]} PRs: ${prs[*]}"
209314
for pr in "${prs[@]}"; do
210315
should_be_labeled_list+=("$pr")
211316
done
212317
fi
213318
done
214319

215-
echo "PRs that should have label: ${should_be_labeled_list[*]}"
216-
echo "PRs that currently have label: ${labeled_prs_list[*]}"
320+
debug_log "PRs that should have label: ${should_be_labeled_list[*]}"
321+
debug_log "PRs that currently have label: ${labeled_prs_list[*]}"
217322

218323
for pr in "${labeled_prs_list[@]}"; do
219324
echo "Checking if PR #${pr} should still have label..."
220325
if ! printf '%s\n' "${should_be_labeled_list[@]}" | grep -q "^${pr}$"; then
221326
echo "Removing duplicate label from PR #${pr}..."
222327
remove_label "$pr" "$duplicate_label"
328+
else
329+
debug_log "PR #${pr} should keep its label"
223330
fi
224331
done
225332

@@ -230,10 +337,11 @@ main() {
230337
github_api "POST" "/repos/${repo_owner}/${repo_name}/issues/${pr}/labels" \
231338
"{\"labels\":[\"${duplicate_label}\"]}"
232339
else
233-
echo "PR #${pr} already has label, skipping..."
340+
debug_log "PR #${pr} already has label, skipping..."
234341
fi
235342
done
236343

344+
debug_log "Script completed successfully"
237345
print_success
238346
exit 0
239347
}

0 commit comments

Comments
 (0)