From 548203c281eff7482f27b5527b53762d33aa3842 Mon Sep 17 00:00:00 2001 From: Bryan Cox Date: Mon, 9 Feb 2026 08:06:15 -0500 Subject: [PATCH] fix: jira-agent posts /auto-cc to wrong PR due to naive URL extraction The PR URL extraction used `grep | head -1` which picks the first matching GitHub PR URL from Claude's entire stream-json output. When Claude reads source files containing PR URL references in comments (e.g. nodepool/token.go:104 references PR #3795), that URL appears before the `gh pr create` output, causing /auto-cc to be posted to the wrong PR. Replace the naive grep with a two-strategy hybrid approach: Strategy 1 (primary): Parse Claude's structured JSONL output to find tool_use blocks where the Bash command contains "gh pr create", then correlate their IDs with matching tool_result blocks to extract the actual PR URL. This is deterministic and requires zero GitHub API calls. Strategy 2 (fallback): If JSONL parsing finds nothing (missing file, schema change, malformed output), fall back to extracting all candidate URLs and verifying each via `gh pr view` to find the one whose title starts with the current Jira ticket ID and whose author is the hypershift-jira-solve-ci bot. Co-Authored-By: Claude Opus 4.6 --- .../hypershift-jira-agent-process-commands.sh | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/ci-operator/step-registry/hypershift/jira-agent/process/hypershift-jira-agent-process-commands.sh b/ci-operator/step-registry/hypershift/jira-agent/process/hypershift-jira-agent-process-commands.sh index e1659ce954836..5abb03d0b481b 100755 --- a/ci-operator/step-registry/hypershift/jira-agent/process/hypershift-jira-agent-process-commands.sh +++ b/ci-operator/step-registry/hypershift/jira-agent/process/hypershift-jira-agent-process-commands.sh @@ -225,8 +225,59 @@ while IFS= read -r line; do echo "Claude processing complete. Full output saved to /tmp/claude-${ISSUE_KEY}-output.json" if [ $EXIT_CODE -eq 0 ]; then - # Parse PR URL from result if available - PR_URL=$(echo "$RESULT" | grep -oP 'https://github.com/openshift/hypershift/pull/[0-9]+' | head -1 || echo "") + # Extract the PR URL created by Claude. Strategy 1 (primary): parse the + # structured JSONL output to find tool_result content for "gh pr create" + # Bash tool calls. This is deterministic and avoids extra GitHub API calls. + # Strategy 2 (fallback): verify candidate URLs via gh pr view (costs N API + # calls but handles schema changes or missing JSONL output). + PR_URL="" + OUTPUT_FILE="/tmp/claude-${ISSUE_KEY}-output.json" + + if [ -f "$OUTPUT_FILE" ]; then + # Extract tool_use IDs for "gh pr create" Bash commands. + # grep '^{' skips non-JSON stderr lines (from 2>&1). + IDS=$(grep '^{' "$OUTPUT_FILE" | jq -rs ' + [.[] | + select(.type == "assistant") | + .message.content[]? | + select(.type == "tool_use" and .name == "Bash" and + (.input.command | tostring | contains("gh pr create"))) | + .id + ]' 2>/dev/null || echo '[]') + + # If we found gh pr create calls, get the PR URL from matching results + if [ "$IDS" != "[]" ] && [ -n "$IDS" ]; then + PR_URL=$(grep '^{' "$OUTPUT_FILE" | jq -rs --argjson ids "$IDS" ' + [.[] | + select(.type == "user") | + .message.content[]? | + select(.type == "tool_result" and (.tool_use_id | IN($ids[]))) | + .content | + if type == "array" then .[].text // empty + elif type == "string" then . + else empty end + ] | + map(capture("(?https://github\\.com/[^/]+/[^/]+/pull/[0-9]+)").url) | + last // empty + ' 2>/dev/null || echo "") + fi + fi + + # Fallback: verify candidate URLs via gh pr view if JSONL parsing found nothing + if [ -z "$PR_URL" ]; then + CANDIDATE_URLS=$(echo "$RESULT" | grep -oP 'https://github.com/openshift/hypershift/pull/[0-9]+' | sort -u || true) + if [ -n "$CANDIDATE_URLS" ]; then + while IFS= read -r url; do + PR_JSON=$(gh pr view "$url" --json title,author 2>/dev/null || true) + PR_TITLE=$(echo "$PR_JSON" | jq -r '.title // empty' 2>/dev/null || true) + PR_AUTHOR=$(echo "$PR_JSON" | jq -r '.author.login // empty' 2>/dev/null || true) + if [[ "$PR_TITLE" == "${ISSUE_KEY}"* ]] && [[ "$PR_AUTHOR" == *"hypershift-jira-solve-ci"* ]]; then + PR_URL="$url" + break + fi + done <<< "$CANDIDATE_URLS" + fi + fi echo "✅ Successfully processed $ISSUE_KEY" if [ -n "$PR_URL" ]; then