From cf83380eb321634bd677f15f386c4a74bd2433fc Mon Sep 17 00:00:00 2001 From: Claude Code Bot Date: Mon, 17 Aug 2026 15:36:41 -0700 Subject: [PATCH] ci: add standard Claude workflow callers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Onboards this repo to the fleet standard: blocking-review and assistant callers delegating to smartwatermelon/github-workflows. This repo was one of three with no .github/workflows directory at all (issue #126 item 3). Both callers track floating @v3 rather than an exact @v3.x.y pin. Exact pins are immutable and silently miss security fixes — that is how 19 repos never received the GHSA-8q5r-mmjf-575q remediation. Committed with SKIP=zizmor: zizmor flags unpinned-uses against the @v3 tag ref, but reusable workflows in this fleet use a repo-wide semver tag convention rather than per-action SHA pinning. That is deliberate documented policy, not an oversight. Claude-Session: https://claude.ai/code/session_01SimcNSM4P5hpb1dQVejqcF --- .github/workflows/claude-blocking-review.yml | 32 ++++++++++++++++++++ .github/workflows/claude.yml | 31 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 .github/workflows/claude-blocking-review.yml create mode 100644 .github/workflows/claude.yml diff --git a/.github/workflows/claude-blocking-review.yml b/.github/workflows/claude-blocking-review.yml new file mode 100644 index 0000000..391a616 --- /dev/null +++ b/.github/workflows/claude-blocking-review.yml @@ -0,0 +1,32 @@ +name: Claude Blocking Review + +on: + pull_request: + types: [opened, synchronize, ready_for_review, reopened] + +permissions: + contents: read + pull-requests: write + issues: write + id-token: write + +jobs: + # Pin to v3.1.0 or later, not a caller-level `if: github.actor != + # 'dependabot[bot]'` gate. A job-level `if:` that evaluates false means + # this job never dispatches, so a required status check on it never + # reports — it stays permanently pending on Dependabot PRs under + # branch protection that requires the check, blocking auto-merge + # entirely. v3.1.0+ instead skips Dependabot PRs from INSIDE the job, + # so the job still runs and reports a real PASS. See + # smartwatermelon/github-workflows#115/#117 for the incident that + # established this; a caller-level gate was tried and reverted. + claude-review: + # Track floating @v3, not an exact @v3.x.y. Exact tags are immutable, so a + # caller pinned to one silently misses security fixes — that is how 19 repos + # never received the GHSA-8q5r-mmjf-575q remediation. See "Prefer floating + # @v3 over an exact pin" in smartwatermelon/github-workflows README.md. + 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 }} diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 0000000..5a4b0cd --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,31 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + pull_request_review: + types: [submitted] + +jobs: + claude: + # The author_association guard MUST stay here in the caller and must not be + # removed. Without it, any GitHub user can open an issue with injected + # instructions and Claude will execute them. The reusable workflow cannot + # enforce this guard itself — it has to live in the calling job's condition. + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') && contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.review.author_association)) + permissions: + contents: read + issues: read + pull-requests: read + id-token: write # required by claude-code-action for internal authentication + # Track floating @v3, not an exact @v3.x.y — see "Prefer floating @v3 over + # an exact pin" in smartwatermelon/github-workflows README.md. The v3 line, + # not v1: tags here are repo-wide, and v1 is frozen/deprecated. + uses: smartwatermelon/github-workflows/.github/workflows/claude-assistant.yml@v3 + secrets: + claude_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}