Files
payload-billing/.github/workflows/claude-implement-issue.yml
Bas van den Aakster 534b0e440f feat: add comprehensive user permission controls for Claude workflows
- Add multi-level permission checking for issue implementation workflow
- Support multiple permission strategies: privileged users, admins only, combined, org-based
- Add permission validation with detailed error messages
- Restrict code review workflow to privileged users and repository members
- Create permission configuration file (.github/claude-config.json)
- Add comprehensive permission documentation

Permission strategies available:
- Privileged users only (most restrictive)
- Repository admins only
- Admins OR privileged users (default)
- Organization members with write access
- Everyone with write access (least restrictive)

Current configuration:
- Issue implementation: admins OR privileged users (bastiaan, xtr-dev-team)
- Code reviews: privileged users and repository members only

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-18 21:16:51 +02:00

332 lines
13 KiB
YAML

name: Claude Issue Implementation
on:
issue_comment:
types: [created]
permissions:
contents: write
issues: write
pull-requests: write
id-token: write
jobs:
claude-implement:
if: |
github.event.issue_comment.issue.state == 'open' &&
(
contains(github.event.comment.body, '@claude implement') ||
contains(github.event.comment.body, '@claude fix') ||
contains(github.event.comment.body, '@claude create')
)
runs-on: ubuntu-latest
steps:
- name: Check user permissions
uses: actions/github-script@v7
with:
script: |
const username = context.actor;
// Method 1: Specific privileged users list
const privilegedUsers = [
'bastiaan', // Repository owner
'xtr-dev-team', // Core team members
// Add more usernames here
];
// Method 2: Check repository permission level
const { data: collaborator } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: username
});
// Method 3: Check organization membership (if applicable)
let isOrgMember = false;
try {
await github.rest.orgs.getMembershipForUser({
org: context.repo.owner,
username: username
});
isOrgMember = true;
} catch (error) {
// User is not an org member or org doesn't exist
isOrgMember = false;
}
// Combined permission check
const isPrivilegedUser = privilegedUsers.includes(username);
const hasAdminAccess = collaborator.permission === 'admin';
const hasWriteAccess = ['admin', 'write'].includes(collaborator.permission);
// Choose your permission strategy:
// Option A: Only specific users
const allowedByUserList = isPrivilegedUser;
// Option B: Only admins
const allowedByAdminAccess = hasAdminAccess;
// Option C: Admin + specific users
const allowedByAdminOrPrivileged = hasAdminAccess || isPrivilegedUser;
// Option D: Organization members with write access
const allowedByOrgAndWrite = isOrgMember && hasWriteAccess;
// Set your chosen strategy here:
const isAllowed = allowedByAdminOrPrivileged; // Change this line to use your preferred strategy
if (!isAllowed) {
const errorMessage = `❌ **Access Denied**: Claude implementation is restricted to privileged users only.
**Your access level**: ${collaborator.permission}
**Privileged user**: ${isPrivilegedUser ? 'Yes' : 'No'}
**Organization member**: ${isOrgMember ? 'Yes' : 'No'}
Contact a repository administrator for access.`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: errorMessage
});
throw new Error('Insufficient permissions for Claude implementation');
}
// Log successful access
console.log(`✅ Access granted to ${username} (${collaborator.permission})`);
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Install pnpm
run: npm install -g pnpm@10.12.4
- name: Create Claude implementation branch
id: create-branch
run: |
# Create a unique branch name based on issue number and timestamp
BRANCH_NAME="claude/issue-${{ github.event.issue.number }}-$(date +%Y%m%d-%H%M%S)"
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
# Create and switch to the new branch
git checkout -b "$BRANCH_NAME"
git push origin "$BRANCH_NAME"
- name: Add comment with implementation start
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `🤖 **Claude Implementation Started**
I'm now working on implementing this issue. Here's what I'm doing:
📋 **Issue**: #${{ github.event.issue.number }} - ${{ github.event.issue.title }}
🌿 **Branch**: \`${{ steps.create-branch.outputs.branch_name }}\`
⏱️ **Started**: ${new Date().toISOString()}
I'll analyze the requirements and create a pull request with the implementation. This may take a few minutes...
You can track the progress in the [Actions tab](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).`
});
- name: Implement with Claude
id: implementation
uses: anthropics/claude-code-action@beta
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# Direct prompt with issue context
direct_prompt: |
Please implement the feature or fix described in this GitHub issue:
**Issue #${{ github.event.issue.number }}**: ${{ github.event.issue.title }}
**Issue Description**:
${{ github.event.issue.body }}
**Implementation Request**:
${{ github.event.comment.body }}
**Instructions**:
1. Analyze the issue requirements carefully
2. Follow the existing code patterns and conventions in this PayloadCMS plugin
3. Add appropriate tests if needed (check for existing test patterns)
4. Update documentation if necessary
5. Ensure the implementation is complete and working
6. Use TypeScript with proper typing
7. Follow the project's ESM module structure with .js extensions
The implementation should be production-ready and follow best practices for a PayloadCMS plugin.
**Repository Context**: This is the @xtr-dev/payload-billing plugin for PayloadCMS.
**Branch**: ${{ steps.create-branch.outputs.branch_name }}
# Allow Claude to run necessary commands
allowed_tools: "Bash(pnpm build),Bash(pnpm typecheck),Bash(pnpm lint),Bash(npm run test)"
- name: Check for changes
id: changes
run: |
if git diff --quiet; then
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "No changes were made during implementation"
else
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "Changes detected, preparing commit"
fi
- name: Commit changes
if: steps.changes.outputs.has_changes == 'true'
run: |
git config --local user.email "action@github.com"
git config --local user.name "Claude Implementation Bot"
git add .
git commit -m "$(cat <<'EOF'
feat: implement issue #${{ github.event.issue.number }} - ${{ github.event.issue.title }}
Implemented via Claude automation based on issue requirements.
Issue: #${{ github.event.issue.number }}
Requested by: @${{ github.event.comment.user.login }}
🤖 Generated with Claude Automation
Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)"
git push origin ${{ steps.create-branch.outputs.branch_name }}
- name: Create Pull Request
if: steps.changes.outputs.has_changes == 'true'
uses: actions/github-script@v7
id: create-pr
with:
script: |
const { data: pr } = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `🤖 Implement: ${{ github.event.issue.title }}`,
head: '${{ steps.create-branch.outputs.branch_name }}',
base: 'dev',
body: `## 🤖 Claude Implementation
This PR was automatically created by Claude to implement the feature/fix requested in issue #${{ github.event.issue.number }}.
### 📋 Issue Details
- **Issue**: #${{ github.event.issue.number }}
- **Title**: ${{ github.event.issue.title }}
- **Requested by**: @${{ github.event.comment.user.login }}
- **Branch**: \`${{ steps.create-branch.outputs.branch_name }}\`
### 🔍 Implementation
Claude analyzed the issue requirements and implemented the requested changes following the project's coding standards and best practices.
### ✅ Review Checklist
- [ ] Code follows project conventions
- [ ] Tests are included (if applicable)
- [ ] Documentation is updated (if needed)
- [ ] Implementation matches issue requirements
- [ ] No breaking changes (unless intended)
### 🔗 Related
Closes #${{ github.event.issue.number }}
---
**Note**: This implementation was generated automatically. Please review carefully before merging.
🤖 *Generated with Claude Automation*`
});
return pr.number;
- name: Update issue with success
if: steps.changes.outputs.has_changes == 'true'
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `✅ **Implementation Complete!**
I've successfully implemented the requested changes and created a pull request:
🎯 **Pull Request**: #${{ steps.create-pr.outputs.result }}
🌿 **Branch**: \`${{ steps.create-branch.outputs.branch_name }}\`
⏱️ **Completed**: ${new Date().toISOString()}
## Next Steps
1. Review the implementation in the pull request
2. Test the changes locally if needed
3. Merge the PR if everything looks good
The implementation follows the project's coding standards and includes appropriate documentation.`
});
- name: Update issue with no changes
if: steps.changes.outputs.has_changes == 'false'
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `⚠️ **Implementation Completed - No Changes**
I analyzed the issue but determined that no code changes are needed. This might be because:
- The feature is already implemented
- The issue requires clarification
- The request is not actionable as a code change
- Additional information is needed
🌿 **Branch**: \`${{ steps.create-branch.outputs.branch_name }}\` (will be cleaned up)
Please review the issue requirements and provide additional details if needed.`
});
- name: Clean up branch if no changes
if: steps.changes.outputs.has_changes == 'false'
run: |
git push origin --delete ${{ steps.create-branch.outputs.branch_name }} || true
- name: Handle implementation failure
if: failure()
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `❌ **Implementation Failed**
I encountered an error while trying to implement this issue. Please check the [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.
Common reasons for failure:
- Issue requirements are unclear or incomplete
- Technical constraints prevent implementation
- Repository permissions or configuration issues
You can try again by commenting \`@claude implement\` or provide more specific requirements.`
});