handle-issue.sh 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #!/bin/bash
  2. # Script to handle issue automation with Claude Code
  3. # This script is called when an issue is opened or commented on
  4. # Ensure HOME is set (systemd might not set it)
  5. if [ -z "$HOME" ]; then
  6. export HOME=$(getent passwd "$(whoami)" | cut -d: -f6)
  7. fi
  8. # Add claude binary to PATH
  9. export PATH="$HOME/.local/bin:$PATH"
  10. # Ensure Claude Code has writable directories for cache and config
  11. export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
  12. export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
  13. export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
  14. export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
  15. # Create these directories if they don't exist
  16. mkdir -p "$XDG_CACHE_HOME" "$XDG_CONFIG_HOME" "$XDG_DATA_HOME" "$XDG_STATE_HOME"
  17. # Parse arguments
  18. OWNER="$1"
  19. REPO="$2"
  20. PUSHER="$3"
  21. ISSUE_NUMBER="$4"
  22. ISSUE_TITLE="$5"
  23. ISSUE_BODY="$6"
  24. ISSUE_ACTION="$7"
  25. COMMENT_BODY="$8"
  26. ASSIGNEE="$9"
  27. # Exit if pusher is claude (avoid loops)
  28. if [ "$PUSHER" = "claude" ]; then
  29. echo "Pusher is claude, skipping automation to avoid loops"
  30. exit 0
  31. fi
  32. # Exit if issue is not assigned to claude
  33. if [ "$ASSIGNEE" != "claude" ]; then
  34. echo "Issue not assigned to claude (assignee: $ASSIGNEE), skipping"
  35. exit 0
  36. fi
  37. # Determine repo path
  38. REPO_PATH="$HOME/$REPO"
  39. # Check if repo exists, if not clone it
  40. if [ ! -d "$REPO_PATH" ]; then
  41. echo "Repository not found at $REPO_PATH, cloning..."
  42. mkdir -p "$HOME"
  43. GIT_URL="ssh://git@207.154.220.231:10022/$OWNER/$REPO.git"
  44. git clone "$GIT_URL" "$REPO_PATH"
  45. if [ $? -ne 0 ]; then
  46. echo "Failed to clone repository"
  47. exit 1
  48. fi
  49. echo "Repository cloned successfully"
  50. else
  51. echo "Repository found at $REPO_PATH"
  52. # Pull latest changes
  53. cd "$REPO_PATH" || exit 1
  54. echo "Pulling latest changes..."
  55. # Try to pull, but don't fail if it errors (might be file system issues)
  56. if ! git pull 2>&1; then
  57. echo "Warning: git pull failed, continuing with existing repository state"
  58. fi
  59. fi
  60. # Change to repo directory
  61. cd "$REPO_PATH" || exit 1
  62. echo "Working directory: $(pwd)"
  63. # Build the prompt for Claude with instructions to use Gogs MCP tool
  64. if [ -n "$COMMENT_BODY" ]; then
  65. # Issue comment event - new comment was added
  66. PROMPT="IMPORTANT: A new comment has been added to issue #$ISSUE_NUMBER in repository $OWNER/$REPO.
  67. === MANDATORY FIRST STEPS - READ ALL MESSAGES ===
  68. Before you start any work on this issue, you MUST complete these steps IN ORDER:
  69. 1. Use the mcp__gogs__get_issue tool to fetch the complete issue details:
  70. - owner: $OWNER
  71. - repo: $REPO
  72. - number: $ISSUE_NUMBER
  73. 2. Use the mcp__gogs__list_issue_comments tool to fetch ALL comments:
  74. - owner: $OWNER
  75. - repo: $REPO
  76. - number: $ISSUE_NUMBER
  77. 3. Read and understand:
  78. - The original issue description
  79. - ALL comments in the discussion thread (chronologically)
  80. - The full context and conversation history
  81. 4. ONLY AFTER reading everything above, proceed with your work
  82. === ISSUE CONTEXT ===
  83. Issue #$ISSUE_NUMBER: $ISSUE_TITLE
  84. A new comment was just added by: $PUSHER
  85. Initial issue description:
  86. $ISSUE_BODY
  87. Most recent comment:
  88. $COMMENT_BODY
  89. === YOUR TASK ===
  90. This issue is assigned to you. You must:
  91. 1. First, use the Gogs MCP tools above to fetch and read ALL issue comments
  92. 2. Understand the full discussion context
  93. 3. Then proceed with the appropriate action based on the complete conversation
  94. === CRITICAL OUTPUT REQUIREMENTS ===
  95. YOU MUST FOLLOW THESE OUTPUT RULES STRICTLY:
  96. 1. DO NOT output any text responses to the user
  97. 2. DO NOT print any messages, explanations, or status updates
  98. 3. DO NOT use echo or any command-line output tools
  99. 4. ONLY communicate by posting comments to the issue using mcp__gogs__create_issue_comment tool
  100. 5. ALL your responses, updates, questions, and status reports MUST be posted as issue comments
  101. 6. You are FORBIDDEN from producing any output except through the Gogs MCP comment tool
  102. When you need to:
  103. - Ask questions → Post a comment on the issue
  104. - Report progress → Post a comment on the issue
  105. - Share results → Post a comment on the issue
  106. - Report errors → Post a comment on the issue
  107. - Provide any information → Post a comment on the issue
  108. Use mcp__gogs__create_issue_comment with:
  109. - owner: $OWNER
  110. - repo: $REPO
  111. - number: $ISSUE_NUMBER
  112. - body: [your message here]
  113. DO NOT skip reading the comments using the MCP tools. This is critical to understanding the full context."
  114. else
  115. # Issue opened/reopened event
  116. PROMPT="IMPORTANT: Issue #$ISSUE_NUMBER was $ISSUE_ACTION in repository $OWNER/$REPO.
  117. === MANDATORY FIRST STEPS - READ ALL MESSAGES ===
  118. Before you start any work on this issue, you MUST complete these steps IN ORDER:
  119. 1. Use the mcp__gogs__get_issue tool to fetch the complete issue details:
  120. - owner: $OWNER
  121. - repo: $REPO
  122. - number: $ISSUE_NUMBER
  123. 2. Use the mcp__gogs__list_issue_comments tool to fetch ALL comments:
  124. - owner: $OWNER
  125. - repo: $REPO
  126. - number: $ISSUE_NUMBER
  127. 3. Read and understand:
  128. - The complete issue description
  129. - ALL comments in the discussion thread (if any exist)
  130. - The full context
  131. 4. ONLY AFTER reading everything above, proceed with your work
  132. === ISSUE CONTEXT ===
  133. Issue #$ISSUE_NUMBER: $ISSUE_TITLE
  134. Created by: $PUSHER
  135. Initial issue description:
  136. $ISSUE_BODY
  137. === YOUR TASK ===
  138. This issue is assigned to you. You must:
  139. 1. First, use the Gogs MCP tools above to fetch and read the issue and ALL comments
  140. 2. Understand the full discussion context (even if there are no comments yet)
  141. 3. Then proceed with the appropriate action
  142. === CRITICAL OUTPUT REQUIREMENTS ===
  143. YOU MUST FOLLOW THESE OUTPUT RULES STRICTLY:
  144. 1. DO NOT output any text responses to the user
  145. 2. DO NOT print any messages, explanations, or status updates
  146. 3. DO NOT use echo or any command-line output tools
  147. 4. ONLY communicate by posting comments to the issue using mcp__gogs__create_issue_comment tool
  148. 5. ALL your responses, updates, questions, and status reports MUST be posted as issue comments
  149. 6. You are FORBIDDEN from producing any output except through the Gogs MCP comment tool
  150. When you need to:
  151. - Ask questions → Post a comment on the issue
  152. - Report progress → Post a comment on the issue
  153. - Share results → Post a comment on the issue
  154. - Report errors → Post a comment on the issue
  155. - Provide any information → Post a comment on the issue
  156. Use mcp__gogs__create_issue_comment with:
  157. - owner: $OWNER
  158. - repo: $REPO
  159. - number: $ISSUE_NUMBER
  160. - body: [your message here]
  161. DO NOT skip reading the comments using the MCP tools. This is critical to understanding the full context."
  162. fi
  163. echo "Calling Claude Code with the issue information..."
  164. echo "---"
  165. # Call claude with the prompt in non-interactive mode
  166. # -p / --print: Non-interactive mode, prints output and exits
  167. # --output-format json: Get structured JSON output for programmatic parsing
  168. # --dangerously-skip-permissions: Skip all permission prompts (safe in controlled environment)
  169. # This allows Claude to run unattended without waiting for user input
  170. OUTPUT=$(claude -p "$PROMPT" --output-format json --dangerously-skip-permissions 2>&1)
  171. EXIT_CODE=$?
  172. echo "---"
  173. echo "Claude Code execution completed (exit code: $EXIT_CODE)"
  174. # Log the output for debugging
  175. if [ $EXIT_CODE -eq 0 ]; then
  176. echo "Claude response received successfully"
  177. # Parse JSON output to check for errors or important info
  178. if command -v jq &> /dev/null; then
  179. echo "Session details:"
  180. echo "$OUTPUT" | jq -r '.sessionId, .cost, .duration' 2>/dev/null || echo "$OUTPUT"
  181. else
  182. echo "Output (first 500 chars): ${OUTPUT:0:500}"
  183. fi
  184. else
  185. echo "Error: Claude Code failed with exit code $EXIT_CODE"
  186. echo "Output: $OUTPUT"
  187. fi
  188. exit $EXIT_CODE