mirror of
https://github.com/xtr-dev/payload-automation.git
synced 2025-12-11 09:13:24 +00:00
Compare commits
2 Commits
dev
...
add-claude
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13968904c0 | ||
|
|
e3b79710ba |
78
.github/workflows/claude-code-review.yml
vendored
Normal file
78
.github/workflows/claude-code-review.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
name: Claude Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
# 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
|
||||
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@beta
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
|
||||
# Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1)
|
||||
# model: "claude-opus-4-1-20250805"
|
||||
|
||||
# Direct prompt for automated review (no @claude mention needed)
|
||||
direct_prompt: |
|
||||
Please review this pull request and provide feedback on:
|
||||
- Code quality and best practices
|
||||
- Potential bugs or issues
|
||||
- Performance considerations
|
||||
- Security concerns
|
||||
- Test coverage
|
||||
|
||||
Be constructive and helpful in your feedback.
|
||||
|
||||
# Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
|
||||
# use_sticky_comment: true
|
||||
|
||||
# Optional: Customize review based on file types
|
||||
# direct_prompt: |
|
||||
# Review this PR focusing on:
|
||||
# - For TypeScript files: Type safety and proper interface usage
|
||||
# - For API endpoints: Security, input validation, and error handling
|
||||
# - For React components: Performance, accessibility, and best practices
|
||||
# - For tests: Coverage, edge cases, and test quality
|
||||
|
||||
# Optional: Different prompts for different authors
|
||||
# direct_prompt: |
|
||||
# ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' &&
|
||||
# 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' ||
|
||||
# 'Please provide a thorough code review focusing on our coding standards and best practices.' }}
|
||||
|
||||
# Optional: Add specific tools for running tests or linting
|
||||
# allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
|
||||
|
||||
# Optional: Skip review for certain conditions
|
||||
# if: |
|
||||
# !contains(github.event.pull_request.title, '[skip-review]') &&
|
||||
# !contains(github.event.pull_request.title, '[WIP]')
|
||||
|
||||
64
.github/workflows/claude.yml
vendored
Normal file
64
.github/workflows/claude.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
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
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
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@beta
|
||||
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: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1)
|
||||
# model: "claude-opus-4-1-20250805"
|
||||
|
||||
# Optional: Customize the trigger phrase (default: @claude)
|
||||
# trigger_phrase: "/claude"
|
||||
|
||||
# Optional: Trigger when specific user is assigned to an issue
|
||||
# assignee_trigger: "claude-bot"
|
||||
|
||||
# Optional: Allow Claude to run specific commands
|
||||
# allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
|
||||
|
||||
# Optional: Add custom instructions for Claude to customize its behavior for your project
|
||||
# custom_instructions: |
|
||||
# Follow our coding standards
|
||||
# Ensure all new code has tests
|
||||
# Use TypeScript for new files
|
||||
|
||||
# Optional: Custom environment variables for Claude
|
||||
# claude_env: |
|
||||
# NODE_ENV: test
|
||||
|
||||
193
README.md
193
README.md
@@ -1,19 +1,18 @@
|
||||
# @xtr-dev/payload-automation
|
||||
|
||||
[](https://www.npmjs.com/package/@xtr-dev/payload-automation)
|
||||
|
||||
A workflow automation plugin for PayloadCMS 3.x. Run steps in workflows triggered by document changes or webhooks.
|
||||
A comprehensive workflow automation plugin for PayloadCMS 3.x that enables visual workflow building, execution tracking, and parallel processing.
|
||||
|
||||
⚠️ **Pre-release Warning**: This package is currently in active development (v0.0.x). Breaking changes may occur before v1.0.0. Not recommended for production use.
|
||||
|
||||
## Features
|
||||
|
||||
- 🔄 Visual workflow builder in PayloadCMS admin
|
||||
- ⚡ Run workflows when documents are created/updated/deleted
|
||||
- 🎯 Trigger workflows via webhooks
|
||||
- 📊 Track workflow execution history
|
||||
- 🔧 HTTP requests, document operations, email sending
|
||||
- 🔗 Use data from previous steps in templates
|
||||
- 🔄 **Visual Workflow Builder** - Create complex workflows with drag-and-drop interface
|
||||
- ⚡ **Parallel Execution** - Smart dependency resolution for optimal performance
|
||||
- 🎯 **Multiple Triggers** - Collection hooks, webhooks, manual execution
|
||||
- ⏰ **Scheduled Workflows** - Use webhook triggers with external cron services
|
||||
- 📊 **Execution Tracking** - Complete history and monitoring of workflow runs
|
||||
- 🔧 **Extensible Steps** - HTTP requests, document CRUD, email notifications
|
||||
- 🔧 **Handlebars Templates** - Dynamic data interpolation with automatic type conversion
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -48,25 +47,94 @@ export default buildConfig({
|
||||
})
|
||||
```
|
||||
|
||||
## Imports
|
||||
## Import Structure
|
||||
|
||||
The plugin uses separate exports to avoid bundling server-side code in client bundles:
|
||||
|
||||
```typescript
|
||||
// Server plugin
|
||||
// Server-side plugin and functions
|
||||
import { workflowsPlugin } from '@xtr-dev/payload-automation/server'
|
||||
|
||||
// Client components
|
||||
// Client-side components
|
||||
import { StatusCell, ErrorDisplay } from '@xtr-dev/payload-automation/client'
|
||||
|
||||
// Types
|
||||
// Helper utilities
|
||||
import { /* helpers */ } from '@xtr-dev/payload-automation/helpers'
|
||||
|
||||
// Types only (safe for both server and client)
|
||||
import type { WorkflowsPluginConfig } from '@xtr-dev/payload-automation'
|
||||
```
|
||||
|
||||
## Step Types
|
||||
|
||||
### HTTP Request
|
||||
Call external APIs. Supports GET, POST, PUT, DELETE, PATCH. Uses Bearer tokens, API keys, or basic auth.
|
||||
Make external API calls with comprehensive error handling and retry logic.
|
||||
|
||||
HTTP steps succeed even with 4xx/5xx status codes. Only network errors (timeouts, DNS failures) cause step failure. Check `{{steps.stepName.output.status}}` for error handling.
|
||||
**Key Features:**
|
||||
- Support for GET, POST, PUT, DELETE, PATCH methods
|
||||
- Authentication: Bearer token, Basic auth, API key headers
|
||||
- Configurable timeouts and retry logic
|
||||
- Handlebars templates for dynamic URLs and request bodies
|
||||
|
||||
**Error Handling:**
|
||||
HTTP Request steps use a **response-based success model** rather than status-code-based failures:
|
||||
|
||||
- ✅ **Successful completion**: All HTTP requests that receive a response (including 4xx/5xx status codes) are marked as "succeeded"
|
||||
- ❌ **Failed execution**: Only network errors, timeouts, DNS failures, and connection issues cause step failure
|
||||
- 📊 **Error information preserved**: HTTP error status codes (404, 500, etc.) are captured in the step output for workflow conditional logic
|
||||
|
||||
**Example workflow logic:**
|
||||
```typescript
|
||||
// Step outputs for a 404 response:
|
||||
{
|
||||
"status": 404,
|
||||
"statusText": "Not Found",
|
||||
"body": "Resource not found",
|
||||
"headers": {...},
|
||||
"duration": 1200
|
||||
}
|
||||
|
||||
// Use in workflow conditions:
|
||||
// "{{steps.apiRequest.output.status}} >= 400" to handle errors
|
||||
```
|
||||
|
||||
This design allows workflows to handle HTTP errors gracefully rather than failing completely, enabling robust error handling and retry logic.
|
||||
|
||||
**Enhanced Error Tracking:**
|
||||
For network failures (timeouts, DNS errors, connection failures), the plugin provides detailed error information through an independent storage system that bypasses PayloadCMS's output limitations:
|
||||
|
||||
```typescript
|
||||
// Timeout error details preserved in workflow context:
|
||||
{
|
||||
"steps": {
|
||||
"httpStep": {
|
||||
"state": "failed",
|
||||
"error": "Task handler returned a failed state",
|
||||
"errorDetails": {
|
||||
"errorType": "timeout",
|
||||
"duration": 2006,
|
||||
"attempts": 1,
|
||||
"finalError": "Request timeout after 2000ms",
|
||||
"context": {
|
||||
"url": "https://api.example.com/data",
|
||||
"method": "GET",
|
||||
"timeout": 2000
|
||||
}
|
||||
},
|
||||
"executionInfo": {
|
||||
"completed": true,
|
||||
"success": false,
|
||||
"executedAt": "2025-09-04T15:16:10.000Z",
|
||||
"duration": 2006
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Access in workflow conditions:
|
||||
// "{{steps.httpStep.errorDetails.errorType}} == 'timeout'"
|
||||
// "{{steps.httpStep.errorDetails.duration}} > 5000"
|
||||
```
|
||||
|
||||
### Document Operations
|
||||
- **Create Document** - Create PayloadCMS documents
|
||||
@@ -77,17 +145,38 @@ HTTP steps succeed even with 4xx/5xx status codes. Only network errors (timeouts
|
||||
### Communication
|
||||
- **Send Email** - Send notifications via PayloadCMS email
|
||||
|
||||
## Templates
|
||||
## Data Resolution
|
||||
|
||||
Use `{{}}` to insert data:
|
||||
Use Handlebars templates to access workflow data:
|
||||
|
||||
- `{{trigger.doc.id}}` - Data from the document that triggered the workflow
|
||||
- `{{steps.stepName.output}}` - Data from previous steps
|
||||
- `{{trigger.doc.id}}` - Access trigger document
|
||||
- `{{steps.stepName.output}}` - Use previous step outputs
|
||||
- `{{context}}` - Access workflow context
|
||||
|
||||
### Template Examples
|
||||
|
||||
Example:
|
||||
```json
|
||||
{
|
||||
"url": "https://api.example.com/posts/{{steps.createPost.output.id}}",
|
||||
"message": "Post {{trigger.doc.title}} was updated by {{trigger.req.user.email}}",
|
||||
"timeout": "{{steps.configStep.output.timeoutMs}}"
|
||||
}
|
||||
```
|
||||
|
||||
### Automatic Type Conversion
|
||||
|
||||
Handlebars templates automatically convert string results to appropriate types based on field names:
|
||||
|
||||
- **Numbers**: `timeout`, `retries`, `delay`, `port`, `count`, etc. → converted to numbers
|
||||
- **Booleans**: `enabled`, `active`, `success`, `complete`, etc. → converted to booleans
|
||||
- **Numeric strings**: `"5000"` → `5000`, `"3.14"` → `3.14`
|
||||
|
||||
### Conditions
|
||||
|
||||
Conditions support Handlebars templates with comparison operators:
|
||||
|
||||
```json
|
||||
{
|
||||
"condition": "{{trigger.doc.status}} == 'published'"
|
||||
}
|
||||
```
|
||||
@@ -98,26 +187,72 @@ Example:
|
||||
- Node.js ^18.20.2 || >=20.9.0
|
||||
- pnpm ^9 || ^10
|
||||
|
||||
## Logging
|
||||
## Environment Variables
|
||||
|
||||
Set `PAYLOAD_AUTOMATION_LOG_LEVEL` to control logs:
|
||||
- `silent`, `error`, `warn` (default), `info`, `debug`, `trace`
|
||||
Control plugin logging with these environment variables:
|
||||
|
||||
### `PAYLOAD_AUTOMATION_LOG_LEVEL`
|
||||
Controls both configuration-time and runtime logging.
|
||||
- **Values**: `silent`, `error`, `warn`, `info`, `debug`, `trace`
|
||||
- **Default**: `warn`
|
||||
- **Example**: `PAYLOAD_AUTOMATION_LOG_LEVEL=debug`
|
||||
|
||||
### `PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL` (optional)
|
||||
Override log level specifically for configuration-time logs (plugin setup).
|
||||
- **Values**: Same as above
|
||||
- **Default**: Falls back to `PAYLOAD_AUTOMATION_LOG_LEVEL` or `warn`
|
||||
- **Example**: `PAYLOAD_AUTOMATION_CONFIG_LOG_LEVEL=silent`
|
||||
|
||||
### Production Usage
|
||||
For production, keep the default (`warn`) or use `error` or `silent`:
|
||||
```bash
|
||||
PAYLOAD_AUTOMATION_LOG_LEVEL=error npm start
|
||||
```
|
||||
|
||||
### Development Usage
|
||||
For debugging, use `debug` or `info`:
|
||||
```bash
|
||||
PAYLOAD_AUTOMATION_LOG_LEVEL=debug npm run dev
|
||||
```
|
||||
|
||||
## Scheduled Workflows
|
||||
|
||||
Use webhook triggers with external cron services:
|
||||
For scheduled workflows, use **webhook triggers** with external cron services instead of built-in cron triggers:
|
||||
|
||||
```bash
|
||||
# Call workflow webhook from cron
|
||||
curl -X POST https://your-app.com/api/workflows-webhook/daily-report
|
||||
### GitHub Actions (Free)
|
||||
```yaml
|
||||
# .github/workflows/daily-report.yml
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 9 * * *' # Daily at 9 AM UTC
|
||||
jobs:
|
||||
trigger-workflow:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: curl -X POST https://your-app.com/api/workflows-webhook/daily-report
|
||||
```
|
||||
|
||||
Built-in cron triggers were removed in v0.0.37+.
|
||||
### Vercel Cron (Serverless)
|
||||
```js
|
||||
// api/cron/daily.js
|
||||
export default async function handler(req, res) {
|
||||
await fetch('https://your-app.com/api/workflows-webhook/daily-report', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ source: 'vercel-cron' })
|
||||
});
|
||||
res.status(200).json({ success: true });
|
||||
}
|
||||
```
|
||||
|
||||
**Benefits**: Better reliability, proper process isolation, easier debugging, and leverages existing infrastructure.
|
||||
|
||||
**Note**: Built-in cron triggers have been removed in v0.0.37+ to focus on webhook-based scheduling which provides better reliability and debugging capabilities.
|
||||
|
||||
## Documentation
|
||||
|
||||
Full documentation coming soon. For now, explore the development environment in the repository for examples and patterns.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
MIT
|
||||
Reference in New Issue
Block a user