关于 ci-cd-ops
面向维护 GitHub Actions 流水线的开发者,提供 CI/CD 配置与发布自动化参考。涵盖触发器、缓存、矩阵、密钥管理和常见部署模式。
主要功能
- 01GitHub Actions 工作流语法参考
- 02触发器与路径筛选模式
- 03多生态缓存与矩阵策略
- 04密钥管理及 OIDC 部署
- 05测试、部署与标签发布模板
适用场景
- 01为拉取请求配置自动化测试
- 02设置合并至 main 后的部署
- 03为多个版本或操作系统构建矩阵
- 04排查权限、缓存和并发部署问题
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ 0xdarkmatter/ claude-mods --skill ci-cd-ops安装后在 Claude Code 中输入/ci-cd-ops确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/.gitkeepreferences/github-actions.mdrelease-automation.mdtesting-pipelines.mdscripts/.gitkeep详细介绍
CI/CD 运维
使用 GitHub Actions、发布自动化工具和测试流水线实现持续集成、交付和部署的全面模式。
GitHub Actions 快速参考
工作流文件结构
name: CI # Display name in Actions tab
on: # Trigger events
push:
branches: [main]
pull_request:
branches: [main]
permissions: # GITHUB_TOKEN scope (least privilege)
contents: read
pull-requests: write
concurrency: # Prevent duplicate runs
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env: # Workflow-level environment variables
NODE_VERSION: "20"
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- run: npm ci
- run: npm test
核心语法元素
| 元素 | 用途 | 示例 |
|---|---|---|
on | 事件触发器 | push、pull_request、schedule |
jobs.<id>.runs-on | 运行器选择 | ubuntu-latest、self-hosted |
jobs.<id>.needs | 作业依赖项 | needs: [build, lint] |
jobs.<id>.if | 条件执行 | if: github.event_name == 'push' |
jobs.<id>.strategy.matrix | 并行变体 | node-version: [18, 20, 22] |
jobs.<id>.environment | 部署目标 | environment: production |
jobs.<id>.permissions | 令牌权限范围 | contents: write |
steps[*].uses | 使用一个操作 | uses: actions/checkout@v4 |
steps[*].run | 运行命令 | run: npm test |
steps[*].env | 步骤环境变量 | env: { CI: true } |
触发器决策树
| 场景 | 触发器 | 配置 |
|---|---|---|
| 每次 PR 时运行测试 | pull_request | branches: [main] |
| 合并到 main 时部署 | push | branches: [main] |
| 使用版本标签发布 | push | tags: ['v*'] |
| 每晚构建 | schedule | cron: '0 2 * * *' |
| 手动部署 | workflow_dispatch | inputs: { environment: ... } |
| 由另一个工作流调用 | workflow_call | inputs:、secrets: |
| PR 标签变更时 | pull_request | types: [labeled] |
| 议题评论时 | issue_comment | types: [created] |
| 发布内容发布时 | release | types: [published] |
| 推送软件包时 | registry_package | types: [published] |
触发器筛选模式
on:
push:
branches: [main, 'release/**'] # Branch patterns
paths: ['src/**', '!src/**/*.test.*'] # Path filters (ignore tests)
tags: ['v*'] # Tag patterns
pull_request:
types: [opened, synchronize, reopened] # Default types
paths-ignore: ['docs/**', '*.md'] # Ignore docs-only changes
缓存策略
| 生态系统 | 操作 / 键 | 路径 | 恢复键 |
|---|---|---|---|
| Node(npm) | actions/setup-node,并设置 cache: npm | 自动 | 自动 |
| Node(pnpm) | actions/setup-node,并设置 cache: pnpm | 自动 | 自动 |
| Go 模块 | actions/setup-go,并设置 cache: true | 自动 | 自动 |
| Cargo | actions/cache@v4 | ~/.cargo/registry、target | cargo-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} |
| pip / uv | actions/setup-python,并设置 cache: pip | 自动 | 自动 |
| Docker 层 | docker/build-push-action | 使用 buildx 缓存 | type=gha 或 type=registry |
| Gradle | actions/setup-java,并设置 cache: gradle | 自动 | 自动 |
| Composer | actions/cache@v4 | vendor | composer-${{ hashFiles('composer.lock') }} |
手动缓存示例
- uses: actions/cache@v4
with:
path: |
~/.cargo/bin
~/.cargo/registry
~/.cargo/git
target
key: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
cargo-${{ runner.os }}-
矩阵策略
strategy:
fail-fast: false # Don't cancel siblings on failure
max-parallel: 4 # Limit concurrent jobs
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20, 22]
include: # Add specific combos
- os: ubuntu-latest
node-version: 22
coverage: true
exclude: # Remove specific combos
- os: windows-latest
node-version: 18
动态矩阵
prepare:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set.outputs.matrix }}
steps:
- id: set
run: echo "matrix=$(jq -c . matrix.json)" >> "$GITHUB_OUTPUT"
test:
needs: prepare
strategy:
matrix: ${{ fromJson(needs.prepare.outputs.matrix) }}
密钥管理
| 范围 | 访问权限 | 使用场景 |
|---|---|---|
| 仓库密钥 | 仓库中的所有工作流 | API 密钥、令牌 |
| 环境密钥 | 目标环境的作业 | 生产环境凭据 |
| 组织密钥 | 组织中选定的仓库 | 共享服务账户 |
| OIDC 令牌 | 联合身份 | 云部署(无需存储密钥) |
密钥最佳实践
# Reference secrets - NEVER echo or log them
- run: deploy --token ${{ secrets.DEPLOY_TOKEN }}
# Mask custom values
- run: echo "::add-mask::$CUSTOM_SECRET"
# Use environments for deployment secrets
jobs:
deploy:
environment: production # Requires approval + has secrets
steps:
- run: deploy --key ${{ secrets.PROD_API_KEY }}
用于云服务的 OIDC(无需存储密钥)
permissions:
id-token: write
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/github-actions
aws-region: us-east-1
常见工作流模式
在拉取请求上运行测试
name: Test
on:
pull_request:
branches: [main]
concurrency:
group: test-${{ github.head_ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: npm }
- run: npm ci
- run: npm run lint
- run: npm test -- --coverage
合并到 Main 时部署
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- run: npx wrangler deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
使用标签发布
name: Release
on:
push:
tags: ['v*']
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- run: |
gh release create ${{ github.ref_name }} \
--generate-notes \
--title "${{ github.ref_name }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
常见问题表
| 常见问题 | 问题 | 修复方法 |
|---|---|---|
| 浅克隆 | git describe 失败,缺少历史记录 | 使用 actions/checkout@v4 并设置 fetch-depth: 0 |
| 默认权限 | GITHUB_TOKEN 默认是只读的 | 显式设置 permissions: |
| 固定 Action 版本 | @main 可能会在没有警告的情况下出问题 | 固定到 SHA:@abc123 或 @v4 |
| 来自分支仓库的 PR 密钥 | 来自分支仓库的 PR 无法使用密钥 | 谨慎使用 pull_request_target |
| 并发部署 | 生产环境中存在竞态条件 | 使用 concurrency: 组 |
| 缓存过时 | 缓存无限增长 | 在键中包含锁文件哈希 |
| Node.js 版本 | setup-node 的默认值各不相同 | 始终指定 node-version |
| Docker 层缓存 | 不使用缓存时会重建所有内容 | 使用 cache-from: type=gha |
| 矩阵 + 环境 | 每个矩阵任务都需要审批 | 在矩阵之后使用单个部署任务 |
| 路径筛选器 + 必需检查 | 被跳过的任务会阻止合并 | 使用 paths-filter Action,或将检查设为非必需 |
PR 中的 GITHUB_TOKEN | 无法触发其他工作流 | 使用 PAT 或 GitHub App 令牌 |
| Windows 换行符 | 脚本会因 \r\n 而失败 | 使用 .gitattributes 或 core.autocrlf |
表达式语法速查
| 表达式 | 结果 |
|---|---|
${{ github.event_name }} | push、pull_request 等 |
${{ github.ref_name }} | 分支或标签名称 |
${{ github.sha }} | 完整的提交 SHA |
${{ github.actor }} | 触发操作的用户 |
${{ runner.os }} | Linux、Windows、macOS |
${{ contains(github.event.head_commit.message, '[skip ci]') }} | 检查提交消息 |
${{ needs.build.outputs.version }} | 先前任务的输出 |
${{ fromJson(steps.meta.outputs.json) }} | 解析 JSON 输出 |
${{ hashFiles('**/package-lock.json') }} | 用于缓存键的哈希 |
${{ format('refs/heads/{0}', matrix.branch) }} | 字符串格式化 |
${{ toJson(matrix) }} | 调试:打印矩阵配置 |
步骤输出
steps:
- id: version
run: echo "value=$(cat VERSION)" >> "$GITHUB_OUTPUT"
- run: echo "Version is ${{ steps.version.outputs.value }}"
任务输出(用于跨任务通信)
jobs:
build:
runs-on: ubuntu-latest
outputs:
artifact-id: ${{ steps.upload.outputs.artifact-id }}
steps:
- id: upload
run: echo "artifact-id=abc123" >> "$GITHUB_OUTPUT"
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deploying ${{ needs.build.outputs.artifact-id }}"
参考文件
| 文件 | 内容 |
|---|---|
references/github-actions.md | 完整的工作流语法、可复用工作流、复合 Action、OIDC、运行器、调试 |
references/release-automation.md | 语义化版本控制、semantic-release、changesets、goreleaser、变更日志、发布 |
references/testing-pipelines.md | 测试阶段、并行化、覆盖率、服务容器、CI 中的端到端测试、部署流水线 |
评论
支持 Markdown