Skip to content

ci(automation): drop GraphQL from assign-linked-issue-author#5166

Closed
jyaunches wants to merge 1 commit into
mainfrom
ci/assign-linked-issue-author-rest
Closed

ci(automation): drop GraphQL from assign-linked-issue-author#5166
jyaunches wants to merge 1 commit into
mainfrom
ci/assign-linked-issue-author-rest

Conversation

@jyaunches

@jyaunches jyaunches commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Replaces the GraphQL closingIssuesReferences field query in .github/workflows/assign-linked-issue-author.yaml with REST + PR-body parsing for closing-keyword discovery, eliminating this workflow's dependency on a GitHub endpoint that periodically 401s on pull_request_target runs.

cc @wscurran (workflow author per git blame).

Related Issue

None — flaky third-party endpoint, no tracking issue filed yet.

Symptom that motivated this

On 2026-06-10, GitHub's GraphQL endpoint started returning HTTP 401 "Requires authentication" intermittently for this workflow's gh pr view --json closingIssuesReferences,... calls. Within a 65-minute window (15:08–16:13 UTC), 8 runs across 6 distinct branches failed identically:

Time (UTC) Branch Event
15:08 codex/onboard-build-patch-config-flow PR
15:20 e2e-migrate/test-onboard-resume PR
15:28 main scheduled
15:28 + 15:40 e2e-migrate/test-model-router-provider-routed-inference PR (×2)
15:49 e2e-migrate/test-openclaw-tui-chat-correlation PR
16:04 e2e-retire/test-strict-tool-call-probe (#5153) PR
16:13 test/freeze-nightly-legacy-e2e PR

All hit the same signature:

HTTP 401: Requires authentication (https://api.github.com/graphql)
Try authenticating with: gh auth login -h github.com

Three rerun-failed attempts on PR #5153's stuck run (27289014670) all hit the same 401 across attempts 1–3. The underlying github.token and permissions are valid; the GraphQL endpoint itself was flaking. REST endpoints used by other workflows during the same window were unaffected (e.g., Security / Code Scanning, nightly-e2e.yaml jobs, and the REST-side gh issue edit calls in this same workflow).

This workflow is non-required (not in branch protection's required-checks set), so the cosmetic red on every affected open PR was non-blocking. But:

  • Visible noise on every PR opened during the bad window;
  • Broke the intended "auto-assign issue authors" loop for any PR that landed during the window;
  • The same flake is plausibly recurring (37 successful runs followed by 8 failures, then recovery — no clear root cause from the GitHub side).

Why drop GraphQL entirely instead of adding retry/backoff

  • The workflow's only need from GraphQL is the closingIssuesReferences computed field.
  • The same outcome is reachable from REST + parsing the PR body for GitHub's documented closing keywords.
  • Removing the dependency removes the failure mode altogether, rather than reducing its probability.
  • REST endpoints used here (/repos/{owner}/{repo}/pulls/{N}, /repos/{owner}/{repo}/issues/{N}/assignees/{user}, POST /repos/{owner}/{repo}/issues/{N}/assignees) did not exhibit the flake.

Changes

Before (GraphQL) After (REST)
gh pr view --json closingIssuesReferences,... gh api repos/{owner}/{repo}/pulls/{N} + body parser
gh pr list --json closingIssuesReferences,... gh api --paginate repos/{owner}/{repo}/pulls?state=open
gh issue edit --add-assignee gh api -X POST repos/{owner}/{repo}/issues/{N}/assignees -f assignees[]=login

Body parser (Python, inline in the workflow) handles GitHub's closing keywords (close/closes/closed, fix/fixes/fixed, resolve/resolves/resolved) and same-repo reference forms:

  • #N
  • OWNER/REPO#N (where the repo matches ${{ github.repository }})
  • GH-N
  • https://github.com/OWNER/REPO/issues/N (same repo)

Strips fenced code blocks and HTML comments before matching so example snippets don't trigger false-positive assignments. Cross-repo refs are excluded — matches prior effective behavior, since gh issue edit --add-assignee would have failed for cross-repo refs returned by GraphQL anyway.

Trade-off acknowledged

Body-parsing does not pick up linked issues added solely via the PR sidebar's "Development" picker without a corresponding closing keyword in the body. That edge case has not been observed for this workflow's job scope; PR templates and contributor norms in this repo use explicit Closes #N / Refs #N lines. If we later see a regression from this, the simplest follow-up is to add a fallback that consults the timeline events REST endpoint (/repos/{owner}/{repo}/issues/{N}/timeline) for cross-referenced events.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only

Verification

  • python3 -c "import yaml; yaml.safe_load(...)" OK

  • Parser unit-tested in isolation against 20 cases: all 9 closing keywords (close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved), Closes: colon variant, mixed case, multiple keywords per body, dedup, same-repo qualified refs, cross-repo exclusion, GH-N form, full-URL form, fenced-code-block exclusion, HTML-comment exclusion, fixed in #N non-match (matches GitHub's parser behavior — keyword and ref must be directly adjacent), empty body, null body. 20/20 pass.

  • Manual end-to-end:

  • npx prek run --all-files passes

  • npm test passes

  • Tests added or updated for new or changed behavior (unit-tested parser inline)

  • No secrets, API keys, or credentials committed

  • Docs updated for user-facing behavior changes

  • npm run docs builds without warnings (doc changes only)

Summary by CodeRabbit

  • Improvements
    • Enhanced workflow for automatically assigning linked issues to pull request authors
    • Improved detection of issue references in PR descriptions across multiple formats
    • Better error reporting when issue assignment encounters issues

Replaces the GraphQL `closingIssuesReferences` field query with REST +
PR-body parsing for closing-keyword discovery, eliminating the workflow's
dependency on a GitHub endpoint that periodically 401s on
`pull_request_target` runs.

Symptom that motivated this:
On 2026-06-10, GitHub's GraphQL endpoint started returning HTTP 401
"Requires authentication" intermittently for this workflow's
`gh pr view --json closingIssuesReferences,...` calls. Within a single
65-minute window (15:08–16:13 UTC), 8 runs across 6 distinct branches
failed identically — including the scheduled run on `main`. The
underlying token and permissions are valid; the endpoint itself was
flaking. Reruns also failed on the same instance for hours.

This workflow is non-required (not in branch-protection's required-checks
set), so the cosmetic red on every affected open PR was non-blocking,
but it was visible noise on every PR opened that day and it broke the
intended "auto-assign issue authors" loop for any PR that landed during
the bad window.

Why drop GraphQL entirely instead of just adding retry/backoff:
- The workflow's only need from GraphQL is the `closingIssuesReferences`
  computed field. The same outcome is reachable from REST + parsing the
  PR body for GitHub's documented closing keywords.
- Removing the dependency removes the failure mode altogether, rather
  than reducing its probability.
- REST endpoints used by this workflow (`/repos/{owner}/{repo}/pulls/{N}`,
  `/repos/{owner}/{repo}/issues/{N}/assignees/{user}`,
  `POST /repos/{owner}/{repo}/issues/{N}/assignees`) have not exhibited
  the same flake.

Changes:
- `gh pr view --json closingIssuesReferences,...` → `gh api repos/{owner}/
  {repo}/pulls/{N}` (REST) + Python body parser for closing keywords.
- `gh pr list --json closingIssuesReferences,...` → `gh api --paginate
  repos/{owner}/{repo}/pulls?state=open` (REST).
- `gh issue edit --add-assignee` → `gh api -X POST repos/{owner}/{repo}/
  issues/{N}/assignees -f assignees[]=login` (REST; `gh issue edit` uses
  GraphQL internally).
- Body parser handles GitHub's closing keywords (close/closes/closed,
  fix/fixes/fixed, resolve/resolves/resolved) and same-repo reference
  forms (`#N`, `OWNER/REPO#N`, `GH-N`, GitHub issue URLs). Ignores
  fenced code blocks and HTML comments. Cross-repo refs are excluded
  because this workflow can only assign authors to issues in its own
  repo (matches prior behavior — `gh issue edit` would have failed for
  cross-repo refs returned by GraphQL).

Trade-off acknowledged:
Body-parsing does not pick up linked issues added solely via the PR
sidebar's "Development" picker without a corresponding closing keyword
in the body. That edge case has not been observed for this workflow's
job scope; PR templates and contributor norms in this repo use
explicit `Closes #N` / `Refs #N` lines.

Verification:
- YAML syntax check: `python3 -c "import yaml; yaml.safe_load(...)"` OK
- Parser unit-tested in isolation against 20 cases including:
  all 9 closing keywords (close, closes, closed, fix, fixes, fixed,
  resolve, resolves, resolved), `Closes:` colon variant, mixed case,
  multiple keywords per body, dedup, same-repo qualified refs,
  cross-repo exclusion, GH-N form, full-URL form, fenced-code-block
  exclusion, HTML-comment exclusion, "fixed in #N" non-match (matches
  GitHub's parser behavior), empty body, null body. 20/20 pass.
- Manual end-to-end check: parsed PR #5119's body (`Closes #5113`) →
  returns `['5113']`. Parsed PR #5153's body (`Refs #N` only, no
  closing keywords) → returns `[]`.
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This pull request migrates the GitHub Actions issue assignment workflow from GraphQL queries and high-level gh issue edit commands to REST API operations combined with Python-based PR body parsing. The workflow now extracts linked issues directly from PR body text, uses REST endpoints to validate and assign assignees, and supports both direct PR invocation and paginated enumeration of open PRs.

Changes

GitHub Actions Issue Assignment Workflow Migration

Layer / File(s) Summary
Issue extraction from PR body
.github/workflows/assign-linked-issue-author.yaml
New extract_linked_issues() helper uses Python to parse the PR body for closing keywords and same-repo issue reference formats (#N, GH-N, OWNER/REPO#N, issue URLs), while filtering out code blocks and HTML comments to avoid false positives.
REST-based assignment and PR processing
.github/workflows/assign-linked-issue-author.yaml
assign_author_to_issue replaces gh issue edit with REST probes: checks assignability via GET /repos/{owner}/{repo}/issues/{issue_number}/assignees/{author} and assigns via POST. process_pr now fetches PR data via REST, extracts author and body with jq, extracts linked issues using the new helper, and iterates assignment calls.
Workflow control flow and PR enumeration
.github/workflows/assign-linked-issue-author.yaml
Direct PR number triggers call process_pr immediately; scheduled/dispatched runs paginate open PRs via gh api --paginate, extract PR numbers, and invoke process_pr for each.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A workflow once spoke only Graph's tongue,
REST now flows where queries once sprung.
With Python to parse and links to find clear,
Each issue finds author, the path shines sincere.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR objectives and actual changes are completely unrelated. The PR modifies a GitHub Actions workflow for issue assignment automation, while the linked issue #5113 requests refactoring of TypeScript gateway-start logic in integration tests. Either unlink issue #5113 or verify that this PR is the wrong one for the stated objectives. The changes do not address the gateway-start helper extraction requirements.
Out of Scope Changes check ⚠️ Warning The PR only modifies .github/workflows/assign-linked-issue-author.yaml to replace GraphQL with REST API calls, which is in scope for the stated PR objectives. However, the linked issue #5113 is completely unrelated to these changes. Clarify the relationship between this PR and linked issue #5113. If #5113 is incorrectly linked, remove it. The workflow changes themselves are focused and in-scope.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: replacing GraphQL with REST API calls in the GitHub Actions workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/assign-linked-issue-author-rest

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: None
Optional E2E: None

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • None. No NemoClaw E2E is recommended because this PR only changes GitHub issue-assignment automation and cannot affect runtime behavior or real assistant user flows. Prefer lightweight workflow/shell validation or review of the parsing logic rather than sandbox E2E.

Optional E2E

  • None.

New E2E recommendations

  • None.

@github-actions

Copy link
Copy Markdown
Contributor

E2E Scenario Advisor Recommendation

Required scenario E2E: None
Optional scenario E2E: None

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • None. Changed file is an unrelated GitHub automation workflow and does not affect the Vitest scenario E2E workflow, scenario registry/runtime support, live tests, fixtures, manifests, or scenario framework behavior.

Optional scenario E2E

  • None.

Relevant changed files

  • None.

@github-actions

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 1 needs attention, 2 worth checking, 0 nice ideas
Top item: Fix PR-body delivery into extract_linked_issues

Review findings

🛠️ Needs attention

  • Parser stdin is consumed by the here-doc instead of the PR body (.github/workflows/assign-linked-issue-author.yaml:56): The workflow pipes the PR body into `extract_linked_issues`, but the function starts Python with `python3 - "$REPO" <<'PY'`. That here-doc is Python's stdin because `-` tells Python to read the program from stdin. The later `body = sys.stdin.read() or ""` therefore cannot read the piped PR body as intended, so `issues` will be empty and the workflow will skip assignment even for bodies like `Closes security: harden gateway auth defaults and restrict auto-pair #123`.
    • Recommendation: Pass the PR body through a separate channel from the Python source, such as exporting it in an environment variable, writing the Python program with `python3 -c`, using a temporary file, or invoking Python with an argument/file descriptor arrangement that leaves stdin available for the body. Add a committed workflow/parser test that exercises the actual shell function invocation.
    • Evidence: Call site: `issues="$(printf '%s' "$body" | extract_linked_issues)"` at line 142. Function: `python3 - "$REPO" <<'PY'` at line 56. Parser: `body = sys.stdin.read() or ""` at line 61.

🔎 Worth checking

  • Source-of-truth review needed: Linked issue discovery in assign-linked-issue-author workflow: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: The workaround rationale and trade-off are documented in workflow comments, but `python3 - "$REPO" <<'PY'` conflicts with `printf '%s' "$body" | extract_linked_issues`, so the new source-of-truth path needs follow-up.
  • No committed coverage for the new trusted workflow parser (.github/workflows/assign-linked-issue-author.yaml:54): This PR replaces GitHub's computed `closingIssuesReferences` field with local parsing inside a `pull_request_target` workflow that has `issues: write`. The PR body describes isolated parser verification, but the repository diff adds no test fixture or workflow-contract test for the shell/Python plumbing or security-relevant parser edge cases.
    • Recommendation: Add deterministic coverage for the actual parser invocation and edge cases before relying on the workflow in production. At minimum, test a body containing `Closes security: harden gateway auth defaults and restrict auto-pair #123`, fenced code/comment exclusions, cross-repo exclusion, same-repo qualified refs, `GH-N`, full same-repo issue URLs, duplicate de-duplication, and a non-closing `Refs security: harden gateway auth defaults and restrict auto-pair #123` body.
    • Evidence: The only changed file is `.github/workflows/assign-linked-issue-author.yaml`; no committed test files or fixtures were added. The parser is newly introduced at lines 54-98.

🌱 Nice ideas

  • None.
Consider writing more tests for
  • **Runtime validation** — extract_linked_issues receives the PR body when invoked from the workflow shell function and returns an issue for `Closes security: harden gateway auth defaults and restrict auto-pair #123`. The changed logic is deterministic and could be unit tested, but because it lives inside a shell-based GitHub Actions workflow with a Python here-doc, the critical risk is the runtime boundary between shell stdin, Python source loading, PR body input, and REST calls.
  • **Runtime validation** — closing keywords inside fenced code blocks and HTML comments do not produce issue assignments. The changed logic is deterministic and could be unit tested, but because it lives inside a shell-based GitHub Actions workflow with a Python here-doc, the critical risk is the runtime boundary between shell stdin, Python source loading, PR body input, and REST calls.
  • **Runtime validation** — cross-repo qualified issue references are ignored while same-repo `OWNER/REPO#N`, `GH-N`, and full issue URLs are accepted. The changed logic is deterministic and could be unit tested, but because it lives inside a shell-based GitHub Actions workflow with a Python here-doc, the critical risk is the runtime boundary between shell stdin, Python source loading, PR body input, and REST calls.
  • **Runtime validation** — scheduled path paginates open PRs and processes each PR number via REST without GraphQL. The changed logic is deterministic and could be unit tested, but because it lives inside a shell-based GitHub Actions workflow with a Python here-doc, the critical risk is the runtime boundary between shell stdin, Python source loading, PR body input, and REST calls.
  • **Runtime validation** — assignment path uses REST POST only after the assignability probe succeeds. The changed logic is deterministic and could be unit tested, but because it lives inside a shell-based GitHub Actions workflow with a Python here-doc, the critical risk is the runtime boundary between shell stdin, Python source loading, PR body input, and REST calls.
  • **No committed coverage for the new trusted workflow parser** — Add deterministic coverage for the actual parser invocation and edge cases before relying on the workflow in production. At minimum, test a body containing `Closes security: harden gateway auth defaults and restrict auto-pair #123`, fenced code/comment exclusions, cross-repo exclusion, same-repo qualified refs, `GH-N`, full same-repo issue URLs, duplicate de-duplication, and a non-closing `Refs security: harden gateway auth defaults and restrict auto-pair #123` body.
  • **Acceptance clause:** Replaces the GraphQL `closingIssuesReferences` field query in `.github/workflows/assign-linked-issue-author.yaml` with REST + PR-body parsing for closing-keyword discovery — add test evidence or identify existing coverage. GraphQL calls were removed and REST calls were added, but the PR-body parser likely never receives the body because the Python script is supplied via stdin using a here-doc.
  • **Acceptance clause:** `gh pr view --json closingIssuesReferences,...` | `gh api repos/{owner}/{repo}/pulls/{N}` + body parser — add test evidence or identify existing coverage. `process_pr` now fetches `gh api "repos/$REPO/pulls/$pr_number"`, but the body parser path is broken at the stdin boundary.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/assign-linked-issue-author.yaml:
- Around line 85-88: The current regex built into pattern (pattern =
re.compile(r"\b" + keyword + r"\b\s*:?\s*" + ref, flags=re.IGNORECASE)) only
captures one issue ref after the keyword; update the logic so it collects
subsequent refs separated by commas or the word "and". Modify the compiled regex
(or add a follow-up findall) to allow repeated occurrences of ref after the
initial match (for example make the part after keyword accept one ref followed
by zero-or-more groups like (?:\s*(?:,|and)\s*ref) or run a second re.findall
using the ref pattern on the substring following the keyword match) and then
iterate those matches to assign each issue; refer to the existing variables
pattern, keyword and ref and update the code that extracts matches so all refs
like "Closes `#1`, `#2` and `#3`" are collected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 32114935-3b0d-4afc-b937-7637025de0b4

📥 Commits

Reviewing files that changed from the base of the PR and between 37064e9 and 1b14c59.

📒 Files selected for processing (1)
  • .github/workflows/assign-linked-issue-author.yaml

Comment on lines +85 to +88
pattern = re.compile(
r"\b" + keyword + r"\b\s*:?\s*" + ref,
flags=re.IGNORECASE,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if any existing PR bodies use comma-separated closing references
gh api --paginate "repos/$GITHUB_REPOSITORY/pulls?state=all&per_page=100" \
  --jq '.[] | select(.body != null) | {number, body}' 2>/dev/null | \
  grep -iE '(close[sd]?|fix(e[sd])?|resolve[sd]?)\s*#[0-9]+\s*,\s*#[0-9]+' | head -5

Repository: NVIDIA/NemoClaw

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Identify whether any PR bodies in this repo contain comma- or "and"-separated issue lists
set -euo pipefail

REPO="${GITHUB_REPOSITORY:-NVIDIA/NemoClaw}"
echo "Repo: $REPO" >&2

# Comma-separated examples: "Closes `#1`, `#2`" or "Fixes `#1`, `#2`"
gh api --paginate "repos/$REPO/pulls?state=all&per_page=100" \
  --jq '.[] | select(.body != null) | {number, body}' 2>/dev/null | \
  rg -i --no-heading '(close[sd]?|fix(e[sd])?|resolve[sd]?)\s*#\d+\s*,\s*#\d+' --max-count 5

# "and"-separated examples: "Fixes `#1` and `#2`"
gh api --paginate "repos/$REPO/pulls?state=all&per_page=100" \
  --jq '.[] | select(.body != null) | {number, body}' 2>/dev/null | \
  rg -i --no-heading '(close[sd]?|fix(e[sd])?|resolve[sd]?)\s*#\d+\s+(and|&)\s*#\d+' --max-count 5

# Also get rough counts for each pattern (without printing bodies)
echo "Counts (comma-separated / and-separated):" >&2
gh api --paginate "repos/$REPO/pulls?state=all&per_page=100" \
  --jq '[.[] | select(.body != null) | select((.body|test("(?i)(close[sd]?|fix(e[sd])?|resolve[sd]?)\\\\s*#\\\\d+\\\\s*,\\\\s*#\\\\d+"))) ] | length' 2>/dev/null
gh api --paginate "repos/$REPO/pulls?state=all&per_page=100" \
  --jq '[.[] | select(.body != null) | select((.body|test("(?i)(close[sd]?|fix(e[sd])?|resolve[sd]?)\\\\s*#\\\\d+\\\\s+(and|&|\\\\band\\\\b)\\\\s*#\\\\d+"))) ] | length' 2>/dev/null

Repository: NVIDIA/NemoClaw

Length of output: 8400


🏁 Script executed:

#!/bin/bash
# Identify whether any PR bodies in this repo contain comma- or "and"-separated issue lists
set -euo pipefail

REPO="${GITHUB_REPOSITORY:-NVIDIA/NemoClaw}"
echo "Repo: $REPO" >&2

comma_regex='(close[sd]?|fix(e[sd])?|resolve[sd]?)\s*#[0-9]+\s*,\s*#[0-9]+'
and_regex='(close[sd]?|fix(e[sd])?|resolve[sd]?)\s*#[0-9]+\s+(and|&)\s*#[0-9]+'

# Print up to 5 matching PR numbers/bodies (compact)
gh api --paginate "repos/$REPO/pulls?state=all&per_page=100" \
  --jq '.[] | select(.body != null) | {number, body}' 2>/dev/null | \
  grep -iE "$comma_regex" | head -5

gh api --paginate "repos/$REPO/pulls?state=all&per_page=100" \
  --jq '.[] | select(.body != null) | {number, body}' 2>/dev/null | \
  grep -iE "$and_regex" | head -5

# Get rough counts (still limited to what the API returns within paginate)
echo "Counts:" >&2
gh api --paginate "repos/$REPO/pulls?state=all&per_page=100" \
  --jq '[.[] | select(.body != null) | select((.body | test($comma_re; "i")))] | length' 2>/dev/null --arg comma_re "$comma_regex"
gh api --paginate "repos/$REPO/pulls?state=all&per_page=100" \
  --jq '[.[] | select(.body != null) | select((.body | test($and_re; "i")))] | length' 2>/dev/null --arg and_re "$and_regex"

Repository: NVIDIA/NemoClaw

Length of output: 8400


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/assign-linked-issue-author.yaml"
echo "== $FILE =="
nl -ba "$FILE" | sed -n '1,200p'

Repository: NVIDIA/NemoClaw

Length of output: 176


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/assign-linked-issue-author.yaml"
echo "== $FILE =="
# cat -n is commonly available; fall back to awk if needed
if command -v cat >/dev/null 2>&1 && command -v sed >/dev/null 2>&1; then
  cat -n "$FILE" | sed -n '1,220p'
else
  awk '{printf "%6d\t%s\n", NR, $0}' "$FILE" | sed -n '1,220p'
fi

Repository: NVIDIA/NemoClaw

Length of output: 7851


Fix linked-issue parsing for multi-issue lists (“Closes #1, #2” / “Fixes #1 and #2”)

.github/workflows/assign-linked-issue-author.yaml builds pattern = re.compile(r"\b" + keyword + r"\b\s*:?\s*" + ref, flags=re.IGNORECASE), which matches only a single keyword + one issue ref per match. For bodies like Closes #3562, #3568 / `Fixes `#1` and `#2, only the first #N gets captured, so later issues won’t be assigned to the PR author.
Extend the regex/parsing to collect additional #N refs after the initial keyword when separated by commas/“and”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/assign-linked-issue-author.yaml around lines 85 - 88, The
current regex built into pattern (pattern = re.compile(r"\b" + keyword +
r"\b\s*:?\s*" + ref, flags=re.IGNORECASE)) only captures one issue ref after the
keyword; update the logic so it collects subsequent refs separated by commas or
the word "and". Modify the compiled regex (or add a follow-up findall) to allow
repeated occurrences of ref after the initial match (for example make the part
after keyword accept one ref followed by zero-or-more groups like
(?:\s*(?:,|and)\s*ref) or run a second re.findall using the ref pattern on the
substring following the keyword match) and then iterate those matches to assign
each issue; refer to the existing variables pattern, keyword and ref and update
the code that extracts matches so all refs like "Closes `#1`, `#2` and `#3`" are
collected.

@cv

cv commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Thanks for jumping on the CI noise here. After looking at the run history, this appears most likely to have been a transient GitHub API/auth failure rather than a durable problem in this workflow or its permissions. The workflow has since recovered, and because this check is non-required, I don't think we should carry a custom REST/body-parser workaround for a temporary upstream outage.

If this starts recurring, I'd rather revisit with a smaller mitigation such as retry/backoff around the existing GitHub-derived linked-issue lookup, or open a GitHub support issue with the failing run IDs. For now, closing this to avoid replacing GitHub's linked-issue source of truth with local parsing logic.

@cv cv closed this Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants