Skip to content

estc-pr-buildkite-detective: pre-fetch logs via setup-commands - #764

Merged
strawgate merged 6 commits into
mainfrom
feat/buildkite-pre-fetch-setup-commands
Mar 20, 2026
Merged

strawgate merged 6 commits into
mainfrom
feat/buildkite-pre-fetch-setup-commands

Conversation

@strawgate

@strawgate strawgate commented Mar 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This refactor removes runtime Buildkite MCP usage from PR Buildkite Detective and switches to local-file analysis.

Buildkite failure data is now pre-fetched by the workflow itself (before the agent runs), and the agent reads only local files under /tmp/gh-aw/.

Workflow changes

  • Removed mcp-servers.buildkite configuration.
  • Removed mcp.buildkite.com from the workflow network allowlist.
  • Removed buildkite-org and buildkite-pipeline inputs.
  • Made BUILDKITE_API_TOKEN required.
  • Added a built-in Fetch Buildkite failure data step that:
    • resolves Buildkite build links from gh pr checks
    • calls the Buildkite API for failed script jobs
    • writes /tmp/gh-aw/buildkite-failures.txt
    • writes per-job logs under /tmp/gh-aw/buildkite-logs/
  • Kept setup-commands as an optional repo-specific step after the pre-fetch step.
  • Removed the mcp-pagination fragment import.
  • Updated Step 2 guidance to read pre-fetched files from /tmp/gh-aw/buildkite-failures.txt and /tmp/gh-aw/buildkite-logs/.
  • Added explicit noop behavior when /tmp/gh-aw/buildkite-failures.txt is absent.

See elastic/beats#49589 for a related usage context.

