GitHub Actions 工作流Workflow #

工作流(Workflow)是GitHub Actions的核心概念,是一个可配置的自动化过程。本节深入探讨工作流的各个方面。

工作流概述 #

什么是工作流? #

工作流是一个定义在YAML文件中的自动化流程,包含以下核心元素:

text
工作流 (Workflow)
├── 触发器 (on)
├── 环境变量 (env)
├── 默认配置 (defaults)
├── 并发控制 (concurrency)
└── 作业 (jobs)
    └── 步骤 (steps)
        └── 动作 (actions) / 命令 (run)

工作流生命周期 #

text
触发事件 → 工作流启动 → 作业排队 → 作业执行 → 完成/失败
                │
                ├── 作业1 (并行)
                ├── 作业2 (并行)
                └── 作业3 (依赖作业1、2)

工作流配置详解 #

name - 工作流名称 #

yaml
name: CI Pipeline

# 使用emoji增强可读性
name: 🚀 Deploy to Production

# 使用变量动态命名
name: Build ${{ github.ref_name }}

on - 触发器配置 #

基本触发 #

yaml
# 单一事件
on: push

# 多个事件
on: [push, pull_request]

# 事件列表
on:
  - push
  - pull_request
  - workflow_dispatch

带过滤器的触发 #

yaml
on:
  push:
    branches:
      - main
      - 'release/**'
      - '!release/**-alpha'  # 排除匹配的分支
    paths:
      - 'src/**'
      - 'tests/**'
    paths-ignore:
      - '**.md'
      - 'docs/**'
    tags:
      - 'v*'

  pull_request:
    branches:
      - main
    types:
      - opened
      - synchronize
      - reopened
      - closed

多事件组合 #

yaml
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment'
        required: true

env - 环境变量 #

yaml
env:
  CI: true
  NODE_VERSION: '20'
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    env:
      JOB_VAR: job-level-value
    steps:
      - env:
          STEP_VAR: step-level-value
        run: |
          echo $CI
          echo $NODE_VERSION
          echo $JOB_VAR
          echo $STEP_VAR

defaults - 默认配置 #

yaml
defaults:
  run:
    shell: bash
    working-directory: ./app

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: pwd  # 在 ./app 目录执行
      - run: ls

concurrency - 并发控制 #

yaml
# 基本并发控制
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

# 按PR分组
concurrency:
  group: pr-${{ github.event.pull_request.number }}
  cancel-in-progress: true

# 按环境分组
concurrency:
  group: deploy-${{ github.event.inputs.environment }}
  cancel-in-progress: false

作业配置 #

作业基本结构 #

yaml
jobs:
  job-id:
    name: Display Name
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello"

作业依赖 #

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.value }}
    steps:
      - id: version
        run: echo "value=1.0.0" >> $GITHUB_OUTPUT

  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: echo "Testing version ${{ needs.build.outputs.version }}"

  deploy:
    needs: [build, test]
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying"

条件执行 #

yaml
jobs:
  deploy:
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to production"

  deploy-staging:
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to staging"

矩阵策略 #

yaml
jobs:
  test:
    strategy:
      matrix:
        node: [16, 18, 20]
        os: [ubuntu-latest, windows-latest]
        include:
          - node: 20
            os: ubuntu-latest
            experimental: true
        exclude:
          - node: 16
            os: windows-latest
      fail-fast: false
      max-parallel: 4
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}

环境配置 #

yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://example.com
    steps:
      - run: echo "Deploying to production"

工作流命令 #

设置输出 #

yaml
steps:
  - id: set-output
    run: echo "name=value" >> $GITHUB_OUTPUT

  - run: echo "${{ steps.set-output.outputs.name }}"

设置环境变量 #

yaml
steps:
  - run: echo "MY_VAR=hello" >> $GITHUB_ENV

  - run: echo $MY_VAR  # 输出: hello

添加路径 #

yaml
steps:
  - run: echo "$HOME/mybin" >> $GITHUB_PATH

添加步骤摘要 #

