بنقرة واحدة
ci-cd-and-automation
自动化 CI/CD 流水线设置。在设置或修改构建和部署流水线时使用。当需要自动化质量门禁、在 CI 中配置测试运行器,或建立部署策略时使用。当需要处理 CI 上不稳定(flaky)的测试时使用。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
自动化 CI/CD 流水线设置。在设置或修改构建和部署流水线时使用。当需要自动化质量门禁、在 CI 中配置测试运行器,或建立部署策略时使用。当需要处理 CI 上不稳定(flaky)的测试时使用。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
指导稳定的 RPC、存储协议和接口设计。在设计节点间 RPC、存储协议语义、模块边界或任何公共接口时使用。在定义 gRPC service、对象存储或文件系统语义、节点间的类型契约,或确立组件边界时使用。
进行多维度代码审查。在合并任何变更之前使用。在审查由你自己、另一个智能体或人类编写的代码时使用。当需要在代码进入主分支之前评估其跨多个维度的质量时使用。当需要评估变更的正确性、可读性、架构与性能,或审查 PR/diff 时使用。
为清晰性而简化代码。在重构代码以提高可读性而不改变行为时使用。当代码可以正常工作但比应有的更难阅读、维护或扩展时使用。在审查已积累不必要复杂性的代码时使用。当组件过度设计、过于炫技而难以维护时使用。当需要清理越来越难读懂的代码时使用。
验证系统的一致性与持久性承诺。在设计或修改复制协议、写路径、崩溃恢复逻辑时使用。当需要证明已确认的写入不丢失、副本间不发散、崩溃后能恢复到一致状态,或评审 fsync/校验和/事务语义时使用。
优化智能体上下文设置。在开始新会话、智能体输出质量下降、在不同任务之间切换,或需要为项目配置规则文件和上下文时使用。
指导系统化的根因调试。当测试失败、构建中断、行为不符合预期,或遇到任何意外错误时使用。当需要系统化地找到并修复根本原因而非猜测时使用。当服务崩溃(panic)、空指针异常、或之前通过的测试突然挂掉时使用。当生产环境间歇性报错、需要定位根因时使用。当测试或构建昨天还通过、今天就挂了时使用。
| name | ci-cd-and-automation |
| description | 自动化 CI/CD 流水线设置。在设置或修改构建和部署流水线时使用。当需要自动化质量门禁、在 CI 中配置测试运行器,或建立部署策略时使用。当需要处理 CI 上不稳定(flaky)的测试时使用。 |
自动化质量门禁,确保没有任何变更在未通过测试、lint、类型检查和构建的情况下到达生产环境。CI/CD 是每个其他技能的强制执行机制——它捕获人类和智能体遗漏的问题,并且在每一次变更上都一致地做到这一点。
左移: 尽可能在流水线的早期阶段捕获问题。在 lint 中捕获的缺陷成本是几分钟;同样的缺陷在生产环境中捕获的成本是数小时。将检查向上游移动——静态分析在测试之前,测试在预发布之前,预发布在生产之前。
更快即更安全: 更小的批次和更频繁的发布降低风险,而非增加风险。包含 3 个变更的部署比包含 30 个变更的部署更容易调试。频繁发布能建立对发布过程本身的信心。
每个变更在合并之前都要通过这些门禁:
Pull Request 已创建
│
▼
┌─────────────────┐
│ LINT 检查 │ golangci-lint / clippy
│ ↓ 通过 │
│ 静态检查 │ go vet / cargo check
│ ↓ 通过 │
│ 单元测试 │ go test / cargo nextest
│ ↓ 通过 │
│ 构建 │ go build / cargo build
│ ↓ 通过 │
│ 集成测试 │ 存储/数据库 集成测试
│ ↓ 通过 │
│ 集群测试(可选)│ 多节点集成 + 故障注入
│ ↓ 通过 │
│ 安全审计 │ govulncheck / cargo audit
│ ↓ 通过 │
│ 二进制体积检查 │ 二进制体积基线
└─────────────────┘
│
▼
准备好接受审查
任何门禁都不能跳过。 如果 lint 失败,修复 lint——不要禁用规则。如果测试失败,修复代码——不要跳过测试。
# .github/workflows/ci.yml
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
- name: Lint
uses: golangci/golangci-lint-action@v6
- name: Vet
run: go vet ./...
- name: Test
run: go test -race -coverprofile=coverage.out ./...
- name: Build
run: go build ./...
- name: Vulnerability check
run: go run golang.org/x/vuln/cmd/govulncheck@latest ./...
integration:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_DB: testdb
POSTGRES_USER: ci_user
POSTGRES_PASSWORD: ${{ secrets.CI_DB_PASSWORD }}
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
- name: Run migrations
run: goose -dir migrations postgres "$DATABASE_URL" up
env:
DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb
- name: Integration tests
run: go test -tags=integration ./internal/store/...
env:
DATABASE_URL: postgresql://ci_user:${{ secrets.CI_DB_PASSWORD }}@localhost:5432/testdb
注意: 即使对于仅用于 CI 的测试数据库,也应使用 GitHub Secrets 管理凭证而非硬编码值。这能培养良好习惯,并防止测试凭证在其他上下文中被意外复用。
cluster-integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: true
- name: Build binaries
run: make build
- name: Start 3-node test cluster
run: ./scripts/test-cluster.sh up --nodes 3
- name: Run cluster integration tests
run: go test -tags=cluster ./tests/cluster/...
- name: Collect cluster logs
if: failure()
run: ./scripts/test-cluster.sh collect-logs
- uses: actions/upload-artifact@v4
if: failure()
with:
name: cluster-logs
path: test-cluster-logs/
慢速、长耗时的测试不进 PR 关键路径,改为按计划运行:
on:
schedule:
- cron: '0 2 * * *' # 每天凌晨运行
jobs:
nightly:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Start test cluster
run: ./scripts/test-cluster.sh up --nodes 5
- name: Fault-injection suite
run: go test -tags=faultinjection ./tests/fault/...
- name: Soak test
run: ./scripts/soak-test.sh --duration 4h --workload mixed
AI 智能体与 CI 结合的力量在于反馈循环。当 CI 失败时:
CI 失败
│
▼
复制失败输出
│
▼
将其提供给智能体:
"CI 流水线因以下错误而失败:
[粘贴具体错误]
修复问题并在再次推送前在本地验证。"
│
▼
智能体修复 → 推送 → CI 再次运行
关键模式:
Lint 失败 → 智能体运行 `golangci-lint run --fix` 并提交
静态检查错误 → 智能体读取错误位置并修复
测试失败 → 智能体遵循 debugging-and-error-recovery 技能
构建错误 → 智能体检查配置和依赖项
每个 PR 将构建产物部署到预发布集群,用于手动验证:
# 在 PR 上将构建产物部署到预发布节点
deploy-staging:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: Build
run: make build
- name: Deploy to staging cluster
run: ./scripts/rolling-deploy.sh --env staging --batch 1
功能标志将部署与发布解耦。将不完整或有风险的功能部署在标志后面,从而可以:
// 简单的功能标志模式
if featureFlags.IsEnabled("new-replication-protocol", nodeID) {
return newReplicator.Replicate(ctx, entries)
}
return legacyReplicator.Replicate(ctx, entries)
标志生命周期: 创建 → 为测试启用 → 灰度 → 全量上线 → 移除标志和死代码。永远存在的标志会变成技术债务——在创建标志时就设置清理日期。
PR 合并到 main
│
▼
预发布部署(自动)
│ 手动验证
▼
生产部署(手动触发或预发布后自动)
│
▼
监控错误(15 分钟窗口期)
│
├── 检测到错误 → 回滚
└── 干净 → 完成
每次部署都应该是可逆的:
# 手动回滚工作流
name: Rollback
on:
workflow_dispatch:
inputs:
version:
description: 'Version to rollback to'
required: true
jobs:
rollback:
runs-on: ubuntu-latest
steps:
- name: Rollback deployment
run: |
# 从包仓库安装指定旧版本,逐节点滚动回退
./scripts/rolling-deploy.sh \
--pkg myservice=${{ inputs.version }} \
--strategy rolling --batch 1
.env.example → 已提交(开发者的模板)
.env → 不提交(本地开发)
.env.test → 已提交(测试环境,无真实机密)
CI 机密 → 存储在 GitHub Secrets / vault 中
生产机密 → 存储在部署平台 / vault 中
CI 永远不应拥有生产机密。为 CI 测试使用单独的机密。
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: gomod
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
- package-ecosystem: cargo
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
指定某人负责保持 CI 绿色。当构建失败时,构建值守者的工作是修复或回滚——而不是导致构建失败的变更的作者。这可以防止在每个人都认为别人会修复时,失败的构建不断积累。
当流水线超过 10 分钟时,按影响顺序应用以下策略:
CI 流水线太慢?
├── 缓存依赖项
│ └── 使用 setup-go 的 cache 选项缓存模块与构建产物,Rust 项目用 sccache
├── 并行运行作业
│ └── 将 lint、vet、test、build 拆分为独立的并行作业
├── 只运行变更相关的部分
│ └── 使用路径过滤器跳过不相关的作业(例如,跳过仅文档 PR 的集群测试)
├── 使用矩阵构建
│ └── 将测试套件分片到多个运行器上
├── 优化测试套件
│ └── 从关键路径中移除慢速测试,改为按计划运行
└── 使用更大的运行器
└── GitHub 托管的更大运行器或自托管运行器用于 CPU 密集型构建
示例:缓存和并行
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with: { go-version: '1.23', cache: true }
- uses: golangci/golangci-lint-action@v6
vet:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with: { go-version: '1.23', cache: true }
- run: go vet ./...
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with: { go-version: '1.23', cache: true }
- run: go test -race -coverprofile=coverage.out ./...
| 合理化借口 | 现实 |
|---|---|
| "CI 太慢了" | 优化流水线(见下方 CI 优化),不要跳过它。一个 5 分钟的流水线可以防止数小时的调试。 |
| "这个变更是小事,跳过 CI" | 小变更也会破坏构建。对小变更来说 CI 本来也很快。 |
| "这个测试不稳定,重新运行就行" | 不稳定的测试掩盖了真正的缺陷,浪费了所有人的时间。修复不稳定性。 |
| "我们以后再加 CI" | 没有 CI 的项目会累积损坏状态。从第一天就设置好它。 |
| "手动测试就够了" | 手动测试不可扩展且不可重复。自动化你能自动化的内容。 |
设置或修改 CI 之后: