-
Notifications
You must be signed in to change notification settings - Fork 149
Add Claude Code workflow for AI-assisted PR reviews #4738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1713c27
875f2a6
8f64c6a
85fa81a
b640037
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| name: Claude Code | ||
|
|
||
| # AI-assisted PR reviews and interactive @claude mentions. | ||
| # | ||
| # The actual Claude Code execution runs in eng-dev-ecosystem on | ||
| # protected runners whose IPs are allowlisted by the Databricks | ||
| # account IP ACL. This workflow is a thin trigger that dispatches | ||
| # to eng-dev-ecosystem via the DECO workflow trigger GitHub App. | ||
|
|
||
| on: | ||
| # Triggers automatic review when a PR is first opened. | ||
| pull_request: | ||
| types: [opened] | ||
|
|
||
| # Enables @claude mentions in PR conversation comments. | ||
| # (GitHub fires issue_comment for top-level PR comments.) | ||
| issue_comment: | ||
| types: [created] | ||
|
|
||
| # Enables @claude mentions in inline review comments. | ||
| pull_request_review_comment: | ||
| types: [created] | ||
|
|
||
| jobs: | ||
| # Automatic review on PR open. For re-reviews, comment "@claude review". | ||
| # Restrict to org members/owners to prevent untrusted users (e.g. external | ||
| # fork PRs) from consuming model serving resources. See: | ||
| # https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/ | ||
| review: | ||
| if: | | ||
| github.event_name == 'pull_request' && | ||
| !github.event.pull_request.head.repo.fork && | ||
| contains(fromJson('["MEMBER","OWNER"]'), github.event.pull_request.author_association) | ||
| concurrency: | ||
| group: claude-review-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
| runs-on: | ||
| group: databricks-deco-testing-runner-group | ||
| labels: ubuntu-latest-deco | ||
| timeout-minutes: 30 | ||
| environment: test-trigger-is | ||
| permissions: | ||
| contents: read | ||
|
|
||
| steps: | ||
| - name: Generate GitHub App token | ||
| id: token | ||
| uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2.2.2 | ||
| with: | ||
| app-id: ${{ secrets.DECO_WORKFLOW_TRIGGER_APP_ID }} | ||
| private-key: ${{ secrets.DECO_WORKFLOW_TRIGGER_PRIVATE_KEY }} | ||
| owner: databricks-eng | ||
| repositories: eng-dev-ecosystem | ||
|
|
||
| - name: Trigger Claude Code review | ||
| run: | | ||
| gh workflow run cli-claude-code.yml \ | ||
| -R databricks-eng/eng-dev-ecosystem \ | ||
| --ref main \ | ||
| -F pull_request_number=${{ github.event.pull_request.number }} \ | ||
| -F event_type=review | ||
| env: | ||
| GH_TOKEN: ${{ steps.token.outputs.token }} | ||
|
|
||
| - name: Track remote run | ||
| run: | | ||
| sleep 10 | ||
| RUN_ID=$(gh run list -R databricks-eng/eng-dev-ecosystem \ | ||
| --workflow cli-claude-code.yml --limit 1 \ | ||
| --json databaseId -q '.[0].databaseId') | ||
| echo "## Claude Code Review" >> "$GITHUB_STEP_SUMMARY" | ||
| echo "[View run](https://github.com/databricks-eng/eng-dev-ecosystem/actions/runs/$RUN_ID)" >> "$GITHUB_STEP_SUMMARY" | ||
| gh run watch "$RUN_ID" -R databricks-eng/eng-dev-ecosystem --exit-status | ||
| env: | ||
| GH_TOKEN: ${{ steps.token.outputs.token }} | ||
|
|
||
| # Interactive @claude mentions (PRs only, trusted authors only). | ||
| # Restrict to org members/owners to prevent untrusted users from triggering | ||
| # Claude with write access to the repo. See: | ||
| # https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/ | ||
| assist: | ||
| if: | | ||
| github.event.comment.user.type != 'Bot' && | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Gap (Nit)] The |
||
| contains(fromJson('["MEMBER","OWNER"]'), github.event.comment.author_association) && | ||
| ( | ||
| (github.event_name == 'issue_comment' && github.event.issue.pull_request && contains(github.event.comment.body, '@claude')) || | ||
| (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) | ||
| ) | ||
|
Comment on lines
+82
to
+88
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Major] No collaborator/author check. This only filters
Recommendation: Add an if: |
github.event.comment.user.type != 'Bot' &&
contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'), github.event.comment.author_association) &&
(...)
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: The concurrency:
group: claude-assist-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: true |
||
| concurrency: | ||
| group: claude-assist-${{ github.event.issue.number || github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
| runs-on: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: The concurrency:
group: claude-assist-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: true |
||
| group: databricks-deco-testing-runner-group | ||
| labels: ubuntu-latest-deco | ||
| timeout-minutes: 30 | ||
| environment: test-trigger-is | ||
| permissions: | ||
| contents: read | ||
|
|
||
| steps: | ||
| - name: Generate GitHub App token | ||
| id: token | ||
| uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2.2.2 | ||
| with: | ||
| app-id: ${{ secrets.DECO_WORKFLOW_TRIGGER_APP_ID }} | ||
| private-key: ${{ secrets.DECO_WORKFLOW_TRIGGER_PRIVATE_KEY }} | ||
| owner: databricks-eng | ||
| repositories: eng-dev-ecosystem | ||
|
|
||
| - name: Determine PR number | ||
| id: pr | ||
| run: | | ||
| if [ -n "$ISSUE_NUMBER" ]; then | ||
| echo "number=$ISSUE_NUMBER" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "number=$PR_NUMBER" >> "$GITHUB_OUTPUT" | ||
| fi | ||
| env: | ||
| ISSUE_NUMBER: ${{ github.event.issue.number }} | ||
| PR_NUMBER: ${{ github.event.pull_request.number }} | ||
|
|
||
| # Skip fork PRs to avoid running Claude against untrusted code. | ||
| # Comment events don't expose fork info in the `if` condition, | ||
| # so we check via API. | ||
| - name: Check if fork PR | ||
| id: fork-check | ||
| run: | | ||
| IS_FORK=$(gh pr view "$PR_NUMBER" --json isCrossRepository --jq '.isCrossRepository') | ||
| echo "is_fork=$IS_FORK" >> "$GITHUB_OUTPUT" | ||
| env: | ||
| PR_NUMBER: ${{ steps.pr.outputs.number }} | ||
| GH_TOKEN: ${{ github.token }} | ||
|
|
||
| - name: Trigger Claude Code assist | ||
| if: steps.fork-check.outputs.is_fork != 'true' | ||
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 | ||
| with: | ||
| github-token: ${{ steps.token.outputs.token }} | ||
| script: | | ||
| await github.rest.actions.createWorkflowDispatch({ | ||
| owner: 'databricks-eng', | ||
| repo: 'eng-dev-ecosystem', | ||
| workflow_id: 'cli-claude-code.yml', | ||
| ref: 'main', | ||
| inputs: { | ||
| pull_request_number: process.env.PR_NUMBER, | ||
| event_type: 'assist', | ||
| comment_body: process.env.COMMENT_BODY | ||
| } | ||
| }); | ||
| env: | ||
| COMMENT_BODY: ${{ github.event.comment.body }} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Major] Any external contributor can write: The downstream workflow must:
Cannot fully verify without seeing |
||
| PR_NUMBER: ${{ steps.pr.outputs.number }} | ||
|
|
||
| - name: Track remote run | ||
| if: steps.fork-check.outputs.is_fork != 'true' | ||
| run: | | ||
| sleep 10 | ||
| RUN_ID=$(gh run list -R databricks-eng/eng-dev-ecosystem \ | ||
| --workflow cli-claude-code.yml --limit 1 \ | ||
| --json databaseId -q '.[0].databaseId') | ||
| echo "## Claude Code Assist" >> "$GITHUB_STEP_SUMMARY" | ||
| echo "[View run](https://github.com/databricks-eng/eng-dev-ecosystem/actions/runs/$RUN_ID)" >> "$GITHUB_STEP_SUMMARY" | ||
| gh run watch "$RUN_ID" -R databricks-eng/eng-dev-ecosystem --exit-status | ||
| env: | ||
| GH_TOKEN: ${{ steps.token.outputs.token }} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Nit] The
reviewjob has a concurrency group, but theassistjob does not. Multiple rapid@claudecomments could spawn parallel sessions on the same PR, wasting resources and potentially producing conflicting actions.Suggestion: Add: