Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Claude Code Review

on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"

jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'

runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Grant pull-request write scope for code-review job

This workflow configures pull-requests: read, but the Claude Code review flow is expected to publish PR feedback; with a read-only token, review comments cannot be created, so the automated review run can complete without delivering actionable output. Anthropic’s own automated review examples for anthropics/claude-code-action use pull-requests: write for this reason, so this permission setting makes the new review workflow effectively non-functional on real PRs.

Useful? React with 👍 / 👎.

issues: read
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
Comment on lines +30 to +36

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify all workflow `uses:` entries are SHA-pinned
rg -nP '^\s*uses:\s*[^@\s]+@(?!(?:[0-9a-f]{40})\b).+' .github/workflows/*.yml
# Expected: no output

Repository: humancto/mango

Length of output: 372


🏁 Script executed:

# Check for dependabot or policy configuration files
find .github -type f -name "*.yml" -o -name "*.yaml" -o -name "*.json" | head -20

Repository: humancto/mango

Length of output: 677


🏁 Script executed:

# Search for any references to "dependabot-selftest" or SHA pinning policies
rg -i "dependabot-selftest|sha.?pin|immutable" .github/ || echo "No references found"

Repository: humancto/mango

Length of output: 1135


🏁 Script executed:

# Check all other workflows to see if SHA pinning is consistently applied
cat .github/workflows/claude.yml | head -40

Repository: humancto/mango

Length of output: 1359


🏁 Script executed:

# Read the dependabot-selftest.yml to understand the enforcement
cat .github/workflows/dependabot-selftest.yml

Repository: humancto/mango

Length of output: 2585


🏁 Script executed:

# Also check the dependabot.yml configuration
cat .github/dependabot.yml

Repository: humancto/mango

Length of output: 3808


🏁 Script executed:

# Verify the test script existence and understand assertion `#15`
head -60 scripts/dependabot-scripts-test.sh | grep -A 5 -B 5 "assertion"

Repository: humancto/mango

Length of output: 532


🏁 Script executed:

# Find assertion `#15` in the test script
rg -n "assertion.?15|uses:" scripts/dependabot-scripts-test.sh | head -30

Repository: humancto/mango

Length of output: 775


Pin action refs to immutable SHAs to unblock CI and harden supply chain.

Lines 30 and 36 use tag-pinned refs (@v4, @v1) and violate the enforced SHA-pin policy. This directly triggers the dependabot-selftest workflow failure (assertion #15 validates all uses: lines must be 40-hex SHAs with optional trailing # <ref> comments).

Suggested fix pattern
-        uses: actions/checkout@v4
+        uses: actions/checkout@<40-hex-commit-sha> # v4

-        uses: anthropics/claude-code-action@v1
+        uses: anthropics/claude-code-action@<40-hex-commit-sha> # v1
🧰 Tools
🪛 GitHub Actions: dependabot-selftest

[error] 30-30: Dependabot scripts check failed: workflow uses are not SHA-pinned with 40-hex. Found 'uses: actions/checkout@v4'.


[error] 36-36: Dependabot scripts check failed: workflow uses are not SHA-pinned with 40-hex. Found 'uses: anthropics/claude-code-action@v1'.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/claude-code-review.yml around lines 30 - 36, The workflow
uses tag refs for actions (actions/checkout@v4 and
anthropics/claude-code-action@v1); replace each `uses:` entry with the
corresponding immutable 40-hex commit SHA for that repo (e.g.,
actions/checkout@<40-hex-sha> and anthropics/claude-code-action@<40-hex-sha>),
optionally appending a trailing comment with the human-readable tag (e.g., "#
v4" or "# v1") to satisfy the SHA-pin policy and unblock the dependabot-selftest
check.

with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
plugins: 'code-review@claude-code-plugins'
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options

50 changes: 50 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
Comment on lines +15 to +20

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add a trusted-actor gate to the @claude trigger condition.

Line 15–20 currently allows any user who can comment to invoke the workflow if they mention @claude. That does not enforce the stated “write-access only” behavior and can be abused for cost/noise.

Suggested fix
   claude:
     if: |
-      (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
-      (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
-      (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
-      (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
+      (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)) ||
+      (github.event_name == 'issues' &&
+        (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) &&
+        contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
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)) ||
(github.event_name == 'issues' &&
(contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association))
runs-on: ubuntu-latest
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/claude.yml around lines 15 - 20, The trigger condition
must be gated by a trusted-actor check so only users with write access can
invoke `@claude`; update the existing if expression to require both the `@claude`
mention and that the event actor’s author_association is one of OWNER, MEMBER or
COLLABORATOR. Concretely, for comment/review/review_comment/issue branches add
an extra clause using the appropriate payload field
(github.event.comment.author_association,
github.event.review.author_association, github.event.issue.author_association)
and require it equals 'OWNER' or 'MEMBER' or 'COLLABORATOR' (combine with ||),
so the final if only passes when a mention exists AND the actor has write-level
association.

permissions:
contents: read
pull-requests: read
issues: read
Comment on lines +22 to +24

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enable write scopes for interactive Claude workflow

The @claude workflow is wired to respond to issue/PR mentions, but contents, pull-requests, and issues are all set to read-only, which prevents Claude from posting responses/comments or making repo updates requested via mentions. In practice this causes triggered runs to be unable to perform the core actions users expect from this workflow; the action’s documented baseline permissions are write-level for these scopes.

Useful? React with 👍 / 👎.

id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
Comment on lines +29 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify all workflow `uses:` entries are SHA-pinned
rg -nP '^\s*uses:\s*[^@\s]+@(?!(?:[0-9a-f]{40})\b).+' .github/workflows/*.yml
# Expected: no output

Repository: humancto/mango

Length of output: 372


Pin GitHub Actions by full commit SHA (required by current CI policy).

Lines 29 and 35 in .github/workflows/claude.yml use tag refs (@v4, @v1) instead of 40-hex SHAs. The same issue exists in .github/workflows/claude-code-review.yml at lines 30 and 36. This is failing dependabot-selftest and should be treated as a merge blocker.

Suggested fix pattern
-      - name: Checkout repository
-        uses: actions/checkout@v4
+      - name: Checkout repository
+        uses: actions/checkout@<40-hex-commit-sha> # v4

...
-      - name: Run Claude Code
-        id: claude
-        uses: anthropics/claude-code-action@v1
+      - name: Run Claude Code
+        id: claude
+        uses: anthropics/claude-code-action@<40-hex-commit-sha> # v1
🧰 Tools
🪛 GitHub Actions: dependabot-selftest

[error] 29-29: Dependabot scripts check failed: workflow uses are not SHA-pinned with 40-hex. Found 'uses: actions/checkout@v4'.


[error] 35-35: Dependabot scripts check failed: workflow uses are not SHA-pinned with 40-hex. Found 'uses: anthropics/claude-code-action@v1'.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/claude.yml around lines 29 - 35, Replace the tag refs with
pinned commit SHAs for the GitHub Actions usages: change actions/checkout@v4 to
the full 40-character commit SHA for the actions/checkout repo and change
anthropics/claude-code-action@v1 to the full 40-character commit SHA for
anthropics/claude-code-action; apply the same replacements in both
`.github/workflows/claude.yml` (the lines that reference actions/checkout@v4 and
anthropics/claude-code-action@v1) and `.github/workflows/claude-code-review.yml`
so both workflows use exact commit SHAs instead of tag refs.

with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'

# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr *)'

Loading