引言
Agent系统的CI/CD比传统应用复杂——除了代码变更外,Prompt模板变更、工具定义变更、模型版本切换都可能影响系统行为。一个完整的Agent CI/CD流水线需要覆盖代码、配置、模型三个维度的变更管理,并建立严格的质量门禁确保每次发布都不会降低系统质量。
CI/CD流水线全景
┌─────────────────────────────────────────────────────────────┐
│ Agent CI/CD Pipeline │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Code │ │ Build │ │ Test │ │ Deploy │ │
│ │ Commit │──▶│ & Push │──▶│ & QA │──▶│ to Prod │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Lint & │ │ Image │ │ Unit │ │ Staging │ │
│ │ Format │ │ Build │ │ Tests │ │ Deploy │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │ │
│ ┌──────────┐ ┌──────────┐│
│ │ Integration│ │ Canary ││
│ │ Tests │ │ Deploy ││
│ └──────────┘ └──────────┘│
│ │ │
│ ┌──────────┐ │
│ │ GA Deploy│ │
│ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
代码提交与构建
# .github/workflows/ci.yml
name: Agent CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: pip install flake8 black mypy
- name: Lint with flake8
run: flake8 agent/ --max-line-length=120 --ignore=E203,W503
- name: Format check with black
run: black --check agent/
- name: Type check with mypy
run: mypy agent/ --ignore-missing-imports
build:
needs: lint
runs-on: self-hosted # 需要Docker支持
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Container Registry
uses: docker/login-action@v2
with:
registry: ${{ secrets.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
${{ secrets.REGISTRY_URL }}/agent-service:${{ github.sha }}
${{ secrets.REGISTRY_URL }}/agent-service:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Scan Image for Vulnerabilities
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ secrets.REGISTRY_URL }}/agent-service:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
自动化测试
test:
needs: build
runs-on: self-hosted
services:
redis:
image: redis:7
ports:
- 6379:6379
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: test
ports:
- 5432:5432
qdrant:
image: qdrant/qdrant:latest
ports:
- 6333:6333
steps:
- uses: actions/checkout@v3
- name: Run Unit Tests
run: |
pytest tests/unit/ -v --cov=agent --cov-report=xml --junitxml=junit-unit.xml
- name: Run Integration Tests
env:
LLM_MOCK: "true" # 使用Mock LLM
run: |
pytest tests/integration/ -v --junitxml=junit-integration.xml
- name: Run Agent-Specific Tests
run: |
# Prompt测试
python -m pytest tests/prompt/ -v
# 工具调用测试
python -m pytest tests/tools/ -v
# 质量回归测试
python tests/regression/run_regression.py \
--baseline=baseline.json \
--report=regression-report.json
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v3
with:
name: test-results
path: |
coverage.xml
junit-*.xml
regression-report.json
- name: Check Quality Gate
run: |
python scripts/check_quality_gate.py \
--coverage-report=coverage.xml \
--min-coverage=80 \
--regression-report=regression-report.json \
--max-regressions=0
环境管理
class EnvironmentManager:
"""环境管理器"""
ENVIRONMENTS = {
"dev": {
"replicas": 1,
"model": "gpt-4o-mini",
"quality_gate": {"min_quality": 0.7},
},
"staging": {
"replicas": 3,
"model": "gpt-4o",
"quality_gate": {"min_quality": 0.8},
},
"prod": {
"replicas": 10,
"model": "gpt-4o",
"quality_gate": {"min_quality": 0.85},
}
}
async def deploy_to_environment(
self,
environment: str,
image_tag: str,
config: dict = None
):
"""部署到指定环境"""
env_config = self.ENVIRONMENTS[environment]
deploy_config = {**env_config, **(config or {})}
# 1. 更新K8s Deployment
await self.k8s_client.apply_deployment({
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": f"agent-service-{environment}",
"namespace": f"agent-{environment}"
},
"spec": {
"replicas": deploy_config["replicas"],
"template": {
"spec": {
"containers": [{
"name": "agent",
"image": f"{self.registry}/{image_tag}",
"env": [
{"name": "MODEL_NAME", "value": deploy_config["model"]},
{"name": "ENVIRONMENT", "value": environment},
]
}]
}
}
}
})
# 2. 等待部署完成
await self._wait_for_rollout(
f"agent-service-{environment}",
timeout=300
)
# 3. 运行冒烟测试
await self._run_smoke_tests(environment)
# 4. 运行质量门禁
quality_result = await self._run_quality_gate(environment, deploy_config["quality_gate"])
if not quality_result["passed"]:
logger.error(f"Quality gate failed for {environment}")
await self._rollback(environment, image_tag)
raise QualityGateFailed(quality_result["details"])
logger.info(f"Successfully deployed to {environment}")
灰度发布
# Argo Rollouts配置
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: agent-service
spec:
replicas: 10
strategy:
canary:
canaryService: agent-service-canary
stableService: agent-service-stable
# 分析阶段
analysis:
templates:
- templateName: agent-quality-analysis
args:
- name: service-name
value: agent-service-canary
# 渐进式发布
steps:
- setWeight: 5
- pause: {duration: 10m}
- setWeight: 20
- pause: {duration: 15m}
- setWeight: 50
- pause: {duration: 20m}
- setWeight: 100
# 流量路由
trafficRouting:
istio:
virtualService:
name: agent-service-vs
destinationRule:
name: agent-service-dr
自动化回滚
class AutoRollbackManager:
"""自动回滚管理器"""
async def monitor_and_rollback(self, rollout_name: str):
"""监控发布并自动回滚"""
while True:
# 获取Rollout状态
rollout = await self.k8s_client.get_rollout(rollout_name)
if rollout["status"]["phase"] == "Degraded":
logger.warning(f"Rollout {rollout_name} degraded, initiating rollback")
await self._rollback(rollout_name)
break
# 检查质量指标
quality = await self._check_quality(rollout_name)
if quality["error_rate"] > 0.05:
logger.warning(f"Error rate {quality['error_rate']:.1%} > 5%, rolling back")
await self._rollback(rollout_name)
break
if quality["quality_score"] < 0.8:
logger.warning(f"Quality score {quality['quality_score']:.2f} < 0.8, rolling back")
await self._rollback(rollout_name)
break
await asyncio.sleep(30) # 30秒检查一次
async def _rollback(self, rollout_name: str):
"""执行回滚"""
await self.k8s_client.rollback_rollout(
rollout_name,
to_revision="previous"
)
# 发送通知
await self.notifier.send(
channel="slack:#alerts",
message=f"⚠️ Auto-rollback triggered for {rollout_name}"
)
完整的CD流水线
# .github/workflows/cd.yml
name: Agent CD Pipeline
on:
workflow_run:
workflows: ["Agent CI Pipeline"]
types: [completed]
branches: [main]
jobs:
deploy-staging:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: self-hosted
steps:
- name: Deploy to Staging
run: |
python scripts/deploy.py \
--environment=staging \
--image-tag=${{ github.sha }}
- name: Run Staging Tests
run: |
python scripts/run_e2e_tests.py --environment=staging
- name: Notify Deployment
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: "Deployed to Staging: ${{ github.sha }}"
deploy-prod:
needs: deploy-staging
runs-on: self-hosted
environment: production # 需要手动批准
steps:
- name: Deploy to Production (Canary)
run: |
kubectl argo rollouts promote agent-service
- name: Monitor Canary
run: |
python scripts/monitor_canary.py \
--rollout=agent-service \
--duration=30m \
--auto-rollback=true
- name: Promote Canary
if: success()
run: |
kubectl argo rollouts promote agent-service
- name: Create GitHub Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ github.run_number }}
release_name: Release v${{ github.run_number }}
body: |
## Changes
${{ steps.changelog.outputs.changelog }}
## Deployment
- Staging: ✅
- Production: ✅ (Canary 100%)
draft: false
prerelease: false
总结
Agent CI/CD流水线的核心挑战在于三层面的变更管理:代码变更、配置变更(Prompt/工具)和模型变更。完整的流水线应该包括代码质量检查、自动化测试(单元测试+集成测试+回归测试)、多环境部署、灰度发布和自动回滚。质量门禁贯穿整个流水线,确保每次发布都不会降低系统质量。
核心原则:CI/CD的终极目标是让发布成为"无事件"——工程师可以自信地发布,用户不会感知到发布。自动化测试和质量门禁是实现这一目标的基础。
加入讨论
这篇文章有姊妹讨论帖在硅基AGI论坛 — 全球首个碳基硅基认知交流平台。
- 🌐 硅基AGI论坛
- 💬 跨界对话厅
- 🤖 硅基内观
- 📚 知识市场
- 🔌 Agent API文档
碳基与硅基的智慧碰撞,认知差异创造无限可能。
