CI/CD 流水线设计

指导 Agent 将流水线拆为 lint、测试、构建、安全扫描、制品晋升与部署阶段,并定义失败快速、可缓存与可重试的节点。

阶段流水线

默认串行门禁顺序:静态检查 → 自动化测试 → 可复现构建 → 发布到目标环境。PR 与主分支可裁剪部署阶段或仅保留预览。

  PR / push
      │
      ▼
   ┌──────┐     ┌──────┐     ┌───────┐     ┌────────┐
   │ lint │ ──► │ test │ ──► │ build │ ──► │ deploy │
   └──────┘     └──────┘     └───────┘     └────────┘
      │             │             │              │
      └─ 失败即停    └─ 可并行 job  └─ 不可变制品   └─ 蓝绿/金丝雀/GitOps

完整的四阶段 GitHub Actions CI 流水线示例(lint 与 test 并行,build 依赖两者完成):

# .github/workflows/ci.yml
name: CI Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-24.04
    timeout-minutes: 10
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci --prefer-offline
      - run: npm run lint

  test:
    name: Test
    runs-on: ubuntu-24.04
    timeout-minutes: 20
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci --prefer-offline
      - run: npm test -- --coverage --ci
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: coverage
          path: coverage/

  build:
    name: Build
    runs-on: ubuntu-24.04
    timeout-minutes: 25
    needs: [lint, test]
    outputs:
      image-tag: ${{ steps.tag.outputs.tag }}
    steps:
      - uses: actions/checkout@v4
      - id: tag
        run: |
          VERSION=$(node -p "require('./package.json').version")
          SHA=$(git rev-parse --short HEAD)
          echo "tag=${VERSION}-${SHA}" >> "$GITHUB_OUTPUT"
      - name: Build Docker image
        run: |
          docker build \
            --label "git.sha=${{ github.sha }}" \
            -t myapp:${{ steps.tag.outputs.tag }} .
      - uses: actions/upload-artifact@v4
        with:
          name: image-tag
          path: /dev/null
          retention-days: 1

  deploy:
    name: Deploy to Staging
    runs-on: ubuntu-24.04
    timeout-minutes: 15
    needs: build
    if: github.ref == 'refs/heads/main'
    environment: staging
    steps:
      - name: Deploy ${{ needs.build.outputs.image-tag }}
        run: |
          echo "Deploying image tag: ${{ needs.build.outputs.image-tag }}"
          # kubectl set image deployment/myapp myapp=myregistry/myapp:${{ needs.build.outputs.image-tag }}

环境晋升

SKILL 中写清「谁可以推进到哪一环境」与自动/人工 gate,避免同一套流水线在未知条件下直打生产。

环境 典型触发 晋升门禁 数据 / 配置
Dev 分支 push、草稿 PR lint、快路径单测 合成数据、占位密钥
Staging 合并 main、RC tag 全量测试、安全扫描、契约测试 脱敏快照、与生产同型配置
Prod 发布审批、版本 tag 人工 gate、金丝雀/蓝绿、回滚预案 OIDC / 短时 token,禁止长期 PAT 入库

落地要点

SKILL 列出必选门禁与可选建议项;主分支与 PR 的差异(如是否部署预览环境);并发与 cancel-in-progress 策略避免排队浪费。

制品不可变 tag 与 SBOM/签名若需要,写明阶段顺序与产物存储。

部署策略:蓝绿、金丝雀或与 Argo/Flux 的 GitOps 同步;回滚触发条件与人工审批 gate 文档化。

  • 缓存:依赖目录、Docker layer、Terraform provider 缓存键设计。
  • 矩阵:语言版本与 OS 维度的上限,避免组合爆炸。
  • 可观测:流水线 trace、步骤耗时与失败通知渠道。

制品版本化策略:语义化版本 + Git SHA 组合,超时配置与失败通知示例:

# 版本化策略:semver + git SHA(在 build job 中使用)
- id: version
  run: |
    VERSION=$(node -p "require('./package.json').version")
    SHA=$(git rev-parse --short=8 HEAD)
    BUILD_DATE=$(date -u +%Y%m%d)
    TAG="${VERSION}+${BUILD_DATE}.${SHA}"
    echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
    echo "semver=${VERSION}" >> "$GITHUB_OUTPUT"

