| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- #!/bin/bash
- # Script to handle issue automation with Claude Code
- # This script is called when an issue is opened or commented on
- # Ensure HOME is set (systemd might not set it)
- if [ -z "$HOME" ]; then
- export HOME=$(getent passwd "$(whoami)" | cut -d: -f6)
- fi
- # Add claude binary to PATH
- export PATH="$HOME/.local/bin:$PATH"
- # Ensure Claude Code has writable directories for cache and config
- export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
- export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
- export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
- export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
- # Create these directories if they don't exist
- mkdir -p "$XDG_CACHE_HOME" "$XDG_CONFIG_HOME" "$XDG_DATA_HOME" "$XDG_STATE_HOME"
- # Parse arguments
- OWNER="$1"
- REPO="$2"
- PUSHER="$3"
- ISSUE_NUMBER="$4"
- ISSUE_TITLE="$5"
- ISSUE_BODY="$6"
- ISSUE_ACTION="$7"
- COMMENT_BODY="$8"
- ASSIGNEE="$9"
- # Exit if pusher is claude (avoid loops)
- if [ "$PUSHER" = "claude" ]; then
- echo "Pusher is claude, skipping automation to avoid loops"
- exit 0
- fi
- # Exit if issue is not assigned to claude
- if [ "$ASSIGNEE" != "claude" ]; then
- echo "Issue not assigned to claude (assignee: $ASSIGNEE), skipping"
- exit 0
- fi
- # Determine repo path
- REPO_PATH="$HOME/$REPO"
- # Check if repo exists, if not clone it
- if [ ! -d "$REPO_PATH" ]; then
- echo "Repository not found at $REPO_PATH, cloning..."
- mkdir -p "$HOME"
- GIT_URL="ssh://git@207.154.220.231:10022/$OWNER/$REPO.git"
- git clone "$GIT_URL" "$REPO_PATH"
- if [ $? -ne 0 ]; then
- echo "Failed to clone repository"
- exit 1
- fi
- echo "Repository cloned successfully"
- else
- echo "Repository found at $REPO_PATH"
- # Pull latest changes
- cd "$REPO_PATH" || exit 1
- echo "Pulling latest changes..."
- # Try to pull, but don't fail if it errors (might be file system issues)
- if ! git pull 2>&1; then
- echo "Warning: git pull failed, continuing with existing repository state"
- fi
- fi
- # Change to repo directory
- cd "$REPO_PATH" || exit 1
- echo "Working directory: $(pwd)"
- # Load .env file to get GOGS_MCP_PATH
- if [ -f "$REPO_PATH/.env" ]; then
- export $(grep -v '^#' "$REPO_PATH/.env" | grep GOGS_MCP_PATH | xargs)
- fi
- # Set default GOGS_MCP_PATH if not set
- GOGS_MCP_PATH="${GOGS_MCP_PATH:-/data/gogs-mcp/dist/index.js}"
- # Generate MCP config file dynamically with environment-specific path
- cat > "$REPO_PATH/.mcp-gogs.json" <<EOF
- {
- "mcpServers": {
- "gogs": {
- "type": "stdio",
- "command": "node",
- "args": [
- "$GOGS_MCP_PATH"
- ],
- "env": {}
- }
- }
- }
- EOF
- echo "Generated MCP config with path: $GOGS_MCP_PATH"
- # Build the prompt for Claude with instructions to use Gogs MCP tool
- if [ -n "$COMMENT_BODY" ]; then
- # Issue comment event - new comment was added
- PROMPT="IMPORTANT: A new comment has been added to issue #$ISSUE_NUMBER in repository $OWNER/$REPO.
- === MANDATORY FIRST STEPS - READ ALL MESSAGES ===
- Before you start any work on this issue, you MUST complete these steps IN ORDER:
- 1. Use the mcp__gogs__get_issue tool to fetch the complete issue details:
- - owner: $OWNER
- - repo: $REPO
- - number: $ISSUE_NUMBER
- 2. Use the mcp__gogs__list_issue_comments tool to fetch ALL comments:
- - owner: $OWNER
- - repo: $REPO
- - number: $ISSUE_NUMBER
- 3. Read and understand:
- - The original issue description
- - ALL comments in the discussion thread (chronologically)
- - The full context and conversation history
- 4. ONLY AFTER reading everything above, proceed with your work
- === ISSUE CONTEXT ===
- Issue #$ISSUE_NUMBER: $ISSUE_TITLE
- A new comment was just added by: $PUSHER
- Initial issue description:
- $ISSUE_BODY
- Most recent comment:
- $COMMENT_BODY
- === YOUR TASK ===
- This issue is assigned to you. You must:
- 1. First, use the Gogs MCP tools above to fetch and read ALL issue comments
- 2. Understand the full discussion context
- 3. Then proceed with the appropriate action based on the complete conversation
- === CRITICAL OUTPUT REQUIREMENTS ===
- YOU MUST FOLLOW THESE OUTPUT RULES STRICTLY:
- 1. DO NOT output any text responses to the user
- 2. DO NOT print any messages, explanations, or status updates
- 3. DO NOT use echo or any command-line output tools
- 4. ONLY communicate by posting comments to the issue using mcp__gogs__create_issue_comment tool
- 5. ALL your responses, updates, questions, and status reports MUST be posted as issue comments
- 6. You are FORBIDDEN from producing any output except through the Gogs MCP comment tool
- When you need to:
- - Ask questions → Post a comment on the issue
- - Report progress → Post a comment on the issue
- - Share results → Post a comment on the issue
- - Report errors → Post a comment on the issue
- - Provide any information → Post a comment on the issue
- Use mcp__gogs__create_issue_comment with:
- - owner: $OWNER
- - repo: $REPO
- - number: $ISSUE_NUMBER
- - body: [your message here]
- DO NOT skip reading the comments using the MCP tools. This is critical to understanding the full context."
- else
- # Issue opened/reopened event
- PROMPT="IMPORTANT: Issue #$ISSUE_NUMBER was $ISSUE_ACTION in repository $OWNER/$REPO.
- === MANDATORY FIRST STEPS - READ ALL MESSAGES ===
- Before you start any work on this issue, you MUST complete these steps IN ORDER:
- 1. Use the mcp__gogs__get_issue tool to fetch the complete issue details:
- - owner: $OWNER
- - repo: $REPO
- - number: $ISSUE_NUMBER
- 2. Use the mcp__gogs__list_issue_comments tool to fetch ALL comments:
- - owner: $OWNER
- - repo: $REPO
- - number: $ISSUE_NUMBER
- 3. Read and understand:
- - The complete issue description
- - ALL comments in the discussion thread (if any exist)
- - The full context
- 4. ONLY AFTER reading everything above, proceed with your work
- === ISSUE CONTEXT ===
- Issue #$ISSUE_NUMBER: $ISSUE_TITLE
- Created by: $PUSHER
- Initial issue description:
- $ISSUE_BODY
- === YOUR TASK ===
- This issue is assigned to you. You must:
- 1. First, use the Gogs MCP tools above to fetch and read the issue and ALL comments
- 2. Understand the full discussion context (even if there are no comments yet)
- 3. Then proceed with the appropriate action
- === CRITICAL OUTPUT REQUIREMENTS ===
- YOU MUST FOLLOW THESE OUTPUT RULES STRICTLY:
- 1. DO NOT output any text responses to the user
- 2. DO NOT print any messages, explanations, or status updates
- 3. DO NOT use echo or any command-line output tools
- 4. ONLY communicate by posting comments to the issue using mcp__gogs__create_issue_comment tool
- 5. ALL your responses, updates, questions, and status reports MUST be posted as issue comments
- 6. You are FORBIDDEN from producing any output except through the Gogs MCP comment tool
- When you need to:
- - Ask questions → Post a comment on the issue
- - Report progress → Post a comment on the issue
- - Share results → Post a comment on the issue
- - Report errors → Post a comment on the issue
- - Provide any information → Post a comment on the issue
- Use mcp__gogs__create_issue_comment with:
- - owner: $OWNER
- - repo: $REPO
- - number: $ISSUE_NUMBER
- - body: [your message here]
- DO NOT skip reading the comments using the MCP tools. This is critical to understanding the full context."
- fi
- echo "Calling Claude Code with the issue information..."
- echo "---"
- # Call claude with the prompt in non-interactive mode
- # -p / --print: Non-interactive mode, prints output and exits
- # --output-format json: Get structured JSON output for programmatic parsing
- # --mcp-config: Load MCP servers from config file (enables gogs MCP tools)
- # --allowedTools: Enable specific tools (MCP Gogs server and file tools)
- # --dangerously-skip-permissions: Skip all permission prompts (safe in controlled environment)
- # This allows Claude to run unattended without waiting for user input
- OUTPUT=$(claude -p "$PROMPT" \
- --output-format json \
- --mcp-config "$REPO_PATH/.mcp-gogs.json" \
- --allowedTools "mcp__gogs,Read,Write,Edit,Bash,Grep,Glob,TodoWrite" \
- --dangerously-skip-permissions 2>&1)
- EXIT_CODE=$?
- echo "---"
- echo "Claude Code execution completed (exit code: $EXIT_CODE)"
- # Log the output for debugging
- if [ $EXIT_CODE -eq 0 ]; then
- echo "Claude response received successfully"
- # Parse JSON output to check for errors or important info
- if command -v jq &> /dev/null; then
- echo "Session details:"
- echo "$OUTPUT" | jq -r '.sessionId, .cost, .duration' 2>/dev/null || echo "$OUTPUT"
- else
- echo "Output (first 500 chars): ${OUTPUT:0:500}"
- fi
- else
- echo "Error: Claude Code failed with exit code $EXIT_CODE"
- echo "Output: $OUTPUT"
- fi
- exit $EXIT_CODE
|