Skip to content

build(deps): bump dtolnay/rust-toolchain from 1.93.0 to 1.100.0 #3764

build(deps): bump dtolnay/rust-toolchain from 1.93.0 to 1.100.0

build(deps): bump dtolnay/rust-toolchain from 1.93.0 to 1.100.0 #3764

Workflow file for this run

name: Claude Assistant
on:
pull_request:
types: [opened, synchronize]
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
workflow_run:
workflows: ["CI"]
types: [completed]
# Filter to find non-member, non-bot comments (for prompt injection prevention)
env:
NONMEMBER_FILTER: '[.[] | select(.user.type != "Bot" and .author_association != "OWNER" and .author_association != "MEMBER" and .author_association != "COLLABORATOR")] | length'
# Note: We use a GitHub App token instead of GITHUB_TOKEN so that:
# 1. All actions appear as "Claude" bot
# 2. PRs created by Claude can trigger CI workflows
# Required: CLAUDE_APP_ID (variable), CLAUDE_APP_PRIVATE_KEY (secret)
jobs:
# Gatekeeper: Check for non-member commits, comments, and author association
safety-check:
runs-on: ubuntu-latest
outputs:
safe: ${{ steps.check.outputs.safe }}
pr_number: ${{ steps.get-pr.outputs.number }}
author_ok: ${{ steps.author.outputs.ok }}
commits_ok: ${{ steps.commits.outputs.ok }}
steps:
- name: Generate token
id: token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
- name: Get PR number
id: get-pr
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "issue_comment" ]; then
echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "pull_request_review_comment" ]; then
echo "number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "workflow_run" ]; then
BRANCH="${{ github.event.workflow_run.head_branch }}"
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
echo "number=0" >> $GITHUB_OUTPUT
else
PR_NUM=$(gh pr list --repo ${{ github.repository }} --head "$BRANCH" --json number --jq '.[0].number // 0')
echo "number=$PR_NUM" >> $GITHUB_OUTPUT
fi
else
echo "number=0" >> $GITHUB_OUTPUT
fi
- name: Get PR author association
id: get-author
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
PR_NUM="${{ steps.get-pr.outputs.number }}"
if [ -z "$PR_NUM" ] || [ "$PR_NUM" = "0" ]; then
# No PR (e.g., main branch CI) - treat as owner
echo "assoc=OWNER" >> $GITHUB_OUTPUT
else
ASSOC=$(gh api repos/${{ github.repository }}/pulls/$PR_NUM --jq '.author_association')
echo "assoc=$ASSOC" >> $GITHUB_OUTPUT
fi
- name: Check author is member
id: author
run: |
ASSOC="${{ steps.get-author.outputs.assoc }}"
if [ "$ASSOC" = "OWNER" ] || [ "$ASSOC" = "MEMBER" ] || [ "$ASSOC" = "COLLABORATOR" ]; then
echo "ok=true" >> $GITHUB_OUTPUT
else
echo "::warning::Blocking Claude - PR author association is $ASSOC (not member)"
echo "ok=false" >> $GITHUB_OUTPUT
fi
- name: Check for non-member commits
id: commits
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
PR_NUM="${{ steps.get-pr.outputs.number }}"
if [ -z "$PR_NUM" ] || [ "$PR_NUM" = "0" ]; then
echo "ok=true" >> $GITHUB_OUTPUT
exit 0
fi
# Check each commit author's association
NON_MEMBER=$(gh api repos/${{ github.repository }}/pulls/$PR_NUM/commits --jq \
'[.[] | select(.author.type != "Bot" and .author.login != null) | .author.login] | unique | .[]' | while read -r LOGIN; do
if [ -n "$LOGIN" ]; then
ASSOC=$(gh api repos/${{ github.repository }}/collaborators/$LOGIN/permission --jq '.permission' 2>/dev/null || echo "none")
# Block if not a collaborator (permission = none)
if [ "$ASSOC" = "none" ]; then
echo "$LOGIN"
fi
fi
done | head -1)
if [ -n "$NON_MEMBER" ]; then
echo "::warning::Blocking Claude - non-member commit author: $NON_MEMBER"
echo "ok=false" >> $GITHUB_OUTPUT
else
echo "ok=true" >> $GITHUB_OUTPUT
fi
- name: Check for non-member comments
id: check
env:
GH_TOKEN: ${{ steps.token.outputs.token }}
run: |
PR_NUM="${{ steps.get-pr.outputs.number }}"
if [ -z "$PR_NUM" ] || [ "$PR_NUM" = "0" ]; then
echo "safe=true" >> $GITHUB_OUTPUT
exit 0
fi
ISSUE=$(gh api repos/${{ github.repository }}/issues/$PR_NUM/comments --jq "$NONMEMBER_FILTER" 2>/dev/null || echo 0)
REVIEW=$(gh api repos/${{ github.repository }}/pulls/$PR_NUM/comments --jq "$NONMEMBER_FILTER" 2>/dev/null || echo 0)
TOTAL=$((ISSUE + REVIEW))
if [ "$TOTAL" -gt 0 ]; then
echo "::warning::Blocking Claude - $TOTAL non-member comment(s) detected"
echo "safe=false" >> $GITHUB_OUTPUT
else
echo "safe=true" >> $GITHUB_OUTPUT
fi
# Review PRs from org members, auto-fix medium/critical issues
review:
needs: safety-check
if: |
needs.safety-check.outputs.safe == 'true' &&
needs.safety-check.outputs.author_ok == 'true' &&
needs.safety-check.outputs.commits_ok == 'true' &&
github.event_name == 'pull_request' &&
!startsWith(github.event.pull_request.head.ref, 'claude/fix-')
runs-on: ubuntu-latest
timeout-minutes: 60
concurrency:
group: claude-review-${{ github.event.pull_request.number }}
cancel-in-progress: true
steps:
- name: Generate Claude token
id: claude-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.claude-token.outputs.token }}
path: fcvm
- uses: ./fcvm/.github/actions/checkout-deps
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Install build dependencies
run: sudo apt-get update && sudo apt-get install -y libfuse3-dev libclang-dev clang
- uses: actions/setup-node@v6
with:
node-version: '20'
- uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
run: cd fcvm/scripts/claude-assistant && pnpm install
- name: Run Claude review
working-directory: fcvm
env:
GH_TOKEN: ${{ steps.claude-token.outputs.token }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
MODE: review
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_BRANCH: ${{ github.event.pull_request.head.ref }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BASE_BRANCH: ${{ github.event.pull_request.base.ref }}
RUN_ID: ${{ github.run_id }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
FUSE_BACKEND_RS: ${{ github.workspace }}/fuse-backend-rs
FUSER: ${{ github.workspace }}/fuser
run: |
cd scripts/claude-assistant && pnpm exec tsx index.ts 2>&1 | tee /tmp/claude-output.log
# Verify completion marker exists (detects if process was killed mid-execution)
if ! grep -q "CLAUDE_ASSISTANT_COMPLETE" /tmp/claude-output.log; then
echo "ERROR: Claude assistant did not complete - process may have been killed"
exit 1
fi
# Manual review via /claude-review comment
manual-review:
needs: safety-check
if: |
needs.safety-check.outputs.safe == 'true' &&
needs.safety-check.outputs.author_ok == 'true' &&
needs.safety-check.outputs.commits_ok == 'true' &&
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '/claude-review')
runs-on: ubuntu-latest
timeout-minutes: 60
concurrency:
group: claude-manual-${{ github.event.issue.number }}
cancel-in-progress: true
steps:
- name: Generate Claude token
id: claude-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: refs/pull/${{ github.event.issue.number }}/head
token: ${{ steps.claude-token.outputs.token }}
path: fcvm
- uses: ./fcvm/.github/actions/checkout-deps
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Install build dependencies
run: sudo apt-get update && sudo apt-get install -y libfuse3-dev libclang-dev clang
- uses: actions/setup-node@v6
with:
node-version: '20'
- uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
run: cd fcvm/scripts/claude-assistant && pnpm install
- name: Get PR info
id: pr
working-directory: fcvm
run: |
PR_DATA=$(gh pr view ${{ github.event.issue.number }} --json headRefName,headRefOid,baseRefName)
echo "head_branch=$(echo $PR_DATA | jq -r .headRefName)" >> $GITHUB_OUTPUT
echo "head_sha=$(echo $PR_DATA | jq -r .headRefOid)" >> $GITHUB_OUTPUT
echo "base_branch=$(echo $PR_DATA | jq -r .baseRefName)" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ steps.claude-token.outputs.token }}
- name: Run Claude review
working-directory: fcvm
env:
GH_TOKEN: ${{ steps.claude-token.outputs.token }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
MODE: review
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
HEAD_BRANCH: ${{ steps.pr.outputs.head_branch }}
HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
BASE_BRANCH: ${{ steps.pr.outputs.base_branch }}
RUN_ID: ${{ github.run_id }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
FUSE_BACKEND_RS: ${{ github.workspace }}/fuse-backend-rs
FUSER: ${{ github.workspace }}/fuser
run: |
cd scripts/claude-assistant && pnpm exec tsx index.ts 2>&1 | tee /tmp/claude-output.log
if ! grep -q "CLAUDE_ASSISTANT_COMPLETE" /tmp/claude-output.log; then
echo "ERROR: Claude assistant did not complete - process may have been killed"
exit 1
fi
# Respond to @claude mentions
respond:
needs: safety-check
if: |
needs.safety-check.outputs.safe == 'true' &&
needs.safety-check.outputs.author_ok == 'true' &&
needs.safety-check.outputs.commits_ok == 'true' &&
!contains(github.event.comment.body, '/claude-review') &&
((github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')))
runs-on: ubuntu-latest
timeout-minutes: 15
concurrency:
group: claude-respond-${{ github.event.comment.id }}
cancel-in-progress: false
steps:
- name: Generate Claude token
id: claude-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.claude-token.outputs.token }}
path: fcvm
- uses: ./fcvm/.github/actions/checkout-deps
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Install build dependencies
run: sudo apt-get update && sudo apt-get install -y libfuse3-dev libclang-dev clang
- uses: actions/setup-node@v6
with:
node-version: '20'
- uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
run: cd fcvm/scripts/claude-assistant && pnpm install
- name: Get PR info
id: pr
working-directory: fcvm
env:
GH_TOKEN: ${{ steps.claude-token.outputs.token }}
run: |
PR_NUM="${{ needs.safety-check.outputs.pr_number }}"
if [ -n "$PR_NUM" ] && [ "$PR_NUM" != "0" ]; then
PR_DATA=$(gh pr view $PR_NUM --json headRefName,headRefOid,baseRefName)
echo "head_branch=$(echo $PR_DATA | jq -r .headRefName)" >> $GITHUB_OUTPUT
echo "head_sha=$(echo $PR_DATA | jq -r .headRefOid)" >> $GITHUB_OUTPUT
echo "base_branch=$(echo $PR_DATA | jq -r .baseRefName)" >> $GITHUB_OUTPUT
else
echo "head_branch=" >> $GITHUB_OUTPUT
echo "head_sha=" >> $GITHUB_OUTPUT
echo "base_branch=" >> $GITHUB_OUTPUT
fi
- name: Run Claude respond
working-directory: fcvm
env:
GH_TOKEN: ${{ steps.claude-token.outputs.token }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
MODE: respond
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ needs.safety-check.outputs.pr_number }}
HEAD_BRANCH: ${{ steps.pr.outputs.head_branch }}
HEAD_SHA: ${{ steps.pr.outputs.head_sha }}
BASE_BRANCH: ${{ steps.pr.outputs.base_branch }}
RUN_ID: ${{ github.run_id }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
COMMENT_BODY: ${{ github.event.comment.body }}
FUSE_BACKEND_RS: ${{ github.workspace }}/fuse-backend-rs
FUSER: ${{ github.workspace }}/fuser
run: |
cd scripts/claude-assistant && pnpm exec tsx index.ts 2>&1 | tee /tmp/claude-output.log
if ! grep -q "CLAUDE_ASSISTANT_COMPLETE" /tmp/claude-output.log; then
echo "ERROR: Claude assistant did not complete - process may have been killed"
exit 1
fi
# Auto-fix CI failures
ci-fix:
needs: safety-check
if: |
needs.safety-check.outputs.safe == 'true' &&
needs.safety-check.outputs.author_ok == 'true' &&
needs.safety-check.outputs.commits_ok == 'true' &&
github.event_name == 'workflow_run' &&
github.event.workflow_run.conclusion == 'failure' &&
!startsWith(github.event.workflow_run.head_branch, 'claude/fix-') &&
github.event.workflow_run.name != 'Claude Assistant'
runs-on: ubuntu-latest
timeout-minutes: 60
concurrency:
group: claude-cifix-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: true
steps:
- name: Generate Claude token
id: claude-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
- uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_sha }}
fetch-depth: 0
token: ${{ steps.claude-token.outputs.token }}
path: fcvm
- uses: ./fcvm/.github/actions/checkout-deps
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Install build dependencies
run: sudo apt-get update && sudo apt-get install -y libfuse3-dev libclang-dev clang
- uses: actions/setup-node@v6
with:
node-version: '20'
- uses: pnpm/action-setup@v4
with:
version: 9
- name: Install dependencies
run: cd fcvm/scripts/claude-assistant && pnpm install
- name: Run Claude CI fix
working-directory: fcvm
env:
GH_TOKEN: ${{ steps.claude-token.outputs.token }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
MODE: ci-fix
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ needs.safety-check.outputs.pr_number }}
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
BASE_BRANCH: main
RUN_ID: ${{ github.run_id }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
FAILED_RUN_ID: ${{ github.event.workflow_run.id }}
FAILED_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}
WORKFLOW_NAME: ${{ github.event.workflow_run.name }}
FUSE_BACKEND_RS: ${{ github.workspace }}/fuse-backend-rs
FUSER: ${{ github.workspace }}/fuser
run: |
cd scripts/claude-assistant && pnpm exec tsx index.ts 2>&1 | tee /tmp/claude-output.log
if ! grep -q "CLAUDE_ASSISTANT_COMPLETE" /tmp/claude-output.log; then
echo "ERROR: Claude assistant did not complete - process may have been killed"
exit 1
fi