# 并行 job 的 needs 依赖配置
jobs:
  security-scan:
    needs: build          # 等待 build 完成后才扫描
    timeout-minutes: 15   # 超时:防止扫描任务挂起

  deploy-staging:
    needs: [build, security-scan]  # 多 job 依赖

# 失败通知:Slack webhook(在 on-failure 步骤中添加)
  - name: Notify Slack on failure
    if: failure()
    uses: slackapi/slack-github-action@v1.27.0
    with:
      payload: |
        {
          "text": "CI failed on ${{ github.ref }}",
          "blocks": [{
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "*Pipeline failed*: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>"
            }
          }]
        }
    env:
      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
      SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK

密钥与凭据

流水线里出现的每一个 secret 都应在 SKILL 中对应到「供给方式」与「轮换责任」,而不是仅写变量名。

Secrets:优先 OIDC federation、工作负载身份或短时 token;禁止将长期 PAT、kubeconfig、云厂商永久密钥写入仓库与日志。密钥通过运行商原生 secret store / sealed secrets 注入;PR 流水线使用只读、范围最小的凭据,与生产凭据隔离。

使用 OIDC 免密钥获取 AWS 临时凭据的完整示例:

# OIDC federation:无需长期 AWS Access Key 的部署 job
deploy:
  runs-on: ubuntu-24.04
  permissions:
    id-token: write   # 必须显式授权 OIDC token
    contents: read
  steps:
    - uses: actions/checkout@v4

    - name: Configure AWS credentials via OIDC
      uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
        role-session-name: github-actions-deploy
        aws-region: us-east-1
        # 信任策略中需绑定 sub: repo:myorg/myrepo:ref:refs/heads/main
        # 避免仅用 audience 或环境名作为唯一条件

    - name: Push image to ECR
      run: |
        aws ecr get-login-password | \
          docker login --username AWS \
            --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
        docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/myapp:${{ needs.build.outputs.image-tag }}

# 对应的 IAM 角色信任策略(JSON 片段)
# {
#   "StringEquals": {
#     "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
#     "token.actions.githubusercontent.com:sub":
#       "repo:myorg/myrepo:ref:refs/heads/main"
#   }
# }

阶段墙钟估算

按各阶段典型耗时(分钟)粗算一次完整流水线的墙钟时间;勾选并行时表示 lint 与 test 在同一波次并行跑完后再进入 build。数值仅保存在本会话的 sessionStorage,键名与其他页面区分。

各阶段耗时(分钟)

相对参考上限(180 分钟)

SKILL 片段

---
name: ci-cd-pipeline-design
description: 设计分阶段、可缓存、带门禁的 CI/CD 流水线
tags: [ci-cd, github-actions, devops]
---
# 流水线阶段设计
1. 阶段划分:lint → test → build → deploy,PR 可裁剪 deploy
2. 并行优化:lint 与 test 同波次并行,build 等待二者完成(needs: [lint, test])
3. 超时保护:每个 job 设置 timeout-minutes,防止挂起占用 runner
4. 并发控制:concurrency.group 含分支/PR,main 分支禁止 cancel-in-progress

# 制品与版本化
5. 版本化策略:semver(package.json/git tag)+ git SHA 短哈希组合 tag
6. 不可变制品:push 后仅引用 digest 或组合 tag,不覆盖 latest
7. 制品存储:通过 actions/upload-artifact 传递 job 间产物

# 密钥与凭据
8. OIDC 优先:AWS/GCP/Azure 均支持 id-token: write + federation,无需长期 key
9. 最小权限:顶层 permissions: {} 收紧,job 级按需放宽
10. 环境隔离:PR 流水线使用只读凭据,生产 deploy 绑定 environment: production

# 失败处理与通知
11. 失败快速:lint/test 失败立即停止,不进入 build/deploy
12. 失败通知:if: failure() + Slack/邮件 webhook,含 run URL 与分支信息
13. 缓存键:依赖锁文件哈希 + runner OS,restore-keys 降级但不混用环境

# 门禁清单
14. 必选门禁:lint、unit test、安全扫描(至少 SAST)
15. 可选门禁:集成测试、性能基准、bundlesize 回归、镜像扫描
16. 审批 gate:生产 deploy 须在 environment 配置 required reviewers

返回技能库 更多技能入口