vault backup: 2026-04-14 20:51:59
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
"permissionMode": "yolo",
|
||||
"model": "opus[1m]",
|
||||
"thinkingBudget": "medium",
|
||||
"effortLevel": "high",
|
||||
"effortLevel": "low",
|
||||
"serviceTier": "default",
|
||||
"enableAutoTitleGeneration": true,
|
||||
"titleGenerationModel": "",
|
||||
@@ -53,7 +53,7 @@
|
||||
"claude": "opus[1m]"
|
||||
},
|
||||
"savedProviderEffort": {
|
||||
"claude": "high"
|
||||
"claude": "low"
|
||||
},
|
||||
"savedProviderServiceTier": {},
|
||||
"savedProviderThinkingBudget": {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
"title": "Greet user in Chinese",
|
||||
"titleGenerationStatus": "success",
|
||||
"createdAt": 1776071385957,
|
||||
"updatedAt": 1776073391615,
|
||||
"lastResponseAt": 1776073391615,
|
||||
"updatedAt": 1776169327308,
|
||||
"lastResponseAt": 1776169327308,
|
||||
"sessionId": "c432006f-72f1-4f80-9625-7cb62e468878",
|
||||
"providerState": {
|
||||
"providerSessionId": "c432006f-72f1-4f80-9625-7cb62e468878"
|
||||
@@ -14,10 +14,10 @@
|
||||
"usage": {
|
||||
"model": "opus[1m]",
|
||||
"inputTokens": 1,
|
||||
"cacheCreationInputTokens": 114,
|
||||
"cacheReadInputTokens": 35166,
|
||||
"cacheCreationInputTokens": 1118,
|
||||
"cacheReadInputTokens": 36301,
|
||||
"contextWindow": 1000000,
|
||||
"contextTokens": 35281,
|
||||
"contextTokens": 37420,
|
||||
"percentage": 4,
|
||||
"contextWindowIsAuthoritative": true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,690 @@
|
||||
|
||||
|
||||
> 本文记录了在 GitLab 项目中集成 Claude Code CLI,实现"给 Issue 打标签即可自动修复 Bug"的完整方案与实践过程。
|
||||
|
||||
---
|
||||
|
||||
## 目录
|
||||
|
||||
- [方案概述](#方案概述)
|
||||
- [整体架构](#整体架构)
|
||||
- [前置条件](#前置条件)
|
||||
- [第一步:配置 CI/CD Variables](#第一步配置-cicd-variables)
|
||||
- [第二步:创建 Pipeline Trigger Token](#第二步创建-pipeline-trigger-token)
|
||||
- [第三步:编写 .gitlab-ci.yml](#第三步编写-gitlab-ciyml)
|
||||
- [Job 1: claude:scan-issues — 扫描 Issue](#job-1-claudescan-issues--扫描-issue)
|
||||
- [Job 2: claude:fix-issue — 执行修复](#job-2-claudefix-issue--执行修复)
|
||||
- [第四步:创建定时调度](#第四步创建定时调度)
|
||||
- [第五步:编写 CLAUDE.md 项目指南](#第五步编写-claudemd-项目指南)
|
||||
- [使用流程](#使用流程)
|
||||
- [手动触发脚本](#手动触发脚本)
|
||||
- [关键设计细节](#关键设计细节)
|
||||
- [踩坑记录与调试经验](#踩坑记录与调试经验)
|
||||
- [完整 .gitlab-ci.yml 参考](#完整-gitlab-ciyml-参考)
|
||||
|
||||
---
|
||||
|
||||
## 方案概述
|
||||
|
||||
核心思路:利用 GitLab CI/CD 的 **Schedule(定时调度)** + **Trigger(触发器)** 机制,定时扫描带有 `auto-fix` 标签的 Issue,自动启动 Claude Code CLI 分析代码、修复 Bug、提交代码并在 Issue 上回复修复摘要。
|
||||
|
||||
**一句话流程**:开发者给 Issue 打上 `auto-fix` 标签 → 定时任务自动触发 → Claude Code 读取 Issue、分析代码、实施修复 → 自动 commit & push → 在 Issue 评论中报告结果。
|
||||
|
||||
---
|
||||
|
||||
## 整体架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ GitLab 项目 │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────────────┐ ┌───────────────────┐ │
|
||||
│ │ Issue │ │ Schedule (定时) │ │ Trigger Pipeline │ │
|
||||
│ │ auto-fix │───▶│ claude:scan-issues│───▶│ claude:fix-issue │ │
|
||||
│ │ 标签 │ │ (alpine:3.19) │ │ (node:20) │ │
|
||||
│ └──────────┘ └──────────────────┘ └─────────┬─────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────▼─────────┐ │
|
||||
│ │ Claude Code CLI │ │
|
||||
│ │ (npm i -g 安装) │ │
|
||||
│ │ │ │
|
||||
│ │ 1. 读取 Issue 详情 │ │
|
||||
│ │ 2. 分析项目代码 │ │
|
||||
│ │ 3. 实施修复 │ │
|
||||
│ │ 4. 验证类型检查 │ │
|
||||
│ │ 5. 提交 & 推送 │ │
|
||||
│ │ 6. 评论 Issue │ │
|
||||
│ └─────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 标签状态机
|
||||
|
||||
Issue 通过标签流转追踪处理状态,确保不会被重复处理:
|
||||
|
||||
```
|
||||
auto-fix ──▶ claude-processing ──▶ claude-done
|
||||
(用户添加) (扫描时切换) (修复完成后设置)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 前置条件
|
||||
|
||||
| 条件 | 说明 |
|
||||
|------|------|
|
||||
| GitLab 实例 | 需要支持 CI/CD Schedules 和 Pipeline Triggers |
|
||||
| Runner | 可执行 Docker 镜像的 GitLab Runner |
|
||||
| Anthropic API 访问 | 直接使用 Anthropic API 或通过内部代理 |
|
||||
| GitLab Personal Access Token | 需要 `api` scope,用于操作 Issue 和推送代码 |
|
||||
|
||||
---
|
||||
|
||||
## 第一步:配置 CI/CD Variables
|
||||
|
||||
进入 GitLab 项目 → **Settings → CI/CD → Variables**,添加以下变量:
|
||||
|
||||
| 变量名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `GITLAB_ACCESS_TOKEN` | Masked | Personal Access Token(api scope),扫描 Job 使用 |
|
||||
| `ANTHROPIC_AUTH_TOKEN` | Masked | Anthropic API Key(或内部代理的 auth token) |
|
||||
| `TRIGGER_TOKEN` | 见下一步 | Pipeline 触发器 Token |
|
||||
|
||||
> **安全提示**:`GITLAB_ACCESS_TOKEN` 和 `ANTHROPIC_AUTH_TOKEN` 务必勾选 **Masked**,防止在日志中泄露。
|
||||
|
||||
### 关于 Anthropic API 访问
|
||||
|
||||
如果你直接使用 Anthropic 官方 API,需要设置:
|
||||
- `ANTHROPIC_AUTH_TOKEN` = 你的 Anthropic API Key
|
||||
|
||||
如果使用内部代理(如本项目使用 `openai.nie.netease.com`),则在 CI Job 中通过环境变量指定:
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
ANTHROPIC_BASE_URL: "https://openai.nie.netease.com" # 内部代理地址
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第二步:创建 Pipeline Trigger Token
|
||||
|
||||
进入 **Settings → CI/CD → Pipeline trigger tokens**,点击 **Add trigger** 创建一个触发器。
|
||||
|
||||
创建后会得到一个 Token,将其记录下来。扫描 Job 将用此 Token 触发修复 Pipeline。
|
||||
|
||||
将该 Token 设置为 CI/CD Variable `TRIGGER_TOKEN`。
|
||||
|
||||
---
|
||||
|
||||
## 第三步:编写 .gitlab-ci.yml
|
||||
|
||||
在 `.gitlab-ci.yml` 中添加 `ai_fix` Stage 和两个 Job。
|
||||
|
||||
### Job 1: claude:scan-issues — 扫描 Issue
|
||||
|
||||
这是一个轻量级 Job,使用 `alpine:3.19` 镜像,只做 API 调用:
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
- ai_fix
|
||||
|
||||
claude:scan-issues:
|
||||
stage: ai_fix
|
||||
image: alpine:3.19
|
||||
before_script:
|
||||
- apk add --no-cache curl jq
|
||||
script:
|
||||
- |
|
||||
echo "Scanning for Issues with label 'auto-fix'..."
|
||||
|
||||
# 校验必要变量
|
||||
for var in GITLAB_ACCESS_TOKEN TRIGGER_TOKEN ANTHROPIC_AUTH_TOKEN; do
|
||||
eval "val=\$$var"
|
||||
if [ -z "$val" ]; then
|
||||
echo "ERROR: $var is not set."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# 查询带 auto-fix 标签的 Issue,排除已处理的
|
||||
ISSUES=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues?labels=auto-fix¬%5Blabels%5D=claude-processing,claude-done&state=opened&per_page=10")
|
||||
|
||||
COUNT=$(echo "$ISSUES" | jq 'length')
|
||||
echo "Found $COUNT issue(s) with 'auto-fix' label."
|
||||
|
||||
if [ "$COUNT" -eq 0 ] || [ "$COUNT" = "null" ]; then
|
||||
echo "Nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 逐个处理
|
||||
echo "$ISSUES" | jq -r '.[].iid' | while read -r IID; do
|
||||
TITLE=$(echo "$ISSUES" | jq -r ".[] | select(.iid == $IID) | .title")
|
||||
echo ">>> Triggering fix for Issue #${IID}: ${TITLE}"
|
||||
|
||||
# 1) 切换标签: auto-fix → claude-processing
|
||||
curl -s --request PUT \
|
||||
--header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{\"remove_labels\": \"auto-fix\", \"add_labels\": \"claude-processing\"}" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$IID" > /dev/null
|
||||
|
||||
# 2) 通过 Trigger API 触发修复 Pipeline
|
||||
curl -s -X POST \
|
||||
--form "token=${TRIGGER_TOKEN}" \
|
||||
--form "ref=${CI_DEFAULT_BRANCH}" \
|
||||
--form "variables[ISSUE_IID]=${IID}" \
|
||||
--form "variables[GITLAB_TOKEN]=${GITLAB_ACCESS_TOKEN}" \
|
||||
--form "variables[ANTHROPIC_AUTH_TOKEN]=${ANTHROPIC_AUTH_TOKEN}" \
|
||||
"https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/trigger/pipeline"
|
||||
done
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule"' # 定时触发
|
||||
- if: '$CI_PIPELINE_SOURCE == "web"' # 手动触发
|
||||
when: manual
|
||||
allow_failure: true
|
||||
timeout: 5m
|
||||
```
|
||||
|
||||
**核心逻辑**:
|
||||
1. 通过 GitLab Issues API 查询 `labels=auto-fix` 且排除 `claude-processing` 和 `claude-done` 的 Issue
|
||||
2. 对每个 Issue 切换标签(防止重复处理)
|
||||
3. 通过 Pipeline Trigger API 启动独立的修复 Pipeline,传入 `ISSUE_IID`、`GITLAB_TOKEN`、`ANTHROPIC_AUTH_TOKEN`
|
||||
|
||||
### Job 2: claude:fix-issue — 执行修复
|
||||
|
||||
这是核心修复 Job,使用 `node:20` 镜像,安装并运行 Claude Code:
|
||||
|
||||
```yaml
|
||||
claude:fix-issue:
|
||||
stage: ai_fix
|
||||
image: node:20
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
GIT_DEPTH: 0 # 完整克隆,Claude 需要完整历史
|
||||
ANTHROPIC_BASE_URL: "https://api.anthropic.com" # 或内部代理地址
|
||||
ANTHROPIC_MODEL: "claude-sonnet-4-6"
|
||||
DISABLE_AUTOUPDATER: "1" # 禁止 Claude Code 自动更新
|
||||
DISABLE_PROMPT_CACHING: "1"
|
||||
before_script:
|
||||
- apt-get update && apt-get install -y git curl jq
|
||||
- npm install -g @anthropic-ai/claude-code
|
||||
- git config --global user.email "claude-bot@example.com"
|
||||
- git config --global user.name "Claude AI Bot"
|
||||
script:
|
||||
- |
|
||||
# Step 1: 获取 Issue 详情
|
||||
if [ -z "$ISSUE_IID" ]; then
|
||||
echo "ERROR: ISSUE_IID variable is required."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ISSUE_JSON=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID")
|
||||
|
||||
ISSUE_TITLE=$(echo "$ISSUE_JSON" | jq -r '.title // empty')
|
||||
ISSUE_DESCRIPTION=$(echo "$ISSUE_JSON" | jq -r '.description // empty')
|
||||
|
||||
if [ -z "$ISSUE_TITLE" ]; then
|
||||
echo "ERROR: Could not fetch Issue #$ISSUE_IID"
|
||||
exit 1
|
||||
fi
|
||||
echo "Processing Issue #${ISSUE_IID}: ${ISSUE_TITLE}"
|
||||
- |
|
||||
# Step 2: 切换到主分支
|
||||
git checkout "$CI_DEFAULT_BRANCH"
|
||||
git pull origin "$CI_DEFAULT_BRANCH"
|
||||
- |
|
||||
# Step 3: 运行 Claude Code
|
||||
export ANTHROPIC_API_KEY="${ANTHROPIC_AUTH_TOKEN}"
|
||||
|
||||
PROMPT="你是一个代码修复助手。请分析并修复以下 GitLab Issue:
|
||||
|
||||
## Issue #${ISSUE_IID}: ${ISSUE_TITLE}
|
||||
|
||||
${ISSUE_DESCRIPTION}
|
||||
|
||||
请:
|
||||
1. 分析项目代码,定位问题根因
|
||||
2. 实施修复
|
||||
3. 确保代码能通过类型检查(TypeScript 项目运行 npx tsc --noEmit)
|
||||
4. 用中文输出修复摘要(包括修改了哪些文件、改了什么、为什么这样改)
|
||||
|
||||
项目根目录已准备就绪。"
|
||||
|
||||
RESULT=$(claude -p "$PROMPT" \
|
||||
--bare \
|
||||
--permission-mode acceptEdits \
|
||||
--allowedTools "Bash,Read,Edit,Write,Glob,Grep" \
|
||||
--max-turns 30 \
|
||||
--output-format text \
|
||||
2>&1) || true
|
||||
|
||||
echo "$RESULT" > repair_summary.txt
|
||||
- |
|
||||
# Step 4: 提交并推送
|
||||
git add -A
|
||||
git reset -- repair_summary.txt claude_stderr.txt 2>/dev/null || true
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo "No file changes detected."
|
||||
COMMIT_STATUS="no_changes"
|
||||
else
|
||||
git commit -m "fix(auto): resolve Issue #${ISSUE_IID} - ${ISSUE_TITLE} [skip ci]"
|
||||
git push "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" \
|
||||
HEAD:"$CI_DEFAULT_BRANCH"
|
||||
COMMIT_STATUS="pushed"
|
||||
fi
|
||||
- |
|
||||
# Step 5: 在 Issue 上发表评论
|
||||
SUMMARY=$(cat repair_summary.txt | head -200 | \
|
||||
sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
|
||||
if [ "$COMMIT_STATUS" = "pushed" ]; then
|
||||
BODY="## ✅ Claude Code 自动修复完成\n\n修复已推送到 \`${CI_DEFAULT_BRANCH}\`。\n\nPipeline: ${CI_PIPELINE_URL}\n\n<details><summary>修复详情</summary>\n\n\`\`\`\n${SUMMARY}\n\`\`\`\n</details>"
|
||||
else
|
||||
BODY="## ⚠️ Claude Code 分析完成\n\n未检测到需要变更的文件。\n\nPipeline: ${CI_PIPELINE_URL}\n\n<details><summary>分析详情</summary>\n\n\`\`\`\n${SUMMARY}\n\`\`\`\n</details>"
|
||||
fi
|
||||
|
||||
curl -s --request POST \
|
||||
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{\"body\": \"${BODY}\"}" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID/notes"
|
||||
- |
|
||||
# Step 6: 更新标签为 claude-done
|
||||
curl -s --request PUT \
|
||||
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{\"remove_labels\": \"claude-processing\", \"add_labels\": \"claude-done\"}" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID" > /dev/null
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "trigger" && $ISSUE_IID' # 被 scan-issues 触发
|
||||
- if: '$CI_PIPELINE_SOURCE == "web" && $ISSUE_IID' # 手动触发(需提供 ISSUE_IID)
|
||||
when: manual
|
||||
allow_failure: true
|
||||
timeout: 30m
|
||||
```
|
||||
|
||||
**Claude Code CLI 关键参数说明**:
|
||||
|
||||
| 参数 | 说明 |
|
||||
|------|------|
|
||||
| `-p "$PROMPT"` | 非交互模式,直接传入提示词 |
|
||||
| `--bare` | 精简输出,去掉装饰性格式 |
|
||||
| `--permission-mode acceptEdits` | 自动接受文件编辑(CI 环境必需) |
|
||||
| `--allowedTools "Bash,Read,Edit,Write,Glob,Grep"` | 限制可用工具,仅保留文件系统操作 |
|
||||
| `--max-turns 30` | 最大对话轮次,防止无限循环 |
|
||||
| `--output-format text` | 纯文本输出 |
|
||||
|
||||
---
|
||||
|
||||
## 第四步:创建定时调度
|
||||
|
||||
进入 **CI/CD → Schedules**,创建定时任务:
|
||||
|
||||
| 配置项 | 建议值 | 说明 |
|
||||
|--------|--------|------|
|
||||
| Description | Auto-fix Issue Scanner | 任务描述 |
|
||||
| Interval Pattern | `*/5 * * * *` | 每 5 分钟扫描一次 |
|
||||
| Cron Timezone | 你的时区 | 例如 Asia/Shanghai |
|
||||
| Target branch | `main` | 主分支 |
|
||||
|
||||
保存后,Schedule 会按设定频率运行 `claude:scan-issues` Job。
|
||||
|
||||
---
|
||||
|
||||
## 第五步:编写 CLAUDE.md 项目指南
|
||||
|
||||
在项目根目录创建 `CLAUDE.md`,Claude Code 在 CI 中运行时会自动读取此文件作为上下文指导:
|
||||
|
||||
```markdown
|
||||
# Project Guidelines
|
||||
|
||||
## 项目结构
|
||||
- `src/` — 主要源码
|
||||
- `tests/` — 测试文件
|
||||
|
||||
## 开发规范
|
||||
- 修改 TypeScript 代码后运行 `npx tsc --noEmit` 验证类型
|
||||
- 不要修改 `.gitlab-ci.yml`(除非 Issue 明确要求)
|
||||
|
||||
## 关键技术
|
||||
- 描述项目使用的框架、库、协议等
|
||||
```
|
||||
|
||||
这个文件非常重要,它相当于给 Claude Code 提供了"项目知识",让 AI 了解项目结构和约束,从而做出更合理的修复。
|
||||
|
||||
---
|
||||
|
||||
## 使用流程
|
||||
|
||||
### 自动模式
|
||||
|
||||
1. 在 GitLab 上创建一个 Issue,描述清楚 Bug 的现象、复现步骤、期望行为
|
||||
2. 给该 Issue 添加标签 **`auto-fix`**
|
||||
3. 等待定时调度运行(默认每 5 分钟扫描一次)
|
||||
4. 标签自动变为 `claude-processing`(正在处理)
|
||||
5. 修复完成后标签变为 `claude-done`,Issue 评论中会出现修复摘要
|
||||
6. 如果有代码变更,commit 会自动推送到 `main` 分支
|
||||
|
||||
### 手动模式(命令行触发)
|
||||
|
||||
项目提供了便捷脚本 `scripts/trigger-fix.sh`:
|
||||
|
||||
```bash
|
||||
# 设置环境变量
|
||||
export TRIGGER_TOKEN="你的 Trigger Token"
|
||||
export PROJECT_ID="项目 ID" # Settings → General 可查看
|
||||
export GITLAB_TOKEN="你的 PAT"
|
||||
export ANTHROPIC_AUTH_TOKEN="你的 API Key"
|
||||
|
||||
# 触发修复
|
||||
./scripts/trigger-fix.sh 42 # 42 是 Issue 的 IID
|
||||
```
|
||||
|
||||
脚本内容很简洁,直接调用 GitLab Pipeline Trigger API:
|
||||
|
||||
```bash
|
||||
curl -X POST \
|
||||
--form "token=${TRIGGER_TOKEN}" \
|
||||
--form "ref=main" \
|
||||
--form "variables[ISSUE_IID]=${ISSUE_IID}" \
|
||||
--form "variables[GITLAB_TOKEN]=${GITLAB_TOKEN}" \
|
||||
--form "variables[ANTHROPIC_AUTH_TOKEN]=${ANTHROPIC_AUTH_TOKEN}" \
|
||||
"https://${GITLAB_HOST}/api/v4/projects/${PROJECT_ID}/trigger/pipeline"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 关键设计细节
|
||||
|
||||
### 1. 为什么用两个 Job + Trigger 而非一个 Job?
|
||||
|
||||
- **隔离性**:扫描和修复在不同 Pipeline 中运行,一个 Issue 修复失败不影响其他 Issue
|
||||
- **并行**:多个 Issue 可以同时被触发修复(各自独立的 Pipeline)
|
||||
- **可追溯**:每个修复有独立的 Pipeline 记录
|
||||
|
||||
### 2. 标签状态机防重复
|
||||
|
||||
```
|
||||
auto-fix → claude-processing → claude-done
|
||||
```
|
||||
|
||||
- 扫描 Query 排除 `claude-processing` 和 `claude-done`
|
||||
- 保证每个 Issue **只被处理一次**
|
||||
|
||||
### 3. `[skip ci]` 避免递归触发
|
||||
|
||||
commit message 中包含 `[skip ci]`,防止修复 commit 触发新的 Pipeline,形成无限循环。
|
||||
|
||||
### 4. 临时文件排除
|
||||
|
||||
`repair_summary.txt` 和 `claude_stderr.txt` 通过 `git reset` 排除暂存区,通过 `.gitignore` 排除版本控制:
|
||||
|
||||
```gitignore
|
||||
repair_summary.txt
|
||||
claude_stderr.txt
|
||||
```
|
||||
|
||||
### 5. Upload Job 与 Fix Job 互不干扰
|
||||
|
||||
Upload Job 的 rules 中明确排除 `schedule` 和 `trigger` 来源:
|
||||
|
||||
```yaml
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
when: never
|
||||
- if: '$CI_PIPELINE_SOURCE == "trigger"'
|
||||
when: never
|
||||
```
|
||||
|
||||
### 6. 完整克隆
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
GIT_DEPTH: 0
|
||||
```
|
||||
|
||||
Claude Code 需要完整的仓库来分析代码,不能使用浅克隆。
|
||||
|
||||
---
|
||||
|
||||
## 踩坑记录与调试经验
|
||||
|
||||
### 1. Anthropic API 配置
|
||||
|
||||
**问题**:Claude Code CLI 的环境变量名是 `ANTHROPIC_API_KEY`,但 CI 变量传递时用了别的名字。
|
||||
|
||||
**解决**:在 script 中显式映射:
|
||||
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY="${ANTHROPIC_AUTH_TOKEN}"
|
||||
```
|
||||
|
||||
如果使用内部代理,还需设置 `ANTHROPIC_BASE_URL`。额外的 `ANTHROPIC_MODEL` 和 `ANTHROPIC_CUSTOM_MODEL_OPTION` 变量用于指定模型。
|
||||
|
||||
### 2. Claude Code 自动更新
|
||||
|
||||
**问题**:CI 环境中 Claude Code 尝试自动更新,导致超时或失败。
|
||||
|
||||
**解决**:设置环境变量禁用:
|
||||
|
||||
```yaml
|
||||
DISABLE_AUTOUPDATER: "1"
|
||||
```
|
||||
|
||||
### 3. Issue 查询排除已处理的 Issue
|
||||
|
||||
**问题**:早期版本未排除 `claude-processing`/`claude-done`,导致同一 Issue 被反复触发。
|
||||
|
||||
**解决**:使用 GitLab API 的 `not[labels]` 参数:
|
||||
|
||||
```
|
||||
?labels=auto-fix¬%5Blabels%5D=claude-processing,claude-done&state=opened
|
||||
```
|
||||
|
||||
### 4. Git Push 认证
|
||||
|
||||
**问题**:CI 环境默认的 git remote 可能不支持 push。
|
||||
|
||||
**解决**:使用 OAuth2 Token 方式构建 push URL:
|
||||
|
||||
```bash
|
||||
git push "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" HEAD:main
|
||||
```
|
||||
|
||||
### 5. 中文输出
|
||||
|
||||
**问题**:Claude Code 默认可能以英文回复。
|
||||
|
||||
**解决**:在 Prompt 中明确要求 "请使用中文回复",确保修复摘要和 Issue 评论为中文。
|
||||
|
||||
### 6. 评论中的特殊字符转义
|
||||
|
||||
**问题**:Claude 的输出可能包含 `"`、`\`、换行等字符,直接放入 JSON 会破坏格式。
|
||||
|
||||
**解决**:通过 `sed` 链式转义:
|
||||
|
||||
```bash
|
||||
SUMMARY=$(cat repair_summary.txt | head -200 | \
|
||||
sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 完整 .gitlab-ci.yml 参考
|
||||
|
||||
以下是 `ai_fix` Stage 的完整配置,可直接复制到你的 `.gitlab-ci.yml` 中:
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
# ... 你的其他 stages
|
||||
- ai_fix
|
||||
|
||||
# ============================================================
|
||||
# AI Fix Stage - Auto-fix GitLab Issues with Claude Code
|
||||
# ============================================================
|
||||
# Required CI/CD Variables:
|
||||
# - GITLAB_ACCESS_TOKEN: Personal Access Token (api scope)
|
||||
# - ANTHROPIC_AUTH_TOKEN: Anthropic API Key
|
||||
# - TRIGGER_TOKEN: Pipeline trigger token
|
||||
#
|
||||
# Setup:
|
||||
# 1. Create a Schedule (CI/CD → Schedules), e.g. every 5 min
|
||||
# 2. Add label "auto-fix" to an Issue → auto triggers fix
|
||||
|
||||
claude:scan-issues:
|
||||
stage: ai_fix
|
||||
image: alpine:3.19
|
||||
before_script:
|
||||
- apk add --no-cache curl jq
|
||||
script:
|
||||
- |
|
||||
for var in GITLAB_ACCESS_TOKEN TRIGGER_TOKEN ANTHROPIC_AUTH_TOKEN; do
|
||||
eval "val=\$$var"
|
||||
if [ -z "$val" ]; then echo "ERROR: $var not set."; exit 1; fi
|
||||
done
|
||||
|
||||
ISSUES=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues?labels=auto-fix¬%5Blabels%5D=claude-processing,claude-done&state=opened&per_page=10")
|
||||
|
||||
COUNT=$(echo "$ISSUES" | jq 'length')
|
||||
echo "Found $COUNT issue(s)."
|
||||
[ "$COUNT" -eq 0 ] || [ "$COUNT" = "null" ] && exit 0
|
||||
|
||||
echo "$ISSUES" | jq -r '.[].iid' | while read -r IID; do
|
||||
TITLE=$(echo "$ISSUES" | jq -r ".[] | select(.iid == $IID) | .title")
|
||||
echo ">>> Issue #${IID}: ${TITLE}"
|
||||
|
||||
curl -s --request PUT \
|
||||
--header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{\"remove_labels\": \"auto-fix\", \"add_labels\": \"claude-processing\"}" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$IID" > /dev/null
|
||||
|
||||
curl -s -X POST \
|
||||
--form "token=${TRIGGER_TOKEN}" \
|
||||
--form "ref=${CI_DEFAULT_BRANCH}" \
|
||||
--form "variables[ISSUE_IID]=${IID}" \
|
||||
--form "variables[GITLAB_TOKEN]=${GITLAB_ACCESS_TOKEN}" \
|
||||
--form "variables[ANTHROPIC_AUTH_TOKEN]=${ANTHROPIC_AUTH_TOKEN}" \
|
||||
"https://${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/trigger/pipeline"
|
||||
done
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule"'
|
||||
- if: '$CI_PIPELINE_SOURCE == "web"'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
timeout: 5m
|
||||
|
||||
claude:fix-issue:
|
||||
stage: ai_fix
|
||||
image: node:20
|
||||
variables:
|
||||
GIT_STRATEGY: clone
|
||||
GIT_DEPTH: 0
|
||||
ANTHROPIC_BASE_URL: "https://api.anthropic.com"
|
||||
ANTHROPIC_MODEL: "claude-sonnet-4-6"
|
||||
DISABLE_AUTOUPDATER: "1"
|
||||
DISABLE_PROMPT_CACHING: "1"
|
||||
before_script:
|
||||
- apt-get update && apt-get install -y git curl jq
|
||||
- npm install -g @anthropic-ai/claude-code
|
||||
- git config --global user.email "claude-bot@example.com"
|
||||
- git config --global user.name "Claude AI Bot"
|
||||
script:
|
||||
- |
|
||||
[ -z "$ISSUE_IID" ] && echo "ERROR: ISSUE_IID required." && exit 1
|
||||
[ -z "$GITLAB_TOKEN" ] && echo "ERROR: GITLAB_TOKEN required." && exit 1
|
||||
|
||||
ISSUE_JSON=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID")
|
||||
ISSUE_TITLE=$(echo "$ISSUE_JSON" | jq -r '.title // empty')
|
||||
ISSUE_DESCRIPTION=$(echo "$ISSUE_JSON" | jq -r '.description // empty')
|
||||
[ -z "$ISSUE_TITLE" ] && echo "ERROR: Cannot fetch Issue" && exit 1
|
||||
- |
|
||||
git checkout "$CI_DEFAULT_BRANCH" && git pull origin "$CI_DEFAULT_BRANCH"
|
||||
- |
|
||||
export ANTHROPIC_API_KEY="${ANTHROPIC_AUTH_TOKEN}"
|
||||
|
||||
PROMPT="你是一个代码修复助手。请使用中文回复。请分析并修复以下 GitLab Issue:
|
||||
|
||||
## Issue #${ISSUE_IID}: ${ISSUE_TITLE}
|
||||
|
||||
${ISSUE_DESCRIPTION}
|
||||
|
||||
请:
|
||||
1. 分析项目代码,定位问题根因
|
||||
2. 实施修复
|
||||
3. 确保代码能通过类型检查(TypeScript 项目运行 npx tsc --noEmit)
|
||||
4. 用中文输出修复摘要
|
||||
|
||||
项目根目录已准备就绪。"
|
||||
|
||||
RESULT=$(claude -p "$PROMPT" \
|
||||
--bare \
|
||||
--permission-mode acceptEdits \
|
||||
--allowedTools "Bash,Read,Edit,Write,Glob,Grep" \
|
||||
--max-turns 30 \
|
||||
--output-format text \
|
||||
2>&1) || true
|
||||
|
||||
echo "$RESULT" > repair_summary.txt
|
||||
- |
|
||||
git add -A
|
||||
git reset -- repair_summary.txt claude_stderr.txt 2>/dev/null || true
|
||||
if git diff --cached --quiet; then
|
||||
COMMIT_STATUS="no_changes"
|
||||
else
|
||||
git commit -m "fix(auto): resolve Issue #${ISSUE_IID} - ${ISSUE_TITLE} [skip ci]"
|
||||
git push "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" \
|
||||
HEAD:"$CI_DEFAULT_BRANCH"
|
||||
COMMIT_STATUS="pushed"
|
||||
fi
|
||||
- |
|
||||
SUMMARY=$(cat repair_summary.txt | head -200 | \
|
||||
sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
|
||||
|
||||
if [ "$COMMIT_STATUS" = "pushed" ]; then
|
||||
BODY="## ✅ Claude Code 自动修复完成\n\n修复已推送到 \`${CI_DEFAULT_BRANCH}\`。\nPipeline: ${CI_PIPELINE_URL}\n\n<details><summary>修复详情</summary>\n\n\`\`\`\n${SUMMARY}\n\`\`\`\n</details>"
|
||||
else
|
||||
BODY="## ⚠️ Claude Code 分析完成\n\n未检测到需要变更的文件。\nPipeline: ${CI_PIPELINE_URL}\n\n<details><summary>分析详情</summary>\n\n\`\`\`\n${SUMMARY}\n\`\`\`\n</details>"
|
||||
fi
|
||||
|
||||
curl -s --request POST \
|
||||
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{\"body\": \"${BODY}\"}" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID/notes"
|
||||
- |
|
||||
curl -s --request PUT \
|
||||
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data "{\"remove_labels\": \"claude-processing\", \"add_labels\": \"claude-done\"}" \
|
||||
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/issues/$ISSUE_IID" > /dev/null
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "trigger" && $ISSUE_IID'
|
||||
- if: '$CI_PIPELINE_SOURCE == "web" && $ISSUE_IID'
|
||||
when: manual
|
||||
allow_failure: true
|
||||
timeout: 30m
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
| 特性 | 实现方式 |
|
||||
|------|----------|
|
||||
| 触发机制 | GitLab Schedule 定时扫描 + Pipeline Trigger 触发修复 |
|
||||
| AI 引擎 | Claude Code CLI (`@anthropic-ai/claude-code`) |
|
||||
| 权限控制 | `--permission-mode acceptEdits` + `--allowedTools` 白名单 |
|
||||
| 防重复 | 标签状态机 `auto-fix → claude-processing → claude-done` |
|
||||
| 防递归 | commit message 中 `[skip ci]` |
|
||||
| 结果反馈 | 自动在 Issue 上发表评论,含修复摘要 |
|
||||
| 项目上下文 | `CLAUDE.md` 项目指南文件 |
|
||||
|
||||
这套方案已在实际项目中运行,成功自动修复了多个 Bug Issue。核心优势是**零人工介入**——开发者只需写好 Issue 描述并打上标签,AI 自动完成从分析到修复到提交的全流程。
|
||||
@@ -1,232 +0,0 @@
|
||||
# 前言
|
||||
|
||||
# 易协作
|
||||
- 相关网址
|
||||
- [Redmine MCP Server (易协作)](https://modelspace.netease.com/mcphub?detail=redmine-mcp-server&namespace=public)
|
||||
- Auth & Token
|
||||
- https://console-auth.nie.netease.com/mymessage/mymessage
|
||||
- https://sa.nie.netease.com/docs/auth/%E8%BF%90%E7%BB%B4%E6%94%AF%E6%92%91/Auth/06-%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8C/04%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7/API%20%E6%96%87%E6%A1%A3/02%20Auth%20API%20v2%20%E6%96%87%E6%A1%A3.md#%E8%83%8C%E6%99%AF
|
||||
|
||||
|
||||
# Redmine MCP Server (易协作)
|
||||
易协作工单管理的 MCP (Model Context Protocol) Server 实现,提供工单查询、详情查看、工单更新、项目管理等功能。
|
||||
|
||||
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%8A%9F%E8%83%BD%E7%89%B9%E6%80%A7)功能特性
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#-%E5%B7%A5%E5%85%B7-tools)🔧 工具 (Tools)
|
||||
- **query_issues**: 搜索/查询易协作工单,支持多种过滤条件(状态、指派人、时间范围、自定义字段等)
|
||||
- **get_issue_detail**: 获取单个工单的完整详情,包括描述内容和图片
|
||||
- **update_issue**: 更新/修改工单信息(状态、指派人、主题、描述、备注等),支持人名、邮箱前缀等多种指派人格式
|
||||
- **get_user_projects**: 获取用户有权限访问的易协作项目列表
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#-%E8%B5%84%E6%BA%90-resources)📚 资源 (Resources)
|
||||
- **redmine://config**: 服务器配置信息
|
||||
- **redmine://hosts**: 所有易协作实例及有权限的项目列表
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%EF%B8%8F-%E8%B5%84%E6%BA%90%E6%A8%A1%E6%9D%BF-resource-templates)🗂️ 资源模板 (Resource Templates)
|
||||
- **redmine://host/{host_name}**: 获取指定易协作实例的详细信息
|
||||
- **redmine://host/{host_name}/{project_name}**: 获取指定项目的详细信息(版本、状态、跟踪标签等)
|
||||
- **redmine://project/{project_name}**: 获取默认实例中项目的详细信息(需配置默认实例)
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#-%E6%8F%90%E7%A4%BA-prompts)💬 提示 (Prompts)
|
||||
- **issue_analysis**: 易协作工单助手,支持状态、优先级、指派人、趋势分析
|
||||
|
||||
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F)使用方式
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#streamablehttp-%E6%8E%A8%E8%8D%90)StreamableHTTP (推荐)
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"redmine-mcp-server": {
|
||||
"type": "streamableHttp",
|
||||
"url": "https://mcp.netease.com/servers/redmine-mcp-server/mcp/"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E6%8C%87%E5%AE%9A%E9%BB%98%E8%AE%A4%E6%98%93%E5%8D%8F%E4%BD%9C%E5%AE%9E%E4%BE%8B%E5%8F%AF%E9%80%89)指定默认易协作实例(可选)
|
||||
如果有多个易协作实例,可通过 `redmine-host` 参数指定默认实例,后续调用工具时可省略 `redmine_host` 参数:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"redmine-mcp-server": {
|
||||
"type": "streamableHttp",
|
||||
"url": "https://mcp.netease.com/servers/redmine-mcp-server/mcp/",
|
||||
"headers": {
|
||||
"redmine-host": "dap-v4.pm.netease.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E8%AE%A4%E8%AF%81%E4%B8%8E%E9%89%B4%E6%9D%83)认证与鉴权
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E8%AE%A4%E8%AF%81%E6%96%B9%E5%BC%8F)认证方式
|
||||
- 通过请求头 `X-Access-Token` 提供用户Token(若在 Codemaker 中使用,无需自行设置)
|
||||
- 系统会验证Token的有效性并获取用户信息
|
||||
- Auth 文档(使用 Auth Key 换取 Token):[https://g.126.fm/04nIr8l](https://g.126.fm/04nIr8l)
|
||||
- Auth 平台:[https://console-auth.nie.netease.com/mymessage/mymessage](https://console-auth.nie.netease.com/mymessage/mymessage)
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E9%89%B4%E6%9D%83%E8%A7%84%E5%88%99)鉴权规则
|
||||
- 用户只能访问其有权限的易协作实例和项目
|
||||
- 权限判断基于用户邮箱是否在项目成员列表中
|
||||
|
||||
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%B7%A5%E5%85%B7%E8%AF%A6%E7%BB%86%E8%AF%B4%E6%98%8E)工具详细说明
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#query_issues---%E6%9F%A5%E8%AF%A2%E5%B7%A5%E5%8D%95)query_issues - 查询工单
|
||||
搜索/查询易协作工单信息,支持丰富的过滤条件。
|
||||
**参数:**
|
||||
|
||||
|参数|类型|必填|说明|
|
||||
|---|---|---|---|
|
||||
|`redmine_host`|string|视配置|易协作实例域名,已配置默认实例时可省略|
|
||||
|`project`|string|是|项目名称|
|
||||
|`filters`|object|否|过滤条件,详见过滤器说明|
|
||||
|`page`|integer|否|页码,默认 1|
|
||||
|`per_page`|integer|否|每页条数,默认 20,最大 100|
|
||||
|
||||
**支持的过滤器:**
|
||||
|
||||
|过滤器字段|操作符|说明|
|
||||
|---|---|---|
|
||||
|`issues_id`|`=`, `!`|工单ID,支持多个ID|
|
||||
|`subject`|`~`, `=`, `!`|主题关键词|
|
||||
|`status`|`=`, `!`, `o`, `c`|状态名称|
|
||||
|`assigned_to_id`|`=`, `!`|指派人(邮箱前缀或 `me`)|
|
||||
|`assigned_to_name`|`=`, `!`|指派人中文名称|
|
||||
|`tracker_id`|`=`, `!`|跟踪标签(名称或ID)|
|
||||
|`fixed_version_id`|`=`, `!`, `o`, `c`|目标版本(名称或ID)|
|
||||
|`updated_on`|`><`, `>=`, `<=`|更新时间|
|
||||
|`created_on`|`><`, `>=`, `<=`|创建时间|
|
||||
|`start_date`|`><`, `>=`, `<=`|开始日期|
|
||||
|`due_date`|`><`, `>=`, `<=`|截止日期|
|
||||
|`done_ratio`|`=`, `!`, `>=`, `<=`|完成度 (0-100)|
|
||||
|`estimated_hours`|`=`, `!`, `>=`, `<=`|预估工时|
|
||||
|`cf`|对象|自定义字段,键为字段ID|
|
||||
|
||||
**操作符说明:** `~` 模糊匹配,`=` 等于,`!` 不等于,`o` 开放状态,`c` 关闭状态,`><` 范围,`>=` 大于等于,`<=` 小于等于
|
||||
|
||||
**过滤器示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"subject": {"op": "~", "value": ["bug"]},
|
||||
"status": {"op": "=", "value": ["开发中"]},
|
||||
"assigned_to_id": {"op": "=", "value": ["me"]}
|
||||
}
|
||||
```
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#get_issue_detail---%E8%8E%B7%E5%8F%96%E5%B7%A5%E5%8D%95%E8%AF%A6%E6%83%85)get_issue_detail - 获取工单详情
|
||||
获取单个易协作工单的完整详情,包括基本信息、自定义字段、描述内容及图片。
|
||||
**参数:**
|
||||
|
||||
|参数|类型|必填|说明|
|
||||
|---|---|---|---|
|
||||
|`redmine_host`|string|视配置|易协作实例域名|
|
||||
|`issue_id`|integer|是|工单ID(如 #12278,传参时传数字 12278)|
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#update_issue---%E6%9B%B4%E6%96%B0%E5%B7%A5%E5%8D%95)update_issue - 更新工单
|
||||
更新/修改易协作工单信息。更新成功后会返回更新后的工单详情。
|
||||
系统会自动获取工单所属项目用于API安全校验,无需手动指定项目。
|
||||
**参数:**
|
||||
|
||||
|参数|类型|必填|说明|
|
||||
|---|---|---|---|
|
||||
|`redmine_host`|string|视配置|易协作实例域名|
|
||||
|`issue_id`|integer|是|工单ID|
|
||||
|`status`|string|否|工单状态名称,如: 新建/开发中/已解决/关闭|
|
||||
|`subject`|string|否|工单主题|
|
||||
|`description`|string|否|工单描述|
|
||||
|`notes`|string|否|工单备注/说明,追加到工单评论中|
|
||||
|`assigned_to_mail`|string|否|指派人,支持多种格式(见下方说明)|
|
||||
|`tracker`|string|否|跟踪标签名称,如: BUG/任务/需求|
|
||||
|`version`|string|否|目标版本号名称|
|
||||
|`start_date`|string|否|开始日期,格式: YYYY-MM-DD|
|
||||
|`due_date`|string|否|完成日期,格式: YYYY-MM-DD|
|
||||
|`estimated_hours`|number|否|预估工作量(小时)|
|
||||
|`author_mail`|string|否|提单作者,格式同指派人|
|
||||
|`follows`|string/array|否|跟进QA,支持单个字符串(逗号分隔多人)或数组|
|
||||
|`watcher_user_ids`|array|否|跟踪者用户ID列表,如: [386, 387]|
|
||||
|`custom_field`|object|否|自定义字段,格式: {"字段ID": "值"}|
|
||||
|
||||
**指派人格式兼容(`assigned_to_mail` / `author_mail` / `follows`):**
|
||||
|
||||
|输入格式|示例|处理方式|
|
||||
|---|---|---|
|
||||
|完整邮箱|`lien02@corp.netease.com`|直接使用|
|
||||
|邮箱前缀|`lien02`|自动补全为 `lien02@corp.netease.com`|
|
||||
|中文名|`李恩`|从项目成员缓存中匹配对应邮箱|
|
||||
|首字母+中文名|`L李恩`|去除首字母前缀后按中文名匹配|
|
||||
|
||||
**更新示例:**
|
||||
```json
|
||||
{
|
||||
"issue_id": 1509,
|
||||
"status": "开发中",
|
||||
"assigned_to_mail": "李恩",
|
||||
"notes": "已开始开发"
|
||||
}
|
||||
```
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#get_user_projects---%E8%8E%B7%E5%8F%96%E9%A1%B9%E7%9B%AE%E5%88%97%E8%A1%A8)get_user_projects - 获取项目列表
|
||||
获取当前用户有权限访问的所有易协作项目列表,按实例分组返回。
|
||||
**参数:** 无
|
||||
|
||||
|
||||
## [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E4%B8%BB%E8%A6%81%E5%8A%9F%E8%83%BD)主要功能
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%B7%A5%E5%8D%95%E6%9F%A5%E8%AF%A2)工单查询
|
||||
支持多种过滤条件:
|
||||
- 主题关键词搜索
|
||||
- 状态筛选(新建/开发中/关闭等)
|
||||
- 指派人筛选(支持邮箱前缀、中文名、`me`)
|
||||
- 跟踪标签/目标版本筛选(支持名称和ID)
|
||||
- 时间范围筛选(创建/更新/开始/截止日期)
|
||||
- 自定义字段筛选
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%B7%A5%E5%8D%95%E8%AF%A6%E6%83%85)工单详情
|
||||
- 查看工单完整信息(基本字段、自定义字段)
|
||||
- 支持描述内容中的图片展示
|
||||
- 显示跟踪者、关注者等协作信息
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E5%B7%A5%E5%8D%95%E6%9B%B4%E6%96%B0)工单更新
|
||||
- 修改工单状态、指派人、主题、描述等字段
|
||||
- 添加备注/评论
|
||||
- 修改目标版本、跟踪标签、日期、工时等
|
||||
- 设置跟进QA、跟踪者、自定义字段
|
||||
- 指派人支持中文名/邮箱前缀/完整邮箱等多种输入格式
|
||||
- 更新成功后自动返回更新后的工单详情
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86)项目管理
|
||||
- 获取用户有权限的项目列表
|
||||
- 查看项目元数据(状态、跟踪标签、版本等)
|
||||
- 支持多实例管理
|
||||
|
||||
### [](https://mcp-ui.netease.com/server/redmine-mcp-server?namespace=public#%E6%95%B0%E6%8D%AE%E7%BC%93%E5%AD%98)数据缓存
|
||||
- 自动数据更新机制
|
||||
- 本地缓存提升性能
|
||||
- 实时流式日志输出
|
||||
|
||||
## 工具
|
||||
|
||||
| 工具名称 | 工具描述 | 工具参数 |
|
||||
| ----------------- | ----------------------------------- | --------------------------------------------------------- |
|
||||
| query_issues | 搜索/查询获取易协作工单信息 | #redmine_host #project #filterspageper_page |
|
||||
| get_user_projects | 获取用户有权限访问的易协作项目列表 | 暂无参数 |
|
||||
| get_issue_detail | 获取单个易协作工单详情 | redmine_host*issue_id* |
|
||||
| update_issue | 更新/修改易协作工单信息,支持修改状态、指派人、主题、描述、备注等字段 | redmine_host*issue_id*statussubjectdescriptionnotes+10 更多 |
|
||||
## 资源
|
||||
|
||||
|资源名称|URI|描述|MIME类型|
|
||||
|---|---|---|---|
|
||||
|服务器配置|`redmine://config`|获取易协作 MCP 服务器的配置信息|application/json|
|
||||
|易协作实例-项目列表|`redmine://hosts`|获取所有易协作实例列表及有权限的项目列表|application/json|
|
||||
|
||||
## 模版资源
|
||||
|
||||
|模板名称|URI模板|描述|MIME类型|
|
||||
|---|---|---|---|
|
||||
|易协作实例详情|`redmine://host/{host_name}`|获取指定易协作实例的详细信息|application/json|
|
||||
|易协作项目详情|`redmine://host/{host_name}/{project_name}`|获取指定易协作实例中特定项目的详细信息,包括项目可用的版本、状态和跟踪标签|application/json|
|
||||
## 提示
|
||||
| | | |
|
||||
| -------------- | ------- | ------------------------------------- |
|
||||
| issue_analysis | 易协作工单助手 | #redmine_host #project #analysis_type |
|
||||
@@ -1,15 +1,18 @@
|
||||
# 前言
|
||||
- [Obsidian CLI 详细教程:官方命令行工具,激进拥抱智能体,高效 + 自动化 + 降低Token消耗。](https://www.bilibili.com/video/BV19TPXzAEtW/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e)
|
||||
|
||||
- [Obsidian CLI 详细教程:官方命令行工具,激进拥抱智能体,高效 + 自动化 + 降低 Token 消耗](https://www.bilibili.com/video/BV19TPXzAEtW/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e)
|
||||
- [如何为 Obsidian 配置 AI Agent?9 个必备 Skill 详解与安装指南](https://www.bilibili.com/video/BV14d9TBiE1S/?share_source=copy_web&vd_source=fe8142e8e12816535feaeabd6f6cdc8e)
|
||||
|
||||
# 步骤
|
||||
1. Obsidian - 小齿轮(Settings)- 开启 命令行界面。
|
||||
2. 安装Obsidian适配ClaudeCode的插件(可选)
|
||||
1. Claudian:https://github.com/YishenTu/claudian
|
||||
2. 配置自定义变量。
|
||||
3. 安装 https://github.com/kepano/obsidian-skills
|
||||
1. npm install -g defuddle
|
||||
4. 安装Obsidian绘图增强Skill https://github.com/axtonliu/axton-obsidian-visual-skills
|
||||
|
||||
# 其他Skill
|
||||
- 学习用Skill:https://github.com/bevibing/tutor-skills
|
||||
1. Obsidian → 小齿轮(Settings)→ 开启**命令行界面**
|
||||
2. 安装 Obsidian 适配 Claude Code 的插件(可选)
|
||||
1. Claudian:https://github.com/YishenTu/claudian
|
||||
2. 配置自定义变量
|
||||
3. 安装 [obsidian-skills](https://github.com/kepano/obsidian-skills)
|
||||
1. `npm install -g defuddle`
|
||||
4. 安装 Obsidian 绘图增强 Skill:[axton-obsidian-visual-skills](https://github.com/axtonliu/axton-obsidian-visual-skills)
|
||||
|
||||
# 其他 Skill
|
||||
|
||||
- 学习用 Skill:[tutor-skills](https://github.com/bevibing/tutor-skills)
|
||||
Reference in New Issue
Block a user