工作流基础语法:name、on、jobs、steps

说实话,很多人刚开始写 GitHub Actions 工作流时,都卡在那些 YAML 关键字上。我见过团队成员把 jobs 拼成 job,然后盯着红叉发呆半小时。其实核心字段就几个,弄清楚了,流水线就能跑起来。

一句话总结:每个工作流文件 (.yml/.yaml) 就像一份施工图,name 是项目名,on 是开工令,jobs 是各施工队,steps 是具体操作步骤。

1. name —— 给你的流水线起个名

工作流名称。这玩意儿不会影响执行逻辑,但会在 GitHub 仓库的 Actions 页面上显示。我个人习惯把名字定义得清晰点,比如「PR 回归测试 - 全量」或「每日构建 + 部署」。你想想看,如果团队里十来个工作流都叫「CI」,找起来得多痛苦。

name: PR Regression Test Suite

小技巧:留空 name 时,GitHub 会自动用工作流文件的路径名作为显示名称。但别偷懒,给个明确的名字,后面排查问题时会感谢自己。

2. on —— 什么时候触发

这是工作流的“触发器”。没有 on,工作流永远不会启动。我遇到过最经典的踩坑:配好了所有步骤,结果忘了写 on,推送代码后干瞪眼。

常用的触发事件:

触发方式示例说明
pushon: push代码推送到任意分支时触发
pull_requeston: pull_request创建或更新 PR 时触发
scheduleon: schedule: - cron: '0 8 * * 1-5'定时触发(cron 语法)
workflow_dispatchon: workflow_dispatch手动触发(点按钮)

还可以组合多个事件:

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

警告:cron 表达式是基于 UTC 时间的。国内团队如果定时任务写的是北京时间,记得减 8 小时。我曾经因为没算时差,团队连续一周半夜被流水线吵醒……嗯,那之后我就在注释里写明时区了。

3. jobs —— 拆解成多个任务

一个工作流可以包含多个 job,每个 job 默认在独立 Runner 上运行。它们可以串行、并行,或者依赖彼此。关键字段:

  • runs-on:指定 Runner 操作系统(ubuntu-latest、windows-latest 等)
  • needs:声明依赖,让 job 按顺序执行
  • strategy:矩阵构建,一次跑多个变体

举个例子:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Running linter..."
  test:
    runs-on: ubuntu-latest
    needs: lint
    steps:
      - run: echo "Running tests..."

这里 test 必须先等 lint 跑完才能开始。实际项目中,我习惯把编译、单元测试、集成测试拆成不同 job,这样哪个环节挂了能立刻定位,而且并行还能节省时间。

4. steps —— 具体每一步做什么

一个 job 里的步骤是顺序执行的。每个 step 要么运行一个 action(用 uses),要么执行一条 shell 命令(用 run)。常见的套路:

steps:
  - name: Checkout code
    uses: actions/checkout@v4

  - name: Set up Node.js
    uses: actions/setup-node@v3
    with:
      node-version: '18'

  - name: Install dependencies
    run: npm ci

  - name: Run tests
    run: npm test

注意 with 是用来传参数的,比如指定 Node 版本。而 run 直接写命令,适合自定义脚本。

经验之谈:我见过有人把几十个命令写进一个 run 里,日志全混一块儿,排查时眼都花了。建议每个逻辑独立步骤拆开,加个 name 说明用途,日志会更清晰。

核心字段速查表

字段必填作用
name否工作流显示名称
on是触发条件(事件/定时/手动)
jobs是任务列表,每个 job 包含 runs-on 和 steps
steps是(每个 job 内)具体操作步骤(uses/run)
uses视情况引用某个 action(仓库/版本)
run视情况执行 shell 命令
with否传入 action 的参数

工作流核心逻辑关系

下图展示了一个回归测试用例自动化工作流的典型骨架:

工作流核心语法结构 name: 工作流名称 on: 触发条件 包括 push / pull_request schedule (cron) workflow_dispatch jobs: 任务集合 job1: lint runs-on: ubuntu-latest steps: - uses: checkout@v4 - run: npm run lint job2: test needs: lint runs-on: ubuntu-latest steps: - uses: checkout@v4 - run: npm test 每个 step 用 uses 或 run

几个常见误区

  • 忘记 actions/checkout:默认 Runner 是空白环境,不 checkout 代码你跑什么测试?我见过新人花一小时找“文件不存在”的报错,最后发现少了这一步。
  • run 里用相对路径:工作目录默认是 GITHUB_WORKSPACE,如果你 checkout 到了子目录,记得先 cd。
  • 滥用 needs:每个需要等待的依赖任务都会延长流水线总时间。如果任务之间没有强依赖,尽量并行。
  • 忽略 env:很多 action 需要通过环境变量传 或密钥,我习惯在 job 或 step 级别定义 env。

我的一个小习惯:每个工作流文件开头都加上注释,写清楚这个流水线是干嘛的、什么时候触发、依赖哪些 secrets。半年后回头看,你会感谢那个写注释的自己。

总结一下

其实工作流的基础语法没那么神秘。你把 name 当标题,on 当闹钟,jobs 当施工队,steps 当操作手册,逻辑就通了。后面章节我们会深入 strategy、matrix、conditions 这些进阶玩法。

现在先拿一个最简单的回归测试用例跑起来——哪怕只有一个 job,一个 step,也算是迈出了自动化第一步。