feat: add deterministic CLAUDE_CODE_OAUTH_TOKEN precondition check - #106
Merged
twistedmelonman merged 5 commits intoAug 8, 2026
Merged
Conversation
mac-dev-server-setup#58 hit a CI failure where the claude-code-action step failed with CLAUDE_OUTCOME: failure and no verdict rendered. The downstream verdict-parsing logic correctly fail-closed to BLOCK, but the actual root cause — a missing CLAUDE_CODE_OAUTH_TOKEN repo secret — was only visible deep in the action's own error output, misreported as a substantive review BLOCK rather than an infrastructure/config gap, wasting a CI cycle before someone dug through logs to find it. Adds a new "Verify CLAUDE_CODE_OAUTH_TOKEN is configured" step to both claude-assistant.yml and claude-blocking-review.yml — the two reusable workflows that actually invoke claude-code-action — placed before that invocation. Checks `secrets.claude_oauth_token != ''` and fails loudly with an actionable ::error:: (pointing at Settings > Secrets and /install-github-app) if the caller's secret resolves empty. claude.yml (the top-level caller stub for claude-assistant.yml) needed no change — it only passes the secret through and never invokes claude-code-action directly, so the check belongs in the reusable workflow where the actual invocation happens. Note: claude-blocking-review.yml's `secrets: claude_oauth_token: required: true` only guarantees the caller supplied a `secrets:` block, not that the underlying repo secret it references is actually set — a caller referencing an unconfigured CLAUDE_CODE_OAUTH_TOKEN still satisfies `required: true` while passing an empty string through, which is exactly the gap this closes. Bumps claude-blocking-review.yml to v3.2.0 (additive header note, matching the file's established versioning convention; tagging happens after merge per repo convention). claude-assistant.yml has no in-file minor-version history to extend, so its header is unchanged. Verified: extracted the shell-side check into a standalone harness and exercised TOKEN_SET=true (proceeds) and TOKEN_SET=false (errors, exit 1). YAML validated on both files. zizmor finding counts/types identical before and after on both files (committed with SKIP=zizmor per the documented escape hatch — dotfiles pre-commit/config.yaml, PR #155 — for the same pre-existing, unrelated findings noted in the #92 and #94 PRs). Closes #90.
Pre-push whole-codebase review (filed as #105) correctly flagged that the "Verify CLAUDE_CODE_OAUTH_TOKEN is configured" step added in the previous commit ran unconditionally right after the permissions preflight — before the "Check for doc-only diff" and "Check for Dependabot PR" skip-detection steps. A repo with CLAUDE_CODE_OAUTH_TOKEN unset would fail the token check even on a doc-only or Dependabot PR that would never have invoked claude-code-action in the first place, breaking the doc-only skip's cost/noise-reduction guarantee for misconfigured repos. Moves the step to immediately before "Run Claude Code Review" and adds the same `if: steps.doc-check.outputs.skip != 'true' && steps.dependabot-check.outputs.skip != 'true'` gate already used by "Estimate review parameters", "Minimize prior review comments", and the review step itself. Net change is a pure move (delete + re-add with the if: gate) — no other logic touched. claude-assistant.yml has no doc-only/Dependabot skip-check steps (it's the @claude-mention assistant, not the PR-gating reviewer), so its token-check placement from the previous commit is unaffected and correct as-is. Verified: YAML valid, zizmor finding count/type on this file unchanged before/after (same 5 pre-existing findings noted in the prior commit). Closes #105 (filed by pre-push review against this PR's first commit).
…nt.yml Pre-push whole-codebase review flagged (as BLOCKING) that the token check in claude-assistant.yml has no `if:` gate, while claude-blocking-review.yml's equivalent step is gated behind doc-only/ Dependabot skip outputs — reading this as a regression that would fail callers who "legitimately omit the secret" per its `required: false` declaration. Investigated and confirmed the premise is incorrect for this file: `required: false` was added in 67630a7 specifically to work around a GitHub dispatch-time validation quirk (required: true + a job-level if: gate on the CALLER's job causes startup_failure even on no-op runs) — it is not a statement that the token is optional when the job actually runs. claude-assistant.yml's `run` job has no internal `if:` of its own to gate behind; the @claude-mention guard lives entirely in the caller (claude.yml), so by the time this job executes at all, an authorized @claude mention has already been confirmed and the token is always required. Verified via `gh search code` that every fleet caller (11+ repos across smartwatermelon and nightowlstudiollc) passes secrets.CLAUDE_CODE_OAUTH_TOKEN through unconditionally — none use an alternate auth path. No functional change — this is a documentation-only commit adding a comment that explains why the unconditional check is deliberate and correct, so a future reader (human or automated reviewer) doesn't repeat the same plausible-but-incorrect inference from `required: false` alone. Addresses the blocking finding from pre-push review on this branch.
twistedmelonman
deleted the
claude/add-oauth-token-precondition-90-session1
branch
August 8, 2026 01:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mac-dev-server-setup#58hit a CI failure whereclaude-code-actionfailed withCLAUDE_OUTCOME: failureand no verdict rendered. The downstream verdict-parsing logic correctly fail-closed to BLOCK, but the actual root cause — a missingCLAUDE_CODE_OAUTH_TOKENrepo secret — was only visible deep in the action's own error output, misreported as a substantive review BLOCK rather than an infrastructure/config gap.claude-assistant.ymlandclaude-blocking-review.yml— the two reusable workflows that actually invokeclaude-code-action— placed before that invocation. Checkssecrets.claude_oauth_token != ''and fails loudly with an actionable::error::if the caller's secret resolves empty.claude.yml(the top-level caller stub forclaude-assistant.yml) needed no change — it only passes the secret through and never invokesclaude-code-actiondirectly.claude-blocking-review.yml, the check is gated behind the samedoc-check/dependabot-checkskip outputs as the review step itself, so a misconfigured repo still gets a clean SKIPPED verdict on doc-only or Dependabot PRs instead of failing on PRs that would never have invokedclaude-code-actionanyway.claude-assistant.yml, the check is deliberately unconditional — that workflow has no skip paths, and by the time its job executes the caller (claude.yml) has already confirmed an authorized@claudemention, so the token is always required. A comment documents whyrequired: falseon that file's secret declaration is a GitHub dispatch-time-validation workaround (see67630a7), not a signal the token is genuinely optional — confirmed viagh search codethat all 11+ fleet callers pass the secret through unconditionally.claude-blocking-review.ymlto v3.2.0 (additive header note, matching the file's established versioning convention; tagging happens after merge per repo convention).Review iteration
This PR went through two rounds of local pre-push review before landing on the final shape:
claude-blocking-review.ymlran before the doc-only/Dependabot skip checks, which would fail misconfigured repos even on PRs that would have skipped review anyway. Fixed by moving the step and adding the matchingif:gate.claude-assistant.yml's check has no equivalentif:gate. Investigated and confirmed this is correct as-is (not a bug) — added a comment explaining why, rather than an incorrect gate.Test plan
TOKEN_SET=true(proceeds) andTOKEN_SET=false(errors, exit 1)SKIP=zizmorper the documented escape hatch — dotfilespre-commit/config.yaml, PRCLAUDE_OUTCOME_RETRYcomment slightly mischaracterizes the skipped-first-step case #155 — for pre-existing, unrelated findings)Closes #90, closes #105.
https://claude.ai/code/session_019yrvtEbtQxBxDmZ4Fu9GrU