diff --git a/.github/CLAUDE_PR_ASSISTANT.md b/.github/CLAUDE_PR_ASSISTANT.md new file mode 100644 index 0000000..98dc675 --- /dev/null +++ b/.github/CLAUDE_PR_ASSISTANT.md @@ -0,0 +1,235 @@ +# Claude PR Assistant + +This workflow allows Claude to assist with Pull Requests by implementing improvements, fixes, and changes directly on the PR branch when mentioned in comments. + +## How to Use + +### 1. Comment on Any PR + +Use one of these trigger commands in a comment on any open pull request: + +- `@claude implement` - Implement new features or functionality +- `@claude fix` - Fix bugs or issues in the PR +- `@claude improve` - Improve existing code quality +- `@claude update` - Update code to match requirements +- `@claude refactor` - Refactor code for better structure +- `@claude help` - General assistance with the PR + +### 2. Example Usage + +``` +@claude fix + +Please fix the TypeScript errors in the payments collection and ensure proper typing for the provider data field. +``` + +``` +@claude improve + +Can you optimize the invoice generation logic and add better error handling? +``` + +``` +@claude implement + +Add validation for email addresses in the customer billing information fields. Make sure it follows the existing validation patterns. +``` + +## What Happens + +1. **Permission Check**: Verifies you are `bvdaakster` (only authorized user) +2. **PR Analysis**: Claude analyzes the current PR context and changes +3. **Implementation**: Makes the requested changes directly on the PR branch +4. **Quality Checks**: Runs build, typecheck, and lint +5. **Commit & Push**: Commits changes with descriptive messages +6. **Notification**: Updates the PR with completion status + +## Features + +### ✅ Direct PR Modification +- Works directly on the existing PR branch +- No new branches or PRs created +- Changes appear immediately in the PR + +### ✅ Smart Context Awareness +- Understands the current PR changes +- Analyzes existing code patterns +- Maintains consistency with the codebase + +### ✅ Comprehensive Request Handling +- Code improvements and refactoring +- Bug fixes within the PR +- Adding missing features +- Documentation updates +- Type error fixes +- Performance optimizations +- Test additions + +### ✅ Quality Assurance +- Follows TypeScript conventions +- Uses ESM module structure +- Runs automated quality checks +- Maintains coding standards + +## Command Reference + +| Command | Purpose | Example | +|---------|---------|---------| +| `@claude implement` | Add new functionality | "implement user authentication" | +| `@claude fix` | Fix bugs or errors | "fix the validation logic" | +| `@claude improve` | Enhance existing code | "improve performance of query" | +| `@claude update` | Update to requirements | "update to use new API format" | +| `@claude refactor` | Restructure code | "refactor into smaller functions" | +| `@claude help` | General assistance | "help with error handling" | + +## Examples + +### Bug Fix Request +``` +@claude fix + +There's a TypeScript error in `src/providers/stripe.ts` on line 45. The `amount` property is missing from the payment object. Please fix this and ensure proper typing. +``` + +### Feature Implementation +``` +@claude implement + +Add support for recurring payments in the Stripe provider. Follow the same pattern as the Mollie provider and include proper webhook handling. +``` + +### Code Improvement +``` +@claude improve + +The `validatePayment` function in utils.ts is getting complex. Please refactor it to be more readable and add proper error messages for each validation case. +``` + +### Documentation Update +``` +@claude update + +Update the JSDoc comments in the billing plugin configuration to include examples of how to use the new customer info extractor feature. +``` + +## Response Types + +### Success Response +``` +✅ PR Assistance Complete! + +🔧 Changes Made: +- ✅ Analyzed PR context and requirements +- ✅ Implemented requested improvements/fixes +- ✅ Followed project coding standards +- ✅ Updated the current PR branch + +Changes are ready for review! 🚀 +``` + +### No Changes Response +``` +ℹ️ PR Assistance Complete - No Changes + +Analysis Result: The requested feature is already implemented + +💡 Suggestions: +- Provide more detailed requirements +- Point to specific files or functions +``` + +### Error Response +``` +❌ PR Assistance Failed + +🔄 Try Again: +- Providing more specific instructions +- Breaking down complex requests +``` + +## Best Practices + +### Clear Instructions +- Be specific about what you want changed +- Reference specific files or functions when possible +- Provide context about the desired outcome + +### Examples of Good Requests +``` +@claude fix the TypeScript error in src/collections/payments.ts line 42 where the status field is missing from the Payment interface + +@claude implement email validation in the customer billing form using the same pattern as the phone validation + +@claude refactor the webhook handler in providers/mollie.ts to extract the payment processing logic into separate functions +``` + +### Examples of Unclear Requests +``` +@claude fix everything +@claude make it better +@claude help with this +``` + +## Limitations + +- **User Restriction**: Only `bvdaakster` can use this feature +- **PR Only**: Works on pull request comments, not issue comments +- **Open PRs**: Only works on open pull requests +- **Branch Access**: Requires write access to the PR branch + +## Technical Details + +### Workflow Triggers +- Event: `issue_comment` on pull requests +- Conditions: Comment contains Claude trigger words +- Permissions: User must be `bvdaakster` + +### Quality Checks +Claude automatically runs: +- `pnpm build` - Verify code compiles +- `pnpm typecheck` - Check TypeScript types +- `pnpm lint` - Ensure code style compliance +- `npm run test` - Run test suite (if available) + +### Commit Messages +Automatic commits include: +- Description of the request +- PR number and requester +- Claude attribution +- Proper co-authoring + +### Branch Strategy +- Works directly on the PR's head branch +- No additional branches created +- Changes pushed to existing PR +- Maintains PR history + +## Troubleshooting + +### Common Issues + +1. **Permission Denied** + - Only `bvdaakster` can use Claude PR assistance + - Verify you're commenting as the correct user + +2. **No Changes Made** + - Request might be unclear or already implemented + - Try providing more specific instructions + - Reference specific files or lines + +3. **Workflow Failed** + - Check the Actions tab for detailed logs + - Verify the PR branch is accessible + - Ensure request is actionable + +### Getting Help + +If Claude assistance isn't working: +1. Check the workflow logs in Actions tab +2. Verify your request is specific and actionable +3. Try breaking complex requests into smaller parts +4. Use different command triggers (@claude fix vs @claude implement) + +--- + +**Note**: This feature uses the official Anthropic Claude Code action for reliable, production-ready assistance. All changes should be reviewed before merging. \ No newline at end of file diff --git a/.github/claude-config.json b/.github/claude-config.json new file mode 100644 index 0000000..7bfe8e7 --- /dev/null +++ b/.github/claude-config.json @@ -0,0 +1,43 @@ +{ + "privilegedUsers": [ + "bvdaakster" + ], + "permissions": { + "issueImplementation": { + "strategy": "privilegedUsers", + "description": "Only bvdaakster can request Claude implementations" + }, + "codeReview": { + "strategy": "privilegedUsers", + "description": "Only bvdaakster can trigger Claude reviews" + }, + "prAssistant": { + "strategy": "privilegedUsers", + "description": "Only bvdaakster can use Claude PR assistance" + } + }, + "workflows": { + "issueImplementation": { + "file": "claude-implement-issue.yml", + "triggers": ["@claude implement", "@claude fix", "@claude create"], + "description": "Creates new branch and PR for issue implementation" + }, + "codeReview": { + "file": "claude-code-review.yml", + "triggers": ["automatic on PR"], + "description": "Automatic code review for PRs from privileged users" + }, + "prAssistant": { + "file": "claude-pr-assistant.yml", + "triggers": ["@claude implement", "@claude fix", "@claude improve", "@claude update", "@claude refactor", "@claude help"], + "description": "Assists with PR improvements directly on the PR branch" + } + }, + "strategies": { + "privilegedUsers": "Only users in the privilegedUsers list", + "adminsOnly": "Only repository admins", + "adminOrPrivileged": "Repository admins OR users in privilegedUsers list", + "orgMembersWithWrite": "Organization members with write access", + "everyone": "All users with repository access" + } +} \ No newline at end of file diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index a12225a..441f16d 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -12,11 +12,8 @@ on: 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' + # Only allow bvdaakster to trigger reviews + if: github.event.pull_request.user.login == 'bvdaakster' runs-on: ubuntu-latest permissions: diff --git a/.github/workflows/claude-implement-issue.yml b/.github/workflows/claude-implement-issue.yml new file mode 100644 index 0000000..2f10f8e --- /dev/null +++ b/.github/workflows/claude-implement-issue.yml @@ -0,0 +1,197 @@ +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: | + if (context.actor !== 'bvdaakster') { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: '❌ **Access Denied**: Only bvdaakster can use Claude implementation.' + }); + throw new Error('Unauthorized user'); + } + + - 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 branch + id: create-branch + run: | + BRANCH_NAME="claude/issue-${{ github.event.issue.number }}-$(date +%Y%m%d-%H%M%S)" + echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT + git checkout -b "$BRANCH_NAME" + git push origin "$BRANCH_NAME" + + - name: Notify 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**\n\n📋 **Issue**: #${{ github.event.issue.number }}\n🌿 **Branch**: \`${{ steps.create-branch.outputs.branch_name }}\`\n\nImplementing your request...` + }); + + - name: Implement with Claude + uses: anthropics/claude-code-action@beta + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + 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 }} + + **User Request**: + ${{ github.event.comment.body }} + + **Instructions**: + 1. Analyze the issue requirements carefully + 2. Follow existing code patterns and conventions + 3. Use TypeScript with proper typing + 4. Follow ESM module structure with .js extensions + 5. Add tests if needed + 6. Update documentation if necessary + + This is the @xtr-dev/payload-billing plugin for PayloadCMS. + 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 && git diff --cached --quiet; then + echo "has_changes=false" >> $GITHUB_OUTPUT + else + echo "has_changes=true" >> $GITHUB_OUTPUT + fi + + - name: Commit and push + 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 "feat: implement issue #${{ github.event.issue.number }} + + Implemented via Claude automation. + + Issue: #${{ github.event.issue.number }} + Requested by: @${{ github.event.comment.user.login }} + + 🤖 Generated with Claude Code + + Co-Authored-By: Claude " + git push origin ${{ steps.create-branch.outputs.branch_name }} + + - name: Create PR + 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 implements issue #${{ github.event.issue.number }}. + + **Issue**: #${{ github.event.issue.number }} + **Requested by**: @${{ github.event.comment.user.login }} + **Branch**: \`${{ steps.create-branch.outputs.branch_name }}\` + + ### Review Checklist + - [ ] Code follows project conventions + - [ ] Build passes + - [ ] Tests pass + - [ ] Implementation matches requirements + + Closes #${{ github.event.issue.number }} + + 🤖 Generated with Claude Code` + }); + return pr.number; + + - name: Notify success + if: steps.changes.outputs.has_changes == 'true' + uses: actions/github-script@v7 + with: + script: | + const prNumber = '${{ steps.create-pr.outputs.result }}'; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: `✅ **Implementation Complete!**\n\n🎯 **Pull Request**: #${prNumber}\n🌿 **Branch**: \`${{ steps.create-branch.outputs.branch_name }}\`\n\nReady for review! 🚀` + }); + + - name: Handle 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: `ℹ️ **No Changes Needed**\n\nI analyzed the issue but no code changes are required.` + }); + + - name: Clean up on no changes + if: steps.changes.outputs.has_changes == 'false' + run: git push origin --delete ${{ steps.create-branch.outputs.branch_name }} || true + + - name: Handle 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**\n\nCheck the [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.` + }); \ No newline at end of file diff --git a/.github/workflows/claude-pr-assistant.yml b/.github/workflows/claude-pr-assistant.yml new file mode 100644 index 0000000..7441a9d --- /dev/null +++ b/.github/workflows/claude-pr-assistant.yml @@ -0,0 +1,172 @@ +name: Claude PR Assistant + +on: + issue_comment: + types: [created] + +permissions: + contents: write + issues: write + pull-requests: write + id-token: write + +jobs: + claude-pr-assist: + if: | + github.event.issue.pull_request && + 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 improve') || + contains(github.event.comment.body, '@claude update') || + contains(github.event.comment.body, '@claude refactor') || + contains(github.event.comment.body, '@claude help') + ) + runs-on: ubuntu-latest + + steps: + - name: Check user permissions + uses: actions/github-script@v7 + with: + script: | + if (context.actor !== 'bvdaakster') { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: '❌ **Access Denied**: Only bvdaakster can use Claude PR assistance.' + }); + throw new Error('Unauthorized user'); + } + + - name: Get PR details + id: pr-details + uses: actions/github-script@v7 + with: + script: | + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number + }); + return { + head_ref: pr.head.ref, + title: pr.title, + body: pr.body + }; + + - name: Checkout PR branch + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ fromJson(steps.pr-details.outputs.result).head_ref }} + 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: Notify 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 PR Assistant Started**\n\n💬 **Request**: ${{ github.event.comment.body }}\n🌿 **Branch**: \`${{ fromJson(steps.pr-details.outputs.result).head_ref }}\`\n\nWorking on your request...` + }); + + - name: Assist with Claude + uses: anthropics/claude-code-action@beta + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + direct_prompt: | + You are assisting with a GitHub Pull Request. Please help with this request: + + **Pull Request #${{ github.event.issue.number }}**: ${{ fromJson(steps.pr-details.outputs.result).title }} + + **PR Description**: + ${{ fromJson(steps.pr-details.outputs.result).body }} + + **User Request**: + ${{ github.event.comment.body }} + + **Instructions**: + 1. Analyze the current PR changes and the user's request + 2. Implement the requested improvements, fixes, or changes + 3. Follow existing code patterns and conventions + 4. Use TypeScript with proper typing + 5. Follow ESM module structure with .js extensions + 6. Run quality checks if needed + + This is the @xtr-dev/payload-billing plugin for PayloadCMS. + Please implement the requested changes directly on this PR branch. + 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 && git diff --cached --quiet; then + echo "has_changes=false" >> $GITHUB_OUTPUT + else + echo "has_changes=true" >> $GITHUB_OUTPUT + fi + + - name: Commit and push + if: steps.changes.outputs.has_changes == 'true' + run: | + git config --local user.email "action@github.com" + git config --local user.name "Claude PR Assistant" + git add . + git commit -m "feat: Claude PR assistance - ${{ github.event.comment.user.login }} request + + Request: ${{ github.event.comment.body }} + PR: #${{ github.event.issue.number }} + + 🤖 Generated with Claude PR Assistant + + Co-Authored-By: Claude " + git push origin ${{ fromJson(steps.pr-details.outputs.result).head_ref }} + + - name: Notify 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: `✅ **PR Assistance Complete!**\n\n🔧 **Changes Made**: Implemented your requested improvements\n🌿 **Branch**: \`${{ fromJson(steps.pr-details.outputs.result).head_ref }}\`\n\nChanges are ready for review! 🚀` + }); + + - name: Handle 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: `ℹ️ **No Changes Needed**\n\nI analyzed your request but no code changes are required.` + }); + + - name: Handle 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: `❌ **PR Assistance Failed**\n\nCheck the [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.` + }); \ No newline at end of file diff --git a/dev/payload-types.ts b/dev/payload-types.ts index 5f1fb92..4fb47ca 100644 --- a/dev/payload-types.ts +++ b/dev/payload-types.ts @@ -158,7 +158,7 @@ export interface Payment { /** * The payment ID from the payment provider */ - providerId: string; + providerId?: string | null; status: 'pending' | 'processing' | 'succeeded' | 'failed' | 'canceled' | 'refunded' | 'partially_refunded'; /** * Amount in cents (e.g., 2000 = $20.00) @@ -198,6 +198,7 @@ export interface Payment { | boolean | null; refunds?: (number | Refund)[] | null; + version?: number | null; updatedAt: string; createdAt: string; } @@ -499,6 +500,7 @@ export interface PaymentsSelect { metadata?: T; providerData?: T; refunds?: T; + version?: T; updatedAt?: T; createdAt?: T; } diff --git a/package.json b/package.json index 5e5a152..aa0701f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xtr-dev/payload-billing", - "version": "0.1.5", + "version": "0.1.6", "description": "PayloadCMS plugin for billing and payment provider integrations with tracking and local testing", "license": "MIT", "type": "module",