第2章:工作流文件结构详解——核心字段配置与顺序
本章深入解析 GitHub Actions 工作流文件的骨架结构。理解 name、on、jobs、steps、uses、run、env 等核心字段的语义、配置语法与书写顺序,是编写可维护、可复用的 CI/CD 流水线的基础。这些字段共同定义了一个工作流的触发条件、执行环境和具体任务。
核心原则:YAML 的缩进代表层级,字段顺序不影响执行逻辑,但遵循社区惯例(从上到下:描述→触发→环境→工作→步骤)能提升可读性。
2.1 字段层级结构与书写顺序
一个完整的工作流文件遵循以下固定层级(缩进使用两个空格):
name: <工作流名称>
run-name: <动态运行名称> # 可选,支持表达式
on: # 触发事件
push:
branches: [main]
pull_request:
branches: [main]
env: # 全局环境变量
GLOBAL_VAR: value
defaults: # 默认行为(可选)
run:
shell: bash
working-directory: ./
jobs: # 作业定义
<job_id>: # 唯一标识
name: <作业显示名>
runs-on: ubuntu-latest
env: # 作业级环境变量
JOB_VAR: value
steps: # 步骤列表(顺序执行)
- name: <步骤名称>
if: <条件表达式> # 可选
uses: <action>@v1 # 或
run: <shell命令>
env: # 步骤级环境变量
STEP_VAR: value
continue-on-error: false
timeout-minutes: 5
关键顺序:
on 在 jobs 之前;env 可以在文件级、作业级、步骤级定义,作用域递减;steps 内每个 step 是一个列表项,按顺序执行。2.2 核心字段详解
| 字段 | 位置 | 用途 | 必填 | 典型取值 |
|---|---|---|---|---|
name |
根 | 工作流显示名称,出现在 Actions Tab | 推荐 | 测试构建与部署 |
run-name |
根 | 运行时名称,支持表达式动态生成 | 否 | ${{ github.workflow }} - ${{ github.event_name }} |
on |
根 | 触发工作流的事件列表 | 是 | push, pull_request, schedule |
env |
根 / 作业 / 步骤 | 设置环境变量 | 否 | NODE_ENV: production |
jobs |
根 | 定义一组作业,作业之间可并行或依赖 | 是 | 至少一个 job |
runs-on |
作业 | 指定运行器类型(操作系统) | 是 | ubuntu-latest, windows-latest |
steps |
作业 | 有序步骤列表,每个步骤执行一个 Action 或命令 | 是 | 至少一个 step |
uses |
步骤 | 引用一个外部 Action 仓库 | 互斥 | actions/checkout@v4 |
run |
步骤 | 执行内联 shell 命令 | 互斥 | echo "Hello" |
注意:uses 和 run 在同一个 step 中只能出现其一,不能同时使用。如果既要运行命令又要引用 Action,必须分两步。
2.3 触发事件 on 的配置模式
on 支持单事件(字符串)、多事件(列表)以及带分支/路径过滤的复杂配置:
on:
push: # 单事件
pull_request: # 多事件,可以组合
branches: [main, dev]
schedule: # 定时触发
- cron: '0 */6 * * *'
workflow_dispatch: # 手动触发
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
repository_dispatch: # API 触发
types: [test-completed]
常见错误:
on 后面直接写 push 字符串会导致 YAML 解析为 push 等同于 null,应使用列表或映射。例如 on: push 会被视为无效,正确写法为 on: [push] 或 on: push: 后跟空映射(不推荐)。2.4 uses 与 run 的互斥与协作
| 字段 | 语法 | 典型场景 | 版本锁定 |
|---|---|---|---|
uses |
organization/repo@ref |
复用社区 Action(如 checkout、setup-node) | 推荐使用 @v4(语义版本)或 @sha(不可变) |
run |
shell 命令字符串 |
执行自定义脚本、编译、测试命令 | 无版本概念,在命令中控制工具版本 |
steps:
- name: Check out repository
uses: actions/checkout@v4 # 使用预编译 Action
- name: Run build script
run: |
npm ci
npm run build
shell: bash # 指定 shell 类型(可选)
2.5 环境变量作用域与优先级
env 可以在三个层级定义,低层级覆盖高层级同名变量:
env:
LEVEL: global
jobs:
build:
env:
LEVEL: job
steps:
- name: Override at step
env:
LEVEL: step
run: echo $LEVEL # 输出 step
实用技巧:使用
${{ secrets.MY_SECRET }} 引用密钥,避免明文暴露。全局 env 适合设置通用标志,步骤级 env 适合临时覆盖。2.6 工作流文件结构流程图
下图展示了工作流文件中各字段的配置顺序与层级关系:
2.7 常见配置错误及调试方法
- 缩进不一致:YAML 要求严格的两个空格缩进,Tab 或混合空格会导致解析失败。建议在本地编辑器安装 YAML 插件。
- 缺少
jobs:工作流必须至少包含一个作业。如果漏写jobs字段,Actions 会报错:Required property is missing: jobs。 uses与run共存于同一步:运行时会被忽略run或抛出歧义错误。应将不同的任务分开:先用 Action,再执行命令。- 事件触发拼写错误:例如将
pull_request写成pullrequest。参考 官方事件列表。 - 环境变量作用域误解:步骤级变量不会自动传递给后续步骤,除非显式通过
$GITHUB_ENV或outputs。
调试技巧:在 Actions 界面点击失败的工作流运行,查看展开的步骤日志;本地可使用
act 工具模拟运行工作流(act -j job_id)。2.8 性能与稳定性优化建议
- 固定 Action 版本:使用
@v4而非@main,避免上游破坏性更新。 - 使用
concurrency:防止同一分支多个 push 并发冲突。 - 减少无用触发:在
on中使用paths-ignore忽略文档或图片修改。 - 适当拆分 jobs:利用矩阵策略并行化,缩短总运行时间。
- 缓存依赖:使用
actions/cache缓存node_modules、~/.m2等,减少重复下载。
# 示例:带缓存的 Node.js 构建步骤
- name: Cache Node modules
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci