📡 API 接口协议设计示例
openapi: 3.0.3
info:
title: 电商系统 API
version: 1.0.0
description: 在线商城系统 RESTful API 接口规范
servers:
- url: https://api.example.com/v1
description: 生产环境
- url: https://staging-api.example.com/v1
description: 预发布环境
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
paths:
/users:
post:
summary: 创建用户
tags: [用户管理]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserCreate'
responses:
'201' :
description: 用户创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400' :
description: 请求参数错误
get:
summary: 获取用户列表
tags: [用户管理]
parameters:
- name: page
in: query
schema:
type: integer
default: 1
- name: limit
in: query
schema:
type: integer
default: 20
responses:
'200' :
description: 成功
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
total:
type: integer
/products/{id}:
get:
summary: 获取商品详情
tags: [商品管理]
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
'200' :
description: 成功
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
'404' :
description: 商品不存在
schemas:
User:
type: object
properties:
id:
type: integer
username:
type: string
email:
type: string
created_at:
type: string
format: date-time
UserCreate:
type: object
required: [username, email, password]
properties:
username:
type: string
minLength: 3
maxLength: 50
email:
type: string
format: email
password:
type: string
minLength: 8
Product:
type: object
properties:
id:
type: integer
name:
type: string
price:
type: number
format: decimal
stock:
type: integer
description:
type: string
💡 AI 辅助 API 设计
使用 APIDesigner-Agent 可以根据 PRD 和技术方案自动生成完整的 OpenAPI 规范文档:
openclaw api-design --from tech_design/ --output api_spec.yaml
AI 会自动识别所有业务实体和操作流程,生成符合 RESTful 规范的 API 接口定义。
💻 AI Coding 实战示例
后端代码生成(Python FastAPI)
$ claude-code "根据 api_spec.yaml 生成用户管理的 CRUD 接口,使用 FastAPI + SQLAlchemy"
from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy.orm import Session
from ..models import User
from ..schemas import UserCreate, UserResponse
from ..database import get_db
router = APIRouter(prefix="/users" , tags=["用户管理" ])
@router.post("" , status_code=201 , response_model=UserResponse)
def create_user (user_data: UserCreate, db: Session = Depends(get_db)):
"""创建新用户"""
existing_user = db.query(User).filter(User.email == user_data.email).first()
if existing_user:
raise HTTPException(status_code=400 , detail="邮箱已被注册" )
new_user = User(
username=user_data.username,
email=user_data.email,
password_hash=hash_password(user_data.password)
)
db.add(new_user)
db.commit()
db.refresh(new_user)
return new_user
@router.get("" , response_model=List[UserResponse])
def get_users (
page: int = 1 ,
limit: int = 20 ,
db: Session = Depends(get_db)
):
"""获取用户列表(分页)"""
offset = (page - 1 ) * limit
users = db.query(User).offset(offset).limit(limit).all()
total = db.query(User).count()
return {"data" : users, "total" : total}
@router.get("/{user_id}" , response_model=UserResponse)
def get_user (user_id: int, db: Session = Depends(get_db)):
"""获取用户详情"""
user = db.query(User).filter(User.id == user_id).first()
if not user:
raise HTTPException(status_code=404 , detail="用户不存在" )
return user
前端代码生成(React + TypeScript)
$ claude-code
"根据 api_spec.yaml 生成用户管理的 React 组件,使用 TypeScript + Ant Design"
import React, { useState, useEffect }
from 'react' ;
import { Table, Button, Space, Modal, Form, Input, message }
from 'antd' ;
import { PlusOutlined, EditOutlined, DeleteOutlined }
from '@ant-design/icons' ;
import { userService }
from '@/services/userService' ;
import { User }
from '@/types/user' ;
const UserManagement: React.FC = () => {
const [users, setUsers] = useState
([]);
const [loading, setLoading] = useState(false );
const [modalVisible, setModalVisible] = useState(false );
const [form] = Form.useForm();
const loadUsers = async () => {
setLoading(true );
try {
const response = await userService.getUsers({ page: 1 , limit: 20 });
setUsers(response.data);
} catch (error) {
message.error('加载失败' );
} finally {
setLoading(false );
}
};
useEffect(() => {
loadUsers();
}, []);
const handleCreate = async (values: any) => {
try {
await userService.createUser(values);
message.success('创建成功' );
setModalVisible(false );
form.resetFields();
loadUsers();
} catch (error) {
message.error('创建失败' );
}
};
const columns = [
{ title: 'ID' , dataIndex: 'id' , key: 'id' },
{ title: '用户名' , dataIndex: 'username' , key: 'username' },
{ title: '邮箱' , dataIndex: 'email' , key: 'email' },
{
title: '操作' ,
key: 'action' ,
render: (_: any, record: User) => (
} size="small" >编辑
}
size="small"
danger
onClick={() => handleDelete(record.id)}
>删除
),
},
];
return (
16 }}>
"primary"
icon={ }
onClick={() => setModalVisible(true )}
>
新增用户
"id"
pagination={{ pageSize: 20 }}
/>
"新增用户"
open={modalVisible}
onCancel={() => setModalVisible(false )}
footer={null }
>
"username"
label="用户名"
rules={[{ required: true , message: '请输入用户名' }]}
>
"email"
label="邮箱"
rules={[
{ required: true , message: '请输入邮箱' },
{ type: 'email' , message: '邮箱格式不正确' }
]}
>
"password"
label="密码"
rules={[{ required: true , message: '请输入密码' , min: 8 }]}
>
"primary" htmlType="submit" >提交
);
};
export default UserManagement;
🎬 视频教程脚本:开发工程师使用 AI Coding 全流程
场景 1:API 协议自动生成(0:00-1:00)
画面: 从技术方案生成 OpenAPI 规范
$ openclaw api-design \
--input ./tech_design/backend_architecture.md \
--output ./api_spec.yaml \
--format openapi3
✅ API 规范生成完成
- 接口数量:24 个
- 数据模型:12 个
- 安全方案:JWT Bearer Token
📄 输出文件:./api_spec.yaml
场景 2:后端代码批量生成(1:00-2:30)
画面: 使用 Claude Code 批量生成后端代码
$ claude-code "/tdd 根据 api_spec.yaml 生成完整的 FastAPI 后端代码,包含 models, schemas, routers, crud 层"
🤖 AI 正在生成代码...
✅ models/user.py - 用户模型
✅ models/product.py - 商品模型
✅ models/order.py - 订单模型
✅ schemas/user.py - 用户 Schema
✅ routers/users.py - 用户路由
✅ crud/user.py - 用户 CRUD 操作
📁 代码已保存至:./backend/app/
⏱️ 生成耗时:3 分 42 秒
场景 3:前端代码批量生成(2:30-4:00)
画面: 使用 Claude Code 批量生成前端代码
$ claude-code "/tdd 根据 api_spec.yaml 生成 React + TypeScript 前端代码,包含 services, components, types"
🤖 AI 正在生成代码...
✅ types/user.ts - 用户类型定义
✅ types/product.ts - 商品类型定义
✅ services/userService.ts - 用户 API 服务
✅ services/productService.ts - 商品 API 服务
✅ components/UserManagement.tsx - 用户管理组件
✅ components/ProductList.tsx - 商品列表组件
📁 代码已保存至:./frontend/src/
⏱️ 生成耗时:4 分 15 秒
场景 4:代码审查与优化(4:00-5:30)
画面: 使用 CodeReviewer-Agent 进行代码审查
$ openclaw code-review ./backend/app/ ./frontend/src/
🔍 代码审查报告:
【后端代码】
✅ 代码规范:通过(PEP 8)
⚠️ 性能警告:users.py 第 45 行 N+1 查询问题
✅ 安全扫描:通过(无 SQL 注入风险)
💡 优化建议:添加数据库连接池配置
【前端代码】
✅ 代码规范:通过(ESLint)
⚠️ 类型警告:ProductList.tsx 第 78 行缺少 null 检查
✅ 无障碍访问:通过(WCAG 2.1 AA)
💡 优化建议:使用 React.memo 优化渲染性能
📄 详细报告:./reports/code_review.md
场景 5:API 文档自动生成(5:30-6:00)
画面: 生成 Swagger UI 文档
$ openclaw doc-gen --input ./api_spec.yaml --output ./docs/api/
📚 API 文档生成完成:
- Swagger UI: ./docs/api/swagger.html
- Redoc: ./docs/api/redoc.html
- Postman Collection: ./docs/api/postman_collection.json
🌐 本地预览:http://localhost:8000/docs
📝 实操练习
从技术方案生成 OpenAPI 规范文档
使用 Claude Code 生成后端 CRUD 代码
使用 Claude Code 生成前端组件代码
运行代码审查工具并修复问题
生成并部署 API 文档(Swagger UI)
运行演示
$ openclaw api-design --input tech_design/ --output api_spec.yaml
📡 API 协议设计中...
✅ 生成 24 个 RESTful 接口
$ claude-code "/tdd 根据 api_spec.yaml 生成完整代码"
🤖 AI Coding 中...
✅ 后端代码:42 个文件
✅ 前端代码:38 个文件
✅ 单元测试:56 个测试用例
$ openclaw code-review ./backend/ ./frontend/
🔍 代码审查完成
- 发现问题:3 个
- 已自动修复:2 个
- 待人工处理:1 个
📁 代码生成完成!
├── backend/app/ (42 files)
├── frontend/src/ (38 files)
└── tests/ (56 test files)
⏱️ 总耗时:12 分钟
测试工程师 Unit Test → 集成测试 → UI 自动化验收
🎯 岗位职责
编写和维护单元测试用例
设计和执行集成测试方案
搭建 E2E 端到端测试框架
实施 UI 自动化测试(Selenium/Playwright)
分析测试结果并跟踪 Bug 修复
维护测试环境和测试数据
🛠️ 使用的 AI Agents
🧪
UnitTestGenerator-Agent
单元测试自动生成 Agent
pytest
Jest
覆盖率分析
🔗
IntegrationTest-Agent
集成测试设计 Agent
API 测试
服务编排
Mock 数据
🎭
E2ETest-Agent
E2E 端到端测试 Agent
Playwright
Cypress
用户旅程
🤖
UITest-Agent
UI 自动化测试 Agent
Selenium
视觉回归
无障碍测试
🧪 单元测试自动生成示例
$ claude-code "/tdd 为 users.py 生成完整的 pytest 单元测试,覆盖所有边界情况"
import pytest
from fastapi.testclient import TestClient
from ..main import app
from ..database import TestingSessionLocal, engine, Base
from ..models import User
@pytest.fixture(scope="function" )
def db_session ():
Base.metadata.create_all(bind=engine)
db = TestingSessionLocal()
yield db
db.close()
Base.metadata.drop_all(bind=engine)
@pytest.fixture
def client (db_session):
def override_get_db ():
try :
yield db_session
finally :
pass
app.dependency_overrides[get_db] = override_get_db
with TestClient(app) as c:
yield c
app.dependency_overrides.clear()
def test_create_user_success (client):
"""测试成功创建用户"""
user_data = {
"username" : "testuser" ,
"email" : "test@example.com" ,
"password" : "securepass123"
}
response = client.post("/users" , json=user_data)
assert response.status_code == 201
data = response.json()
assert data["username" ] == "testuser"
assert data["email" ] == "test@example.com"
assert "id" in data
assert "password" not in data
def test_create_user_duplicate_email (client, db_session):
"""测试重复邮箱创建失败"""
existing_user = User(username="existing" , email="dup@example.com" )
db_session.add(existing_user)
db_session.commit()
user_data = {
"username" : "newuser" ,
"email" : "dup@example.com" ,
"password" : "securepass123"
}
response = client.post("/users" , json=user_data)
assert response.status_code == 400
assert "邮箱已被注册" in response.json()["detail" ]
def test_create_user_invalid_email (client):
"""测试无效邮箱格式"""
user_data = {
"username" : "testuser" ,
"email" : "invalid-email" ,
"password" : "securepass123"
}
response = client.post("/users" , json=user_data)
assert response.status_code == 422
def test_create_user_short_password (client):
"""测试密码长度不足"""
user_data = {
"username" : "testuser" ,
"email" : "test@example.com" ,
"password" : "short"
}
response = client.post("/users" , json=user_data)
assert response.status_code == 422
def test_get_users_pagination (client, db_session):
"""测试用户列表分页"""
for i in range(25 ):
user = User(username=f"user{i}" , email=f"user{i}@example.com" )
db_session.add(user)
db_session.commit()
response = client.get("/users?page=1&limit=20" )
assert response.status_code == 200
data = response.json()
assert len(data["data" ]) == 20
assert data["total" ] == 25
response = client.get("/users?page=2&limit=20" )
data = response.json()
assert len(data["data" ]) == 5
def test_get_user_not_found (client):
"""测试获取不存在的用户"""
response = client.get("/users/99999" )
assert response.status_code == 404
assert "用户不存在" in response.json()["detail" ]
✅ 测试覆盖率目标
使用 AI 自动生成单元测试可达到90%+ 的代码覆盖率。运行覆盖率报告:
pytest --cov=./app --cov-report=html
AI 会分析未覆盖的代码分支并自动补充测试用例。
🔗 集成测试示例
import pytest
from httpx import AsyncClient
from ..services.order_service import create_order
from ..services.payment_service import process_payment
@pytest.mark.asyncio
async def test_complete_order_flow ():
"""测试完整的下单流程:创建订单 -> 扣减库存 -> 支付 -> 更新订单状态"""
async with AsyncClient() as client:
user_response = await client.post("/users" , json={
"username" : "order_test_user" ,
"email" : "order@test.com" ,
"password" : "testpass123"
})
assert user_response.status_code == 201
user_id = user_response.json()["id" ]
product_response = await client.post("/products" , json={
"name" : "测试商品" ,
"price" : 99.99 ,
"stock" : 100
})
assert product_response.status_code == 201
product_id = product_response.json()["id" ]
order_response = await client.post("/orders" , json={
"user_id" : user_id,
"items" : [{
"product_id" : product_id,
"quantity" : 2
}]
})
assert order_response.status_code == 201
order_id = order_response.json()["id" ]
product_detail = await client.get(f"/products/{product_id}" )
assert product_detail.json()["stock" ] == 98
payment_response = await client.post(f"/orders/{order_id}/pay" , json={
"payment_method" : "alipay"
})
assert payment_response.status_code == 200
order_detail = await client.get(f"/orders/{order_id}" )
assert order_detail.json()["status" ] == "paid"
expected_total = 99.99 * 2
assert abs(order_detail.json()["total_amount" ] - expected_total) < 0.01
🎭 E2E 端到端测试示例(Playwright)
import pytest
from playwright.sync_api import Page, expect
from datetime import datetime
@pytest.mark.e2e
def test_user_registration_to_order (page: Page, base_url: str):
"""E2E 测试:从用户注册到成功下单的完整流程"""
page.goto(base_url)
expect(page).to_have_title("在线商城" )
page.click('text="注册"' )
expect(page).to_have_url(f"{base_url}/register" )
timestamp = datetime.now().strftime("%Y%m%d%H%M%S" )
page.fill('input[name="username"]' , f"e2e_user_{timestamp}" )
page.fill('input[name="email"]' , f"e2e_{timestamp}@test.com" )
page.fill('input[name="password"]' , "TestPass123!" )
page.fill('input[name="confirm_password"]' , "TestPass123!" )
page.click('button[type="submit"]' )
expect(page).to_have_url(f"{base_url}/login" )
expect(page.locator('.alert-success' )).to_be_visible()
page.fill('input[name="email"]' , f"e2e_{timestamp}@test.com" )
page.fill('input[name="password"]' , "TestPass123!" )
page.click('button[type="submit"]' )
expect(page).to_have_url(f"{base_url}/" )
expect(page.locator('.user-menu' )).to_be_visible()
page.click('text="手机数码"' )
expect(page).to_have_url(f"{base_url}/products?category=electronics" )
page.click('.product-card:first-child' )
expect(page.locator('h1.product-name' )).to_be_visible()
page.select_option('select[name="quantity"]' , "2" )
page.click('button:has-text("加入购物车")' )
expect(page.locator('.toast-success' )).to_contain_text("已加入购物车" )
page.click('.cart-icon' )
expect(page).to_have_url(f"{base_url}/cart" )
expect(page.locator('.cart-item' )).to_have_count(1 )
expect(page.locator('.cart-quantity' )).to_contain_text("× 2" )
page.click('button:has-text("去结算")' )
expect(page).to_have_url(f"{base_url}/checkout" )
page.fill('input[name="receiver_name"]' , "测试用户" )
page.fill('input[name="receiver_phone"]' , "13800138000" )
page.fill('textarea[name="address"]' , "北京市朝阳区测试路 1 号" )
page.click('input[value="alipay"]' )
page.click('button:has-text("提交订单")' )
expect(page).to_have_url(f"{base_url}/orders/\\d+" )
expect(page.locator('.order-status' )).to_contain_text("待支付" )
page.click('button:has-text("立即支付")' )
expect(page.locator('.payment-success' )).to_be_visible()
expect(page.locator('.order-status' )).to_contain_text("已支付" )
page.screenshot(path=f"screenshots/e2e_order_{timestamp}.png" )
🤖 UI 自动化测试示例(Selenium)
from selenium import webdriver
from selenium.webdriver.common.by import By
from PIL import Image
import imagehash
import pytest
@pytest.mark.visual
def test_homepage_visual_regression ():
"""首页视觉回归测试"""
options = webdriver.ChromeOptions()
options.add_argument('--headless' )
driver = webdriver.Chrome(options=options)
try :
driver.get("https://example.com" )
driver.set_window_size(1920 , 1080 )
current_screenshot = "screenshots/current_homepage.png"
driver.save_screenshot(current_screenshot)
baseline_screenshot = "screenshots/baseline_homepage.png"
hash_current = imagehash.average_hash(Image.open(current_screenshot))
hash_baseline = imagehash.average_hash(Image.open(baseline_screenshot))
diff = hash_current - hash_baseline
print(f"图片差异度:{diff}" )
assert diff < 10 , f"视觉回归测试失败:差异度过大 ({diff})"
finally :
driver.quit()
@pytest.mark.accessibility
def test_accessibility_compliance ():
"""无障碍访问测试(WCAG 2.1 AA)"""
from axe_selenium_python import Axe
driver = webdriver.Chrome()
try :
driver.get("https://example.com" )
axe = Axe(driver)
axe.inject()
results = axe.run()
assert len(results["violations" ]) == 0 , \
f"发现无障碍问题:{results['violations']}"
finally :
driver.quit()
🎬 视频教程脚本:测试工程师 AI 自动化测试全流程
场景 1:单元测试自动生成(0:00-1:30)
画面: AI 分析代码并生成单元测试
$ openclaw unit-test --source ./backend/app/ --output ./tests/unit/
🧪 单元测试生成中...
✅ 分析源代码文件:42 个
✅ 生成测试用例:156 个
✅ 预估覆盖率:92%
📁 测试文件已保存:
├── tests/unit/test_users.py
├── tests/unit/test_products.py
├── tests/unit/test_orders.py
└── ... (共 28 个测试文件)
⏱️ 生成耗时:5 分 20 秒
场景 2:运行单元测试并生成报告(1:30-2:30)
画面: 执行测试并查看覆盖率报告
$ pytest tests/unit/ --cov=./app --cov-report=html -v
============================= test session starts ==============================
collected 156 items
tests/unit/test_users.py::test_create_user_success PASSED
tests/unit/test_users.py::test_create_user_duplicate_email PASSED
tests/unit/test_users.py::test_get_users_pagination PASSED
...
======================== 156 passed in 12.34s ========================
---------- coverage: platform linux, python 3.12.0 -----------
Name Stmts Miss Cover
-----------------------------------------
app/models.py 45 0 100%
app/schemas.py 67 2 97%
app/routers/users.py 89 5 94%
app/crud/user.py 56 3 95%
-----------------------------------------
TOTAL 1245 98 92%
Coverage HTML written to dir htmlcov
✅ 测试通过率:100%
✅ 代码覆盖率:92%
场景 2:集成测试执行(2:30-3:30)
画面: 运行集成测试验证服务间交互
$ pytest tests/integration/ -v --tb=short
============================= test session starts ==============================
collected 24 items
tests/integration/test_order_flow.py::test_complete_order_flow PASSED
tests/integration/test_payment_integration.py::test_alipay_payment PASSED
tests/integration/test_inventory_management.py::test_stock_deduction PASSED
...
======================== 24 passed in 45.67s ========================
✅ 集成测试全部通过
✅ 服务间调用正常
✅ 数据一致性验证通过
场景 3:E2E 测试执行(3:30-5:00)
画面: Playwright 执行端到端测试
$ pytest tests/e2e/ -v --browser chromium
============================= test session starts ==============================
collected 8 items
tests/e2e/test_user_journey.py::test_user_registration_to_order PASSED
tests/e2e/test_checkout_flow.py::test_guest_checkout PASSED
tests/e2e/test_admin_panel.py::test_product_management PASSED
...
======================== 8 passed in 2m 15s ========================
📸 截图已保存至:./screenshots/e2e/
🎥 录屏已保存至:./recordings/e2e/
✅ E2E 测试全部通过
✅ 用户旅程验证成功
场景 4:UI 自动化视觉回归测试(5:00-6:00)
画面: 执行视觉回归和无障碍测试
$ pytest tests/ui/ -v -m "visual or accessibility"
============================= test session starts ==============================
collected 12 items
tests/ui/test_visual_regression.py::test_homepage_visual_regression PASSED
tests/ui/test_visual_regression.py::test_product_page_visual_regression PASSED
tests/ui/test_accessibility.py::test_wcag_compliance PASSED
tests/ui/test_accessibility.py::test_keyboard_navigation PASSED
...
======================== 12 passed in 1m 30s ========================
✅ 视觉回归测试通过(无意外 UI 变化)
✅ 无障碍访问符合 WCAG 2.1 AA 标准
✅ 键盘导航测试通过
场景 5:生成综合测试报告(6:00-7:00)
画面: AI 汇总所有测试结果生成报告
$ openclaw test-report --output ./reports/test_summary.html
📊 测试报告生成完成:
【测试概览】
- 单元测试:156 个,通过率 100%,覆盖率 92%
- 集成测试:24 个,通过率 100%
- E2E 测试:8 个,通过率 100%
- UI 自动化:12 个,通过率 100%
【质量指标】
- 总体通过率:100% (200/200)
- 代码覆盖率:92%
- 关键路径覆盖:100%
- 无障碍合规:AA 级
【发现的问题】
- 严重:0
- 警告:2(已记录)
- 建议:5(已记录)
📄 详细报告:./reports/test_summary.html
📈 趋势图表:./reports/trend_charts.png
📝 实操练习
使用 AI 为后端代码生成单元测试
运行单元测试并生成覆盖率报告
编写集成测试验证服务间交互
使用 Playwright 编写 E2E 测试脚本
执行 UI 自动化视觉回归测试
生成综合测试报告并分析质量指标
运行演示
$ openclaw unit-test --source ./backend/app/
🧪 生成单元测试...
✅ 生成 156 个测试用例
$ pytest tests/unit/ --cov=./app
======================== 156 passed in 12.34s ========================
✅ 代码覆盖率:92%
$ pytest tests/integration/
======================== 24 passed in 45.67s ========================
$ pytest tests/e2e/ --browser chromium
======================== 8 passed in 2m 15s ========================
$ openclaw test-report --output reports/test_summary.html
📊 测试报告生成完成
- 总测试数:200 个
- 通过率:100%
- 覆盖率:92%
⏱️ 总耗时:8 分钟
DevOps 工程师 CI/Jenkins + Docker + K8S(KubeSphere) 自动部署
🎯 岗位职责
设计和维护 CI/CD 流水线(Jenkins/GitLab CI)
编写 Dockerfile 和 Docker Compose 配置
管理 Kubernetes 集群和 KubeSphere 平台
实施自动化部署和灰度发布策略
监控系统性能和日志聚合
保障系统高可用和灾难恢复
🛠️ 使用的 AI Agents
🔄
CICDPipeline-Agent
CI/CD 流水线自动生成 Agent
Jenkins
GitLab CI
GitHub Actions
🐳
DockerBuilder-Agent
Docker 镜像构建 Agent
Dockerfile
多阶段构建
镜像优化
☸️
K8SDeploy-Agent
Kubernetes 部署配置生成 Agent
Deployment
Service
Ingress
HPA
📊
MonitorAgent
监控告警配置 Agent
Prometheus
Grafana
ELK Stack
🔄 Jenkins CI/CD 流水线配置
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'registry.example.com'
IMAGE_NAME = 'ecommerce-app'
K8S_NAMESPACE = 'production'
KUBECONFIG_CREDENTIALS_ID = 'k8s-prod-config'
}
tools {
nodejs 'NodeJS 18'
jdk 'JDK 17'
}
stages {
stage('Checkout' ) {
steps {
checkout scm
script {
env.GIT_COMMIT_SHORT = sh(returnStdout: true , script: 'git rev-parse --short HEAD' ).trim()
env.BUILD_VERSION = "${env.BUILD_NUMBER}-${env.GIT_COMMIT_SHORT}"
}
}
}
stage('Code Quality Check' ) {
parallel {
stage('Backend Lint' ) {
steps {
sh 'pip install flake8 black'
sh 'flake8 backend/app/'
sh 'black --check backend/app/'
}
}
stage('Frontend Lint' ) {
steps {
dir('frontend' ) {
sh 'npm ci'
sh 'npm run lint'
}
}
}
stage('Security Scan' ) {
steps {
sh 'pip install bandit safety'
sh 'bandit -r backend/app/'
sh 'safety check'
}
}
}
}
stage('Unit Tests' ) {
steps {
parallel {
stage('Backend Tests' ) {
steps {
sh 'pip install pytest pytest-cov'
sh 'pytest tests/unit/ --cov=./app --cov-report=xml'
}
post {
always {
junit 'tests/unit/results.xml'
publishCoverage adapters: [coberturaAdapter('coverage.xml' )], sourceFileEncoding: 'UTF-8'
}
}
}
stage('Frontend Tests' ) {
steps {
dir('frontend' ) {
sh 'npm ci'
sh 'npm run test:coverage'
}
}
post {
always {
junit 'frontend/coverage/junit.xml'
}
}
}
}
}
}
stage('Integration Tests' ) {
steps {
script {
docker-compose -f docker-compose.test.yml up -d
sleep 30
}
sh 'pytest tests/integration/ -v'
}
post {
always {
script {
docker-compose -f docker-compose.test.yml down
}
}
}
}
stage('Build Docker Image' ) {
steps {
script {
env.DOCKER_IMAGE = "${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_VERSION}"
}
sh 'docker build -t ${DOCKER_IMAGE} -f backend/Dockerfile .'
sh 'docker tag ${DOCKER_IMAGE} ${DOCKER_REGISTRY}/${IMAGE_NAME}:latest'
}
}
stage('Push Docker Image' ) {
steps {
withCredentials([usernamePassword(credentialsId: 'docker-registry-creds' , usernameVariable: 'DOCKER_USER' , passwordVariable: 'DOCKER_PASS' )]) {
sh 'echo ${DOCKER_PASS} | docker login ${DOCKER_REGISTRY} -u ${DOCKER_USER} --password-stdin'
sh 'docker push ${DOCKER_IMAGE}'
sh 'docker push ${DOCKER_REGISTRY}/${IMAGE_NAME}:latest'
}
}
}
stage('Deploy to K8S' ) {
when {
branch 'main'
}
steps {
withKubeConfig([credentialsId: '${KUBECONFIG_CREDENTIALS_ID}' , serverUrl: '' ]) {
sh 'kubectl set image deployment/${IMAGE_NAME} app=${DOCKER_IMAGE} -n ${K8S_NAMESPACE}'
sh 'kubectl rollout status deployment/${IMAGE_NAME} -n ${K8S_NAMESPACE} --timeout=300s'
}
}
}
stage('Smoke Tests' ) {
when {
branch 'main'
}
steps {
script {
def healthCheck = sh(
script: 'curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health' ,
returnStdout: true
).trim()
if (healthCheck != '200' ) {
error('健康检查失败!触发自动回滚...' )
}
}
}
}
}
post {
success {
echo '🎉 构建和部署成功!'
script {
slackSend(color: 'good' , message: "构建 #${env.BUILD_NUMBER} 成功!\n版本:${env.BUILD_VERSION}\n镜像:${env.DOCKER_IMAGE}" )
}
}
failure {
echo '❌ 构建失败!'
script {
slackSend(color: 'danger' , message: "构建 #${env.BUILD_NUMBER} 失败!\n请检查:${env.BUILD_URL}" )
}
}
always {
cleanWs()
}
}
}
💡 AI 辅助生成 Jenkinsfile
使用 CICDPipeline-Agent 可根据项目结构自动生成 Jenkins 流水线配置:
openclaw cicd --type jenkins --output Jenkinsfile
AI 会自动识别项目的技术栈(Python/Node.js/Java 等),生成包含代码检查、测试、构建、部署的完整流水线。
🐳 Dockerfile 配置示例
FROM python:3.12-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y \\
gcc \\
libpq-dev \\
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
RUN useradd -m -u 1000 appuser
COPY --from=builder /root/.local /home/appuser/.local
COPY --from=builder /app .
COPY backend/app/ ./app/
ENV PATH=/home/appuser/.local/bin:$PATH \\
PYTHONUNBUFFERED=1 \\
PYTHONDONTWRITEBYTECODE=1
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
前端服务 Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s \\
CMD wget --quiet --tries=1 --spider http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
Docker Compose 配置
version: '3.8'
services:
backend:
build:
context: .
dockerfile: backend/Dockerfile
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://postgres:postgres@db:5432/ecommerce
- REDIS_URL=redis://redis:6379/0
- ENVIRONMENT=development
volumes:
- ./backend/app:/app/app
depends_on:
- db
- redis
networks:
- ecommerce-network
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
environment:
- REACT_APP_API_URL=http://localhost:8000
volumes:
- ./frontend/src:/app/src
depends_on:
- backend
networks:
- ecommerce-network
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=ecommerce
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432"
networks:
- ecommerce-network
redis:
image: redis:7-alpine
ports:
- "6379:6379"
networks:
- ecommerce-network
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- backend
- frontend
networks:
- ecommerce-network
volumes:
postgres-data:
networks:
ecommerce-network:
driver: bridge
☸️ Kubernetes 部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: ecommerce-backend
namespace: production
labels:
app: ecommerce
component: backend
spec:
replicas: 3
selector:
matchLabels:
app: ecommerce
component: backend
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: ecommerce
component: backend
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8000"
spec:
containers:
- name: backend
image: registry.example.com/ecommerce-app:v1.2.3
imagePullPolicy: Always
ports:
- containerPort: 8000
name: http
protocol: TCP
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
- name: REDIS_URL
valueFrom:
configMapKeyRef:
name: app-config
key: redis-url
- name: ENVIRONMENT
value: "production"
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8000
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: logs
mountPath: /app/logs
volumes:
- name: logs
emptyDir: {}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: ecommerce
component: backend
topologyKey: kubernetes.io/hostname
---
apiVersion: v1
kind: Service
metadata:
name: ecommerce-backend-service
namespace: production
spec:
selector:
app: ecommerce
component: backend
ports:
- port: 80
targetPort: 8000
protocol: TCP
name: http
type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ecommerce-backend-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ecommerce-backend
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
Ingress 配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ecommerce-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
tls:
- hosts:
- api.example.com
- www.example.com
secretName: ecommerce-tls
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ecommerce-backend-service
port:
number: 80
- host: www.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ecommerce-frontend-service
port:
number: 80
📊 KubeSphere 集成配置
apiVersion: devops.kubesphere.io/v1alpha3
kind: Pipeline
metadata:
name: ecommerce-pipeline
namespace: ecommerce-project
labels:
app: ecommerce
spec:
pipeline:
definition:
cpsScmFlow:
scm:
type: git
source:
url: https://github.com/example/ecommerce.git
credentialsId: github-credentials
scriptPath: Jenkinsfile
description: 电商系统 CI/CD 流水线
---
apiVersion: app.k8s.io/v1beta1
kind: Application
metadata:
name: ecommerce-app
namespace: ecommerce-project
spec:
selector:
matchLabels:
app: ecommerce
componentKinds:
- group: apps/v1
kind: Deployment
- group: v1
kind: Service
- group: networking.k8s.io/v1
kind: Ingress
descriptor:
version: "1.2.3"
description: "电商系统应用"
maintainers:
- name: DevOps Team
email: devops@example.com
✅ KubeSphere 优势
KubeSphere 提供企业级多租户容器平台,内置 DevOps 流水线、服务网格、监控告警等功能。通过图形化界面可轻松管理 K8S 集群,支持蓝绿部署、金丝雀发布等高级部署策略。
🎬 视频教程脚本:DevOps 自动化部署全流程
场景 1:CI/CD 流水线自动生成(0:00-1:30)
画面: AI 分析项目结构生成 Jenkinsfile
$ openclaw cicd --type jenkins --output Jenkinsfile
🔄 CI/CD 流水线生成完成:
✅ 代码质量检查(Lint + Security)
✅ 单元测试(Backend + Frontend)
✅ 集成测试
✅ Docker 镜像构建
✅ K8S 自动部署
✅ 健康检查 + 自动回滚
📄 配置文件:./Jenkinsfile
⏱️ 生成耗时:45 秒
场景 2:Docker 镜像构建(1:30-2:30)
画面: 构建并推送 Docker 镜像
$ docker build -t registry.example.com/ecommerce-app:v1.2.3 -f backend/Dockerfile .
Sending build context to Docker daemon 45.2MB
Step 1/15 : FROM python:3.12-slim AS builder
---> a1b2c3d4e5f6
...
Step 15/15 : CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
---> Running in 1a2b3c4d5e6f
Successfully built 7g8h9i0j1k2l
Successfully tagged registry.example.com/ecommerce-app:v1.2.3
$ docker push registry.example.com/ecommerce-app:v1.2.3
The push refers to repository [registry.example.com/ecommerce-app]
abc123: Pushed
def456: Pushed
ghi789: Pushed
v1.2.3: digest: sha256:abc123def456 size: 2456
✅ 镜像构建完成(大小:245MB)
✅ 推送成功(耗时:2 分 15 秒)
场景 3:K8S 部署执行(2:30-4:00)
画面: 使用 kubectl 部署到 K8S 集群
$ kubectl apply -f k8s/deployment.yaml
deployment.apps/ecommerce-backend configured
$ kubectl apply -f k8s/service.yaml
service/ecommerce-backend-service configured
$ kubectl apply -f k8s/ingress.yaml
ingress.networking.k8s.io/ecommerce-ingress configured
$ kubectl rollout status deployment/ecommerce-backend -n production
Waiting for deployment "ecommerce-backend" rollout to finish: 0 out of 3 new replicas have been updated...
Waiting for deployment "ecommerce-backend" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "ecommerce-backend" rollout to finish: 2 out of 3 new replicas have been updated...
deployment "ecommerce-backend" successfully rolled out
✅ 部署成功(滚动更新完成)
✅ 当前副本数:3/3
⏱️ 部署耗时:1 分 45 秒
场景 4:健康检查验证(4:00-5:00)
画面: 执行健康检查和冒烟测试
$ curl -s https://api.example.com/health | jq
{
"status": "healthy",
"timestamp": "2026-03-14T10:30:45Z",
"services": {
"database": "connected",
"redis": "connected",
"cache": "operational"
},
"version": "v1.2.3"
}
$ openclaw smoke-test --endpoint https://api.example.com
🔍 执行冒烟测试...
✅ GET /api/users - 200 OK (45ms)
✅ GET /api/products - 200 OK (38ms)
✅ POST /api/orders - 201 Created (125ms)
✅ 所有冒烟测试通过
✅ 平均响应时间:69ms
场景 5:KubeSphere 监控面板(5:00-6:00)
画面: 查看 KubeSphere 监控仪表盘
$ kubectl get pods -n production -l app=ecommerce
NAME READY STATUS RESTARTS AGE
ecommerce-backend-7d8f9c6b5-abc12 1/1 Running 0 5m
ecommerce-backend-7d8f9c6b5-def34 1/1 Running 0 5m
ecommerce-backend-7d8f9c6b5-ghi56 1/1 Running 0 5m
$ kubectl get hpa -n production
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
ecommerce-backend-hpa Deployment/ecommerce-backend 45%/70% 3 10 3
$ kubectl top pods -n production -l app=ecommerce
NAME CPU(cores) MEMORY(bytes)
ecommerce-backend-7d8f9c6b5-abc12 125m 456Mi
ecommerce-backend-7d8f9c6b5-def34 118m 442Mi
ecommerce-backend-7d8f9c6b5-ghi56 132m 468Mi
✅ 系统运行正常
✅ 资源使用率:CPU 45%, Memory 62%
✅ 自动扩缩容已启用
📝 实操练习
使用 AI 生成 Jenkins CI/CD 流水线配置
编写 Dockerfile 并构建优化镜像
配置 Docker Compose 本地开发环境
编写 K8S Deployment/Service/Ingress 配置
配置 HPA 自动扩缩容策略
在 KubeSphere 中创建 DevOps 项目并部署应用
配置 Prometheus 监控和 Grafana 仪表盘
运行演示
$ openclaw cicd --type jenkins --output Jenkinsfile
🔄 生成 CI/CD 流水线...
✅ Jenkinsfile 已创建
$ docker build -t ecommerce-app:v1.2.3 .
✅ 镜像构建完成(245MB)
$ docker push registry.example.com/ecommerce-app:v1.2.3
✅ 镜像推送成功
$ kubectl apply -f k8s/
deployment.apps/ecommerce-backend configured
service/ecommerce-backend-service configured
ingress.networking.k8s.io/ecommerce-ingress configured
$ kubectl rollout status deployment/ecommerce-backend
✅ 部署成功(滚动更新完成)
$ openclaw smoke-test --endpoint https://api.example.com
✅ 冒烟测试全部通过
📊 部署总结:
- 镜像版本:v1.2.3
- 副本数:3/3
- 部署耗时:2 分 30 秒
- 健康状态:Healthy
⏱️ 总耗时:5 分钟
🤝 人机协同操作指南
💡 核心理念
本系统采用"AI 主导 + 人工审核" 的协同模式。AI 负责重复性、标准化的工作(代码生成、测试编写、部署配置),人类专家负责创造性决策、质量把关和异常处理。
🎯 各角色人机协同最佳实践
产品经理 协同要点
工作环节
AI 负责
人工负责
协同方式
需求收集
整理会议纪要、提取关键点
与利益相关者沟通、判断优先级
AI 记录 → 人工确认
PRD 编写
生成文档框架、填充标准内容
定义核心业务逻辑、验收标准
AI 初稿 → 人工审核修改
用户故事
批量生成故事卡片
验证 INVEST 原则、调整优先级
AI 生成 → 人工筛选排序
架构师 协同要点
工作环节
AI 负责
人工负责
协同方式
技术选型
提供多方案对比、成本估算
基于业务场景做最终决策
AI 分析 → 人工决策
架构设计
生成架构图、ER 图、数据流图
审查设计合理性、识别风险点
AI 绘图 → 人工评审
规范制定
生成编码规范模板
定制团队特定规范
AI 模板 → 人工定制
开发工程师 协同要点
工作环节
AI 负责
人工负责
协同方式
代码编写
生成 CRUD 代码、样板代码
实现核心业务逻辑、算法优化
AI 生成 → 人工补充关键逻辑
代码审查
自动检测规范问题、安全漏洞
审查业务逻辑正确性、可维护性
AI 初筛 → 人工深度审查
Bug 修复
定位问题、提供修复建议
验证修复方案、防止回归
AI 诊断 → 人工验证
测试工程师 协同要点
工作环节
AI 负责
人工负责
协同方式
测试用例
自动生成单元测试、边界测试
设计复杂场景测试、探索性测试
AI 生成基础 → 人工补充复杂场景
测试执行
自动化执行测试、生成报告
分析失败原因、判断是否 Bug
AI 执行 → 人工分析
质量评估
统计覆盖率、性能指标
评估发布风险、决策是否上线
AI 数据 → 人工决策
DevOps 工程师 协同要点
工作环节
AI 负责
人工负责
协同方式
流水线配置
生成 CI/CD 模板、Dockerfile
定制特殊流程、审批节点
AI 模板 → 人工定制
部署执行
自动部署、健康检查
审批生产发布、处理异常
AI 执行 → 人工监督
监控告警
自动采集指标、触发告警
分析告警根因、制定优化方案
AI 监控 → 人工响应
⚠️ 人机协同注意事项
🔴 必须人工介入的场景
安全敏感操作: 生产环境数据库变更、密钥管理、权限调整
重大业务决策: 影响核心业务流程的功能变更、API 不兼容更新
合规审计要求: 金融、医疗等强监管行业的代码变更
AI 置信度低: 当 AI 标注"不确定"或"需要人工确认"时
异常情况处理: CI/CD 流水线连续失败、生产事故应急响应
✅ 可完全自动化的场景
标准化代码: CRUD 接口、DTO 转换、日志记录
常规测试: 单元测试、回归测试、性能基准测试
开发环境部署: 开发/测试环境的自动部署和销毁
文档生成: API 文档、代码注释、README 文件
代码格式化: Linter 自动修复、代码风格统一
📋 人机协同检查清单
需求阶段
AI 生成的 PRD 是否经过产品经理审核确认?
关键业务逻辑是否有明确的责任人签字?
需求优先级是否经过团队讨论确认?
开发阶段
AI 生成的代码是否经过 Code Review?
核心算法和业务逻辑是否有详细注释?
安全敏感代码是否有双人复核?
测试阶段
测试覆盖率是否达到团队标准(90%+)?
所有 P0 级别 Bug 是否已修复并验证?
性能测试结果是否满足 SLA 要求?
部署阶段
生产发布是否经过 Change Approval 审批?
回滚方案是否已准备并测试?
监控告警是否已配置并验证?
🎬 视频教程系列
本培训课件配套视频教程共 8 集,每集 15-20 分钟,覆盖从需求到部署的全流程。
📺
第 1 集:系统概览
介绍 OpenClaw + Claude Code 双引擎架构、各角色 Agents 职责、整体工作流程
15 分钟
入门必修
📺
第 2 集:产品经理实战
演示如何使用 AI Agent 从原始需求生成完整 PRD 文档和用户故事地图
18 分钟
产品必备
📺
第 3 集:架构师实战
展示 AI 如何生成多套技术方案对比、绘制架构图、设计数据库模型
20 分钟
架构必备
📺
第 4 集:开发工程师实战
完整演示 AI Coding 流程:API 设计 → 代码生成 → 代码审查 → 文档生成
25 分钟
开发核心
📺
第 5 集:测试工程师实战
展示 AI 自动生成单元测试、集成测试、E2E 测试和 UI 自动化测试
22 分钟
测试必备
📺
第 6 集:DevOps 工程师实战
演示 CI/CD 流水线配置、Docker 镜像构建、K8S 部署和 KubeSphere 集成
25 分钟
运维核心
📺
第 7 集:人机协同最佳实践
讲解各角色如何与 AI 高效协作、哪些场景必须人工介入、常见陷阱避免
18 分钟
全员必修
📺
第 8 集:完整项目演示
从零开始完整演示一个电商系统的端到端自动化研发全流程(加速版)
30 分钟
综合实战
📥 视频教程脚本下载
每个视频教程都配有详细脚本和操作手册,可供团队成员自学参考。
教程资源列表
📄 视频教程脚本全集.pdf - 包含全部 8 集视频的详细脚本和分镜
📄 实操练习手册.md - 每集配套的动手练习和指导
📄 常见问题 FAQ.md - 培训过程中遇到的典型问题和解答
📄 命令速查表.pdf - OpenClaw 和 Claude Code 常用命令快速参考
🎬 演示代码仓库 - GitHub: github.com/example/openclaw-training-demo
📥 下载全部教程资源
📝 培训考核与认证
考核方式
角色
理论考试
实操考核
通过标准
产品经理
30 分钟选择题(60 题)
独立完成 PRD 生成
理论≥80 分 + 实操通过
架构师
45 分钟案例分析(3 题)
完成技术方案设计
理论≥80 分 + 实操通过
开发工程师
30 分钟编程题(5 题)
完成模块代码生成
理论≥85 分 + 实操通过
测试工程师
30 分钟测试设计(4 题)
完成测试套件编写
理论≥85 分 + 实操通过
DevOps 工程师
40 分钟场景题(3 题)
完成 CI/CD 配置
理论≥85 分 + 实操通过
🏆 认证证书
通过考核的学员将获得"OpenClaw + Claude Code 端到端研发自动化系统认证工程师" 证书,有效期 2 年。续证需参加最新版本的更新培训和考核。