2. GitHub Actions 核心概念:Workflow、Job、Step、Runner、Event、Action
GitHub Actions 是一个事件驱动的自动化平台,其执行模型由六个核心概念构成:Workflow(工作流)、Job(作业)、Step(步骤)、Runner(运行器)、Event(事件)和 Action(动作)。理解这六个概念之间的关系,是编写 CI/CD 流水线的起点。
2.1 概念对比与职责划分
| 概念 | 定义 | 生命周期 | 配置位置 | 关键属性 |
|---|---|---|---|---|
| Event | 触发工作流运行的事件 | 瞬时(触发器) | workflow 文件的 on: 字段 | push, pull_request, schedule, workflow_dispatch |
| Workflow | 一个完整的自动化流程定义 | 从触发到所有 Job 完成 | .github/workflows/*.yml | name, on, jobs |
| Job | 工作流中的一组步骤,运行在同一 Runner | 与其 Step 同步 | jobs.<job_id> | runs-on, needs, strategy |
| Step | Job 内的单个任务,含命令或 Action | 顺序执行 | jobs.<job_id>.steps | name, run, uses |
| Runner | 执行 Job 的虚拟环境或机器 | Job 期间存活 | runs-on 指定标签 | ubuntu-latest, windows-latest, 自托管标签 |
| Action | 可复用的自定义或社区步骤 | Step 调用时运行 | 独立仓库或 Docker 镜像 | uses: owner/repo@version |
2.2 配置结构与执行流程
一个典型的 Workflow 文件以 YAML 格式编写,GitHub 在推送到仓库后立即解析并排队。以下是后端测试场景中最基础的流水线配置:
name: Backend Test CI
on:
push:
branches: [ "main", "develop" ]
pull_request:
branches: [ "main" ]
jobs:
unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm run test:unit
integration-test:
needs: unit-test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: testpass
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Run integration tests
run: npm run test:integration
执行顺序解析:
- Event 触发: 开发者推送代码到 main 分支 → Event 为
push,分支main。 - Workflow 激活: 仓库发现
.github/workflows/ci.yml,匹配on.push.branches,创建运行实例。 - Job 调度:
unit-test无needs,立即在 ubuntu-latest Runner 上执行。
integration-test声明needs: unit-test,等待 unit-test 成功后启动。 - Step 顺序执行: 在每个 Job 内部,Step 列表从上到下依次运行。如果某 Step 返回非零退出码,默认整个 Job 失败停止。
- Action 复用:
actions/checkout@v4是由 GitHub 官方维护的 Action,负责检出仓库代码。用户也可以将自己常用的 shell 命令封装为自定义 Action。
2.3 Runner 的隔离性与上下文
每个 Job 会分配到独立的 Runner 实例,Runner 环境之间完全隔离。下表总结了 GitHub 托管 Runner 和自托管 Runner 的关键差异:
| 特性 | GitHub 托管 Runner | 自托管 Runner |
|---|---|---|
| 维护成本 | 无(由 GitHub 管理) | 高(需自行更新 OS、工具链) |
| 网络隔离 | 可访问公网,无法访问内网资源 | 可配置对内网访问,适合数据库/微服务测试 |
| 安全边界 | 每次 Job 运行在全新 VM,无持久化 | 需手动加固,避免工作流间数据泄露 |
| 计费 | 按分钟计费(免费额度 2000 分钟/月) | 免费(仅需承担硬件和运维成本) |
| 适用场景 | 开源项目、标准构建测试 | 企业内网部署、对GPU/专用硬件有依赖的场景 |
2.4 Action 的三种来源
在使用 uses: 关键字时,可以从以下三种位置引用 Action:
- GitHub 官方 Action: 前缀为
actions/,如actions/checkout@v4、actions/setup-node@v4。经过大量验证,推荐生产环境使用。 - 社区/第三方 Action: 格式
author/repo@tag,例如docker/login-action@v3。使用时建议固定到语义化标签或 commit SHA。 - 本地 Action: 通过
./path/to/action引用仓库目录内的 Action 定义,适合团队内部测试工具复用。
生产部署建议: 在 CI/CD 流水线中固定 Action 版本时,优先使用完整 SHA-1 commit 哈希(如 uses: actions/checkout@a81bbbf8298c0fa03ea29cdc473d45769f953675),而不是语义化标签。标签可以被覆盖,存在安全风险;SHA 不可变,保证重复构建的一致性。
2.5 Event 触发矩阵与常见陷阱
Workflow 可以响应多种事件,事件还可以组合过滤条件。下面列出后端测试中最常用的四个事件及其注意事项:
| 事件类型 | 典型配置 | 常见陷阱 |
|---|---|---|
push | branches: [ main ] | 未添加 paths-ignore 过滤文档/README 变更,造成不必要运行 |
pull_request | types: [ opened, synchronize ] | 默认包含 labeled、unlabeled 等事件,可能导致 PR 操作时重复触发 |
schedule | cron: '0 6 * * *' | 只会在默认分支(main)上运行,不会在其他分支触发定时任务 |
workflow_dispatch | 手动触发,可输入参数 | 必须手工触发,不适合自动化流程;但适合调试和回滚 |
2.6 Job 依赖与矩阵策略
在复杂后管任务测试中,经常需要并行运行多版本测试。GitHub Actions 通过 strategy.matrix 实现测试矩阵,同时利用 needs 建立 Job 间依赖。
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm run lint
test:
needs: lint
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
deploy-staging:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- run: echo "Deploying to staging..."
依赖阻塞陷阱: 当 Job A(needs: [])和 Job B(needs: A)并行启动但 B 依赖 A 时,B 会等待 A 全部完成(包括矩阵中所有组合)后才开始。如果矩阵组合过多且平均完成时间差异大,整体流水线延迟会较长。建议对关键路径上的矩阵 Job 单独设置较短的超时时间:timeout-minutes: 30。
2.7 Step 的上下文与表达式
Step 可以通过 ${{ }} 表达式访问上下文信息,包括 github、env、secrets、steps 和 runner 等。以下示例展示如何在 Step 之间传递数据:
jobs:
build:
runs-on: ubuntu-latest
steps:
- id: step1
name: Generate version
run: echo "version=1.0.0-$(date +%s)" >> "$GITHUB_OUTPUT"
- name: Use version from previous step
run: |
echo "Building version: ${{ steps.step1.outputs.version }}"
# 实际构建命令使用该版本号
输出传递机制: 通过写入 $GITHUB_OUTPUT 环境文件(推荐方式,替代已弃用的 ::set-output 命令),下游 Step 可以通过 steps.<id>.outputs.<key> 获取。此机制在并行 Job 之间不可用,跨 Job 传递请使用 artifacts 或 workflow_dispatch 参数。
2.8 性能稳定性关键参数
在日常调试和优化中,以下参数直接影响 Workflow 的执行稳定性:
| 参数 | 默认值 | 推荐调整策略 |
|---|---|---|
timeout-minutes(Job 级) | 360 | 日常 CI 设置为 30-60 分钟;长任务(如集成测试)设置为 120 分钟,避免幽灵占用 Runner 配额 |
continue-on-error(Step 级) | false | 矩阵中允许特定组合失败但不阻塞其他组合时设置为 true;主流程步骤应保持 false |
max-parallel(矩阵内) | 无限制 | 免费账户建议主动设置为 5 以下,避免瞬间耗尽并发限制 |
concurrency(Workflow 级) | 无 | 同一分支上只保留最新一次运行:concurrency: group: ${{ github.workflow }}-${{ github.ref }} |
调试实用命令: 在 Step 中添加以下命令可实时查看 Runner 上下文变量,非常适合排查表达式引用错误:
jobs:
debug-context:
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJSON(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Dump runner context
env:
RUNNER_CONTEXT: ${{ toJSON(runner) }}
run: echo "$RUNNER_CONTEXT"
输出会以 JSON 格式打印在 Workflow 运行日志中,注意不要将 secrets 一起打印到日志(日志会自动将 secret 值遮蔽为 ***)。