yaml
steps:
  - name: Generate Summary
    run: |
      echo "## Build Results" >> $GITHUB_STEP_SUMMARY
      echo "" >> $GITHUB_STEP_SUMMARY
      echo "✅ Build succeeded" >> $GITHUB_STEP_SUMMARY

掩码敏感信息 #

yaml
steps:
  - run: echo "::add-mask::${{ secrets.MY_SECRET }}"

停止命令处理 #

yaml
steps:
  - run: |
      echo "::stop-commands::`echo "my-token"`"
      echo "::set-env name=MY_VAR::value"  # 这行不会被处理
      echo "::`echo "my-token"`::"
      echo "::set-env name=MY_VAR::value"  # 这行会被处理

工作流重用 #

可重用工作流 #

创建 .github/workflows/reusable.yml

yaml
name: Reusable Workflow

on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
    secrets:
      deploy-token:
        required: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to ${{ inputs.environment }}"
        env:
          TOKEN: ${{ secrets.deploy-token }}

调用可重用工作流 #

yaml
name: Deploy

on:
  push:
    branches: [main]

jobs:
  call-workflow:
    uses: ./.github/workflows/reusable.yml
    with:
      environment: production
    secrets:
      deploy-token: ${{ secrets.DEPLOY_TOKEN }}

从其他仓库调用 #

yaml
jobs:
  call-remote-workflow:
    uses: owner/repo/.github/workflows/workflow.yml@main
    with:
      environment: production
    secrets: inherit

工作流模板 #

CI模板 #

yaml
name: CI

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

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

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

  test:
    needs: lint
    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

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

CD模板 #

yaml
name: CD

on:
  push:
    tags:
      - 'v*'

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.value }}
    steps:
      - uses: actions/checkout@v4
      - id: version
        run: echo "value=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
      - run: npm ci
      - run: npm run build

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment: production
    steps:
      - run: echo "Deploying version ${{ needs.build.outputs.version }}"

工作流可视化 #

依赖关系图 #

text
┌─────────────────────────────────────────────────────────────┐
│                      Workflow: CI/CD                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────┐                                                │
│  │  lint   │                                                │
│  └────┬────┘                                                │
│       │                                                     │
│       ▼                                                     │
│  ┌─────────┐                                                │
│  │  test   │                                                │
│  └────┬────┘                                                │
│       │                                                     │
│       ├──────────────────────┐                              │
│       │                      │                              │
│       ▼                      ▼                              │
│  ┌─────────┐          ┌─────────────┐                       │
│  │  build  │          │ integration │                       │
│  └────┬────┘          └──────┬──────┘                       │
│       │                      │                              │
│       └──────────┬───────────┘                              │
│                  │                                          │
│                  ▼                                          │
│           ┌──────────┐                                      │
│           │  deploy  │                                      │
│           └──────────┘                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

最佳实践 #

1. 使用有意义的名称 #

yaml
name: 🧪 Test and Build

jobs:
  lint-and-test:
    name: Lint & Test
    steps:
      - name: Install dependencies
      - name: Run linter
      - name: Run tests

2. 使用并发控制 #

yaml
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

3. 使用缓存 #

yaml
- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'

4. 使用矩阵优化测试 #

yaml
strategy:
  matrix:
    include:
      - node: 20
        os: ubuntu-latest
      - node: 18
        os: ubuntu-latest

5. 添加超时 #

yaml
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 30

常见问题 #

Q: 如何调试工作流? #

yaml
steps:
  - name: Debug
    run: |
      echo "Event: ${{ github.event_name }}"
      echo "Ref: ${{ github.ref }}"
      echo "SHA: ${{ github.sha }}"

Q: 如何跳过工作流? #

在提交消息中添加 [skip ci][ci skip]

text
git commit -m "docs: update readme [skip ci]"

Q: 如何限制工作流权限? #

yaml
permissions:
  contents: read
  pull-requests: write

下一步学习 #

小结 #

  • 工作流是GitHub Actions的核心配置单元
  • 使用YAML格式定义工作流
  • 工作流包含触发器、作业、步骤等组件
  • 支持工作流重用和模板化
  • 使用并发控制优化资源使用
  • 遵循最佳实践提高工作流质量
最后更新:2026-03-28