Developer Tools

GitHub Actions CI/CD:从零开始构建、测试和部署工作流

学习如何为持续集成和部署配置 GitHub Actions。涵盖触发器、作业、矩阵、密钥、缓存、Docker 以及真实世界的工作流示例。

10分钟阅读

GitHub 代码协作界面

GitHub Actions 将每次推送、拉取请求和合并都转化为自动化流水线——运行测试、构建产物、扫描漏洞并部署到生产环境。这是一个直接内置于代码仓库中的 CI/CD 平台,无需管理任何基础设施。

GitHub Actions 的工作原理

每个工作流都是 .github/workflows/ 目录下的一个 YAML 文件。当触发事件发生时,GitHub 会启动一台全新的虚拟机,运行你的作业并报告结果——整个过程在几秒内完成。

推送到 main
  ↓
工作流触发
  ↓
作业:构建与测试(ubuntu-latest)
  ├── 步骤 1:检出代码
  ├── 步骤 2:安装 Node.js
  ├── 步骤 3:npm ci
  ├── 步骤 4:npm test
  └── 步骤 5:npm run build
  ↓
✅ 所有检查通过

你的第一个工作流

创建 .github/workflows/ci.yml

name: CI

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

jobs:
  build:
    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 build

就这些。现在每次推送到 main 以及每个 PR 都会自动运行你的测试套件。

触发器:工作流的运行时机

代码事件

on:
  push:
    branches: [main, develop]
    paths: ['src/**', 'package.json']  # 仅在这些文件变更时运行
  pull_request:
    types: [opened, synchronize]

定时执行(cron)

on:
  schedule:
    - cron: '0 6 * * 1'  # 每周一 UTC 时间 6:00

手动触发

on:
  workflow_dispatch:
    inputs:
      environment:
        description: '部署目标'
        required: true
        type: choice
        options: [staging, production]

这会在 GitHub UI 中添加一个"运行工作流"按钮,供你选择参数。

可复用工作流

on:
  workflow_call:
    inputs:
      node-version:
        type: string
        default: '20'

在另一个工作流中使用 uses: ./.github/workflows/reusable.yml 调用它。

作业与步骤

并行作业

作业默认并行运行:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm test

  build:
    runs-on: ubuntu-latest
    needs: [lint, test]  # 等待两者均通过
    steps:
      - uses: actions/checkout@v4
      - run: npm run build

矩阵策略——跨版本测试

在多种配置下运行相同的作业:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20, 22]
        os: [ubuntu-latest, windows-latest]
      fail-fast: false
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm test

这将创建 6 个并行作业(3 个版本 × 2 个操作系统)。

密钥与环境变量

使用密钥

Settings → Secrets and variables → Actions 中存储敏感值:

steps:
  - name: 部署
    env:
      API_KEY: ${{ secrets.API_KEY }}
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
    run: ./deploy.sh

密钥在日志中会被屏蔽,且不会暴露给 fork 仓库。

环境变量

# 工作流级别
env:
  NODE_ENV: production

jobs:
  build:
    # 作业级别
    env:
      CI: true
    steps:
      - name: 构建
        # 步骤级别
        env:
          VITE_API_URL: https://api.example.com
        run: npm run build

缓存以加快构建速度

不使用缓存时,每次运行都需要从头下载所有依赖。使用缓存可将构建时间缩短 50-80%:

- uses: actions/setup-node@v4
  with:
    node-version: 20
    cache: npm  # 内置 npm 缓存

# 或手动为其他工具配置缓存
- uses: actions/cache@v4
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
    restore-keys: |
      ${{ runner.os }}-pip-

产物:在作业之间共享数据

从一个作业上传构建输出,在另一个作业中下载:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
      - run: ./deploy.sh

真实世界工作流示例

Docker 构建与推送

name: Docker

on:
  push:
    tags: ['v*']

permissions:
  packages: write

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

部署到 Cloudflare Pages

name: 部署

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci && npm run build
      - uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          command: pages deploy dist --project-name=my-site

发布版本并生成更新日志

name: 发布

on:
  push:
    tags: ['v*.*.*']

permissions:
  contents: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: 生成更新日志
        run: |
          git log $(git describe --tags --abbrev=0 HEAD^)..HEAD \
            --pretty=format:"- %s" > CHANGELOG.md
      - uses: softprops/action-gh-release@v2
        with:
          body_path: CHANGELOG.md
          generate_release_notes: true

条件执行

控制步骤和作业的运行时机:

steps:
  - name: 部署到生产环境
    if: github.ref == 'refs/heads/main'
    run: ./deploy-prod.sh

  - name: 部署到预发布环境
    if: github.event_name == 'pull_request'
    run: ./deploy-staging.sh

  - name: 失败时发送通知
    if: failure()
    run: curl -X POST ${{ secrets.SLACK_WEBHOOK }} -d '{"text":"构建失败!"}'

安全最佳实践

1. 将 Action 版本固定到 SHA

# ❌ 可变标签——可能被篡改
- uses: actions/checkout@v4

# ✅ 固定到精确的提交 SHA
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11

2. 使用最小权限原则

permissions:
  contents: read    # 只授予必要的权限
  packages: write

3. 切勿输出密钥

# ❌ 绝对不要这样做
- run: echo ${{ secrets.API_KEY }}

# ✅ 使用环境变量
- env:
    API_KEY: ${{ secrets.API_KEY }}
  run: ./script-that-uses-api-key.sh

4. 限制来自 fork 的 PR 权限

on:
  pull_request_target:  # 在基础分支的上下文中运行
    types: [opened, synchronize]

调试失败的工作流

  1. 查看日志 — 点击任何失败的步骤查看完整输出
  2. 添加调试日志 — 将密钥 ACTIONS_STEP_DEBUG 设置为 true
  3. 使用 act 本地运行 — 通过 nektos/act 在本机运行工作流
  4. SSH 连接到运行器 — 使用 mxschmitt/action-tmate 进行交互式调试

可视化构建工作流

不想手写 YAML?使用我们的 GitHub Actions 生成器 通过可视化界面构建工作流,提供 Node.js、Python、Docker、部署等模板,并可下载生产就绪的 YAML 文件。

总结

GitHub Actions 为你提供了直接内置于代码仓库的 CI/CD 能力:

  1. 从简单开始 — 一个包含构建和测试的工作流文件
  2. 添加缓存 — 使用 actions/cache 或内置语言缓存缩短构建时间
  3. 使用矩阵 — 跨版本和操作系统进行测试
  4. 保护密钥 — 永远不要硬编码,始终使用加密密钥
  5. 自动化一切 — 发布、部署、安全扫描、定时任务

最好的 CI/CD 流水线,是那种每次提交都能自动运行、无需你费心的那种。配置一次,剩下的交给 GitHub 处理。