From 71be2c26d9d03e6ac3b6ef8397b5dcf74a8d08ee Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 30 Mar 2026 18:36:20 -0700 Subject: [PATCH 1/4] Fix blocked-label check falsely matching "documentation" The blocked-patterns loop word-split "DO NOT MERGE" into individual words, so "DO" matched as a substring of "documentation" via grep. Replace with a single grep -qiE regex and read labels line-by-line from jq to also handle multi-word label names correctly. Made-with: Cursor --- .github/workflows/pr-metadata-check.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pr-metadata-check.yml b/.github/workflows/pr-metadata-check.yml index e1e2b4d5fc..3ff4e14eec 100644 --- a/.github/workflows/pr-metadata-check.yml +++ b/.github/workflows/pr-metadata-check.yml @@ -84,15 +84,14 @@ jobs: fi # Block PRs with labels that indicate they are not ready to merge. - BLOCKED_PATTERNS="blocked DO NOT MERGE do not merge" - for label in $LABEL_NAMES; do - for pattern in $BLOCKED_PATTERNS; do - if echo "$label" | grep -qi "$pattern"; then - ERRORS="${ERRORS}- **Blocked label detected**: label \`$label\` prevents merging. Remove it when the PR is ready.\n" - break - fi - done - done + # Read labels line-by-line (jq outputs one per line) to handle + # multi-word label names; match with a single regex to avoid + # word-splitting "DO NOT MERGE" into individual grep patterns. + while IFS= read -r label; do + if echo "$label" | grep -qiE "blocked|do not merge"; then + ERRORS="${ERRORS}- **Blocked label detected**: label \`$label\` prevents merging. Remove it when the PR is ready.\n" + fi + done < <(echo "$LABELS" | jq -r '.[].name') if [ -n "$ERRORS" ]; then echo "::error::This PR is missing required metadata. See the job summary for details." From c6b46b5417efdbb0a2817a1eb94ac840e5d75e7e Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 31 Mar 2026 12:56:26 -0700 Subject: [PATCH 2/4] Apply reviewer suggestion: Match blocked labels exactly (case-insensitively) Co-authored-by: Phillip Cloud <417981+cpcloud@users.noreply.github.com> --- .github/workflows/pr-metadata-check.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr-metadata-check.yml b/.github/workflows/pr-metadata-check.yml index 3ff4e14eec..90482ad5ee 100644 --- a/.github/workflows/pr-metadata-check.yml +++ b/.github/workflows/pr-metadata-check.yml @@ -84,14 +84,18 @@ jobs: fi # Block PRs with labels that indicate they are not ready to merge. - # Read labels line-by-line (jq outputs one per line) to handle - # multi-word label names; match with a single regex to avoid - # word-splitting "DO NOT MERGE" into individual grep patterns. + # Match blocked labels exactly (case-insensitively) using the PR + # payload we already have, instead of doing substring matches. + BLOCKED_LABELS=$(jq -r ' + [.[].name | ascii_downcase] as $pr_labels + | ["blocked", "do not merge"] as $blocking + | $pr_labels - ($pr_labels - $blocking) + | .[] + ' <<<"$LABELS") while IFS= read -r label; do - if echo "$label" | grep -qiE "blocked|do not merge"; then - ERRORS="${ERRORS}- **Blocked label detected**: label \`$label\` prevents merging. Remove it when the PR is ready.\n" - fi - done < <(echo "$LABELS" | jq -r '.[].name') + [ -n "$label" ] || continue + ERRORS="${ERRORS}- **Blocked label detected**: label \`$label\` prevents merging. Remove it when the PR is ready.\n" + done <<<"$BLOCKED_LABELS" if [ -n "$ERRORS" ]; then echo "::error::This PR is missing required metadata. See the job summary for details." From 1cb9360326e11376de88d42d15e96725541b5809 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 31 Mar 2026 13:16:56 -0700 Subject: [PATCH 3/4] fix(ci): iterate PR labels line-wise for module/type checks Shell word-splitting on $LABEL_NAMES broke multi-word GitHub label names. Read jq output with while read and build LABEL_LIST from the same jq stream. Made-with: Cursor --- .github/workflows/pr-metadata-check.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr-metadata-check.yml b/.github/workflows/pr-metadata-check.yml index 90482ad5ee..e9bd40fe6b 100644 --- a/.github/workflows/pr-metadata-check.yml +++ b/.github/workflows/pr-metadata-check.yml @@ -46,18 +46,20 @@ jobs: # Module labels identify which package the PR touches. # Cross-cutting labels exempt PRs from needing a module label. - LABEL_NAMES=$(echo "$LABELS" | jq -r '.[].name') + # Read label names line-by-line (jq outputs one per line) so + # multi-word GitHub labels are not split by shell word-splitting. MODULE_LABELS="cuda.bindings cuda.core cuda.pathfinder" MODULE_EXEMPT_LABELS="CI/CD" HAS_MODULE=false - for label in $LABEL_NAMES; do + while IFS= read -r label; do + [ -n "$label" ] || continue for mod in $MODULE_LABELS $MODULE_EXEMPT_LABELS; do if [ "$label" = "$mod" ]; then HAS_MODULE=true break 2 fi done - done + done < <(echo "$LABELS" | jq -r '.[].name') if [ "$HAS_MODULE" = "false" ]; then ERRORS="${ERRORS}- **Missing module label**: add at least one of: \`cuda.bindings\`, \`cuda.core\`, \`cuda.pathfinder\` (or a cross-cutting label such as \`CI/CD\`).\n" @@ -66,14 +68,15 @@ jobs: # Type labels categorize the kind of change. TYPE_LABELS="bug enhancement feature documentation test example CI/CD packaging dependencies performance experiment RFC support P0 P1 P2" HAS_TYPE=false - for label in $LABEL_NAMES; do + while IFS= read -r label; do + [ -n "$label" ] || continue for typ in $TYPE_LABELS; do if [ "$label" = "$typ" ]; then HAS_TYPE=true break 2 fi done - done + done < <(echo "$LABELS" | jq -r '.[].name') if [ "$HAS_TYPE" = "false" ]; then ERRORS="${ERRORS}- **Missing type label**: add at least one of: \`bug\`, \`enhancement\`, \`feature\`, \`documentation\`, \`test\`, \`example\`, \`CI/CD\`, \`packaging\`, \`dependencies\`, \`performance\`, \`experiment\`, \`RFC\`, \`support\`, \`P0\`, \`P1\`, \`P2\`.\n" @@ -110,7 +113,7 @@ jobs: fi ASSIGNEE_LIST=$(echo "$ASSIGNEES" | jq -r '.[].login' | paste -sd ', ' -) - LABEL_LIST=$(echo "$LABEL_NAMES" | paste -sd ', ' -) + LABEL_LIST=$(echo "$LABELS" | jq -r '.[].name' | paste -sd ', ' -) { echo "## PR Metadata Check Passed" echo "" From fb8f52d741cb805c7d79b22f89f0017f8240aeaf Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 31 Mar 2026 13:22:02 -0700 Subject: [PATCH 4/4] fix(ci): show GitHub casing for blocked-label errors Emit each label's original .name from the PR payload when it matches the blocked list case-insensitively, instead of lowercased names from jq. Made-with: Cursor --- .github/workflows/pr-metadata-check.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-metadata-check.yml b/.github/workflows/pr-metadata-check.yml index e9bd40fe6b..d8cf91579d 100644 --- a/.github/workflows/pr-metadata-check.yml +++ b/.github/workflows/pr-metadata-check.yml @@ -87,13 +87,16 @@ jobs: fi # Block PRs with labels that indicate they are not ready to merge. - # Match blocked labels exactly (case-insensitively) using the PR - # payload we already have, instead of doing substring matches. + # Match blocked label names exactly (case-insensitively); emit the + # original spelling from the payload so error text matches GitHub. BLOCKED_LABELS=$(jq -r ' - [.[].name | ascii_downcase] as $pr_labels - | ["blocked", "do not merge"] as $blocking - | $pr_labels - ($pr_labels - $blocking) + (["blocked", "do not merge"]) as $blocking | .[] + | .name as $n + | if ($blocking | index($n | ascii_downcase)) != null + then $n + else empty + end ' <<<"$LABELS") while IFS= read -r label; do [ -n "$label" ] || continue