Test plan

  • Compiled lock file (make compile)
  • Verify BUILDKITE_API_TOKEN is available to the built-in fetch step
  • Verify the fetch step writes /tmp/gh-aw/buildkite-failures.txt and /tmp/gh-aw/buildkite-logs/*
  • Verify the agent reads pre-fetched files and does not query Buildkite MCP directly
  • Verify noop is called when /tmp/gh-aw/buildkite-failures.txt is absent

The body of this PR is automatically managed by the Trigger Update PR Body workflow.

strawgate and others added 2 commits March 20, 2026 14:25
- Replace remote mcp.buildkite.com HTTP MCP with buildkite/mcp-server container
- Allow api.buildkite.com for REST API egress; drop mcp.buildkite.com
- Update estc-pr-buildkite-detective README

Made-with: Cursor
- Expose BUILDKITE_API_TOKEN in the setup-commands env so callers can
  pre-fetch Buildkite failure data before the agent runs
- Add Step 2 shortcut: if /tmp/gh-aw/buildkite-failures.txt exists
  (summary) with per-job logs under /tmp/gh-aw/buildkite-logs/, skip
  MCP and public-page steps entirely
- Improve MCP guidance from real-world dry-run findings:
  - Filter builds by commit SHA not branch (fork PRs use fork:branch format)
  - Distinguish failed (ran, exit != 0) from broken (never ran, no logs)
  - Use tail_logs first; list_annotations is infra metrics, not failures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…gs only

The workflow now relies entirely on data pre-fetched by setup-commands
into /tmp/gh-aw/buildkite-failures.txt and /tmp/gh-aw/buildkite-logs/.
The agent never needs direct Buildkite API access.

- Remove mcp-servers.buildkite and api.buildkite.com network allowlist
- Remove buildkite-org and buildkite-pipeline inputs (no longer needed)
- Make BUILDKITE_API_TOKEN required (used by setup-commands to fetch data)
- Remove mcp-pagination import
- Simplify Step 2 to just read the pre-fetched files
- Remove all MCP/public-page fallback instructions from prompt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Mar 20, 2026 •

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Removed buildkite-org and buildkite-pipeline workflow inputs and made BUILDKITE_API_TOKEN a required secret. Buildkite MCP server configuration and related mcp.buildkite.com allowlist entries were removed; gateway/container no longer passes BUILDKITE_API_TOKEN. Agent logic and prompts were changed to consume pre-fetched Buildkite failure data from /tmp/gh-aw/buildkite-failures.txt and logs under /tmp/gh-aw/buildkite-logs/ (noop if absent). Documentation and embedded workflow instructions were updated to reflect these changes.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/buildkite-pre-fetch-setup-commands
  • 🛠️ Update Documentation: Commit on current branch
  • 🛠️ Update Documentation: Create PR

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

coderabbitai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/gh-aw-estc-pr-buildkite-detective.md (1)

148-149: ⚠️ Potential issue | 🟠 Major

Branch-based PR filtering can drop valid fork PRs

The branch match gate can discard correct PRs for forked branches (owner:branch format mismatch). Since you already resolve by commit_sha, keep commit association as the primary filter and avoid hard branch equality here.

Suggested adjustment
-  - Otherwise, use `bash` + `gh api repos/${{ github.repository }}/commits/{commit_sha}/pulls` to find PRs containing the commit SHA. Filter the results to keep only PRs whose `state` is `"open"` and, when `branches` is non-empty, whose `head.ref` matches one of the listed branches. If no candidates remain, also try searching open PRs whose head branch matches one of the branches.
+  - Otherwise, use `bash` + `gh api repos/${{ github.repository }}/commits/{commit_sha}/pulls` to find PRs containing the commit SHA. Filter the results to keep only PRs whose `state` is `"open"`. Do not require branch-name equality for fork PRs; use branch matching only as an optional tiebreaker when multiple open PRs remain.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/gh-aw-estc-pr-buildkite-detective.md around lines 148 -
149, When filtering PRs returned by gh api repos/${{ github.repository
}}/commits/{commit_sha}/pulls, do not drop PRs solely because head.ref does not
exactly equal an entry in branches (this breaks fork PRs with owner:branch
formats); instead keep all PRs associated with the commit_sha as primary
candidates and only apply relaxed branch matching: consider a branch match if
head.ref === branch OR head.ref endsWith(`/${branch}`) OR
head.ref.split(':').pop() === branch. Update the filter logic around checking
state === "open" and branches to use this relaxed comparison, and only if no
candidates remain then run the fallback search of open PRs by head branch using
the same relaxed match before calling noop with "No pull request associated with
failed commit status; nothing to do".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/gh-aw-estc-pr-buildkite-detective.md:
- Around line 46-47: The BUILDKITE_API_TOKEN requirement is currently
unconditional; change the workflow so BUILDKITE_API_TOKEN is required only when
the setup-prefetch path is used (i.e., when the workflow input like
inputs.setup-commands or a boolean input enabling setup prefetch is true).
Update the job/input validation logic that declares BUILDKITE_API_TOKEN to make
it conditional based on inputs.setup-commands (or the corresponding
setup-prefetch input) so callers that don't use setup commands are not forced to
provide the token; ensure the requirement is evaluated at workflow
dispatch/usage time and keep the environment variable name BUILDKITE_API_TOKEN
unchanged.

---

Outside diff comments:
In @.github/workflows/gh-aw-estc-pr-buildkite-detective.md:
- Around line 148-149: When filtering PRs returned by gh api repos/${{
github.repository }}/commits/{commit_sha}/pulls, do not drop PRs solely because
head.ref does not exactly equal an entry in branches (this breaks fork PRs with
owner:branch formats); instead keep all PRs associated with the commit_sha as
primary candidates and only apply relaxed branch matching: consider a branch
match if head.ref === branch OR head.ref endsWith(`/${branch}`) OR
head.ref.split(':').pop() === branch. Update the filter logic around checking
state === "open" and branches to use this relaxed comparison, and only if no
candidates remain then run the fallback search of open PRs by head branch using
the same relaxed match before calling noop with "No pull request associated with
failed commit status; nothing to do".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5681a3ca-e1aa-40f3-a600-d7d7629d3377

📥 Commits

Reviewing files that changed from the base of the PR and between 30e7007 and f536254.

📒 Files selected for processing (1)
  • .github/workflows/gh-aw-estc-pr-buildkite-detective.md

Comment on lines 46 to +47
BUILDKITE_API_TOKEN:
required: false
required: true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Scope BUILDKITE_API_TOKEN requirement to setup-command usage

Making BUILDKITE_API_TOKEN globally required breaks callers that don’t use inputs.setup-commands. This should be conditionally enforced only when setup prefetch is enabled.

Suggested adjustment
secrets:
  COPILOT_GITHUB_TOKEN:
    required: true
  BUILDKITE_API_TOKEN:
-    required: true
+    required: false
  - name: Repo-specific setup
    if: ${{ inputs.setup-commands != '' }}
    env:
      SETUP_COMMANDS: ${{ inputs.setup-commands }}
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_API_TOKEN }}
-   run: eval "$SETUP_COMMANDS"
+   run: |
+     set -euo pipefail
+     if [ -z "${BUILDKITE_API_TOKEN:-}" ]; then
+       echo "BUILDKITE_API_TOKEN is required when setup-commands is provided" >&2
+       exit 1
+     fi
+     eval "$SETUP_COMMANDS"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/gh-aw-estc-pr-buildkite-detective.md around lines 46 - 47,
The BUILDKITE_API_TOKEN requirement is currently unconditional; change the
workflow so BUILDKITE_API_TOKEN is required only when the setup-prefetch path is
used (i.e., when the workflow input like inputs.setup-commands or a boolean
input enabling setup prefetch is true). Update the job/input validation logic
that declares BUILDKITE_API_TOKEN to make it conditional based on
inputs.setup-commands (or the corresponding setup-prefetch input) so callers
that don't use setup commands are not forced to provide the token; ensure the
requirement is evaluated at workflow dispatch/usage time and keep the
environment variable name BUILDKITE_API_TOKEN unchanged.

@github-actions github-actions Bot added the medium_boom Medium PR blast radius; likely benefits from human review label Mar 20, 2026
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## How it works

Triggered automatically when a commit status or check run reports a failure. Looks up the related Buildkite build via MCP, analyzes failed jobs/logs/annotations, and posts a comment with root cause and recommended fixes. Read-only — never pushes changes.
Triggered automatically when a commit status or check run reports a failure. Looks up the related Buildkite build via the [Buildkite MCP server](https://buildkite.com/docs/apis/mcp-server/local/installing) (`buildkite/mcp-server`, stdio), analyzes failed jobs/logs/annotations, and posts a comment with root cause and recommended fixes. Read-only — never pushes changes.

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.

The README now conflicts with the workflow contract introduced in this PR.

This line says the detective queries Buildkite via MCP, but the workflow now expects pre-fetched local artifacts (/tmp/gh-aw/buildkite-failures.txt and /tmp/gh-aw/buildkite-logs/*) and noops when they are missing.

Please update this section to describe the setup-commands prefetch flow. Also align the Inputs/Secrets sections with the new contract (removed buildkite-org/buildkite-pipeline, and BUILDKITE_API_TOKEN now required).

Move the pre-fetch script into the workflow itself as a dedicated step
that runs between event context resolution and the agent. BUILDKITE_API_TOKEN
is used here directly — callers no longer need setup-commands for this.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot mentioned this pull request Mar 20, 2026
pass

if not pr_number:
print('No PR number found in event context; skipping Buildkite data fetch')

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.

The new prefetch step exits early when pr_numbers is empty, but Resolve event context always writes pr_numbers: empty for status events (line 86). That means status-triggered failures skip Buildkite prefetch entirely, /tmp/gh-aw/buildkite-failures.txt is never produced, and Step 2 later noops.

Please add a fallback here to resolve PRs from commit_sha (e.g., gh api repos/\$\{REPO}/commits/{sha}/pulls and filter open PRs), so status events still fetch logs.

- Remove buildkite-org and buildkite-pipeline from example.yml (inputs no longer exist)
- Update README: remove MCP server mention, remove stale inputs, make
  BUILDKITE_API_TOKEN required
- Recompile to regenerate trigger-estc-pr-buildkite-detective.yml

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@strawgate
strawgate merged commit d355ec5 into main Mar 20, 2026
17 of 18 checks passed
@strawgate
strawgate deleted the feat/buildkite-pre-fetch-setup-commands branch March 20, 2026 21:29
for job in failed:
total_failed += 1
slug = slugify(job.get('name', f'job-{job["id"]}'))
log_file = f'/tmp/gh-aw/buildkite-logs/{pipeline}-{slug}.txt'

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.

Log filenames can collide across builds and overwrite earlier failure evidence.

log_file is currently keyed by only pipeline + slugified job name, so two failed jobs with the same name (common with retries/matrix jobs or multiple failed builds in one run) write to the same path. That can make the summary point multiple entries at one overwritten file.

Consider including a unique identifier like build number and/or job id in the filename, for example:

Suggested change
log_file = f'/tmp/gh-aw/buildkite-logs/{pipeline}-{slug}.txt'
log_file = f'/tmp/gh-aw/buildkite-logs/{pipeline}-{number}-{job["id"]}-{slug}.txt'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

medium_boom Medium PR blast radius; likely benefits from human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant