mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-27 23:07:12 +02:00
197 lines
6.6 KiB
YAML
197 lines
6.6 KiB
YAML
name: 'Util: Claude Task Runner'
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
task:
|
|
description: 'Task description - what should Claude do?'
|
|
required: true
|
|
type: string
|
|
resumeUrl:
|
|
description: 'Optional callback URL to call with the result when the workflow completes'
|
|
required: false
|
|
type: string
|
|
model:
|
|
description: 'Claude model to use (e.g., claude-opus-4-6, claude-sonnet-4-5, claude-haiku-4-5)'
|
|
required: false
|
|
type: string
|
|
default: 'claude-sonnet-4-5-20250929'
|
|
use_raw_prompt:
|
|
description: 'Pass the task input directly as the prompt without wrapping it with guidelines and instructions'
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
max_turns:
|
|
description: 'Maximum conversation turns before Claude stops gracefully'
|
|
required: false
|
|
type: number
|
|
default: 50
|
|
suppress_output:
|
|
description: 'Suppress console output and job summary'
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
ref:
|
|
description: 'Git ref (branch/tag/SHA) to check out and work on'
|
|
required: false
|
|
type: string
|
|
default: 'master'
|
|
|
|
jobs:
|
|
run-claude-task:
|
|
runs-on: blacksmith-4vcpu-ubuntu-2204
|
|
timeout-minutes: 60
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
issues: write
|
|
|
|
steps:
|
|
- name: Generate GitHub App Token
|
|
id: generate_token
|
|
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
|
|
with:
|
|
app-id: ${{ secrets.N8N_ASSISTANT_APP_ID }}
|
|
private-key: ${{ secrets.N8N_ASSISTANT_PRIVATE_KEY }}
|
|
|
|
- name: Checkout repository
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: ${{ inputs.ref }}
|
|
fetch-depth: 1
|
|
token: ${{ steps.generate_token.outputs.token }}
|
|
|
|
- name: Configure git remote with token
|
|
run: git remote set-url origin "https://x-access-token:${{ steps.generate_token.outputs.token }}@github.com/${{ github.repository }}.git"
|
|
|
|
- name: Setup Node.js
|
|
uses: ./.github/actions/setup-nodejs
|
|
with:
|
|
build-command: ''
|
|
|
|
- name: Create working branch
|
|
run: |
|
|
BRANCH_NAME="claude/task-${{ github.run_id }}-${{ github.run_attempt }}"
|
|
echo "BRANCH_NAME=$BRANCH_NAME" >> "$GITHUB_ENV"
|
|
git checkout -b "$BRANCH_NAME"
|
|
|
|
- name: Configure git author
|
|
run: |
|
|
git config user.name "${{ github.actor }}"
|
|
git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
|
|
echo "Git author configured as: ${{ github.actor }}"
|
|
|
|
- name: Prepare Claude prompt
|
|
env:
|
|
INPUT_TASK: ${{ inputs.task }}
|
|
USE_RAW_PROMPT: ${{ inputs.use_raw_prompt }}
|
|
run: node .github/scripts/claude-task/prepare-claude-prompt.mjs
|
|
|
|
- name: Create MCP config
|
|
run: |
|
|
cat > /tmp/mcp-config.json << 'MCPEOF'
|
|
{
|
|
"mcpServers": {
|
|
"linear": {
|
|
"command": "npx",
|
|
"args": [
|
|
"-y",
|
|
"mcp-remote",
|
|
"https://mcp.linear.app/sse",
|
|
"--header",
|
|
"Authorization:${AUTH_HEADER}"
|
|
],
|
|
"env": {
|
|
"AUTH_HEADER": "Bearer MCP_LINEAR_API_KEY_PLACEHOLDER"
|
|
}
|
|
},
|
|
"notion": {
|
|
"command": "npx",
|
|
"args": ["-y", "@notionhq/notion-mcp-server"],
|
|
"env": {
|
|
"OPENAPI_MCP_HEADERS": "{\"Authorization\":\"Bearer MCP_NOTION_TOKEN_PLACEHOLDER\",\"Notion-Version\":\"2025-02-19\"}"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MCPEOF
|
|
sed -i "s|MCP_LINEAR_API_KEY_PLACEHOLDER|${{ secrets.MCP_LINEAR_API_KEY }}|g" /tmp/mcp-config.json
|
|
sed -i "s|MCP_NOTION_TOKEN_PLACEHOLDER|${{ secrets.MCP_NOTION_TOKEN }}|g" /tmp/mcp-config.json
|
|
|
|
- name: Run Claude
|
|
id: claude
|
|
continue-on-error: true
|
|
uses: anthropics/claude-code-action@d668cc452deb931732f24c6b1bbf24d97bc0c586 # v1
|
|
with:
|
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
github_token: ${{ steps.generate_token.outputs.token }}
|
|
prompt: ${{ env.CLAUDE_PROMPT }}
|
|
show_full_output: ${{ inputs.suppress_output != true }}
|
|
display_report: false
|
|
settings: |
|
|
{
|
|
"permissions": {
|
|
"allow": [
|
|
"Bash",
|
|
"Read",
|
|
"Write",
|
|
"Edit",
|
|
"Glob",
|
|
"Grep",
|
|
"WebFetch",
|
|
"WebSearch",
|
|
"TodoWrite",
|
|
"Skill",
|
|
"Task",
|
|
"mcp__linear__*",
|
|
"mcp__notion__*"
|
|
]
|
|
}
|
|
}
|
|
claude_args: |
|
|
--model ${{ inputs.model }} --max-turns ${{ inputs.max_turns }} --mcp-config /tmp/mcp-config.json
|
|
|
|
- name: Push branch
|
|
if: always()
|
|
env:
|
|
REF: ${{ inputs.ref }}
|
|
run: |
|
|
if ! git diff --quiet "$REF" 2>/dev/null; then
|
|
git push -u origin "$BRANCH_NAME"
|
|
echo "::notice::Changes pushed to branch $BRANCH_NAME"
|
|
else
|
|
echo "::notice::No changes to push."
|
|
fi
|
|
|
|
- name: Summary
|
|
if: always()
|
|
env:
|
|
CLAUDE_OUTCOME: ${{ steps.claude.outcome }}
|
|
CLAUDE_SESSION_ID: ${{ steps.claude.outputs.session_id }}
|
|
run: |
|
|
{
|
|
echo "## Claude Task Runner"
|
|
echo "**Branch:** ${BRANCH_NAME:-N/A}"
|
|
echo "**Claude outcome:** $CLAUDE_OUTCOME"
|
|
if [ -n "$CLAUDE_SESSION_ID" ]; then
|
|
echo "**Session ID:** \`$CLAUDE_SESSION_ID\`"
|
|
fi
|
|
} >> "$GITHUB_STEP_SUMMARY"
|
|
|
|
- name: Call resume url
|
|
if: always() && inputs.resumeUrl != ''
|
|
env:
|
|
RESUME_URL: ${{ inputs.resumeUrl }}
|
|
EXECUTION_FILE: ${{ steps.claude.outputs.execution_file }}
|
|
CLAUDE_OUTCOME: ${{ steps.claude.outcome }}
|
|
CLAUDE_SESSION_ID: ${{ steps.claude.outputs.session_id }}
|
|
run: node .github/scripts/claude-task/resume-callback.mjs
|
|
|
|
- name: Check final status
|
|
if: always()
|
|
run: |
|
|
if [ "${{ steps.claude.outcome }}" = "failure" ]; then
|
|
echo "::error::Claude task failed. Check the 'Run Claude' step logs for details."
|
|
exit 1
|
|
fi
|