From f315b2c1c0a07ddb6e4b57986b4eb11bf7b985d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 16:29:18 +0000 Subject: [PATCH 1/6] Initial plan From dd792d6f01661570376161c995ff4c50f142ff32 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 16:49:29 +0000 Subject: [PATCH 2/6] Add cleanup job to delete older detective comments after new one is posted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduces comment spam on PRs with multiple failing commits by ensuring at most one PR Buildkite Detective comment exists at any time: - Same diagnosis → agent emits noop, existing comment unchanged - New diagnosis → new comment posted, cleanup deletes older ones The cleanup job identifies detective comments using three structural markers (ela.st/github-ai-tools footer, buildkite.com build link, ### TL;DR response header) and deletes all matching older comments while keeping the newly created one. Agent-Logs-Url: https://github.com/elastic/ai-github-actions/sessions/c3669670-d35a-41bd-a062-76bd739798cd Co-authored-by: v1v <2871786+v1v@users.noreply.github.com> --- .../trigger-estc-pr-buildkite-detective.yml | 72 +++++++++++++++++++ .../estc-pr-buildkite-detective.md | 26 ++++++- .../estc-pr-buildkite-detective/README.md | 9 ++- .../estc-pr-buildkite-detective/example.yml | 72 +++++++++++++++++++ 4 files changed, 177 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trigger-estc-pr-buildkite-detective.yml b/.github/workflows/trigger-estc-pr-buildkite-detective.yml index b7769576..b2d8112c 100644 --- a/.github/workflows/trigger-estc-pr-buildkite-detective.yml +++ b/.github/workflows/trigger-estc-pr-buildkite-detective.yml @@ -22,3 +22,75 @@ jobs: secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_API_TOKEN }} + + cleanup: + name: Remove older detective comments + needs: run + if: needs.run.result != 'skipped' && needs.run.outputs.comment_id != '' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Delete older detective comments + uses: actions/github-script@v7 + env: + NEW_COMMENT_ID: ${{ needs.run.outputs.comment_id }} + with: + script: | + const newCommentId = process.env.NEW_COMMENT_ID; + + // Resolve the PR number from the triggering event + let prNumber; + if (context.eventName === 'check_run') { + const prs = context.payload.check_run.pull_requests; + if (prs && prs.length > 0) { + prNumber = prs[0].number; + } + } else if (context.eventName === 'status') { + const sha = context.payload.commit.sha; + const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ + owner: context.repo.owner, + repo: context.repo.repo, + commit_sha: sha, + }); + if (prs.length > 0) { + prNumber = prs[0].number; + } + } + + if (!prNumber) { + core.info('No PR number found, skipping cleanup'); + return; + } + + core.info(`Cleaning up older detective comments on PR #${prNumber} (keeping comment ${newCommentId})`); + + // List all comments on the PR + const comments = await github.paginate(github.rest.issues.listComments, { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); + + // Identify and delete older detective comments. + // Detective comments are recognized by three structural markers: + // 1. ela.st/github-ai-tools — present in the gh-aw footer of every detective comment + // 2. buildkite.com — present in the Buildkite build evidence link + // 3. ### TL;DR — the mandatory header in every detective comment response + for (const comment of comments) { + if (comment.id.toString() === newCommentId) continue; + const body = comment.body || ''; + if ( + body.includes('ela.st/github-ai-tools') && + body.includes('buildkite.com') && + body.includes('### TL;DR') + ) { + core.info(`Deleting older detective comment ${comment.id}`); + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id, + }); + } + } diff --git a/docs/workflows/gh-agent-workflows/estc-pr-buildkite-detective.md b/docs/workflows/gh-agent-workflows/estc-pr-buildkite-detective.md index b9898154..061cf972 100644 --- a/docs/workflows/gh-agent-workflows/estc-pr-buildkite-detective.md +++ b/docs/workflows/gh-agent-workflows/estc-pr-buildkite-detective.md @@ -53,9 +53,16 @@ if: >- - Proceeds only when failed script jobs are found, writes summaries/log tails under `/tmp/gh-aw/`, and analyzes those logs. - Performs deduplication against the latest prior detective comment; emits `noop` instead of a duplicate diagnosis. +## Comment lifecycle + +The workflow keeps **at most one detective comment** per PR: + +- **Same diagnosis**: the agent emits `noop` and the existing comment is left untouched. +- **New diagnosis**: a new comment is posted, then any previous detective comments on the PR are deleted by the `cleanup` job, leaving only the latest analysis visible. + ## Safe outputs -- `add-comment` — post a PR comment with root cause and remediation (max 1, older detective comments hidden) +- `add-comment` — post a PR comment with root cause and remediation (max 1 per run; older detective comments deleted after posting) - `noop` — emitted when: - the agent starts but Buildkite failure data is unavailable, or - diagnosis is unchanged from the most recent detective report @@ -85,4 +92,21 @@ jobs: secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_API_TOKEN }} + + cleanup: + name: Remove older detective comments + needs: run + if: needs.run.result != 'skipped' && needs.run.outputs.comment_id != '' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Delete older detective comments + uses: actions/github-script@v7 + env: + NEW_COMMENT_ID: ${{ needs.run.outputs.comment_id }} + with: + script: | + # see example.yml for the full script ``` diff --git a/gh-agent-workflows/estc-pr-buildkite-detective/README.md b/gh-agent-workflows/estc-pr-buildkite-detective/README.md index 27226e6d..ee2fd9cf 100644 --- a/gh-agent-workflows/estc-pr-buildkite-detective/README.md +++ b/gh-agent-workflows/estc-pr-buildkite-detective/README.md @@ -38,7 +38,14 @@ See [example.yml](example.yml) for the full workflow file. ## Safe Outputs -- `add-comment` — post a comment explaining the failure (max 1, hides older detective comments) +- `add-comment` — post a comment explaining the failure (max 1 per run) - `noop` — emitted when diagnosis is unchanged since the last report If the agent starts but the pre-fetched Buildkite summary is unavailable, it emits `noop` (`No Buildkite failure data`). If no failed script jobs are found (or the build is not a PR build / not in a failed state), the workflow exits early with a notice and does not emit `noop`. + +## Comment Lifecycle + +The workflow keeps **at most one detective comment** per PR: + +- **Same diagnosis**: the agent emits `noop` and the existing comment is left untouched. +- **New diagnosis**: a new comment is posted, then any previous detective comments on the PR are deleted by the `cleanup` job, leaving only the latest analysis visible. diff --git a/gh-agent-workflows/estc-pr-buildkite-detective/example.yml b/gh-agent-workflows/estc-pr-buildkite-detective/example.yml index 0a06e9c1..28216c26 100644 --- a/gh-agent-workflows/estc-pr-buildkite-detective/example.yml +++ b/gh-agent-workflows/estc-pr-buildkite-detective/example.yml @@ -20,3 +20,75 @@ jobs: secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_API_TOKEN }} + + cleanup: + name: Remove older detective comments + needs: run + if: needs.run.result != 'skipped' && needs.run.outputs.comment_id != '' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Delete older detective comments + uses: actions/github-script@v7 + env: + NEW_COMMENT_ID: ${{ needs.run.outputs.comment_id }} + with: + script: | + const newCommentId = process.env.NEW_COMMENT_ID; + + // Resolve the PR number from the triggering event + let prNumber; + if (context.eventName === 'check_run') { + const prs = context.payload.check_run.pull_requests; + if (prs && prs.length > 0) { + prNumber = prs[0].number; + } + } else if (context.eventName === 'status') { + const sha = context.payload.commit.sha; + const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ + owner: context.repo.owner, + repo: context.repo.repo, + commit_sha: sha, + }); + if (prs.length > 0) { + prNumber = prs[0].number; + } + } + + if (!prNumber) { + core.info('No PR number found, skipping cleanup'); + return; + } + + core.info(`Cleaning up older detective comments on PR #${prNumber} (keeping comment ${newCommentId})`); + + // List all comments on the PR + const comments = await github.paginate(github.rest.issues.listComments, { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); + + // Identify and delete older detective comments. + // Detective comments are recognized by three structural markers: + // 1. ela.st/github-ai-tools — present in the gh-aw footer of every detective comment + // 2. buildkite.com — present in the Buildkite build evidence link + // 3. ### TL;DR — the mandatory header in every detective comment response + for (const comment of comments) { + if (comment.id.toString() === newCommentId) continue; + const body = comment.body || ''; + if ( + body.includes('ela.st/github-ai-tools') && + body.includes('buildkite.com') && + body.includes('### TL;DR') + ) { + core.info(`Deleting older detective comment ${comment.id}`); + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id, + }); + } + } From ab127ed7a7d2a03f4fb5d35b37721a44a223f92e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 16:50:47 +0000 Subject: [PATCH 3/6] Address code review feedback: use success check and add context.repo comment Agent-Logs-Url: https://github.com/elastic/ai-github-actions/sessions/c3669670-d35a-41bd-a062-76bd739798cd Co-authored-by: v1v <2871786+v1v@users.noreply.github.com> --- .github/workflows/trigger-estc-pr-buildkite-detective.yml | 3 ++- gh-agent-workflows/estc-pr-buildkite-detective/example.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/trigger-estc-pr-buildkite-detective.yml b/.github/workflows/trigger-estc-pr-buildkite-detective.yml index b2d8112c..cb0bb472 100644 --- a/.github/workflows/trigger-estc-pr-buildkite-detective.yml +++ b/.github/workflows/trigger-estc-pr-buildkite-detective.yml @@ -26,7 +26,7 @@ jobs: cleanup: name: Remove older detective comments needs: run - if: needs.run.result != 'skipped' && needs.run.outputs.comment_id != '' + if: needs.run.result == 'success' && needs.run.outputs.comment_id != '' runs-on: ubuntu-latest permissions: issues: write @@ -67,6 +67,7 @@ jobs: core.info(`Cleaning up older detective comments on PR #${prNumber} (keeping comment ${newCommentId})`); // List all comments on the PR + // context.repo is { owner, repo } where repo is the repository name const comments = await github.paginate(github.rest.issues.listComments, { owner: context.repo.owner, repo: context.repo.repo, diff --git a/gh-agent-workflows/estc-pr-buildkite-detective/example.yml b/gh-agent-workflows/estc-pr-buildkite-detective/example.yml index 28216c26..05344f48 100644 --- a/gh-agent-workflows/estc-pr-buildkite-detective/example.yml +++ b/gh-agent-workflows/estc-pr-buildkite-detective/example.yml @@ -24,7 +24,7 @@ jobs: cleanup: name: Remove older detective comments needs: run - if: needs.run.result != 'skipped' && needs.run.outputs.comment_id != '' + if: needs.run.result == 'success' && needs.run.outputs.comment_id != '' runs-on: ubuntu-latest permissions: issues: write @@ -65,6 +65,7 @@ jobs: core.info(`Cleaning up older detective comments on PR #${prNumber} (keeping comment ${newCommentId})`); // List all comments on the PR + // context.repo is { owner, repo } where repo is the repository name const comments = await github.paginate(github.rest.issues.listComments, { owner: context.repo.owner, repo: context.repo.repo, From 146002f0a0e77df4a06dc9709017f5160d94fc1c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 17:25:16 +0000 Subject: [PATCH 4/6] Implement marker-based upsert for ESTC PR Buildkite Detective comments Per @v1v's action plan: 1. Add stable HTML marker to every detective comment for deterministic identification 2. Replace hide-older-comments fragment with safe-output-add-comment-pr.md to switch from add+hide to marker-based upsert semantics 3. Update agent instructions: Step 1.5 searches for existing comment with marker; Step 3 passes reply_to_id to update in place when found 4. Recompile lock file reflecting new safe-outputs config (hide_older_comments removed; reply_to_id-based upsert enabled) 5. Update README and docs to reflect comment lifecycle behavior 6. Revert cleanup job from example.yml (no longer needed) Agent-Logs-Url: https://github.com/elastic/ai-github-actions/sessions/bf72f7ac-12c3-4a34-92d4-1ba756d9310e Co-authored-by: v1v <2871786+v1v@users.noreply.github.com> --- ...gh-aw-estc-pr-buildkite-detective.lock.yml | 39 ++++++---- .../gh-aw-estc-pr-buildkite-detective.md | 13 +++- .../trigger-estc-pr-buildkite-detective.yml | 73 ------------------- .../estc-pr-buildkite-detective.md | 25 ++----- .../estc-pr-buildkite-detective/README.md | 4 +- .../estc-pr-buildkite-detective/example.yml | 73 ------------------- 6 files changed, 40 insertions(+), 187 deletions(-) diff --git a/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml b/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml index 40b1d0d0..8d54741b 100644 --- a/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml +++ b/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"277d5b4787991f78a7b71ca43ce7b2b9582304625eb9f0949781bfdaf8604b87","agent_id":"copilot","agent_model":"${{ inputs.model }}"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"089869caa3d7b063aa6af22927ceb1345e6cd07594e05c4939f868bff187a8bf","agent_id":"copilot","agent_model":"${{ inputs.model }}"} # gh-aw-manifest: {"version":1,"secrets":["BUILDKITE_API_TOKEN","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"40f1582b2485089dde7abd97c1529aa768e1baff","version":"v5"},{"repo":"actions/setup-node","sha":"6044e13b5dc448c55e2357c09f80417699197238","version":"v6"},{"repo":"actions/setup-python","sha":"a26af69be951a213d495a4c3e4e4022e16d87065","version":"v5"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"e58605a9b6da7c637471fab8847a5e5a6b8df081","version":"v5"},{"repo":"github/gh-aw/actions/setup","sha":"ce1794953e0ec42adc41b6fca05e02ab49ee21c3","version":"v0.68.3"},{"repo":"ruby/setup-ruby","sha":"4c56a21280b36d862b5fc31348f463d60bdc55d5","version":"v1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -32,7 +32,7 @@ # - gh-aw-fragments/network-ecosystems.md # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md -# - gh-aw-fragments/safe-output-add-comment-pr-hide-older.md +# - gh-aw-fragments/safe-output-add-comment-pr.md # # inlined-imports: true # @@ -203,14 +203,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_0d6e5341c6867908_EOF' + cat << 'GH_AW_PROMPT_43a9ae945f674598_EOF' - GH_AW_PROMPT_0d6e5341c6867908_EOF + GH_AW_PROMPT_43a9ae945f674598_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_0d6e5341c6867908_EOF' + cat << 'GH_AW_PROMPT_43a9ae945f674598_EOF' Tools: add_comment, missing_tool, missing_data, noop @@ -242,9 +242,9 @@ jobs: {{/if}} - GH_AW_PROMPT_0d6e5341c6867908_EOF + GH_AW_PROMPT_43a9ae945f674598_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_0d6e5341c6867908_EOF' + cat << 'GH_AW_PROMPT_43a9ae945f674598_EOF' ## MCP Servers @@ -305,6 +305,7 @@ jobs: 2. Read `/tmp/gh-aw/buildkite-failures.txt` for the failed job summary. If it does not exist, call `noop` with "No Buildkite failure data" and stop. 3. Read the individual log files listed in the summary (under `/tmp/gh-aw/buildkite-logs/`). 4. Call `pull_request_read` with method `get` on the PR number to get the author, diff, and recent changes. + 5. Call `pull_request_read` with method `get_comments` on the PR number to find any existing detective comment. An existing detective comment contains the marker `` in its body. If one exists, note its `id` — you will use it to update the comment in place rather than creating a new one. ### Step 2: Analyze @@ -323,13 +324,19 @@ jobs: 3. If the error involves an external library or tool, use `web-fetch` to check docs/changelogs. 4. Propose a concrete fix or, if inconclusive, state what additional data is needed. - **Deduplication**: Check the most recent prior detective comment on the PR. If the root cause and remediation are the same, call `noop` instead of posting a duplicate. + **Deduplication**: Check the existing detective comment found in Step 1.5 (look for ``). If the root cause and remediation are the same as already documented there, call `noop` instead of posting a duplicate. ### Step 3: Respond - Call `add_comment` on the PR using this structure: + Always include the invisible marker `` as the very first line of the comment body. This marker is used to find and update the comment on subsequent runs. + + - If an existing detective comment was found in Step 1.5: call `add_comment` with `reply_to_id` set to that comment's `id`. This updates the comment in place so the PR has at most one detective comment at a time. + - If no existing detective comment was found: call `add_comment` without `reply_to_id` to create a new one. + + Use this structure for the body: ```markdown + ### TL;DR [1-2 sentences: what failed and the immediate action needed] @@ -361,7 +368,7 @@ jobs: __GH_AW_EXPR_49B959F1__ - GH_AW_PROMPT_0d6e5341c6867908_EOF + GH_AW_PROMPT_43a9ae945f674598_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -600,9 +607,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_8e2812b3491f85c5_EOF' - {"add_comment":{"hide_older_comments":true,"max":1,"target":"triggering"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_8e2812b3491f85c5_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_c6c0ddacd75b916f_EOF' + {"add_comment":{"max":1,"target":"triggering"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_c6c0ddacd75b916f_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -786,7 +793,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_7e4e8e010ae746d5_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_256c35996d837f4a_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -841,7 +848,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_7e4e8e010ae746d5_EOF + GH_AW_MCP_CONFIG_256c35996d837f4a_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: @@ -1418,7 +1425,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.gradle-enterprise.cloud,*.hackage.haskell.org,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,buildkite.com,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,deps.files.ghostty.org,develocity.apache.org,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.jetbrains.com,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,ge.spockframework.org,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven-central.storage-download.googleapis.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,maven.pkg.jetbrains.space,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,repository.apache.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,scala.jfrog.io,scans-in.gradle.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.googleapis.com,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1,\"target\":\"triggering\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"triggering\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-estc-pr-buildkite-detective.md b/.github/workflows/gh-aw-estc-pr-buildkite-detective.md index eab40f68..a830cc00 100644 --- a/.github/workflows/gh-aw-estc-pr-buildkite-detective.md +++ b/.github/workflows/gh-aw-estc-pr-buildkite-detective.md @@ -7,7 +7,7 @@ imports: - gh-aw-fragments/formatting.md - gh-aw-fragments/rigor.md - gh-aw-fragments/messages-footer.md - - gh-aw-fragments/safe-output-add-comment-pr-hide-older.md + - gh-aw-fragments/safe-output-add-comment-pr.md - gh-aw-fragments/network-ecosystems.md engine: id: copilot @@ -229,6 +229,7 @@ Analyze failed Buildkite CI builds for pull requests in ${{ github.repository }} 2. Read `/tmp/gh-aw/buildkite-failures.txt` for the failed job summary. If it does not exist, call `noop` with "No Buildkite failure data" and stop. 3. Read the individual log files listed in the summary (under `/tmp/gh-aw/buildkite-logs/`). 4. Call `pull_request_read` with method `get` on the PR number to get the author, diff, and recent changes. +5. Call `pull_request_read` with method `get_comments` on the PR number to find any existing detective comment. An existing detective comment contains the marker `` in its body. If one exists, note its `id` — you will use it to update the comment in place rather than creating a new one. ### Step 2: Analyze @@ -247,13 +248,19 @@ For each: 3. If the error involves an external library or tool, use `web-fetch` to check docs/changelogs. 4. Propose a concrete fix or, if inconclusive, state what additional data is needed. -**Deduplication**: Check the most recent prior detective comment on the PR. If the root cause and remediation are the same, call `noop` instead of posting a duplicate. +**Deduplication**: Check the existing detective comment found in Step 1.5 (look for ``). If the root cause and remediation are the same as already documented there, call `noop` instead of posting a duplicate. ### Step 3: Respond -Call `add_comment` on the PR using this structure: +Always include the invisible marker `` as the very first line of the comment body. This marker is used to find and update the comment on subsequent runs. + +- If an existing detective comment was found in Step 1.5: call `add_comment` with `reply_to_id` set to that comment's `id`. This updates the comment in place so the PR has at most one detective comment at a time. +- If no existing detective comment was found: call `add_comment` without `reply_to_id` to create a new one. + +Use this structure for the body: ```markdown + ### TL;DR [1-2 sentences: what failed and the immediate action needed] diff --git a/.github/workflows/trigger-estc-pr-buildkite-detective.yml b/.github/workflows/trigger-estc-pr-buildkite-detective.yml index cb0bb472..b7769576 100644 --- a/.github/workflows/trigger-estc-pr-buildkite-detective.yml +++ b/.github/workflows/trigger-estc-pr-buildkite-detective.yml @@ -22,76 +22,3 @@ jobs: secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_API_TOKEN }} - - cleanup: - name: Remove older detective comments - needs: run - if: needs.run.result == 'success' && needs.run.outputs.comment_id != '' - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - name: Delete older detective comments - uses: actions/github-script@v7 - env: - NEW_COMMENT_ID: ${{ needs.run.outputs.comment_id }} - with: - script: | - const newCommentId = process.env.NEW_COMMENT_ID; - - // Resolve the PR number from the triggering event - let prNumber; - if (context.eventName === 'check_run') { - const prs = context.payload.check_run.pull_requests; - if (prs && prs.length > 0) { - prNumber = prs[0].number; - } - } else if (context.eventName === 'status') { - const sha = context.payload.commit.sha; - const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ - owner: context.repo.owner, - repo: context.repo.repo, - commit_sha: sha, - }); - if (prs.length > 0) { - prNumber = prs[0].number; - } - } - - if (!prNumber) { - core.info('No PR number found, skipping cleanup'); - return; - } - - core.info(`Cleaning up older detective comments on PR #${prNumber} (keeping comment ${newCommentId})`); - - // List all comments on the PR - // context.repo is { owner, repo } where repo is the repository name - const comments = await github.paginate(github.rest.issues.listComments, { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - }); - - // Identify and delete older detective comments. - // Detective comments are recognized by three structural markers: - // 1. ela.st/github-ai-tools — present in the gh-aw footer of every detective comment - // 2. buildkite.com — present in the Buildkite build evidence link - // 3. ### TL;DR — the mandatory header in every detective comment response - for (const comment of comments) { - if (comment.id.toString() === newCommentId) continue; - const body = comment.body || ''; - if ( - body.includes('ela.st/github-ai-tools') && - body.includes('buildkite.com') && - body.includes('### TL;DR') - ) { - core.info(`Deleting older detective comment ${comment.id}`); - await github.rest.issues.deleteComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: comment.id, - }); - } - } diff --git a/docs/workflows/gh-agent-workflows/estc-pr-buildkite-detective.md b/docs/workflows/gh-agent-workflows/estc-pr-buildkite-detective.md index 061cf972..7beb3278 100644 --- a/docs/workflows/gh-agent-workflows/estc-pr-buildkite-detective.md +++ b/docs/workflows/gh-agent-workflows/estc-pr-buildkite-detective.md @@ -57,12 +57,14 @@ if: >- The workflow keeps **at most one detective comment** per PR: -- **Same diagnosis**: the agent emits `noop` and the existing comment is left untouched. -- **New diagnosis**: a new comment is posted, then any previous detective comments on the PR are deleted by the `cleanup` job, leaving only the latest analysis visible. +- Every detective comment includes an invisible HTML marker: ``. +- On each run the agent searches PR comments for this marker to find the existing detective comment. +- **Same diagnosis**: the agent emits `noop`; the existing comment is left untouched. +- **New diagnosis**: the agent calls `add_comment` with `reply_to_id` set to the existing comment's ID, updating it in place. If no prior comment exists, a new one is created. ## Safe outputs -- `add-comment` — post a PR comment with root cause and remediation (max 1 per run; older detective comments deleted after posting) +- `add-comment` — post or update a PR comment with root cause and remediation (max 1 per run; uses `reply_to_id` to update existing detective comment in place) - `noop` — emitted when: - the agent starts but Buildkite failure data is unavailable, or - diagnosis is unchanged from the most recent detective report @@ -92,21 +94,4 @@ jobs: secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_API_TOKEN }} - - cleanup: - name: Remove older detective comments - needs: run - if: needs.run.result != 'skipped' && needs.run.outputs.comment_id != '' - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - name: Delete older detective comments - uses: actions/github-script@v7 - env: - NEW_COMMENT_ID: ${{ needs.run.outputs.comment_id }} - with: - script: | - # see example.yml for the full script ``` diff --git a/gh-agent-workflows/estc-pr-buildkite-detective/README.md b/gh-agent-workflows/estc-pr-buildkite-detective/README.md index ee2fd9cf..c2780bb4 100644 --- a/gh-agent-workflows/estc-pr-buildkite-detective/README.md +++ b/gh-agent-workflows/estc-pr-buildkite-detective/README.md @@ -38,7 +38,7 @@ See [example.yml](example.yml) for the full workflow file. ## Safe Outputs -- `add-comment` — post a comment explaining the failure (max 1 per run) +- `add-comment` — post a comment explaining the failure (max 1 per run); uses `reply_to_id` to update the existing detective comment in place when one is found - `noop` — emitted when diagnosis is unchanged since the last report If the agent starts but the pre-fetched Buildkite summary is unavailable, it emits `noop` (`No Buildkite failure data`). If no failed script jobs are found (or the build is not a PR build / not in a failed state), the workflow exits early with a notice and does not emit `noop`. @@ -48,4 +48,4 @@ If the agent starts but the pre-fetched Buildkite summary is unavailable, it emi The workflow keeps **at most one detective comment** per PR: - **Same diagnosis**: the agent emits `noop` and the existing comment is left untouched. -- **New diagnosis**: a new comment is posted, then any previous detective comments on the PR are deleted by the `cleanup` job, leaving only the latest analysis visible. +- **New diagnosis**: the agent finds the existing detective comment (identified by the `` marker) and updates it in place via `reply_to_id`. If no previous comment exists, a new one is created. diff --git a/gh-agent-workflows/estc-pr-buildkite-detective/example.yml b/gh-agent-workflows/estc-pr-buildkite-detective/example.yml index 05344f48..0a06e9c1 100644 --- a/gh-agent-workflows/estc-pr-buildkite-detective/example.yml +++ b/gh-agent-workflows/estc-pr-buildkite-detective/example.yml @@ -20,76 +20,3 @@ jobs: secrets: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} BUILDKITE_API_TOKEN: ${{ secrets.BUILDKITE_API_TOKEN }} - - cleanup: - name: Remove older detective comments - needs: run - if: needs.run.result == 'success' && needs.run.outputs.comment_id != '' - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - name: Delete older detective comments - uses: actions/github-script@v7 - env: - NEW_COMMENT_ID: ${{ needs.run.outputs.comment_id }} - with: - script: | - const newCommentId = process.env.NEW_COMMENT_ID; - - // Resolve the PR number from the triggering event - let prNumber; - if (context.eventName === 'check_run') { - const prs = context.payload.check_run.pull_requests; - if (prs && prs.length > 0) { - prNumber = prs[0].number; - } - } else if (context.eventName === 'status') { - const sha = context.payload.commit.sha; - const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ - owner: context.repo.owner, - repo: context.repo.repo, - commit_sha: sha, - }); - if (prs.length > 0) { - prNumber = prs[0].number; - } - } - - if (!prNumber) { - core.info('No PR number found, skipping cleanup'); - return; - } - - core.info(`Cleaning up older detective comments on PR #${prNumber} (keeping comment ${newCommentId})`); - - // List all comments on the PR - // context.repo is { owner, repo } where repo is the repository name - const comments = await github.paginate(github.rest.issues.listComments, { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - }); - - // Identify and delete older detective comments. - // Detective comments are recognized by three structural markers: - // 1. ela.st/github-ai-tools — present in the gh-aw footer of every detective comment - // 2. buildkite.com — present in the Buildkite build evidence link - // 3. ### TL;DR — the mandatory header in every detective comment response - for (const comment of comments) { - if (comment.id.toString() === newCommentId) continue; - const body = comment.body || ''; - if ( - body.includes('ela.st/github-ai-tools') && - body.includes('buildkite.com') && - body.includes('### TL;DR') - ) { - core.info(`Deleting older detective comment ${comment.id}`); - await github.rest.issues.deleteComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: comment.id, - }); - } - } From 8724502af21686216b659fc1b346260a6fbb8c80 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 17:29:27 +0000 Subject: [PATCH 5/6] Fix HTML marker references stripped by gh-aw compiler The gh-aw compiler strips all patterns globally even within inline code spans. Fix by: - Referencing the marker as plain text `gh-aw-detective: estc-pr-buildkite-detective` in instruction text (preserved by compiler) - Keeping the full HTML comment in the fenced code block template (code blocks are not processed by the compiler) - Describing the Step 3 marker as "the gh-aw-detective HTML comment on the first line of the template below" The agent searches for `gh-aw-detective: estc-pr-buildkite-detective` in comment bodies (present in HTML comments as raw text) and writes the full `` HTML comment at the top of each response as shown in the template. Agent-Logs-Url: https://github.com/elastic/ai-github-actions/sessions/bf72f7ac-12c3-4a34-92d4-1ba756d9310e Co-authored-by: v1v <2871786+v1v@users.noreply.github.com> --- ...gh-aw-estc-pr-buildkite-detective.lock.yml | 28 +++++++++---------- .../gh-aw-estc-pr-buildkite-detective.md | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml b/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml index 8d54741b..aebc9594 100644 --- a/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml +++ b/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"089869caa3d7b063aa6af22927ceb1345e6cd07594e05c4939f868bff187a8bf","agent_id":"copilot","agent_model":"${{ inputs.model }}"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"63d5fb36a82fdffc1b87553fea719cdeaab274bb3a7c57ca7dba9911bf5b24e6","agent_id":"copilot","agent_model":"${{ inputs.model }}"} # gh-aw-manifest: {"version":1,"secrets":["BUILDKITE_API_TOKEN","COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/setup-go","sha":"40f1582b2485089dde7abd97c1529aa768e1baff","version":"v5"},{"repo":"actions/setup-node","sha":"6044e13b5dc448c55e2357c09f80417699197238","version":"v6"},{"repo":"actions/setup-python","sha":"a26af69be951a213d495a4c3e4e4022e16d87065","version":"v5"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"e58605a9b6da7c637471fab8847a5e5a6b8df081","version":"v5"},{"repo":"github/gh-aw/actions/setup","sha":"ce1794953e0ec42adc41b6fca05e02ab49ee21c3","version":"v0.68.3"},{"repo":"ruby/setup-ruby","sha":"4c56a21280b36d862b5fc31348f463d60bdc55d5","version":"v1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.20"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.20"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.2.19"},{"image":"ghcr.io/github/github-mcp-server:v0.32.0"},{"image":"node:lts-alpine"}]} # ___ _ _ # / _ \ | | (_) @@ -203,14 +203,14 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_43a9ae945f674598_EOF' + cat << 'GH_AW_PROMPT_1a1a27f180e88700_EOF' - GH_AW_PROMPT_43a9ae945f674598_EOF + GH_AW_PROMPT_1a1a27f180e88700_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_43a9ae945f674598_EOF' + cat << 'GH_AW_PROMPT_1a1a27f180e88700_EOF' Tools: add_comment, missing_tool, missing_data, noop @@ -242,9 +242,9 @@ jobs: {{/if}} - GH_AW_PROMPT_43a9ae945f674598_EOF + GH_AW_PROMPT_1a1a27f180e88700_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_43a9ae945f674598_EOF' + cat << 'GH_AW_PROMPT_1a1a27f180e88700_EOF' ## MCP Servers @@ -305,7 +305,7 @@ jobs: 2. Read `/tmp/gh-aw/buildkite-failures.txt` for the failed job summary. If it does not exist, call `noop` with "No Buildkite failure data" and stop. 3. Read the individual log files listed in the summary (under `/tmp/gh-aw/buildkite-logs/`). 4. Call `pull_request_read` with method `get` on the PR number to get the author, diff, and recent changes. - 5. Call `pull_request_read` with method `get_comments` on the PR number to find any existing detective comment. An existing detective comment contains the marker `` in its body. If one exists, note its `id` — you will use it to update the comment in place rather than creating a new one. + 5. Call `pull_request_read` with method `get_comments` on the PR number to find any existing detective comment. An existing detective comment contains the text `gh-aw-detective: estc-pr-buildkite-detective` in its body (embedded as an HTML comment). If one exists, note its `id` — you will use it to update the comment in place rather than creating a new one. ### Step 2: Analyze @@ -324,11 +324,11 @@ jobs: 3. If the error involves an external library or tool, use `web-fetch` to check docs/changelogs. 4. Propose a concrete fix or, if inconclusive, state what additional data is needed. - **Deduplication**: Check the existing detective comment found in Step 1.5 (look for ``). If the root cause and remediation are the same as already documented there, call `noop` instead of posting a duplicate. + **Deduplication**: Check the existing detective comment found in Step 1.5 (body contains `gh-aw-detective: estc-pr-buildkite-detective`). If the root cause and remediation are the same as already documented there, call `noop` instead of posting a duplicate. ### Step 3: Respond - Always include the invisible marker `` as the very first line of the comment body. This marker is used to find and update the comment on subsequent runs. + Always begin the comment body with the marker line shown at the top of the template below (the `gh-aw-detective` HTML comment on the first line). This marker lets future runs find and update this comment in place. - If an existing detective comment was found in Step 1.5: call `add_comment` with `reply_to_id` set to that comment's `id`. This updates the comment in place so the PR has at most one detective comment at a time. - If no existing detective comment was found: call `add_comment` without `reply_to_id` to create a new one. @@ -368,7 +368,7 @@ jobs: __GH_AW_EXPR_49B959F1__ - GH_AW_PROMPT_43a9ae945f674598_EOF + GH_AW_PROMPT_1a1a27f180e88700_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@373c709c69115d41ff229c7e5df9f8788daa9553 # v9 @@ -607,9 +607,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_c6c0ddacd75b916f_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_142b99b968c9b4eb_EOF' {"add_comment":{"max":1,"target":"triggering"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_c6c0ddacd75b916f_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_142b99b968c9b4eb_EOF - name: Write Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -793,7 +793,7 @@ jobs: export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.2.19' mkdir -p /home/runner/.copilot - cat << GH_AW_MCP_CONFIG_256c35996d837f4a_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" + cat << GH_AW_MCP_CONFIG_29848c897dd49212_EOF | bash "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh" { "mcpServers": { "github": { @@ -848,7 +848,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_256c35996d837f4a_EOF + GH_AW_MCP_CONFIG_29848c897dd49212_EOF - name: Download activation artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/gh-aw-estc-pr-buildkite-detective.md b/.github/workflows/gh-aw-estc-pr-buildkite-detective.md index a830cc00..34c3dd01 100644 --- a/.github/workflows/gh-aw-estc-pr-buildkite-detective.md +++ b/.github/workflows/gh-aw-estc-pr-buildkite-detective.md @@ -229,7 +229,7 @@ Analyze failed Buildkite CI builds for pull requests in ${{ github.repository }} 2. Read `/tmp/gh-aw/buildkite-failures.txt` for the failed job summary. If it does not exist, call `noop` with "No Buildkite failure data" and stop. 3. Read the individual log files listed in the summary (under `/tmp/gh-aw/buildkite-logs/`). 4. Call `pull_request_read` with method `get` on the PR number to get the author, diff, and recent changes. -5. Call `pull_request_read` with method `get_comments` on the PR number to find any existing detective comment. An existing detective comment contains the marker `` in its body. If one exists, note its `id` — you will use it to update the comment in place rather than creating a new one. +5. Call `pull_request_read` with method `get_comments` on the PR number to find any existing detective comment. An existing detective comment contains the text `gh-aw-detective: estc-pr-buildkite-detective` in its body (embedded as an HTML comment). If one exists, note its `id` — you will use it to update the comment in place rather than creating a new one. ### Step 2: Analyze @@ -248,11 +248,11 @@ For each: 3. If the error involves an external library or tool, use `web-fetch` to check docs/changelogs. 4. Propose a concrete fix or, if inconclusive, state what additional data is needed. -**Deduplication**: Check the existing detective comment found in Step 1.5 (look for ``). If the root cause and remediation are the same as already documented there, call `noop` instead of posting a duplicate. +**Deduplication**: Check the existing detective comment found in Step 1.5 (body contains `gh-aw-detective: estc-pr-buildkite-detective`). If the root cause and remediation are the same as already documented there, call `noop` instead of posting a duplicate. ### Step 3: Respond -Always include the invisible marker `` as the very first line of the comment body. This marker is used to find and update the comment on subsequent runs. +Always begin the comment body with the marker line shown at the top of the template below (the `gh-aw-detective` HTML comment on the first line). This marker lets future runs find and update this comment in place. - If an existing detective comment was found in Step 1.5: call `add_comment` with `reply_to_id` set to that comment's `id`. This updates the comment in place so the PR has at most one detective comment at a time. - If no existing detective comment was found: call `add_comment` without `reply_to_id` to create a new one. From 39f32201a74e52a20a15613ea2bf6ea85a59999e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2026 09:35:47 +0000 Subject: [PATCH 6/6] Fix merge conflict resolution: restore PR changes to detective workflow The previous merge commit incorrectly resolved conflicts by taking main's versions of: - .github/workflows/gh-aw-estc-pr-buildkite-detective.md: restore safe-output-add-comment-pr-hide-older.md import and PR's prompt changes - .github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml: recompiled with correct source and v0.79.6 compiler - .github/aw/actions-lock.json: updated with correct action versions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/aw/actions-lock.json | 16 +-- ...gh-aw-estc-pr-buildkite-detective.lock.yml | 113 +++++++++--------- .../gh-aw-estc-pr-buildkite-detective.md | 13 +- 3 files changed, 65 insertions(+), 77 deletions(-) diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index fa885344..c2ae2173 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -40,10 +40,15 @@ "version": "v5", "sha": "e58605a9b6da7c637471fab8847a5e5a6b8df081" }, - "github/gh-aw-actions/setup@v0.79.8": { + "github/gh-aw-actions/setup-cli@v0.79.6": { + "repo": "github/gh-aw-actions/setup-cli", + "version": "v0.79.6", + "sha": "5c2fe865bb4dc46e1450f6ee0d0541d759aea73a" + }, + "github/gh-aw-actions/setup@v0.79.6": { "repo": "github/gh-aw-actions/setup", - "version": "v0.79.8", - "sha": "c0338fef4749d08c21f8f975fb0e37efa17dda47" + "version": "v0.79.6", + "sha": "5c2fe865bb4dc46e1450f6ee0d0541d759aea73a" }, "github/gh-aw/actions/setup-cli@v0.65.1": { "repo": "github/gh-aw/actions/setup-cli", @@ -95,11 +100,6 @@ "version": "v0.79.6", "sha": "9c481b8bc46dce8b92fce8ffc51781e5c330d37c" }, - "github/gh-aw/actions/setup-cli@v0.79.8": { - "repo": "github/gh-aw/actions/setup-cli", - "version": "v0.79.8", - "sha": "8b02ab336d100a5746e9f53b8bc2b22878278a6f" - }, "github/gh-aw/actions/setup@v0.43.23": { "repo": "github/gh-aw/actions/setup", "version": "v0.43.23", diff --git a/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml b/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml index ac9dac9b..f361960a 100644 --- a/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml +++ b/.github/workflows/gh-aw-estc-pr-buildkite-detective.lock.yml @@ -1,7 +1,5 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"00017024594c6772b4379aa7fcc5b1875581d8246d9973769609ef93fe070956","body_hash":"7d3a60abfd2ed204ebf60aed20c5e049f631c82f2fee5746efedc35633cb9c45","compiler_version":"v0.79.8","agent_id":"copilot","agent_model":"${{ inputs.model }}","engine_versions":{"copilot":"1.0.60"}} -# gh-aw-manifest: {"version":1,"secrets":["BUILDKITE_API_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"40f1582b2485089dde7abd97c1529aa768e1baff","version":"v5"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"6044e13b5dc448c55e2357c09f80417699197238","version":"v6"},{"repo":"actions/setup-python","sha":"a26af69be951a213d495a4c3e4e4022e16d87065","version":"v5"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"e58605a9b6da7c637471fab8847a5e5a6b8df081","version":"v5"},{"repo":"github/gh-aw-actions/setup","sha":"c0338fef4749d08c21f8f975fb0e37efa17dda47","version":"v0.79.8"},{"repo":"github/gh-aw/actions/setup-cli","sha":"8b02ab336d100a5746e9f53b8bc2b22878278a6f","version":"v0.79.8"},{"repo":"ruby/setup-ruby","sha":"afeafc3d1ab54a631816aba4c914a0081c12ff2f","version":"v1.310.0 (source v1)"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} -# This file was automatically generated by gh-aw (v0.79.8). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md -# +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"6287fe711b438a1a82896d3f7ee12e516212575b8310eef4c4033655c0dc6c1c","body_hash":"9cd3b52ebec5747dd266ff2460983488ce6e37e069cb591cd606ada5c5e88df9","compiler_version":"v0.79.6","agent_id":"copilot","agent_model":"${{ inputs.model }}","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["BUILDKITE_API_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"373c709c69115d41ff229c7e5df9f8788daa9553","version":"v9"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"40f1582b2485089dde7abd97c1529aa768e1baff","version":"v5"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"6044e13b5dc448c55e2357c09f80417699197238","version":"v6"},{"repo":"actions/setup-python","sha":"a26af69be951a213d495a4c3e4e4022e16d87065","version":"v5"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"astral-sh/setup-uv","sha":"e58605a9b6da7c637471fab8847a5e5a6b8df081","version":"v5"},{"repo":"github/gh-aw/actions/setup","sha":"9c481b8bc46dce8b92fce8ffc51781e5c330d37c","version":"v0.79.6"},{"repo":"github/gh-aw/actions/setup-cli","sha":"9c481b8bc46dce8b92fce8ffc51781e5c330d37c","version":"v0.79.6"},{"repo":"ruby/setup-ruby","sha":"afeafc3d1ab54a631816aba4c914a0081c12ff2f","version":"v1.310.0 (source v1)"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2","digest":"sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.2@sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2","digest":"sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.2@sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2","digest":"sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.2@sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.25","digest":"sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.25@sha256:c10331ad17668ef89f38f5e356678788a40b0cd5fef96e8f92e1d9c1de47cbaa"},{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} # ___ _ _ # / _ \ | | (_) # | |_| | __ _ ___ _ __ | |_ _ ___ @@ -16,6 +14,7 @@ # \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ # \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ # +# This file was automatically generated by gh-aw (v0.79.6). DO NOT EDIT. # # To update this file, edit the corresponding .md file and run: # gh aw compile @@ -33,7 +32,7 @@ # - gh-aw-fragments/network-ecosystems.md # - gh-aw-fragments/rigor.md # - gh-aw-fragments/runtime-setup.md -# - gh-aw-fragments/safe-output-add-comment-pr.md +# - gh-aw-fragments/safe-output-add-comment-pr-hide-older.md # # inlined-imports: true # @@ -54,8 +53,8 @@ # - actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 # - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 # - astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 -# - github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8 -# - github/gh-aw/actions/setup-cli@8b02ab336d100a5746e9f53b8bc2b22878278a6f # v0.79.8 +# - github/gh-aw/actions/setup-cli@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 +# - github/gh-aw/actions/setup@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 # - ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 (source v1) # # Container images used: @@ -136,9 +135,9 @@ jobs: artifact_prefix: ${{ steps.artifact-prefix.outputs.prefix }} comment_id: "" comment_repo: "" - daily_ai_credits_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_exceeded == 'true' }} - daily_ai_credits_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_threshold || '' }} - daily_ai_credits_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_ai_credits_total_effective_tokens || '' }} + daily_effective_workflow_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_exceeded == 'true' }} + daily_effective_workflow_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_threshold || '' }} + daily_effective_workflow_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_total_effective_tokens || '' }} engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} model: ${{ steps.generate_aw_info.outputs.model }} @@ -148,7 +147,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8 + uses: github/gh-aw/actions/setup@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -175,7 +174,7 @@ jobs: GH_AW_INFO_MODEL: "${{ inputs.model }}" GH_AW_INFO_VERSION: "1.0.60" GH_AW_INFO_AGENT_VERSION: "1.0.60" - GH_AW_INFO_CLI_VERSION: "v0.79.8" + GH_AW_INFO_CLI_VERSION: "v0.79.6" GH_AW_INFO_WORKFLOW_NAME: "PR Buildkite Detective" GH_AW_INFO_EXPERIMENTAL: "false" GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" @@ -236,7 +235,7 @@ jobs: - name: Check compile-agentic version uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 env: - GH_AW_COMPILED_VERSION: "v0.79.8" + GH_AW_COMPILED_VERSION: "v0.79.6" with: script: | const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); @@ -260,20 +259,20 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_9a87a2c07b165c32_EOF' + cat << 'GH_AW_PROMPT_4c6ef8a24772b82d_EOF' - GH_AW_PROMPT_9a87a2c07b165c32_EOF + GH_AW_PROMPT_4c6ef8a24772b82d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_9a87a2c07b165c32_EOF' + cat << 'GH_AW_PROMPT_4c6ef8a24772b82d_EOF' Tools: add_comment, missing_tool, missing_data, noop - GH_AW_PROMPT_9a87a2c07b165c32_EOF + GH_AW_PROMPT_4c6ef8a24772b82d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_9a87a2c07b165c32_EOF' + cat << 'GH_AW_PROMPT_4c6ef8a24772b82d_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -302,9 +301,9 @@ jobs: {{/if}} - GH_AW_PROMPT_9a87a2c07b165c32_EOF + GH_AW_PROMPT_4c6ef8a24772b82d_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_9a87a2c07b165c32_EOF' + cat << 'GH_AW_PROMPT_4c6ef8a24772b82d_EOF' ## MCP Servers @@ -365,7 +364,6 @@ jobs: 2. Read `/tmp/gh-aw/buildkite-failures.txt` for the failed job summary. If it does not exist, call `noop` with "No Buildkite failure data" and stop. 3. Read the individual log files listed in the summary (under `/tmp/gh-aw/buildkite-logs/`). 4. Call `pull_request_read` with method `get` on the PR number to get the author, diff, and recent changes. - 5. Call `pull_request_read` with method `get_comments` on the PR number to find any existing detective comment. An existing detective comment contains the text `gh-aw-detective: estc-pr-buildkite-detective` in its body (embedded as an HTML comment). If one exists, note its `id` — you will use it to update the comment in place rather than creating a new one. ### Step 2: Analyze @@ -384,19 +382,13 @@ jobs: 3. If the error involves an external library or tool, use `web-fetch` to check docs/changelogs. 4. Propose a concrete fix or, if inconclusive, state what additional data is needed. - **Deduplication**: Check the existing detective comment found in Step 1.5 (body contains `gh-aw-detective: estc-pr-buildkite-detective`). If the root cause and remediation are the same as already documented there, call `noop` instead of posting a duplicate. + **Deduplication**: Check the most recent prior detective comment on the PR. If the root cause and remediation are the same, call `noop` instead of posting a duplicate. ### Step 3: Respond - Always begin the comment body with the marker line shown at the top of the template below (the `gh-aw-detective` HTML comment on the first line). This marker lets future runs find and update this comment in place. - - - If an existing detective comment was found in Step 1.5: call `add_comment` with `reply_to_id` set to that comment's `id`. This updates the comment in place so the PR has at most one detective comment at a time. - - If no existing detective comment was found: call `add_comment` without `reply_to_id` to create a new one. - - Use this structure for the body: + Call `add_comment` on the PR using this structure: ```markdown - ### TL;DR [1-2 sentences: what failed and the immediate action needed] @@ -428,7 +420,7 @@ jobs: __GH_AW_EXPR_49B959F1__ - GH_AW_PROMPT_9a87a2c07b165c32_EOF + GH_AW_PROMPT_4c6ef8a24772b82d_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -500,6 +492,7 @@ jobs: include-hidden-files: true path: | /tmp/gh-aw/aw_info.json + /tmp/gh-aw/model_multipliers.json /tmp/gh-aw/models.json /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/aw-prompts/prompt-template.txt @@ -513,7 +506,7 @@ jobs: agent: needs: activation - if: needs.activation.outputs.daily_ai_credits_exceeded != 'true' + if: needs.activation.outputs.daily_effective_workflow_exceeded != 'true' runs-on: ubuntu-latest permissions: actions: read @@ -553,7 +546,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8 + uses: github/gh-aw/actions/setup@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -579,9 +572,9 @@ jobs: with: persist-credentials: false - name: Install gh-aw extension - uses: github/gh-aw/actions/setup-cli@8b02ab336d100a5746e9f53b8bc2b22878278a6f # v0.79.8 + uses: github/gh-aw/actions/setup-cli@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 with: - version: 'v0.79.8' + version: 'v0.79.6' - name: Create gh-aw temp directory run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh" - name: Configure gh CLI for GitHub Enterprise @@ -718,9 +711,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_7c6d636483f3c924_EOF' - {"add_comment":{"max":1,"target":"triggering"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} - GH_AW_SAFE_OUTPUTS_CONFIG_7c6d636483f3c924_EOF + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_7ec39694efd703a0_EOF' + {"add_comment":{"hide_older_comments":true,"max":1,"target":"triggering"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_7ec39694efd703a0_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -912,7 +905,7 @@ jobs: DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' - mkdir -p "$HOME/.copilot" + mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) cat << GH_AW_MCP_CONFIG_61d1d58ba0c40cb8_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { @@ -998,11 +991,9 @@ jobs: run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt - trap 'rm -f "$HOME/.copilot/settings.json"' EXIT - mkdir -p "$HOME/.copilot" - printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json" - export XDG_CONFIG_HOME="$HOME" - export GH_AW_MCP_CONFIG="$HOME/.copilot/mcp-config.json" + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json touch /tmp/gh-aw/agent-step-summary.md GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN @@ -1010,6 +1001,7 @@ jobs: (umask 177 && touch /tmp/gh-aw/agent-stdio.log) GH_AW_MAX_AI_CREDITS="${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}" printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"*.docker.com\",\"*.docker.io\",\"*.githubusercontent.com\",\"*.gradle-enterprise.cloud\",\"*.hackage.haskell.org\",\"*.pythonhosted.org\",\"*.rvm.io\",\"*.vsblob.vsassets.io\",\"adoptium.net\",\"agents-md-generator.fastmcp.app\",\"anaconda.org\",\"api.adoptium.net\",\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.foojay.io\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"api.npms.io\",\"api.nuget.org\",\"api.rubygems.org\",\"api.snapcraft.io\",\"apt.llvm.org\",\"apt.releases.hashicorp.com\",\"archive.apache.org\",\"archive.ubuntu.com\",\"archlinux.org\",\"artifacts.elastic.co\",\"auth.docker.io\",\"azure.archive.ubuntu.com\",\"azuresearch-usnc.nuget.org\",\"azuresearch-ussc.nuget.org\",\"binstar.org\",\"bitbucket.org\",\"bootstrap.pypa.io\",\"buildkite.com\",\"builds.dotnet.microsoft.com\",\"builds.hex.pm\",\"bun.sh\",\"bundler.rubygems.org\",\"cache.ruby-lang.org\",\"cdn.azul.com\",\"cdn.cocoapods.org\",\"cdn.hex.pm\",\"cdn.jsdelivr.net\",\"cdn.playwright.dev\",\"cdn.redhat.com\",\"cdn.sheetjs.com\",\"central.sonatype.com\",\"ci.dot.net\",\"clojars.org\",\"cloud.elastic.co\",\"cocoapods.org\",\"code.jquery.com\",\"codeload.github.com\",\"conda.anaconda.org\",\"conda.binstar.org\",\"cpan.metacpan.org\",\"cpan.org\",\"crates.io\",\"crl.geotrust.com\",\"crl.globalsign.com\",\"crl.identrust.com\",\"crl.sectigo.com\",\"crl.thawte.com\",\"crl.usertrust.com\",\"crl.verisign.com\",\"crl3.digicert.com\",\"crl4.digicert.com\",\"crls.ssl.com\",\"data.jsdelivr.com\",\"dc.services.visualstudio.com\",\"deb.debian.org\",\"deb.nodesource.com\",\"debian.map.fastlydns.net\",\"deno.land\",\"deps.files.ghostty.org\",\"develocity.apache.org\",\"dist.nuget.org\",\"dl-cdn.alpinelinux.org\",\"dl.bintray.com\",\"dl.fedoraproject.org\",\"dl.google.com\",\"dl.k8s.io\",\"dlcdn.apache.org\",\"docs.github.com\",\"dot.net\",\"dotnet.microsoft.com\",\"dotnetcli.blob.core.windows.net\",\"download.eclipse.org\",\"download.fedoraproject.org\",\"download.java.net\",\"download.jetbrains.com\",\"download.opensuse.org\",\"download.oracle.com\",\"download.swift.org\",\"downloads.gradle-dn.com\",\"downloads.haskell.org\",\"ela.st\",\"elastic.co\",\"elastic.dev\",\"elastic.github.io\",\"esm.sh\",\"fastly.hex.pm\",\"files.pythonhosted.org\",\"fonts.googleapis.com\",\"fonts.gstatic.com\",\"gcr.io\",\"ge.jetbrains.com\",\"ge.spockframework.org\",\"gems.rubyforge.org\",\"gems.rubyonrails.org\",\"get-ghcup.haskell.org\",\"get.pnpm.io\",\"getcomposer.org\",\"ghcr.io\",\"github-cloud.githubusercontent.com\",\"github-cloud.s3.amazonaws.com\",\"github.blog\",\"github.com\",\"github.githubassets.com\",\"go.dev\",\"golang.org\",\"googleapis.deno.dev\",\"googlechromelabs.github.io\",\"goproxy.io\",\"gradle.org\",\"haskell.org\",\"hex.pm\",\"host.docker.internal\",\"index.crates.io\",\"index.rubygems.org\",\"jcenter.bintray.com\",\"jdk.java.net\",\"jitpack.io\",\"json-schema.org\",\"json.schemastore.org\",\"jsr.io\",\"keyring.debian.org\",\"keyserver.ubuntu.com\",\"kotlin.bintray.com\",\"lfs.github.com\",\"maven-central.storage-download.googleapis.com\",\"maven.apache.org\",\"maven.google.com\",\"maven.oracle.com\",\"maven.pkg.github.com\",\"maven.pkg.jetbrains.space\",\"mcr.microsoft.com\",\"metacpan.org\",\"mirror.archlinux.org\",\"mirror.centos.org\",\"mirrors.fedoraproject.org\",\"nodejs.org\",\"npm.pkg.github.com\",\"npmjs.com\",\"npmjs.org\",\"nuget.org\",\"nuget.pkg.github.com\",\"nugetregistryv2prod.blob.core.windows.net\",\"objects.githubusercontent.com\",\"ocsp.digicert.com\",\"ocsp.geotrust.com\",\"ocsp.globalsign.com\",\"ocsp.identrust.com\",\"ocsp.sectigo.com\",\"ocsp.ssl.com\",\"ocsp.thawte.com\",\"ocsp.usertrust.com\",\"ocsp.verisign.com\",\"oneocsp.microsoft.com\",\"packagecloud.io\",\"packages.cloud.google.com\",\"packages.debian.org\",\"packages.jetbrains.team\",\"packages.microsoft.com\",\"packagist.org\",\"patch-diff.githubusercontent.com\",\"pip.pypa.io\",\"pkg.alpinelinux.org\",\"pkg.go.dev\",\"pkg.machengine.org\",\"pkgs.dev.azure.com\",\"pkgs.k8s.io\",\"playwright.download.prss.microsoft.com\",\"plugins-artifacts.gradle.org\",\"plugins.gradle.org\",\"ppa.launchpad.net\",\"production.cloudflare.docker.com\",\"productionresultssa0.blob.core.windows.net\",\"productionresultssa1.blob.core.windows.net\",\"productionresultssa10.blob.core.windows.net\",\"productionresultssa11.blob.core.windows.net\",\"productionresultssa12.blob.core.windows.net\",\"productionresultssa13.blob.core.windows.net\",\"productionresultssa14.blob.core.windows.net\",\"productionresultssa15.blob.core.windows.net\",\"productionresultssa16.blob.core.windows.net\",\"productionresultssa17.blob.core.windows.net\",\"productionresultssa18.blob.core.windows.net\",\"productionresultssa19.blob.core.windows.net\",\"productionresultssa2.blob.core.windows.net\",\"productionresultssa3.blob.core.windows.net\",\"productionresultssa4.blob.core.windows.net\",\"productionresultssa5.blob.core.windows.net\",\"productionresultssa6.blob.core.windows.net\",\"productionresultssa7.blob.core.windows.net\",\"productionresultssa8.blob.core.windows.net\",\"productionresultssa9.blob.core.windows.net\",\"proxy.golang.org\",\"pub.dartlang.org\",\"pub.dev\",\"public-code-search.fastmcp.app\",\"pypi.org\",\"pypi.python.org\",\"quay.io\",\"raw.githubusercontent.com\",\"registry.bower.io\",\"registry.hub.docker.com\",\"registry.npmjs.com\",\"registry.npmjs.org\",\"registry.terraform.io\",\"registry.yarnpkg.com\",\"releases.hashicorp.com\",\"repo.anaconda.com\",\"repo.clojars.org\",\"repo.continuum.io\",\"repo.gradle.org\",\"repo.grails.org\",\"repo.hex.pm\",\"repo.maven.apache.org\",\"repo.packagist.org\",\"repo.scala-sbt.org\",\"repo.spring.io\",\"repo.typesafe.com\",\"repo.yarnpkg.com\",\"repo1.maven.org\",\"repository.apache.org\",\"rubygems.org\",\"rubygems.pkg.github.com\",\"s.symcb.com\",\"s.symcd.com\",\"scala-ci.typesafe.com\",\"scala.jfrog.io\",\"scans-in.gradle.com\",\"security.debian.org\",\"security.ubuntu.com\",\"services.gradle.org\",\"sh.rustup.rs\",\"skimdb.npmjs.com\",\"static.crates.io\",\"static.rust-lang.org\",\"storage.googleapis.com\",\"sum.golang.org\",\"swift.org\",\"telemetry.enterprise.githubcopilot.com\",\"telemetry.vercel.com\",\"ts-crl.ws.symantec.com\",\"ts-ocsp.ws.symantec.com\",\"vault.centos.org\",\"www.cpan.org\",\"www.elastic.co\",\"www.googleapis.com\",\"www.java.com\",\"www.microsoft.com\",\"www.npmjs.com\",\"www.npmjs.org\",\"yarnpkg.com\",\"yum.releases.hashicorp.com\",\"ziglang.org\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS},\"models\":{\"agent\":[\"sonnet-6x\",\"gpt-5.4\",\"gpt-5.3\",\"gemini-pro\",\"any\"],\"antigravity\":[\"copilot/antigravity*\",\"google/antigravity*\",\"gemini/antigravity*\"],\"any\":[\"copilot/*\",\"anthropic/*\",\"openai/*\",\"google/*\",\"gemini/*\"],\"claude\":[\"agent\"],\"codex\":[\"agent\"],\"coding\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\",\"gpt-5-codex\"],\"computer-use\":[\"copilot/*computer-use*\",\"google/*computer-use*\",\"gemini/*computer-use*\",\"openai/*computer-use*\"],\"copilot\":[\"agent\"],\"deep-research\":[\"copilot/deep-research*\",\"copilot/o3-deep-research*\",\"copilot/o4-mini-deep-research*\",\"google/deep-research*\",\"gemini/deep-research*\",\"openai/o3-deep-research*\",\"openai/o4-mini-deep-research*\"],\"gemini\":[\"agent\"],\"gemini-3-flash\":[\"copilot/gemini-3*flash*\",\"google/gemini-3*flash*\",\"gemini/gemini-3*flash*\"],\"gemini-3-pro\":[\"copilot/gemini-3*pro*\",\"google/gemini-3*pro*\",\"google/nano-banana*\",\"gemini/gemini-3*pro*\"],\"gemini-3.1-flash\":[\"copilot/gemini-3.1*flash*\",\"google/gemini-3.1*flash*\",\"gemini/gemini-3.1*flash*\"],\"gemini-3.1-pro\":[\"copilot/gemini-3.1*pro*\",\"google/gemini-3.1*pro*\",\"gemini/gemini-3.1*pro*\"],\"gemini-3.5-flash\":[\"copilot/gemini-3.5*flash*\",\"google/gemini-3.5*flash*\",\"gemini/gemini-3.5*flash*\"],\"gemini-flash\":[\"copilot/gemini-*flash*\",\"google/gemini-*flash*\",\"gemini/gemini-*flash*\"],\"gemini-flash-lite\":[\"copilot/gemini-*flash*lite*\",\"google/gemini-*flash*lite*\",\"gemini/gemini-*flash*lite*\"],\"gemini-pro\":[\"copilot/gemini-*pro*\",\"google/gemini-*pro*\",\"gemini/gemini-*pro*\"],\"gemma\":[\"copilot/gemma*\",\"google/gemma*\",\"gemini/gemma*\"],\"gpt-5\":[\"copilot/gpt-5*\",\"openai/gpt-5*\"],\"gpt-5-codex\":[\"copilot/gpt-5*codex*\",\"openai/gpt-5*codex*\"],\"gpt-5-mini\":[\"copilot/gpt-5*mini*\",\"openai/gpt-5*mini*\"],\"gpt-5-nano\":[\"copilot/gpt-5*nano*\",\"openai/gpt-5*nano*\"],\"gpt-5-pro\":[\"copilot/gpt-5*pro*\",\"openai/gpt-5*pro*\"],\"gpt-5.2\":[\"copilot/gpt-5.2*\",\"openai/gpt-5.2*\"],\"gpt-5.3\":[\"copilot/gpt-5.3*\",\"openai/gpt-5.3*\"],\"gpt-5.4\":[\"copilot/gpt-5.4*\",\"openai/gpt-5.4*\"],\"gpt-5.5\":[\"copilot/gpt-5.5*\",\"openai/gpt-5.5*\"],\"haiku\":[\"copilot/*haiku*\",\"anthropic/*haiku*\"],\"large\":[\"sonnet\",\"gpt-5-pro\",\"gpt-5\",\"gemini-pro\"],\"mai-code\":[\"copilot/MAI-Code*\",\"copilot/mai-code*\",\"openai/MAI-Code*\"],\"mini\":[\"haiku\",\"gpt-5-mini\",\"gpt-5-nano\",\"gemini-flash-lite\"],\"nano-banana\":[\"copilot/nano-banana*\",\"google/nano-banana*\",\"gemini/nano-banana*\"],\"opus\":[\"copilot/*opus*\",\"anthropic/*opus*\"],\"opusplan\":[\"opus?effort=high\"],\"reasoning\":[\"copilot/o1*\",\"copilot/o3*\",\"copilot/o4*\",\"openai/o1*\",\"openai/o3*\",\"openai/o4*\"],\"robotics\":[\"copilot/*robotics*\",\"google/*robotics*\",\"gemini/*robotics*\"],\"small\":[\"mini\"],\"small-agent\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash\"],\"sonnet\":[\"copilot/*sonnet*\",\"anthropic/*sonnet*\"],\"sonnet-6x\":[\"copilot/*sonnet-4.5*\",\"copilot/*sonnet-4.6*\",\"copilot/*sonnet-4-5-*\",\"anthropic/*sonnet-4-5-*\",\"copilot/*sonnet-4-6*\",\"anthropic/*sonnet-4-6*\"],\"summarization\":[\"haiku\",\"gpt-5-mini\",\"gemini-flash-lite\",\"mini\"],\"vision\":[\"copilot/gemini-*image*\",\"gemini/gemini-*image*\",\"copilot/gemini-*flash*\",\"gemini/gemini-*flash*\"]}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" @@ -1035,11 +1027,12 @@ jobs: COPILOT_GITHUB_TOKEN: ${{ github.token }} COPILOT_MODEL: ${{ inputs.model }} GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json GH_AW_PHASE: agent GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} GH_AW_TIMEOUT_MINUTES: 30 - GH_AW_VERSION: v0.79.8 + GH_AW_VERSION: v0.79.6 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -1055,6 +1048,7 @@ jobs: GIT_COMMITTER_NAME: github-actions[bot] RUNNER_TEMP: ${{ runner.temp }} S2STOKENS: true + XDG_CONFIG_HOME: /home/runner - name: Detect agent errors if: always() id: detect-agent-errors @@ -1222,7 +1216,7 @@ jobs: - safe_outputs if: > always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || - needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_ai_credits_exceeded == 'true') + needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_effective_workflow_exceeded == 'true') runs-on: ubuntu-slim permissions: contents: read @@ -1239,7 +1233,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8 + uses: github/gh-aw/actions/setup@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1396,9 +1390,9 @@ jobs: GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} - GH_AW_DAILY_AI_CREDITS_EXCEEDED: ${{ needs.activation.outputs.daily_ai_credits_exceeded }} - GH_AW_DAILY_AI_CREDITS_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_ai_credits_total_effective_tokens }} - GH_AW_DAILY_AI_CREDITS_THRESHOLD: ${{ needs.activation.outputs.daily_ai_credits_threshold }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_effective_workflow_total_effective_tokens }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_THRESHOLD: ${{ needs.activation.outputs.daily_effective_workflow_threshold }} GH_AW_SAFE_OUTPUT_MESSAGES: "{\"footer\":\"${{ inputs.messages-footer || format('---\\n[What is this?](https://ela.st/github-ai-tools) | [From workflow: {0}]({{run_url}})\\n\\nGive us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.', github.workflow) }}\",\"activationComments\":\"false\"}" GH_AW_GROUP_REPORTS: "false" GH_AW_FAILURE_REPORT_AS_ISSUE: "true" @@ -1431,7 +1425,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8 + uses: github/gh-aw/actions/setup@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1488,7 +1482,7 @@ jobs: if: always() && steps.detection_guard.outputs.run_detection == 'true' run: | rm -f "${RUNNER_TEMP}/gh-aw/mcp-config/mcp-servers.json" - rm -f "$HOME/.copilot/mcp-config.json" + rm -f /home/runner/.copilot/mcp-config.json rm -f "$GITHUB_WORKSPACE/.gemini/settings.json" - name: Prepare threat detection files if: always() && steps.detection_guard.outputs.run_detection == 'true' @@ -1546,10 +1540,9 @@ jobs: run: | set -o pipefail printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt - trap 'rm -f "$HOME/.copilot/settings.json"' EXIT - mkdir -p "$HOME/.copilot" - printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > "$HOME/.copilot/settings.json" - export XDG_CONFIG_HOME="$HOME" + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json touch /tmp/gh-aw/agent-step-summary.md GH_AW_NODE_BIN=$(command -v node 2>/dev/null || true) export GH_AW_NODE_BIN @@ -1557,6 +1550,7 @@ jobs: (umask 177 && touch /tmp/gh-aw/threat-detection/detection.log) GH_AW_MAX_AI_CREDITS="${{ vars.GH_AW_DEFAULT_DETECTION_MAX_AI_CREDITS || '400' }}" printf '%s\n' "{\"\$schema\":\"https://github.com/github/gh-aw-firewall/releases/download/v0.27.2/awf-config.schema.json\",\"network\":{\"allowDomains\":[\"api.business.githubcopilot.com\",\"api.enterprise.githubcopilot.com\",\"api.github.com\",\"api.githubcopilot.com\",\"api.individual.githubcopilot.com\",\"github.com\",\"host.docker.internal\",\"registry.npmjs.org\",\"telemetry.enterprise.githubcopilot.com\"]},\"apiProxy\":{\"enabled\":true,\"enableTokenSteering\":true,\"maxRuns\":500,\"maxAiCredits\":${GH_AW_MAX_AI_CREDITS}},\"container\":{\"imageTag\":\"0.27.2,squid=sha256:2e3a717e5f19a654cd9a2263beb52012b56bcb68562ec5ae2e42f9d156b49591,agent=sha256:f88e5b17b6b7a600117bc121114d6ce2155c88c983c0c939c5df884f730fa1d6,api-proxy=sha256:ee39841d980878ebbb87592903b06d31a1af500c71525c9616f7e8e2a27041a4,cli-proxy=sha256:02f3ec08f32dc26c5427920c6a2e2f3036238fce44802f2f11ef49ed8621b5d0\"}}" > "${RUNNER_TEMP}/gh-aw/awf-config.json" + GH_AW_MODEL_MULTIPLIERS_PATH="/tmp/gh-aw/model_multipliers.json" node "${RUNNER_TEMP}/gh-aw/actions/merge_awf_model_multipliers.cjs" cp "${RUNNER_TEMP}/gh-aw/awf-config.json" /tmp/gh-aw/awf-config.json export GH_AW_MODELS_JSON_PATH="/tmp/gh-aw/models.json" GH_AW_DOCKER_HOST_PATH_PREFIX_ARGS="" @@ -1585,7 +1579,7 @@ jobs: GH_AW_PHASE: detection GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt GH_AW_TIMEOUT_MINUTES: 20 - GH_AW_VERSION: v0.79.8 + GH_AW_VERSION: v0.79.6 GITHUB_API_URL: ${{ github.api_url }} GITHUB_AW: true GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows @@ -1600,6 +1594,7 @@ jobs: GIT_COMMITTER_NAME: github-actions[bot] RUNNER_TEMP: ${{ runner.temp }} S2STOKENS: true + XDG_CONFIG_HOME: /home/runner - name: Parse threat detection token usage for step summary id: parse_detection_token_usage if: always() @@ -1664,7 +1659,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8 + uses: github/gh-aw/actions/setup@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1728,7 +1723,7 @@ jobs: steps: - name: Setup Scripts id: setup - uses: github/gh-aw-actions/setup@c0338fef4749d08c21f8f975fb0e37efa17dda47 # v0.79.8 + uses: github/gh-aw/actions/setup@9c481b8bc46dce8b92fce8ffc51781e5c330d37c # v0.79.6 with: destination: ${{ runner.temp }}/gh-aw/actions job-name: ${{ github.job }} @@ -1774,7 +1769,7 @@ jobs: GH_AW_ALLOWED_DOMAINS: "*.docker.com,*.docker.io,*.githubusercontent.com,*.gradle-enterprise.cloud,*.hackage.haskell.org,*.pythonhosted.org,*.rvm.io,*.vsblob.vsassets.io,adoptium.net,agents-md-generator.fastmcp.app,anaconda.org,api.adoptium.net,api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.foojay.io,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.npms.io,api.nuget.org,api.rubygems.org,api.snapcraft.io,apt.llvm.org,apt.releases.hashicorp.com,archive.apache.org,archive.ubuntu.com,archlinux.org,artifacts.elastic.co,auth.docker.io,azure.archive.ubuntu.com,azuresearch-usnc.nuget.org,azuresearch-ussc.nuget.org,binstar.org,bitbucket.org,bootstrap.pypa.io,buildkite.com,builds.dotnet.microsoft.com,builds.hex.pm,bun.sh,bundler.rubygems.org,cache.ruby-lang.org,cdn.azul.com,cdn.cocoapods.org,cdn.hex.pm,cdn.jsdelivr.net,cdn.playwright.dev,cdn.redhat.com,cdn.sheetjs.com,central.sonatype.com,ci.dot.net,clojars.org,cloud.elastic.co,cocoapods.org,code.jquery.com,codeload.github.com,conda.anaconda.org,conda.binstar.org,cpan.metacpan.org,cpan.org,crates.io,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,data.jsdelivr.com,dc.services.visualstudio.com,deb.debian.org,deb.nodesource.com,debian.map.fastlydns.net,deno.land,deps.files.ghostty.org,develocity.apache.org,dist.nuget.org,dl-cdn.alpinelinux.org,dl.bintray.com,dl.fedoraproject.org,dl.google.com,dl.k8s.io,dlcdn.apache.org,docs.github.com,dot.net,dotnet.microsoft.com,dotnetcli.blob.core.windows.net,download.eclipse.org,download.fedoraproject.org,download.java.net,download.jetbrains.com,download.opensuse.org,download.oracle.com,download.swift.org,downloads.gradle-dn.com,downloads.haskell.org,ela.st,elastic.co,elastic.dev,elastic.github.io,esm.sh,fastly.hex.pm,files.pythonhosted.org,fonts.googleapis.com,fonts.gstatic.com,gcr.io,ge.jetbrains.com,ge.spockframework.org,gems.rubyforge.org,gems.rubyonrails.org,get-ghcup.haskell.org,get.pnpm.io,getcomposer.org,ghcr.io,github-cloud.githubusercontent.com,github-cloud.s3.amazonaws.com,github.blog,github.com,github.githubassets.com,go.dev,golang.org,googleapis.deno.dev,googlechromelabs.github.io,goproxy.io,gradle.org,haskell.org,hex.pm,host.docker.internal,index.crates.io,index.rubygems.org,jcenter.bintray.com,jdk.java.net,jitpack.io,json-schema.org,json.schemastore.org,jsr.io,keyring.debian.org,keyserver.ubuntu.com,kotlin.bintray.com,lfs.github.com,maven-central.storage-download.googleapis.com,maven.apache.org,maven.google.com,maven.oracle.com,maven.pkg.github.com,maven.pkg.jetbrains.space,mcr.microsoft.com,metacpan.org,mirror.archlinux.org,mirror.centos.org,mirrors.fedoraproject.org,nodejs.org,npm.pkg.github.com,npmjs.com,npmjs.org,nuget.org,nuget.pkg.github.com,nugetregistryv2prod.blob.core.windows.net,objects.githubusercontent.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,oneocsp.microsoft.com,packagecloud.io,packages.cloud.google.com,packages.debian.org,packages.jetbrains.team,packages.microsoft.com,packagist.org,patch-diff.githubusercontent.com,pip.pypa.io,pkg.alpinelinux.org,pkg.go.dev,pkg.machengine.org,pkgs.dev.azure.com,pkgs.k8s.io,playwright.download.prss.microsoft.com,plugins-artifacts.gradle.org,plugins.gradle.org,ppa.launchpad.net,production.cloudflare.docker.com,productionresultssa0.blob.core.windows.net,productionresultssa1.blob.core.windows.net,productionresultssa10.blob.core.windows.net,productionresultssa11.blob.core.windows.net,productionresultssa12.blob.core.windows.net,productionresultssa13.blob.core.windows.net,productionresultssa14.blob.core.windows.net,productionresultssa15.blob.core.windows.net,productionresultssa16.blob.core.windows.net,productionresultssa17.blob.core.windows.net,productionresultssa18.blob.core.windows.net,productionresultssa19.blob.core.windows.net,productionresultssa2.blob.core.windows.net,productionresultssa3.blob.core.windows.net,productionresultssa4.blob.core.windows.net,productionresultssa5.blob.core.windows.net,productionresultssa6.blob.core.windows.net,productionresultssa7.blob.core.windows.net,productionresultssa8.blob.core.windows.net,productionresultssa9.blob.core.windows.net,proxy.golang.org,pub.dartlang.org,pub.dev,public-code-search.fastmcp.app,pypi.org,pypi.python.org,quay.io,raw.githubusercontent.com,registry.bower.io,registry.hub.docker.com,registry.npmjs.com,registry.npmjs.org,registry.terraform.io,registry.yarnpkg.com,releases.hashicorp.com,repo.anaconda.com,repo.clojars.org,repo.continuum.io,repo.gradle.org,repo.grails.org,repo.hex.pm,repo.maven.apache.org,repo.packagist.org,repo.scala-sbt.org,repo.spring.io,repo.typesafe.com,repo.yarnpkg.com,repo1.maven.org,repository.apache.org,rubygems.org,rubygems.pkg.github.com,s.symcb.com,s.symcd.com,scala-ci.typesafe.com,scala.jfrog.io,scans-in.gradle.com,security.debian.org,security.ubuntu.com,services.gradle.org,sh.rustup.rs,skimdb.npmjs.com,static.crates.io,static.rust-lang.org,storage.googleapis.com,sum.golang.org,swift.org,telemetry.enterprise.githubcopilot.com,telemetry.vercel.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,vault.centos.org,www.cpan.org,www.elastic.co,www.googleapis.com,www.java.com,www.microsoft.com,www.npmjs.com,www.npmjs.org,yarnpkg.com,yum.releases.hashicorp.com,ziglang.org" GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_API_URL: ${{ github.api_url }} - GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1,\"target\":\"triggering\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"hide_older_comments\":true,\"max\":1,\"target\":\"triggering\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" with: github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/gh-aw-estc-pr-buildkite-detective.md b/.github/workflows/gh-aw-estc-pr-buildkite-detective.md index 5bf7ee1a..756e23e3 100644 --- a/.github/workflows/gh-aw-estc-pr-buildkite-detective.md +++ b/.github/workflows/gh-aw-estc-pr-buildkite-detective.md @@ -7,7 +7,7 @@ imports: - gh-aw-fragments/formatting.md - gh-aw-fragments/rigor.md - gh-aw-fragments/messages-footer.md - - gh-aw-fragments/safe-output-add-comment-pr.md + - gh-aw-fragments/safe-output-add-comment-pr-hide-older.md - gh-aw-fragments/network-ecosystems.md engine: id: copilot @@ -228,7 +228,6 @@ Analyze failed Buildkite CI builds for pull requests in ${{ github.repository }} 2. Read `/tmp/gh-aw/buildkite-failures.txt` for the failed job summary. If it does not exist, call `noop` with "No Buildkite failure data" and stop. 3. Read the individual log files listed in the summary (under `/tmp/gh-aw/buildkite-logs/`). 4. Call `pull_request_read` with method `get` on the PR number to get the author, diff, and recent changes. -5. Call `pull_request_read` with method `get_comments` on the PR number to find any existing detective comment. An existing detective comment contains the text `gh-aw-detective: estc-pr-buildkite-detective` in its body (embedded as an HTML comment). If one exists, note its `id` — you will use it to update the comment in place rather than creating a new one. ### Step 2: Analyze @@ -247,19 +246,13 @@ For each: 3. If the error involves an external library or tool, use `web-fetch` to check docs/changelogs. 4. Propose a concrete fix or, if inconclusive, state what additional data is needed. -**Deduplication**: Check the existing detective comment found in Step 1.5 (body contains `gh-aw-detective: estc-pr-buildkite-detective`). If the root cause and remediation are the same as already documented there, call `noop` instead of posting a duplicate. +**Deduplication**: Check the most recent prior detective comment on the PR. If the root cause and remediation are the same, call `noop` instead of posting a duplicate. ### Step 3: Respond -Always begin the comment body with the marker line shown at the top of the template below (the `gh-aw-detective` HTML comment on the first line). This marker lets future runs find and update this comment in place. - -- If an existing detective comment was found in Step 1.5: call `add_comment` with `reply_to_id` set to that comment's `id`. This updates the comment in place so the PR has at most one detective comment at a time. -- If no existing detective comment was found: call `add_comment` without `reply_to_id` to create a new one. - -Use this structure for the body: +Call `add_comment` on the PR using this structure: ```markdown - ### TL;DR [1-2 sentences: what failed and the immediate action needed]