624 lines
20 KiB
Markdown
624 lines
20 KiB
Markdown
# code_ai_agent CI/CD 工作流方案设计
|
||
|
||
**计划文件:** `.omc/plans/code_ai_agent_cicd.md`
|
||
**创建日期:** 2026-03-27
|
||
**状态:** 待用户确认
|
||
|
||
---
|
||
|
||
## 1. 方案概述
|
||
|
||
将 `code_ai_agent` 从单纯的代码生成服务升级为具备完整 DevOps 工作流能力的「代码员工 Agent」。新增 Git 操作、SSH 远程执行、K8s 部署触发能力,全部通过 HTTP API 暴露。
|
||
|
||
### 完整工作流
|
||
|
||
```
|
||
外部调用方 (agent-manager / 人工)
|
||
│
|
||
▼
|
||
code_ai_agent Pod
|
||
┌──────────────────────────────────────────┐
|
||
│ api_server.py (HTTP 路由层) │
|
||
│ ┌──────────┬──────────┬──────────────┐ │
|
||
│ │ /git/* │ /ssh/* │ /deploy/k8s │ │
|
||
│ └────┬─────┴────┬─────┴──────┬───────┘ │
|
||
│ │ │ │ │
|
||
│ src/server/tools/ (工具实现层) │
|
||
│ ┌────▼─────┐ ┌──▼──────┐ ┌──▼────────┐ │
|
||
│ │git_tools │ │ssh_tools│ │deploy_tools│ │
|
||
│ └────┬─────┘ └──┬──────┘ └──┬────────┘ │
|
||
│ │ │ │ │
|
||
│ /workspace/{task_id}/ (隔离工作空间) │
|
||
└───┬───┴──────────┴────────────┴───────────┘
|
||
│
|
||
├─► Gitee (http://gitee.ath.cx:3000)
|
||
├─► Azure VM (SSH 22)
|
||
└─► K8s API Server
|
||
```
|
||
|
||
### 典型工作流序列
|
||
|
||
```
|
||
1. POST /api/v1/git/clone → 克隆仓库到 /workspace/{task_id}
|
||
2. POST /api/v1/git/branch → 创建 feature/xxx 分支
|
||
3. POST /api/v1/code/generate → 使用现有能力生成/修改代码
|
||
4. POST /api/v1/git/status → 确认变更
|
||
5. POST /api/v1/git/commit-push → 提交并推送
|
||
6. POST /api/v1/ssh/exec → SSH 到 Azure VM 执行测试
|
||
7. POST /api/v1/deploy/k8s → 测试通过后触发 K8s 部署
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 新增 API 端点设计(api_server.py)
|
||
|
||
### 2.1 Git 操作端点
|
||
|
||
#### `POST /api/v1/git/clone`
|
||
|
||
```json
|
||
// 请求
|
||
{
|
||
"repo_url": "http://gitee.ath.cx:3000/zhanggangyong/agent_management.git",
|
||
"task_id": "task-20260327-001",
|
||
"branch": "main",
|
||
"depth": 1
|
||
}
|
||
// 响应
|
||
{
|
||
"success": true,
|
||
"task_id": "task-20260327-001",
|
||
"workspace": "/workspace/task-20260327-001",
|
||
"branch": "main",
|
||
"commit": "abc1234"
|
||
}
|
||
```
|
||
|
||
#### `POST /api/v1/git/branch`
|
||
|
||
```json
|
||
// 请求
|
||
{
|
||
"task_id": "task-20260327-001",
|
||
"branch_name": "feature/auto-fix-bug-123",
|
||
"from_branch": "main"
|
||
}
|
||
// 响应
|
||
{ "success": true, "branch": "feature/auto-fix-bug-123", "base_commit": "abc1234" }
|
||
```
|
||
|
||
#### `POST /api/v1/git/status`
|
||
|
||
```json
|
||
// 请求
|
||
{ "task_id": "task-20260327-001" }
|
||
// 响应
|
||
{
|
||
"success": true,
|
||
"branch": "feature/auto-fix-bug-123",
|
||
"staged": ["src/main.py"],
|
||
"unstaged": ["README.md"],
|
||
"untracked": ["new_file.py"],
|
||
"raw_output": "M src/main.py\n?? new_file.py"
|
||
}
|
||
```
|
||
|
||
#### `POST /api/v1/git/commit-push`
|
||
|
||
```json
|
||
// 请求
|
||
{
|
||
"task_id": "task-20260327-001",
|
||
"message": "fix: resolve null pointer in agent executor",
|
||
"files": ["src/agent.py"],
|
||
"push": true
|
||
}
|
||
// 响应
|
||
{ "success": true, "commit": "def5678", "pushed": true, "branch": "feature/auto-fix-bug-123" }
|
||
```
|
||
|
||
#### `POST /api/v1/git/diff`
|
||
|
||
```json
|
||
// 请求
|
||
{ "task_id": "task-20260327-001", "staged": false }
|
||
// 响应
|
||
{ "success": true, "diff": "--- a/src/main.py\n+++ b/src/main.py\n..." }
|
||
```
|
||
|
||
### 2.2 SSH 操作端点
|
||
|
||
#### `POST /api/v1/ssh/exec`
|
||
|
||
```json
|
||
// 请求
|
||
{
|
||
"host": "<azure-vm-ip>",
|
||
"user": "azureuser",
|
||
"command": "cd /app && pytest tests/ -v --tb=short",
|
||
"timeout": 300,
|
||
"task_id": "task-20260327-001"
|
||
}
|
||
// 响应
|
||
{
|
||
"success": true,
|
||
"exit_code": 0,
|
||
"stdout": "collected 42 items ... 42 passed",
|
||
"stderr": "",
|
||
"duration_seconds": 45.2
|
||
}
|
||
```
|
||
|
||
**说明:** `host` 若不传,从环境变量 `SSH_TEST_HOST` 读取;`user` 从 `SSH_USER` 读取,默认 `azureuser`。
|
||
|
||
### 2.3 部署端点
|
||
|
||
#### `POST /api/v1/deploy/k8s`
|
||
|
||
```json
|
||
// 请求
|
||
{
|
||
"namespace": "agent-manager",
|
||
"deployment": "agent-manager",
|
||
"image": "agnettaiji.azurecr.io/ai-agents/agent-manager:v1.2.3",
|
||
"strategy": "set-image",
|
||
"wait": true,
|
||
"timeout": 300
|
||
}
|
||
// strategy: "rollout-restart" | "set-image"
|
||
// 响应
|
||
{ "success": true, "deployment": "agent-manager", "status": "rolled out", "duration_seconds": 62 }
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 新增工具函数设计(mcp_server.py + tools/ 模块)
|
||
|
||
### 3.1 文件结构变化
|
||
|
||
```
|
||
agent_templates/agents/code_ai_agent/
|
||
├── Dockerfile # 修改:增加 git/ssh/kubectl
|
||
├── requirements.txt # 修改:增加 paramiko, gitpython
|
||
├── src/server/
|
||
│ ├── api_server.py # 修改:新增 /git /ssh /deploy 路由
|
||
│ ├── mcp_server.py # 修改:新增工具注册
|
||
│ ├── mcp_http_server.py # 不变
|
||
│ └── tools/ # 新增目录
|
||
│ ├── __init__.py
|
||
│ ├── git_tools.py # Git 操作实现
|
||
│ ├── ssh_tools.py # SSH 操作实现
|
||
│ ├── deploy_tools.py # K8s 部署实现
|
||
│ └── workspace.py # 工作空间管理
|
||
└── k8s/ # 新增:agent 专属 K8s 配置
|
||
├── code-ai-agent-deployment.yaml
|
||
└── code-ai-agent-secret.yaml
|
||
```
|
||
|
||
### 3.2 git_tools.py 核心接口
|
||
|
||
```python
|
||
class GitTools:
|
||
def __init__(self):
|
||
self.workspace_root = "/workspace"
|
||
self._gitee_user = os.getenv("GITEE_USERNAME")
|
||
self._gitee_token = os.getenv("GITEE_TOKEN")
|
||
|
||
def clone(self, repo_url, task_id, branch="main", depth=1) -> dict
|
||
def create_branch(self, task_id, branch_name, from_branch=None) -> dict
|
||
def get_status(self, task_id) -> dict
|
||
def stage_files(self, task_id, files=None) -> dict # None = git add -A
|
||
def commit(self, task_id, message) -> dict
|
||
def push(self, task_id, branch=None) -> dict
|
||
def get_diff(self, task_id, staged=False) -> dict
|
||
def cleanup(self, task_id) -> dict # 删除工作空间
|
||
|
||
def _inject_credentials(self, repo_url) -> str:
|
||
# http://user:token@gitee.ath.cx:3000/...
|
||
parsed = urlparse(repo_url)
|
||
return parsed._replace(
|
||
netloc=f"{self._gitee_user}:{self._gitee_token}@{parsed.hostname}:{parsed.port}"
|
||
).geturl()
|
||
|
||
def _run(self, cmd, cwd) -> tuple[int, str, str]
|
||
# subprocess.run,捕获 stdout/stderr,设置超时
|
||
```
|
||
|
||
### 3.3 ssh_tools.py 核心接口
|
||
|
||
```python
|
||
class SSHTools:
|
||
def __init__(self):
|
||
self._key_path = "/root/.ssh/id_rsa" # 从 Secret 挂载
|
||
self._default_host = os.getenv("SSH_TEST_HOST")
|
||
self._default_user = os.getenv("SSH_USER", "azureuser")
|
||
|
||
def exec(self, command, host=None, user=None, timeout=120, task_id=None) -> dict:
|
||
# 使用 paramiko 连接,执行命令,返回 stdout/stderr/exit_code
|
||
# 每次调用建立新连接,操作完毕后关闭
|
||
|
||
def _get_client(self, host, user) -> paramiko.SSHClient
|
||
```
|
||
|
||
### 3.4 deploy_tools.py 核心接口
|
||
|
||
```python
|
||
class DeployTools:
|
||
def __init__(self):
|
||
# 优先使用挂载的 kubeconfig,其次 in-cluster config
|
||
self._kubeconfig = "/root/.kube/config"
|
||
|
||
def rollout_restart(self, namespace, deployment, wait=True, timeout=300) -> dict
|
||
def set_image(self, namespace, deployment, image, wait=True, timeout=300) -> dict
|
||
def get_status(self, namespace, deployment) -> dict
|
||
def _run_kubectl(self, args) -> tuple[int, str, str]
|
||
```
|
||
|
||
### 3.5 workspace.py — 工作空间管理
|
||
|
||
```python
|
||
class WorkspaceManager:
|
||
ROOT = "/workspace"
|
||
|
||
@staticmethod
|
||
def get_path(task_id: str) -> str:
|
||
# 返回 /workspace/{task_id}
|
||
# task_id 只允许 [a-zA-Z0-9_-],防止路径注入
|
||
|
||
@staticmethod
|
||
def create(task_id: str) -> str
|
||
|
||
@staticmethod
|
||
def cleanup(task_id: str) -> None
|
||
|
||
@staticmethod
|
||
def list_tasks() -> list[str]
|
||
|
||
@staticmethod
|
||
def disk_usage() -> dict # 返回各 task_id 占用磁盘大小
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 安全设计
|
||
|
||
### 4.1 SSH 私钥注入
|
||
|
||
**方案:K8s Secret → Volume Mount(只读)**
|
||
|
||
```yaml
|
||
# 新建 Secret(在 code-ai-agent 命名空间下)
|
||
apiVersion: v1
|
||
kind: Secret
|
||
metadata:
|
||
name: code-ai-agent-ssh-secret
|
||
namespace: agent-manager
|
||
type: Opaque
|
||
data:
|
||
id_rsa: <base64-encoded-private-key>
|
||
id_rsa.pub: <base64-encoded-public-key>
|
||
known_hosts: <base64-encoded-known_hosts> # 预置 Azure VM
|
||
|
||
|
||
```
|
||
|
||
```yaml
|
||
# Deployment volumeMounts
|
||
volumeMounts:
|
||
- name: ssh-secret
|
||
mountPath: /root/.ssh
|
||
readOnly: true
|
||
volumes:
|
||
- name: ssh-secret
|
||
secret:
|
||
secretName: code-ai-agent-ssh-secret
|
||
defaultMode: 0400 # 私钥必须 0400,否则 SSH 拒绝
|
||
```
|
||
|
||
初始化:容器 entrypoint 或 initContainer 执行 `chmod 700 /root/.ssh && chmod 600 /root/.ssh/id_rsa`。
|
||
|
||
### 4.2 Git 凭证安全传递
|
||
|
||
| 方案 | 说明 | 推荐度 |
|
||
|------|------|--------|
|
||
| Token 嵌入 URL | `http://user:token@host/repo` 内存拼接,不落盘 | P0 首选 |
|
||
| git credential store | 写入 `~/.git-credentials` 文件权限 600 | 备选 |
|
||
| SSH key for git | gitee 配置 deploy key,统一 SSH | P2 升级 |
|
||
|
||
实现要点:`_inject_credentials()` 在内存拼接带 token 的 URL;clone 完成后用 `git remote set-url origin <无密码URL>` 替换;日志中对 URL 做 token 脱敏。
|
||
|
||
### 4.3 权限隔离
|
||
|
||
- code_ai_agent 使用独立 ServiceAccount `code-ai-agent`
|
||
- RBAC 只授予 `agent-manager` 命名空间下 Deployment 的 `get/patch/update`
|
||
- SSH 连接只允许白名单 host(`SSH_ALLOWED_HOSTS` 环境变量,ssh_tools.py 校验)
|
||
- `/workspace` 挂载独立 emptyDir,不与其他 agent 共享
|
||
- API 通过现有 `X-API-Key` header 鉴权
|
||
|
||
---
|
||
|
||
## 5. 工作空间设计
|
||
|
||
### 5.1 目录结构
|
||
|
||
```
|
||
/workspace/
|
||
├── task-20260327-001/
|
||
│ ├── agent_management/ # 克隆的仓库
|
||
│ └── .meta.json # 任务元数据(时间、branch、状态)
|
||
├── task-20260327-002/
|
||
│ └── agent_management/
|
||
└── .workspace_index.json
|
||
```
|
||
|
||
### 5.2 并发隔离策略
|
||
|
||
- `task_id` 由调用方传入或服务端 `uuid4()` 自动生成
|
||
- 每个 task_id 对应独立目录,无共享文件
|
||
- 任务完成后调用清理接口或设置 TTL 自动清理
|
||
- 磁盘告警:workspace 总占用超过 10GB 返回 503
|
||
- `task_id` 只允许 `[a-zA-Z0-9_-]`,防止路径穿越注入
|
||
|
||
### 5.3 新增管理端点
|
||
|
||
```
|
||
GET /api/v1/workspace/list → 列出所有 task_id 和磁盘占用
|
||
DELETE /api/v1/workspace/{task_id} → 清理指定工作空间
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Dockerfile 修改
|
||
|
||
**当前状态:** 只安装 `gcc`,无 git/ssh/kubectl。
|
||
|
||
**修改后关键变更:**
|
||
|
||
```dockerfile
|
||
FROM python:3.12-slim
|
||
|
||
WORKDIR /app
|
||
ENV PYTHONUNBUFFERED=1 PYTHONDONTWRITEBYTECODE=1
|
||
|
||
# 新增:git + openssh-client + curl(kubectl 安装需要)
|
||
RUN apt-get update && apt-get install -y \
|
||
gcc git openssh-client curl ca-certificates gnupg \
|
||
&& rm -rf /var/lib/apt/lists/*
|
||
|
||
# 新增:安装 kubectl
|
||
RUN curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \
|
||
&& chmod +x kubectl && mv kubectl /usr/local/bin/
|
||
|
||
# 新增:paramiko(SSH)、gitpython(可选,subprocess git 为主)
|
||
RUN pip install --no-cache-dir -r requirements.txt requests paramiko gitpython
|
||
|
||
# 新增:工作空间目录(PVC 挂载时会覆盖)
|
||
RUN mkdir -p /workspace /tmp/projects
|
||
|
||
EXPOSE 8000 8001
|
||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||
CMD curl -f http://localhost:8000/health || exit 1
|
||
CMD ["python", "run_api_server.py"]
|
||
```
|
||
|
||
**镜像大小预估影响:** git + openssh ≈ +30MB,kubectl ≈ +50MB,paramiko ≈ +5MB。总增量约 85MB,可接受。
|
||
|
||
---
|
||
|
||
## 7. K8s 部署配置修改
|
||
|
||
### 7.1 新增文件:code-ai-agent-deployment.yaml
|
||
|
||
code_ai_agent 需要独立 Deployment(与 agent-manager 主服务分离),关键新增配置段:
|
||
|
||
```yaml
|
||
spec:
|
||
template:
|
||
spec:
|
||
serviceAccountName: code-ai-agent
|
||
containers:
|
||
- name: code-ai-agent
|
||
env:
|
||
- name: GITEE_USERNAME
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: agent-manager-secret
|
||
key: GITEE_USERNAME
|
||
- name: GITEE_TOKEN
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: agent-manager-secret
|
||
key: GITEE_TOKEN
|
||
- name: SSH_TEST_HOST
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: code-ai-agent-ssh-secret
|
||
key: SSH_TEST_HOST
|
||
- name: SSH_USER
|
||
value: "azureuser"
|
||
volumeMounts:
|
||
- name: ssh-secret
|
||
mountPath: /root/.ssh
|
||
readOnly: true
|
||
- name: kubeconfig
|
||
mountPath: /root/.kube
|
||
readOnly: true
|
||
- name: workspace
|
||
mountPath: /workspace
|
||
resources:
|
||
requests:
|
||
memory: "512Mi"
|
||
cpu: "300m"
|
||
limits:
|
||
memory: "1Gi"
|
||
cpu: "1000m"
|
||
volumes:
|
||
- name: ssh-secret
|
||
secret:
|
||
secretName: code-ai-agent-ssh-secret
|
||
defaultMode: 0400
|
||
- name: kubeconfig
|
||
secret:
|
||
secretName: kubeconfig-secret
|
||
optional: true
|
||
- name: workspace
|
||
emptyDir:
|
||
sizeLimit: 20Gi
|
||
```
|
||
|
||
### 7.2 agent-manager-secret 新增 key
|
||
|
||
在现有 `k8s/agent-manager-secret.yaml` 补充:
|
||
```yaml
|
||
GITEE_USERNAME: "zhanggangyong"
|
||
```
|
||
|
||
### 7.3 新建 code-ai-agent-ssh-secret.yaml
|
||
|
||
```yaml
|
||
apiVersion: v1
|
||
kind: Secret
|
||
metadata:
|
||
name: code-ai-agent-ssh-secret
|
||
namespace: agent-manager
|
||
type: Opaque
|
||
data:
|
||
id_rsa: <base64-encoded-private-key>
|
||
known_hosts: <base64-encoded-known_hosts>
|
||
SSH_TEST_HOST: <base64-encoded-azure-vm-ip>
|
||
```
|
||
|
||
### 7.4 RBAC 新增 Role + RoleBinding
|
||
|
||
```yaml
|
||
apiVersion: rbac.authorization.k8s.io/v1
|
||
kind: Role
|
||
metadata:
|
||
name: code-ai-agent-role
|
||
namespace: agent-manager
|
||
rules:
|
||
- apiGroups: ["apps"]
|
||
resources: ["deployments"]
|
||
verbs: ["get", "patch", "update"]
|
||
- apiGroups: [""]
|
||
resources: ["pods"]
|
||
verbs: ["get", "list"]
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 实现优先级
|
||
|
||
### P0 — 核心能力(第一阶段,必须先完成)
|
||
|
||
| 编号 | 内容 | 验收标准 |
|
||
|------|------|----------|
|
||
| P0-1 | Dockerfile 安装 git + openssh-client + kubectl | `docker run ... git --version` 输出正常 |
|
||
| P0-2 | workspace.py 工作空间管理 | 单元测试覆盖路径注入防护(task_id 含 `../` 时拒绝)|
|
||
| P0-3 | git_tools.py:clone + branch + status + commit + push | 成功 clone gitee 仓库,创建分支并推送 |
|
||
| P0-4 | ssh_tools.py:exec | SSH 到 Azure VM 执行 `echo ok`,返回 exit_code=0 |
|
||
| P0-5 | api_server.py 新增 /git/* 和 /ssh/exec 路由 | HTTP 调用返回正确 JSON,异常时返回 4xx/5xx |
|
||
| P0-6 | SSH Secret + Volume Mount K8s 配置 | Pod 启动后 `/root/.ssh/id_rsa` 权限为 0400 |
|
||
|
||
### P1 — 完整工作流(第二阶段)
|
||
|
||
| 编号 | 内容 | 验收标准 |
|
||
|------|------|----------|
|
||
| P1-1 | deploy_tools.py:rollout-restart + set-image | 成功触发 K8s 滚动更新,等待就绪返回 |
|
||
| P1-2 | api_server.py 新增 /deploy/k8s 路由 | 调用后 deployment 完成更新,status 字段正确 |
|
||
| P1-3 | RBAC:code-ai-agent ServiceAccount + Role | `kubectl auth can-i patch deployment` 返回 yes |
|
||
| P1-4 | git diff 接口 | 返回正确 unified diff 格式 |
|
||
| P1-5 | workspace list/cleanup 管理端点 | GET /workspace/list 返回含磁盘占用的列表 |
|
||
| P1-6 | mcp_server.py 注册新工具 | MCP 工具列表中出现 git_clone、ssh_exec、k8s_deploy |
|
||
|
||
### P2 — 增强与优化(第三阶段)
|
||
|
||
| 编号 | 内容 | 说明 |
|
||
|------|------|------|
|
||
| P2-1 | 替换 HTTP token 为 SSH key 方式访问 git | 更安全,需 gitee 配置 deploy key |
|
||
| P2-2 | workspace 磁盘告警 + TTL 自动清理 | 防止 emptyDir 耗尽,定时任务每小时扫描 |
|
||
| P2-3 | SSH 连接池(paramiko Transport 复用) | 减少高频调用连接建立开销 |
|
||
| P2-4 | /api/v1/pipeline/run 编排端点 | 单次调用完成 clone→修改→测试→部署全流程 |
|
||
| P2-5 | 操作审计日志(structured log) | 所有 git/ssh/deploy 操作可追溯,含 task_id |
|
||
|
||
---
|
||
|
||
## 9. 潜在风险与注意事项
|
||
|
||
### 风险 1:Git Token 泄露
|
||
- **场景:** token 嵌入 URL 后被 `git remote -v`、进程环境变量或日志打印
|
||
- **缓解:** clone 后立即 `git remote set-url origin <无密码URL>`;日志中 URL 做正则脱敏;不将 token 写入任何文件
|
||
|
||
### 风险 2:workspace 磁盘耗尽
|
||
- **场景:** 大量任务未清理,emptyDir 超限导致 Pod 被驱逐
|
||
- **缓解:** emptyDir 设 `sizeLimit: 20Gi`;API 层磁盘检查(超 10GB 返回 503);P2 阶段加 TTL 自动清理
|
||
|
||
### 风险 3:SSH 私钥被容器内进程读取
|
||
- **场景:** 容器内其他进程或代码执行漏洞读取 `/root/.ssh/id_rsa`
|
||
- **缓解:** Volume `defaultMode: 0400`;容器以非 root 用户运行(P2 阶段);考虑使用 Vault Agent Injector 替代 Secret Volume
|
||
|
||
### 风险 4:K8s 部署权限过宽
|
||
- **场景:** code_ai_agent 被攻击后可滥用 kubectl 权限影响其他服务
|
||
- **缓解:** RBAC 严格限制到 `agent-manager` 命名空间,只允许 get/patch/update Deployment;禁止 delete、exec、secret 等危险操作
|
||
|
||
### 风险 5:并发 git 操作冲突
|
||
- **场景:** 两个任务使用相同 task_id 或同一仓库并发操作
|
||
- **缓解:** task_id 全局唯一(UUID);每个 task_id 独立目录;api_server.py 对同一 task_id 的写操作加文件锁
|
||
|
||
### 风险 6:Azure VM SSH 连接超时或不可达
|
||
- **场景:** 网络抖动或 VM 重启导致 SSH 命令挂起
|
||
- **缓解:** paramiko 设置 `banner_timeout`、`auth_timeout`、`timeout`;所有 ssh.exec 调用强制设置 `timeout` 参数(默认 120s);超时后返回明确错误而非挂起
|
||
|
||
### 风险 7:CI/CD 循环触发
|
||
- **场景:** code_ai_agent 推送代码触发 CI,CI 再触发 code_ai_agent,形成死循环
|
||
- **缓解:** commit message 加 `[skip-ci]` 标记;部署端点需要明确的 image tag 参数,不自动推断
|
||
|
||
---
|
||
|
||
## 10. 工作计划(Task Flow)
|
||
|
||
### Step 1:基础设施准备(P0-1, P0-6)
|
||
- 修改 `Dockerfile`,安装 git/openssh/kubectl
|
||
- 创建 `code-ai-agent-ssh-secret.yaml`
|
||
- 更新 `agent-manager-secret.yaml` 补充 `GITEE_USERNAME`
|
||
- **验收:** Pod 启动正常,`/root/.ssh/id_rsa` 权限 0400
|
||
|
||
### Step 2:工作空间与 Git 工具(P0-2, P0-3)
|
||
- 实现 `src/server/tools/workspace.py`
|
||
- 实现 `src/server/tools/git_tools.py`
|
||
- 编写单元测试
|
||
- **验收:** 能 clone gitee 仓库,创建分支,commit+push
|
||
|
||
### Step 3:SSH 工具与 API 路由(P0-4, P0-5)
|
||
- 实现 `src/server/tools/ssh_tools.py`
|
||
- 在 `api_server.py` 注册 `/git/*` 和 `/ssh/exec` 路由
|
||
- **验收:** HTTP 调用 clone + ssh exec 全流程通
|
||
|
||
### Step 4:部署工具与完整流程(P1-1 ~ P1-3)
|
||
- 实现 `src/server/tools/deploy_tools.py`
|
||
- 注册 `/deploy/k8s` 路由
|
||
- 配置 RBAC
|
||
- **验收:** 调用 `/deploy/k8s` 触发滚动更新成功
|
||
|
||
### Step 5:MCP 工具注册与增强(P1-4 ~ P1-6, P2)
|
||
- 在 `mcp_server.py` 注册新工具
|
||
- workspace 管理端点
|
||
- 按需推进 P2 优化项
|
||
|
||
---
|
||
|
||
## 成功标准
|
||
|
||
1. 完整工作流(clone → branch → 代码修改 → commit/push → SSH 测试 → K8s 部署)可通过 HTTP API 驱动,无人工干预
|
||
2. 所有凭证(git token、SSH 私钥)通过 K8s Secret 注入,不硬编码
|
||
3. 并发多任务互不干扰(task_id 隔离)
|
||
4. 单个操作失败有明确错误信息,不影响其他任务
|
||
5. Pod 重启后工作空间可按需重建(无状态设计)
|
||
|
||
---
|
||
|
||
**Does this plan capture your intent?**
|
||
- `proceed` — 开始实现,移交 executor
|
||
- `adjust [X]` — 返回调整某个模块设计
|
||
- `restart` — 废弃重新开始
|