From a2cac87e2759e8936c7e05edb8001b9298a2b5cb Mon Sep 17 00:00:00 2001 From: Ashwin Bhat Date: Fri, 14 Aug 2026 16:40:34 -0700 Subject: [PATCH] ci: skip Claude-backed test jobs on fork PRs (#1655) * ci: skip Claude-backed test jobs on fork PRs Jobs that run the action against the Claude API authenticate via workload identity federation, which fork PRs cannot mint an OIDC token for, so they always failed on external contributions. Gate each such job on the PR head repo matching the base repo; push and workflow_dispatch runs are unaffected. No-Verification-Needed: CI workflow config only, exercised by Actions on the PR * test: pin the bare remote's initial branch in fetch-depth test The shallow-clone case created its bare remote with a plain git init, so HEAD pointed at whatever init.defaultBranch resolves to (master on CI) while the test only pushed main. git clone --depth=1 implies --single-branch, and with a dangling remote HEAD it produces an empty, non-shallow clone, so the is-shallow assertion failed on runners whose default branch is not main. No-Verification-Needed: test-only change --- .github/workflows/claude-review.yml | 2 ++ .github/workflows/test-base-action.yml | 4 ++++ .github/workflows/test-custom-executables.yml | 2 ++ .github/workflows/test-mcp-servers.yml | 4 ++++ .github/workflows/test-settings.yml | 8 ++++++++ .github/workflows/test-structured-output.yml | 12 +++++++++++- test/fetch-depth.test.ts | 11 ++++++++++- 7 files changed, 41 insertions(+), 2 deletions(-) diff --git a/.github/workflows/claude-review.yml b/.github/workflows/claude-review.yml index 6f4dde5c..899659b9 100644 --- a/.github/workflows/claude-review.yml +++ b/.github/workflows/claude-review.yml @@ -6,6 +6,8 @@ on: jobs: review: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/test-base-action.yml b/.github/workflows/test-base-action.yml index 0688d2d8..53b8f549 100644 --- a/.github/workflows/test-base-action.yml +++ b/.github/workflows/test-base-action.yml @@ -19,6 +19,8 @@ permissions: jobs: test-inline-prompt: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -70,6 +72,8 @@ jobs: fi test-prompt-file: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/test-custom-executables.yml b/.github/workflows/test-custom-executables.yml index 432d39e5..11f5d5eb 100644 --- a/.github/workflows/test-custom-executables.yml +++ b/.github/workflows/test-custom-executables.yml @@ -14,6 +14,8 @@ permissions: jobs: test-custom-executables: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/test-mcp-servers.yml b/.github/workflows/test-mcp-servers.yml index 9c8df033..1942afcf 100644 --- a/.github/workflows/test-mcp-servers.yml +++ b/.github/workflows/test-mcp-servers.yml @@ -14,6 +14,8 @@ permissions: jobs: test-mcp-integration: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - name: Checkout repository @@ -94,6 +96,8 @@ jobs: echo "✓ All MCP server checks passed!" test-mcp-config-flag: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/.github/workflows/test-settings.yml b/.github/workflows/test-settings.yml index 9bf13d4c..21dd7163 100644 --- a/.github/workflows/test-settings.yml +++ b/.github/workflows/test-settings.yml @@ -14,6 +14,8 @@ permissions: jobs: test-settings-inline-allow: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -65,6 +67,8 @@ jobs: fi test-settings-inline-deny: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -99,6 +103,8 @@ jobs: fi test-settings-file-allow: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -155,6 +161,8 @@ jobs: fi test-settings-file-deny: + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.github/workflows/test-structured-output.yml b/.github/workflows/test-structured-output.yml index 1deaf884..2c75eb27 100644 --- a/.github/workflows/test-structured-output.yml +++ b/.github/workflows/test-structured-output.yml @@ -15,6 +15,8 @@ permissions: jobs: test-basic-types: name: Test Basic Type Conversions + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - name: Checkout @@ -76,6 +78,8 @@ jobs: test-complex-types: name: Test Arrays and Objects + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - name: Checkout @@ -129,6 +133,8 @@ jobs: test-edge-cases: name: Test Edge Cases + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - name: Checkout @@ -190,6 +196,8 @@ jobs: test-name-sanitization: name: Test Output Name Sanitization + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - name: Checkout @@ -232,6 +240,8 @@ jobs: test-execution-file-structure: name: Test Execution File Format + # Skip on fork PRs since they can't mint the OIDC token used for Claude API auth + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest steps: - name: Checkout @@ -284,7 +294,7 @@ jobs: - test-edge-cases - test-name-sanitization - test-execution-file-structure - if: always() + if: ${{ always() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} steps: - name: Generate Summary run: | diff --git a/test/fetch-depth.test.ts b/test/fetch-depth.test.ts index 57ba25b8..9830c962 100644 --- a/test/fetch-depth.test.ts +++ b/test/fetch-depth.test.ts @@ -28,7 +28,16 @@ describe("setupBranch fetch depth", () => { repoDir = join(tempDir, "repo"); const remoteDir = join(tempDir, "origin.git"); - execFileSync("git", ["init", "--bare", remoteDir], { stdio: "pipe" }); + // Pin the remote's HEAD to main: with the default init.defaultBranch of + // master it would dangle, and `git clone --depth=1` (which implies + // --single-branch) then produces an empty, non-shallow clone. + execFileSync( + "git", + ["init", "--bare", "--initial-branch=main", remoteDir], + { + stdio: "pipe", + }, + ); execFileSync("git", ["init", repoDir], { stdio: "pipe" }); git(["checkout", "-b", "main"]); git(["config", "user.email", "test@example.com"]);