Observation
Claude Code Review (caller: claude-code-review.yml → claude-blocking-review.yml@v3) fails with startup_failure and zero dispatched jobs on every Dependabot-authored PR, confirmed on smartwatermelon/repo-template PR #1 on both 2026-08-07 and 2026-08-11 (unrelated to the dependabot-auto-merge v2 migration work in progress on that PR — the failures predate it).
Root cause
claude-blocking-review.yml's workflow_call interface declares:
secrets:
claude_oauth_token:
required: true
The caller stub forwards it as secrets.CLAUDE_CODE_OAUTH_TOKEN. GitHub validates required-secret workflow_call contracts at dispatch time, before any job (or step inside a job) runs. Dependabot-triggered pull_request events run under a restricted token context that does not have access to repository secrets — so the secret the caller tries to forward resolves to nothing, GitHub can't satisfy the reusable workflow's required-secret contract, and the whole run fails to start: conclusion: startup_failure, jobs: [], billable: {}.
The reusable workflow already has a dependabot-check step (added per the "add dependabot fast-pass" commit, f723490) intended to skip AI review for Dependabot PRs cheaply. This fast-pass can never fire for this failure mode — it's a step inside the job, and the job never starts. The fast-pass only protects against wasted API spend on a running job; it does nothing for a startup_failure.
Impact
Every Dependabot PR across the fleet that uses claude-code-review.yml → claude-blocking-review.yml gets a permanently red/failed check, even though the intent (per the existing fast-pass logic) was always to skip — not fail — AI review on these PRs. This is a false-negative CI signal fleet-wide, not specific to repo-template.
Suggested fix
Move the Dependabot skip decision to the caller (before the secret is ever referenced), e.g.:
jobs:
claude-review:
if: github.actor != 'dependabot[bot]'
uses: smartwatermelon/github-workflows/.github/workflows/claude-blocking-review.yml@v3
with:
pr_number: ${{ github.event.pull_request.number }}
secrets:
claude_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
A caller-level if: prevents the reusable workflow from being invoked at all for Dependabot PRs, so the required-secret contract is never evaluated in a context where it can't be satisfied. This needs to land in the README's caller-stub example and in every consuming repo's claude-code-review.yml (or equivalent) — likely most/all of the same 31 repos touched by the dependabot-auto-merge v2 migration (dev-env#20), since they'd have copied the same caller-stub pattern.
The existing in-job dependabot-check fast-pass can stay as defense-in-depth for any trigger path that isn't gated by the caller-level if: (e.g. a repo-specific workflow that doesn't yet have it).
Discovered during
Canary testing the dependabot-auto-merge v2 migration on smartwatermelon/repo-template (dev-env#20) — unrelated to that work, but caught in the same investigation.
Claude-Session: https://claude.ai/code/session_01Q5QrbCLnJdAPjcCLu9UHNp
Observation
Claude Code Review(caller:claude-code-review.yml→claude-blocking-review.yml@v3) fails withstartup_failureand zero dispatched jobs on every Dependabot-authored PR, confirmed onsmartwatermelon/repo-templatePR #1 on both 2026-08-07 and 2026-08-11 (unrelated to the dependabot-auto-merge v2 migration work in progress on that PR — the failures predate it).Root cause
claude-blocking-review.yml'sworkflow_callinterface declares:The caller stub forwards it as
secrets.CLAUDE_CODE_OAUTH_TOKEN. GitHub validates required-secretworkflow_callcontracts at dispatch time, before any job (or step inside a job) runs. Dependabot-triggeredpull_requestevents run under a restricted token context that does not have access to repository secrets — so the secret the caller tries to forward resolves to nothing, GitHub can't satisfy the reusable workflow's required-secret contract, and the whole run fails to start:conclusion: startup_failure,jobs: [],billable: {}.The reusable workflow already has a
dependabot-checkstep (added per the "add dependabot fast-pass" commit,f723490) intended to skip AI review for Dependabot PRs cheaply. This fast-pass can never fire for this failure mode — it's a step inside the job, and the job never starts. The fast-pass only protects against wasted API spend on a running job; it does nothing for astartup_failure.Impact
Every Dependabot PR across the fleet that uses
claude-code-review.yml→claude-blocking-review.ymlgets a permanently red/failed check, even though the intent (per the existing fast-pass logic) was always to skip — not fail — AI review on these PRs. This is a false-negative CI signal fleet-wide, not specific torepo-template.Suggested fix
Move the Dependabot skip decision to the caller (before the secret is ever referenced), e.g.:
A caller-level
if:prevents the reusable workflow from being invoked at all for Dependabot PRs, so the required-secret contract is never evaluated in a context where it can't be satisfied. This needs to land in the README's caller-stub example and in every consuming repo'sclaude-code-review.yml(or equivalent) — likely most/all of the same 31 repos touched by the dependabot-auto-merge v2 migration (dev-env#20), since they'd have copied the same caller-stub pattern.The existing in-job
dependabot-checkfast-pass can stay as defense-in-depth for any trigger path that isn't gated by the caller-levelif:(e.g. a repo-specific workflow that doesn't yet have it).Discovered during
Canary testing the dependabot-auto-merge v2 migration on
smartwatermelon/repo-template(dev-env#20) — unrelated to that work, but caught in the same investigation.Claude-Session: https://claude.ai/code/session_01Q5QrbCLnJdAPjcCLu9UHNp