handle-issue.sh.deprecated 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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. # Load .env file to get GOGS_MCP_PATH
  64. if [ -f "$REPO_PATH/.env" ]; then
  65. export $(grep -v '^#' "$REPO_PATH/.env" | grep GOGS_MCP_PATH | xargs)
  66. fi
  67. # Set default GOGS_MCP_PATH if not set
  68. GOGS_MCP_PATH="${GOGS_MCP_PATH:-/data/gogs-mcp/dist/index.js}"
  69. # Generate MCP config file dynamically with environment-specific path
  70. cat > "$REPO_PATH/.mcp-gogs.json" <<EOF
  71. {
  72. "mcpServers": {
  73. "gogs": {
  74. "type": "stdio",
  75. "command": "node",
  76. "args": [
  77. "$GOGS_MCP_PATH"
  78. ],
  79. "env": {}
  80. }
  81. }
  82. }
  83. EOF
  84. echo "Generated MCP config with path: $GOGS_MCP_PATH"
  85. # Build the prompt for Claude with instructions to use Gogs MCP tool
  86. if [ -n "$COMMENT_BODY" ]; then
  87. # Issue comment event - new comment was added
  88. PROMPT="IMPORTANT: A new comment has been added to issue #$ISSUE_NUMBER in repository $OWNER/$REPO.
  89. === MANDATORY FIRST STEPS - READ ALL MESSAGES ===
  90. Before you start any work on this issue, you MUST complete these steps IN ORDER:
  91. 1. Use the mcp__gogs__get_issue tool to fetch the complete issue details:
  92. - owner: $OWNER
  93. - repo: $REPO
  94. - number: $ISSUE_NUMBER
  95. 2. Use the mcp__gogs__list_issue_comments tool to fetch ALL comments:
  96. - owner: $OWNER
  97. - repo: $REPO
  98. - number: $ISSUE_NUMBER
  99. 3. Read and understand:
  100. - The original issue description
  101. - ALL comments in the discussion thread (chronologically)
  102. - The full context and conversation history
  103. 4. ONLY AFTER reading everything above, proceed with your work
  104. === ISSUE CONTEXT ===
  105. Issue #$ISSUE_NUMBER: $ISSUE_TITLE
  106. A new comment was just added by: $PUSHER
  107. Initial issue description:
  108. $ISSUE_BODY
  109. Most recent comment:
  110. $COMMENT_BODY
  111. === YOUR TASK ===
  112. This issue is assigned to you. You must:
  113. 1. First, use the Gogs MCP tools above to fetch and read ALL issue comments
  114. 2. Understand the full discussion context
  115. 3. Then proceed with the appropriate action based on the complete conversation
  116. === CRITICAL OUTPUT REQUIREMENTS ===
  117. YOU MUST FOLLOW THESE OUTPUT RULES STRICTLY:
  118. 1. DO NOT output any text responses to the user
  119. 2. DO NOT print any messages, explanations, or status updates
  120. 3. DO NOT use echo or any command-line output tools
  121. 4. ONLY communicate by posting comments to the issue using mcp__gogs__create_issue_comment tool
  122. 5. ALL your responses, updates, questions, and status reports MUST be posted as issue comments
  123. 6. You are FORBIDDEN from producing any output except through the Gogs MCP comment tool
  124. When you need to:
  125. - Ask questions → Post a comment on the issue
  126. - Report progress → Post a comment on the issue
  127. - Share results → Post a comment on the issue
  128. - Report errors → Post a comment on the issue
  129. - Provide any information → Post a comment on the issue
  130. Use mcp__gogs__create_issue_comment with:
  131. - owner: $OWNER
  132. - repo: $REPO
  133. - number: $ISSUE_NUMBER
  134. - body: [your message here]
  135. DO NOT skip reading the comments using the MCP tools. This is critical to understanding the full context."
  136. else
  137. # Issue opened/reopened event
  138. PROMPT="IMPORTANT: Issue #$ISSUE_NUMBER was $ISSUE_ACTION in repository $OWNER/$REPO.
  139. === MANDATORY FIRST STEPS - READ ALL MESSAGES ===
  140. Before you start any work on this issue, you MUST complete these steps IN ORDER:
  141. 1. Use the mcp__gogs__get_issue tool to fetch the complete issue details:
  142. - owner: $OWNER
  143. - repo: $REPO
  144. - number: $ISSUE_NUMBER
  145. 2. Use the mcp__gogs__list_issue_comments tool to fetch ALL comments:
  146. - owner: $OWNER
  147. - repo: $REPO
  148. - number: $ISSUE_NUMBER
  149. 3. Read and understand:
  150. - The complete issue description
  151. - ALL comments in the discussion thread (if any exist)
  152. - The full context
  153. 4. ONLY AFTER reading everything above, proceed with your work
  154. === ISSUE CONTEXT ===
  155. Issue #$ISSUE_NUMBER: $ISSUE_TITLE
  156. Created by: $PUSHER
  157. Initial issue description:
  158. $ISSUE_BODY
  159. === YOUR TASK ===
  160. This issue is assigned to you. You must:
  161. 1. First, use the Gogs MCP tools above to fetch and read the issue and ALL comments
  162. 2. Understand the full discussion context (even if there are no comments yet)
  163. 3. Then proceed with the appropriate action
  164. === CRITICAL OUTPUT REQUIREMENTS ===
  165. YOU MUST FOLLOW THESE OUTPUT RULES STRICTLY:
  166. 1. DO NOT output any text responses to the user
  167. 2. DO NOT print any messages, explanations, or status updates
  168. 3. DO NOT use echo or any command-line output tools
  169. 4. ONLY communicate by posting comments to the issue using mcp__gogs__create_issue_comment tool
  170. 5. ALL your responses, updates, questions, and status reports MUST be posted as issue comments
  171. 6. You are FORBIDDEN from producing any output except through the Gogs MCP comment tool
  172. When you need to:
  173. - Ask questions → Post a comment on the issue
  174. - Report progress → Post a comment on the issue
  175. - Share results → Post a comment on the issue
  176. - Report errors → Post a comment on the issue
  177. - Provide any information → Post a comment on the issue
  178. Use mcp__gogs__create_issue_comment with:
  179. - owner: $OWNER
  180. - repo: $REPO
  181. - number: $ISSUE_NUMBER
  182. - body: [your message here]
  183. DO NOT skip reading the comments using the MCP tools. This is critical to understanding the full context."
  184. fi
  185. echo "Calling Claude Code with the issue information..."
  186. echo "---"
  187. # Call claude with the prompt in non-interactive mode
  188. # -p / --print: Non-interactive mode, prints output and exits
  189. # --output-format json: Get structured JSON output for programmatic parsing
  190. # --mcp-config: Load MCP servers from config file (enables gogs MCP tools)
  191. # --allowedTools: Enable specific tools (all gogs MCP tools and essential file tools)
  192. # User tools: get_current_user, get_user, search_users
  193. # Repository tools: list_user_repositories, search_repositories, get_repository, create_repository, delete_repository
  194. # Content tools: get_contents, get_raw_content, list_branches, get_commits
  195. # Issue tools: list_issues, get_issue, create_issue, update_issue, list_issue_comments, create_issue_comment, update_issue_comment
  196. # --dangerously-skip-permissions: Skip all permission prompts (safe in controlled environment)
  197. # This allows Claude to run unattended without waiting for user input
  198. OUTPUT=$(claude -p "$PROMPT" \
  199. --output-format json \
  200. --mcp-config "$REPO_PATH/.mcp-gogs.json" \
  201. --allowedTools "mcp__gogs__get_current_user,mcp__gogs__get_user,mcp__gogs__search_users,mcp__gogs__list_user_repositories,mcp__gogs__search_repositories,mcp__gogs__get_repository,mcp__gogs__create_repository,mcp__gogs__delete_repository,mcp__gogs__get_contents,mcp__gogs__get_raw_content,mcp__gogs__list_branches,mcp__gogs__get_commits,mcp__gogs__list_issues,mcp__gogs__get_issue,mcp__gogs__create_issue,mcp__gogs__update_issue,mcp__gogs__list_issue_comments,mcp__gogs__create_issue_comment,mcp__gogs__update_issue_comment,Read,Write,Edit,Bash,Grep,Glob,TodoWrite" \
  202. --dangerously-skip-permissions 2>&1)
  203. EXIT_CODE=$?
  204. echo "---"
  205. echo "Claude Code execution completed (exit code: $EXIT_CODE)"
  206. # Log the output for debugging
  207. if [ $EXIT_CODE -eq 0 ]; then
  208. echo "Claude response received successfully"
  209. # Parse JSON output to check for errors or important info
  210. if command -v jq &> /dev/null; then
  211. echo "Session details:"
  212. echo "$OUTPUT" | jq -r '.sessionId, .cost, .duration' 2>/dev/null || echo "$OUTPUT"
  213. else
  214. echo "Output (first 500 chars): ${OUTPUT:0:500}"
  215. fi
  216. else
  217. echo "Error: Claude Code failed with exit code $EXIT_CODE"
  218. echo "Output: $OUTPUT"
  219. fi
  220. exit $EXIT_CODE