正在学习

使用示例

将源文件路径映射到测试。在实际项目中,你可能需要解析导入图。

mapping = { "app/app.py": ["tests/test_app.py"] }

changed_json = sys.stdin.read() changed = json.loads(changed_json)["changed"] selected = set()

for path in changed: if path in mapping: for t in mapping[path]: if Path(t).exists(): selected.add(t)

如果没有匹配到任何内容,则回退到完整测试套件

if not selected: selected = {"tests"}

print(" ".join(sorted(selected)))

scripts/build_image.sh
```bash
#!/usr/bin/env bash
set -euo pipefail

APP_NAME="opt-pipeline-demo"
IMAGE="{IMAGE:-ghcr.io/{GITHUB_REPOSITORY}/${APP_NAME}}"
TAG="{TAG:-{GITHUB_SHA::7}}"

echo "[build] 正在构建 TAG (使用缓存)"
docker build \
    --file - \
    --tag "TAG" \
    --tag "$IMAGE:latest" \
    --cache-from "$IMAGE:latest" \
    . <<'DOCKER'
FROM python:3.11-slim
WORKDIR /app
COPY app/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app/ .
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
DOCKER

.github/workflows/ci.yml

name: 优化的 CI
on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
  workflow_dispatch: {}
concurrency:
  group: opt-ci-${{ github.ref }}
  cancel-in-progress: true
env:
  PYTHON_VERSION: "3.11"
  CLAUDE_MODEL: claude-3.5-sonnet
  CLAUDE_BUDGET_USD: "0.05"
  EXPECTED_OUTPUT_TOKENS: "1800"
jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      changed: ${{ steps.diff.outputs.changed }}
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - id: diff
        run: |
          python3 scripts/changed_paths.py > changed.json
          echo "changed=GITHUB_OUTPUT
  test:
    needs: prepare
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: actions/setup-python@v5
        with: { python-version: ${{ env.PYTHON_VERSION }} }
      - name: 缓存 pip
        uses: actions/cache@v4
        with:
          path: ~/.cache/pip
          key: pip-{{ env.PYTHON_VERSION }}-${{ hashFiles('app/requirements.txt') }}
          restore-keys: pip-{{ env.PYTHON_VERSION }}-
      - name: 安装依赖 + pytest
        run: |
          python -m pip install --upgrade pip
          pip install -r app/requirements.txt pytest
      - name: 选择性测试列表
        id: select
        run: |
          echo '{{ needs.prepare.outputs.changed }}' '{changed:$changed}' \
          | python scripts/selective_tests.py > tests_to_run.txt
          echo "tests=GITHUB_OUTPUT
      - name: 运行测试
        run: |
          echo "正在运行: ${{ steps.select.outputs.tests }}"
          pytest -q ${{ steps.select.outputs.tests }}
  build:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - name: 登录 GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: 拉取最新镜像以供缓存使用
        run: |
          docker pull ghcr.io/${{ github.repository }}/opt-pipeline-demo:latest || true
      - name: 使用缓存构建并推送
        env:
          GITHUB_REPOSITORY: ${{ github.repository }}
          GITHUB_SHA: ${{ github.sha }}
        run: |
          bash scripts/build_image.sh
          docker push ghcr.io/${{ github.repository }}/opt-pipeline-demo:latest
          docker push ghcr.io/{GITHUB_SHA::7}
  docs_with_claude:
    needs: [test]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: 准备提示词
        run: |
          cat > .prompt.txt <<'PROMPT'
          总结 FastAPI 服务并生成一个简洁的 README 章节,内容包括:
          - 用途和接口
          - 本地运行说明
          - 健康检查示例
          PROMPT
      - name: 估算 Claude 成本并执行门控
        id: estimate
        env:
          CLAUDE_MODEL: ${{ env.CLAUDE_MODEL }}
          CLAUDE_BUDGET_USD: ${{ env.CLAUDE_BUDGET_USD }}
          EXPECTED_OUTPUT_TOKENS: ${{ env.EXPECTED_OUTPUT_TOKENS }}
        run: |
          python3 scripts/estimate_tokens.py .prompt.txt > estimate.json || exit_code=$?
          cat estimate.json
          echo "decision=GITHUB_OUTPUT
          echo "model=GITHUB_OUTPUT
          echo "est_cost=GITHUB_OUTPUT
          exit ${exit_code:-0}
      - name: 使用 Claude 生成文档(模拟)
        if: steps.estimate.outputs.decision == 'allow'
        run: |
          echo "## README(自动生成)" > README.md
          echo "" >> README.md
          echo "- 模型: ${{ steps.estimate.outputs.model }}" >> README.md
          echo "- 预估成本: $${{ steps.estimate.outputs.est_cost }}" >> README.md
          echo "" >> README.md
          echo "### 服务" >> README.md
          echo "FastAPI 应用暴露 /health 接口,并使用 Uvicorn 运行。" >> README.md
      - name: 回退到更便宜的模型结果(模拟)
        if: steps.estimate.outputs.decision == 'switch'
        run: |
          echo "## README(自动生成,预算回退至 Haiku)" > README.md
          echo "FastAPI 应用暴露 /health 接口,并使用 Uvicorn 运行。" >> README.md
      - uses: actions/upload-artifact@v4
        with:
          name: 生成的 README
          path: README.md

此工作流展示了组合优化:

  • 基于 requirements.txt 哈希的确定性依赖缓存。
  • 在构建前拉取 :latest 镜像并确定性打标签,以实现 Docker 层复用。
  • 基于变更的测试选择,必要时回退到完整测试套件。
  • Token 成本估算,自动限流或降级 Claude 使用。
  • 并发取消机制,确保只有最新提交的流水线能运行完成。

说明表格:优化、机制与效果

优化项 机制 实施位置 预期影响
确定性依赖缓存 按 requirements 的哈希值缓存 测试作业中的 actions/cache 安装速度提升 2–10 倍
Docker 层缓存 拉取最新镜像并复用层 构建作业的 pull + cache-from 构建时间减少 30–80%
基于变更的执行 将变更文件映射到测试 selective_tests.py 和 changed_paths.py 跳过无关测试,反馈更快
并发取消 同一引用上的先前运行被取消 concurrency 块 节省 runner 分钟数和成本
AI 支出门控 估算 token 并与预算比较 docs_with_claude 中的 estimate_tokens.py Claude 成本可预测
回退策略 切换到更便宜的模型或存根 docs_with_claude 的决策分支 在预算内保持流水线通过
制品复用 上传生成的文档 upload-artifact 输出清晰,无需重跑

通过将缓存复用、路径感知执行、Docker 层缓存、并行化以及 Claude token 门控层层叠加,你把一条既昂贵又缓慢的流水线转变成了一个可预测、速度快且尊重预算的系统。该方法具备可扩展性:可以添加更多映射以细化选择性测试、将镜像缓存提升到远程注册表缓存,或扩展成本门控以在多个 Claude 模型及最大输出大小之间进行选择。借助这些模式,你的 CI 既对开发者友好,又对财务友好,同时保持代码和文档的相同质量标准。

第 13 章 – Claude Code 故障排查与调优

练习题

在 CI 工作流中,当 scripts/estimate_tokens.py 脚本与 docs_with_claude 作业集成时,其主要目的是什么?

A. 计算仓库中已更改文件的数量
B. 根据 token 数量和模型定价估算调用 Claude API 的成本
C. 构建 Docker 镜像并将其推送到镜像仓库
D. 根据已更改的文件运行选择性测试

以下哪些是前述知识点中提到的、且适用于所述CI工作流的AI可观测性最佳实践?

A. 集中日志:将所有使用日志存储在单个存储库或数据库中,以便进行分析和审计。
B. 自动告警:配置成本阈值、高延迟响应或异常活动激增的告警。
C. 对所有微服务使用FastAPI以确保一致性。
D. 集成仪表板:使用Prometheus + Grafana或Elastic Stack等工具获取实时可视化洞察。
E. 始终使用最昂贵的Claude模型以确保高质量输出。

CI 工作流中的 build 任务依赖于 test 任务的成功完成,以确保只有经过测试和验证的代码才会被构建并推送到镜像仓库。

在 CI 工作流中,___ 作业负责准备已更改文件的列表,以确定需要选择性地运行哪些测试。

登录后解锁笔记、知识点解析、AI 问答

立即登录