From dd038b34a24e858566a0e35a4ff06763b9b11370 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 12 Oct 2026 01:36:26 +0000 Subject: [PATCH] fix(agent-ingress): pin ci-failure-analyst to its v1-stable channel; fix the analyst loop guard Two defects carried over unchanged from the pre-collapse ci-failure-analyst stub: - The job pinned the reusable to a bare commit SHA (b5851027), so channel promotions and rollbacks never reached markets (org pinning standard, petry-projects/.github-private#2176). It now pins @ci-failure-analyst/v1-stable, like the other four roles pin their channels. The reusable at v1-stable (cc0bc61) has the same interface (the single required CLAUDE_CODE_OAUTH_TOKEN secret, job `analyze`) and the same steps; the only difference is a workflow-level permissions block that this job already grants. - The loop guard excluded check runs starting 'CI Failure Analyst', but the analyst's own check run is 'ci-failure-analyst / analyze', so a failed analyst run would re-trigger the analyst (petry-projects/.github-private#2175). The guard now matches 'ci-failure-analyst'. The canonical template (petry-projects/.github standards/workflows/agent-ingress.yml) gets the same block in the same window. Refs petry-projects/.github-private#1729 Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Muchy4bnEhyVEnd89TUtjj --- .../scripts/tests/agent-ingress-workflow.bats | 24 +++++++++++++++++-- .github/workflows/agent-ingress.yml | 4 ++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/.github/scripts/tests/agent-ingress-workflow.bats b/.github/scripts/tests/agent-ingress-workflow.bats index 9667ef32..0fe4dd6c 100644 --- a/.github/scripts/tests/agent-ingress-workflow.bats +++ b/.github/scripts/tests/agent-ingress-workflow.bats @@ -101,7 +101,7 @@ ROLES=(dev-lead pr-auto-review pr-review pr-review-mention ci-failure-analyst) [[ "$output" == *"/pr-review-mention-reusable.yml@pr-review-mention/v2-stable" ]] run yq '.jobs.ci-failure-analyst.uses' "$WORKFLOW" [ "$status" -eq 0 ] - [[ "$output" == *"/ci-failure-analyst-reusable.yml@b58510275dd1cbbd13c0733c15265d51fd63b992" ]] + [[ "$output" == *"/ci-failure-analyst-reusable.yml@ci-failure-analyst/v1-stable" ]] } @test "dev-lead job keeps the base=main PR filter and declares no caller concurrency" { @@ -149,7 +149,7 @@ ROLES=(dev-lead pr-auto-review pr-review pr-review-mention ci-failure-analyst) run yq '.jobs.ci-failure-analyst.if' "$WORKFLOW" [[ "$output" == *"github.event_name == 'check_run'"* ]] [[ "$output" == *"github.event.check_run.conclusion == 'failure'"* ]] - [[ "$output" == *"!startsWith(github.event.check_run.name, 'CI Failure Analyst')"* ]] + [[ "$output" == *"!startsWith(github.event.check_run.name, 'ci-failure-analyst')"* ]] } @test "if: guards never read repo state (vars/secrets/needs/hashFiles)" { @@ -168,3 +168,23 @@ ROLES=(dev-lead pr-auto-review pr-review pr-review-mention ci-failure-analyst) [[ "$output" =~ @pr-review/v1-stable[[:space:]]+#[[:space:]]*NOSONAR\(githubactions:S7637\)[[:space:]]+first-party[[:space:]]+channel[[:space:]]+ref ]] [[ "$output" != *"DEFECTIVE PIN"* ]] } + +@test "ci-failure-analyst loop guard matches the analyst's own check run name (#2175)" { + # A reusable-workflow job's check run is named ' / ', + # so the analyst's own check is 'ci-failure-analyst / analyze'. The guard must + # match that prefix, or a failed analyst run re-triggers the analyst. + run yq '.jobs.ci-failure-analyst.if' "$WORKFLOW" + [ "$status" -eq 0 ] + local prefix + prefix="$(printf '%s' "$output" | sed -n "s/.*!startsWith(github.event.check_run.name, '\([^']*\)').*/\1/p")" + [ -n "$prefix" ] + # The reusable's job id is 'analyze' (ci-failure-analyst-reusable.yml). + [[ 'ci-failure-analyst / analyze' == "$prefix"* ]] +} + +@test "ci-failure-analyst pins its channel, not a bare SHA (#2176)" { + run grep -E '/ci-failure-analyst-reusable\.yml@' "$WORKFLOW" + [ "$status" -eq 0 ] + [[ "$output" =~ @ci-failure-analyst/v1-stable[[:space:]]+#[[:space:]]*NOSONAR\(githubactions:S7637\)[[:space:]]+first-party[[:space:]]+channel[[:space:]]+ref ]] + [[ "$output" != *"DEFECTIVE PIN"* ]] +} diff --git a/.github/workflows/agent-ingress.yml b/.github/workflows/agent-ingress.yml index d411cff0..a0c97e13 100644 --- a/.github/workflows/agent-ingress.yml +++ b/.github/workflows/agent-ingress.yml @@ -169,7 +169,7 @@ jobs: if: >- github.event_name == 'check_run' && github.event.check_run.conclusion == 'failure' - && !startsWith(github.event.check_run.name, 'CI Failure Analyst') + && !startsWith(github.event.check_run.name, 'ci-failure-analyst') concurrency: group: "ci-failure-analyst-${{ github.event.check_run.head_sha }}" cancel-in-progress: false @@ -179,6 +179,6 @@ jobs: actions: read contents: read checks: read - uses: petry-projects/.github-private/.github/workflows/ci-failure-analyst-reusable.yml@b58510275dd1cbbd13c0733c15265d51fd63b992 # DEFECTIVE PIN — bare SHA, see §5 + uses: petry-projects/.github-private/.github/workflows/ci-failure-analyst-reusable.yml@ci-failure-analyst/v1-stable # NOSONAR(githubactions:S7637) first-party channel ref secrets: CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}