名称: cicd-pipeline
描述: 使用 GitHub Actions 创建、调试和管理 CI/CD 流水线。适用于用户需要设置自动化测试、部署、发布或工作流时。涵盖工作流语法、常见模式、密钥管理、缓存、矩阵构建和故障排除。
元数据: {"clawdbot":{"emoji":"🚀","requires":{"anyBins":["gh","git"]},"os":["linux","darwin","win32"]}}
使用 GitHub Actions 设置和管理 CI/CD 流水线。涵盖工作流创建、测试、部署、发布自动化和调试。
# .github/workflows/ci.yml
名称: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
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 test
- run: npm run lint
# .github/workflows/ci.yml
名称: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
- run: pip install -r requirements.txt
- run: pytest
- run: ruff check .
# .github/workflows/ci.yml
名称: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- run: go test ./...
- run: go vet ./...
# .github/workflows/ci.yml
名称: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test
- run: cargo clippy -- -D warnings
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [18, 20, 22]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
deploy:
needs: test
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./deploy.sh
# Node.js (使用 setup-node 自动缓存)
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm # 或 yarn, pnpm
# 通用缓存
- uses: actions/cache@v4
with:
path: |
~/.cache/pip
~/.cargo/registry
node_modules
key: ${{ runner.os }}-deps-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-deps-
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
# 在另一个作业中下载
- uses: actions/download-artifact@v4
with:
name: build-output
path: dist/
on:
schedule:
- cron: "0 6 * * 1" # 每周一 UTC 时间 6:00
workflow_dispatch: # 同时允许手动触发
名称: Release
on:
push:
tags:
- "v*"
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- run: npm test
# 创建 GitHub Release
- uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
dist/*.js
dist/*.css
名称: Deploy
on:
push:
branches: [main, staging]
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- run: |
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
./deploy.sh production
else
./deploy.sh staging
fi
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
名称: Docker
on:
push:
branches: [main]
tags: ["v*"]
jobs:
build:
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
名称: Publish
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
- run: npm ci
- run: npm test
- run: npm publish --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# 设置仓库密钥
gh secret set DEPLOY_TOKEN --body "my-secret-value"
# 从文件设置
gh secret set SSH_KEY < ~/.ssh/deploy_key
# 为特定环境设置
gh secret set DB_PASSWORD --env production --body "p@ssw0rd"
# 列出密钥
gh secret list
# 删除密钥
gh secret delete OLD_SECRET
env:
# 此作业中所有步骤可用
DATABASE_URL: ${{ secrets.DATABASE_URL }}
steps:
- run: echo "Deploying..."
env:
# 仅此步骤可用
API_KEY: ${{ secrets.API_KEY }}
通过 GitHub UI 或 API 设置:
- 部署前需要审核者
- 等待计时器
- 分支限制
- 自定义部署分支策略
# 查看环境
gh api repos/{owner}/{repo}/environments | jq '.environments[].name'
# 列出最近的工作流运行
gh run list --limit 10
# 查看特定运行
gh run view <run-id>
# 查看失败作业的日志
gh run view <run-id> --log-failed
# 仅重新运行失败的作业
gh run rerun <run-id> --failed
# 重新运行整个工作流
gh run rerun <run-id>
# 在失败步骤前添加此步骤
- uses: mxschmitt/action-tmate@v3
if: failure()
with:
limit-access-to-actor: true
脚本“权限被拒绝”
- run: chmod +x ./scripts/deploy.sh && ./scripts/deploy.sh
“找不到 Node 模块”
# 确保 npm ci 在 npm test 之前运行
- run: npm ci # 安装 lockfile 中精确的版本
- run: npm test # 现在 node_modules 已存在
“集成无法访问资源”
# 添加权限块
permissions:
contents: write
packages: write
pull-requests: write
缓存未恢复
# 检查缓存键是否匹配 - 对 lockfile 使用 hashFiles
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
# 不要用: key: ${{ runner.os }}-node-${{ hashFiles('package.json') }}
工作流未触发
- 检查:工作流文件是否在默认分支上?
- 检查:触发事件是否匹配?(push 与 pull_request)
- 检查:分支过滤器是否正确?
# 手动触发工作流
gh workflow run ci.yml --ref main
# 检查 YAML 语法
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/ci.yml'))" && echo "Valid"
# 使用 actionlint(如果已安装)
actionlint .github/workflows/ci.yml
# 或通过 Docker
docker run --rm -v "$(pwd):/repo" -w /repo rhysd/actionlint:latest
# 列出所有工作流
gh workflow list
# 查看工作流定义
gh workflow view ci.yml
# 监视正在运行的工作流
gh run watch
# .github/workflows/reusable-test.yml
名称: Reusable Test
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: "20"
secrets:
npm-token:
required: false
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
- run: npm test
# .github/workflows/ci.yml - 调用者
名称: CI
on: [push, pull_request]
jobs:
test:
uses: ./.github/workflows/reusable-test.yml
with:
node-version: "20"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # 取消同一分支的先前运行
on:
push:
paths:
- "src/**"
- "package.json"
- "package-lock.json"
- ".github/workflows/ci.yml"
paths-ignore:
- "docs/**"
- "*.md"
jobs:
changes:
runs-on: ubuntu-latest
outputs:
api: ${{ steps.filter.outputs.api }}
web: ${{ steps.filter.outputs.web }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
api:
- 'packages/api/**'
web:
- 'packages/web/**'
test-api:
needs: changes
if: needs.changes.outputs.api == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cd packages/api && npm ci && npm test
test-web:
needs: changes
if: needs.changes.outputs.web == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cd packages/web && npm ci && npm test
workflow_dispatch,以便在调试时手动触发uses: actions/checkout@b4ffde...continue-on-error: truetimeout-minutes 以防止失控的构建(默认为 360 分钟)outputs: result: ${{ steps.step-id.outputs.value }}runs-on: self-hosted 并使用标签定位特定机器