切换语言
切换主题

GitHub Actions 入门:YAML 工作流基础与触发器配置

凌晨三点,屏幕上的红色报错刺眼得让人想砸键盘。

代码明明在本地跑得好好的,一推到 GitHub 就挂。那个 YAML 文件我改了六遍,每次都是缩进问题。当时我就想:这玩意儿怎么比写代码还难?

其实 GitHub Actions 本身不复杂。难的是那些文档,一上来就扔给你几百页的配置说明,看得人头晕眼花。这篇文章,我想用最简单的方式,带你搞懂 YAML 工作流的核心结构。

你会学到:

  • YAML 文件的四大核心字段,每个字段的实际作用
  • 8 种常用触发器的配置方法和使用场景
  • 一个可以直接复制使用的完整工作流模板
  • 我踩过的那些坑,以及怎么避开它们

准备好了吗?我们开始。

YAML 工作流文件:四大核心字段

说实话,我刚接触 GitHub Actions 的时候,看到那个 .github/workflows 目录下的 YAML 文件,感觉就像在看天书。一堆缩进,一堆冒号,改错一个空格就全挂了。

后来我才发现,这玩意儿其实就四个核心部分。搞懂这四个,其他的都是锦上添花。

name:给工作流起个名字

这个字段最简单,但很多人(包括我)一开始都会忽略它。

name: CI for Node.js App

name 就是你的工作流在 GitHub Actions 标签页显示的名字。你推代码后,点进仓库的 Actions 页面,看到的那行字就是它。

起名有个小技巧:用 项目名 + 功能描述。比如 MyApp CIBackend Deploy。这样以后工作流多了,你一眼就能找到想看的那条。

这个字段其实可以省略。如果你不写,GitHub 会用文件名代替。但我不建议省略——文件名通常是英文缩写,看着没那直观。

on:什么时候触发

8种
常用触发器

on 是整个工作流的”开关”。你告诉 GitHub:什么情况下,跑这个工作流。

最简单的写法:

on: push

意思是:只要有代码推送,就触发。

但实际项目中,你通常需要更精细的控制。比如只在 main 分支有推送时才跑:

on:
  push:
    branches: [main]

或者你想在创建 Pull Request 时也触发:

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

触发器是 GitHub Actions 的精髓,后面我会专门用一整节来讲 8 种常用场景。这里你只需要记住:on 决定了工作流的”触发时机”。

jobs:定义要做什么

jobs 是工作流的主体,定义”具体要执行什么任务”。

一个工作流可以包含多个 job,它们默认并行执行。每个 job 需要指定运行环境,用 runs-on 字段:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # ...步骤列表

上面这段代码定义了一个叫 build 的 job,它会在 GitHub 提供的 Ubuntu 最新版本上运行。

如果你的工作流有多个 job,可以用 needs 字段定义依赖关系:

jobs:
  test:
    runs-on: ubuntu-latest
    # ... 测试步骤

  deploy:
    needs: test  # 等 test 跑完才执行
    runs-on: ubuntu-latest
    # ... 部署步骤

这样 deploy 就会等 test 跑完才开始。如果 test 挂了,deploy 就不会执行。

steps:具体的执行步骤

steps 是 job 里面的最小执行单位,一条条命令或 Action 按顺序执行。

每个 step 有两种写法:

1. 用 run 执行命令:

steps:
  - name: Install dependencies
    run: npm ci

  - name: Run tests
    run: npm test

run 后面就是你要在终端里执行的命令,和在本地敲命令一样。

2. 用 uses 调用 Action:

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

  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '20'

uses 是 GitHub Actions 的杀手锏。别人写好的 Action,你直接拿来用。比如 actions/checkout@v4 会帮你把代码拉下来,actions/setup-node@v4 会帮你配置 Node.js 环境。

with 是给 Action 传参数。比如上面的 node-version: '20',就是告诉 setup-node:我要用 Node.js 20 版本。

四个字段说完了。是不是比想象中简单?

触发器全解析:8 种常用场景

前面提到 on 字段决定触发时机。GitHub Actions 支持几十种触发器,但说实话,常用的就那么几个。

我整理了一张表,帮你快速了解每种触发器的使用场景:

触发器典型场景配置示例
push代码推送到分支on: push: branches: [main]
pull_requestPR 创建或更新on: pull_request: types: [opened, synchronize]
schedule定时任务(Cron)on: schedule: - cron: '0 0 * * *'
workflow_dispatch手动触发on: workflow_dispatch: inputs: env: ...
workflow_call可复用工作流on: workflow_call: inputs: ...
release发布事件on: release: types: [published]
issuesIssue 事件on: issues: types: [opened, labeled]
repository_dispatch外部事件on: repository_dispatch: types: [deploy]

下面我挑几个最常用的展开讲讲。

push:最基础的触发器

push 是你最先会遇到的触发器。代码推送到分支时触发。

简单配置:

on: push

但这样配置有个问题:任何分支的推送都会触发。如果你的仓库有 20 个分支,每个人推代码都会跑工作流,那免费额度很快就用光了。

更合理的配置是限制分支:

on:
  push:
    branches: [main, develop]

或者用通配符:

on:
  push:
    branches:
      - 'main'
      - 'release/**'  # 匹配 release/v1.0, release/v2.0 等

pull_request:代码合并前的守护者

pull_request 在创建或更新 PR 时触发,通常用于跑测试、检查代码风格。

on:
  pull_request:
    branches: [main]

你可以用 types 字段进一步控制触发时机:

on:
  pull_request:
    types: [opened, synchronize, reopened]
  • opened:PR 刚创建
  • synchronize:PR 有新提交
  • reopened:PR 重新打开

这样配置后,只有在这三种情况下才会跑工作流,不会浪费资源。

schedule:定时任务

schedule 用 Cron 表达式定义定时触发。比如每天凌晨跑一次测试:

on:
  schedule:
    - cron: '0 0 * * *'  # 每天 UTC 0点

Cron 表达式有 5 个字段:分钟、小时、日、月、星期。

几个常用的时间:

  • 0 0 * * *:每天 UTC 0 点(北京时间早上 8 点)
  • 0 */6 * * *:每 6 小时一次
  • 30 2 * * 1:每周一 UTC 2:30

有个坑要注意:GitHub 用的是 UTC 时间。如果你在北京时间早上 9 点想跑任务,要设置为 UTC 1 点(0 1 * * *)。

workflow_dispatch:手动触发

有时候你不想自动触发,而是想点个按钮手动跑。workflow_dispatch 就是干这个的。

on:
  workflow_dispatch:
    inputs:
      environment:
        description: '部署环境'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

配置好后,在 Actions 页面会出现一个”Run workflow”按钮,点击可以选择环境参数再触发。

这个触发器在部署场景特别实用:自动测试,手动部署。

workflow_call:复用工作流

如果你的工作流逻辑很复杂,或者多个仓库要用同一套流程,可以用 workflow_call 把工作流变成可复用的组件。

定义一个可复用工作流:

# .github/workflows/ci.yml
on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci && npm test

在另一个工作流里调用它:

# .github/workflows/main.yml
on: push

jobs:
  call-ci:
    uses: ./.github/workflows/ci.yml
    with:
      node-version: '20'

这样你就可以在不同仓库间复用同一套 CI 逻辑,改一处,处处生效。

其他几个触发器(releaseissuesrepository_dispatch)相对用得少,我就不展开了。感兴趣的话,可以看看 GitHub 官方文档。

实战:第一个工作流模板

讲了这么多概念,不如直接上手试试。

下面是一个完整的 Node.js 项目 CI 工作流。你可以直接复制到自己的项目里用:

name: CI

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

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      # 1. 拉取代码
      - name: Checkout code
        uses: actions/checkout@v4

      # 2. 配置 Node.js 环境
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      # 3. 安装依赖
      - name: Install dependencies
        run: npm ci

      # 4. 运行测试
      - name: Run tests
        run: npm test

怎么用?

第一步: 在项目根目录创建 .github/workflows 文件夹(如果还没有的话)。

第二步: 在这个文件夹里创建 ci.yml 文件,把上面的代码粘贴进去。

第三步: 提交并推送到 GitHub。

推上去之后,点开仓库的 Actions 标签页,你应该就能看到工作流在跑了。

逐行解释一下

  • name: CI:工作流名称,会显示在 Actions 页面
  • on: push: branches: [main]:往 main 分支推代码时触发
  • on: pull_request: branches: [main]:有人提 PR 到 main 时也触发
  • jobs: build::定义一个叫 build 的 job
  • runs-on: ubuntu-latest:在 GitHub 提供的最新 Ubuntu 上跑
  • actions/checkout@v4:官方 Action,把你的代码拉到虚拟机上
  • actions/setup-node@v4:官方 Action,配置 Node.js 环境
  • npm ci:安装依赖(比 npm install 更快更干净)
  • npm test:跑测试

如果你的项目不是 Node.js,把中间的步骤换掉就行。比如 Python 项目:

steps:
  - uses: actions/checkout@v4
  - uses: actions/setup-python@v5
    with:
      python-version: '3.11'
  - run: pip install -r requirements.txt
  - run: pytest

基本上就是一个”拉代码 → 配环境 → 装依赖 → 跑测试”的套路。

常见配置错误排查

我踩过的坑,希望你别再踩。

这里整理了一份排查清单,遇到问题时对照检查:

错误现象可能原因解决方案
工作流不触发分支过滤条件错误检查 branches 配置,确认分支名大小写正确
YAML 解析失败缩进使用 Tab全部改为空格缩进,YAML 不支持 Tab
Secrets 不生效作用域错误认 secrets 在正确的层级(job 或 step)
Job 依赖失败needs 引用错误检查 job-id 拼写,区分大小写
工作流运行很慢没用缓存actions/cache 缓存依赖
权限不足报错GITHUB_TOKEN 权限不够在 job 里加 permissions 配置

错误 1:缩进用错了

这是最常见的错误,没有之一。

YAML 对缩进极其敏感。必须用空格,不能用 Tab。而且每一层缩进必须是 2 个空格(或者统一的其他数字,但 GitHub Actions 默认是 2)。

# 错误示范:缩进乱了
jobs:
  build:
  runs-on: ubuntu-latest  # 这行应该缩进 4 个空格
# 正确写法
jobs:
  build:
    runs-on: ubuntu-latest  # 缩进 4 个空格

大多数编辑器(VS Code、WebStorm)都能配置成”按 Tab 键自动插入空格”。建议把这个配置打开,省得每次手动敲空格。

错误 2:分支名写错了

GitHub 的分支名是区分大小写的。mainMain 是两个不同的分支。

# 如果你的分支叫 main
on:
  push:
    branches: [Main]  # 错了,触发不了

# 正确写法
on:
  push:
    branches: [main]  # 小写

如果你不确定分支名,可以去 GitHub 仓库页面看一眼,或者本地跑 git branch

错误 3:job-id 拼写错误

当你的工作流有多个 job 且它们有依赖关系时,needs 字段必须准确引用其他 job 的 id。

jobs:
  test:
    runs-on: ubuntu-latest
    # ...

  deploy:
    needs: Test  # 错了,大小写不匹配
    runs-on: ubuntu-latest
# 正确写法
jobs:
  test:
    runs-on: ubuntu-latest

  deploy:
    needs: test  # 小写,和上面的 job id 一致
    runs-on: ubuntu-latest

错误 4:Secrets 用错了层级

GitHub 的 Secrets 有两个作用域:仓库级别和环境级别。引用时用 ${{ secrets.XXX }}

# 错误示范:secrets 写错位置
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      API_KEY: secrets.MY_KEY  # 错了,没有 ${{ }}
# 正确写法
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      API_KEY: ${{ secrets.MY_KEY }}  # 用 ${{ }} 包裹

另外,Secrets 是加密的,你在日志里看不到它的实际值。如果要在日志里确认是否传递成功,可以打印一个替代值:

- name: Debug
  run: echo "API_KEY is set: ${{ secrets.MY_KEY != '' }}"

这样不会泄露实际的 Key,但能确认它是不是空的。

常见问题

GitHub Actions 工作流必须包含哪些字段?
最简配置只需要 `on`(触发器)和 `jobs`(任务定义)两个字段。`name` 和 `steps` 可选但不建议省略,它们让工作流更易读。
push 和 pull_request 触发器有什么区别?
`push` 在代码推送到分支时触发,适合部署流程;`pull_request` 在 PR 创建或更新时触发,适合代码检查和测试。通常两者配合使用:PR 跑测试,合并后跑部署。
YAML 缩进用 Tab 还是空格?
必须用空格。YAML 不支持 Tab 缩进。建议在 VS Code 中开启「按 Tab 插入空格」设置,避免踩坑。每层缩进通常用 2 个空格。
免费额度是多少?超了怎么办?
私有仓库每月 2000 分钟,公开仓库无限制。超了可以购买额外额度,或使用 self-hosted runner(自托管运行环境,不计入免费额度)。

GitHub Actions vs 其他 CI/CD 工具

你可能用过 Jenkins、GitLab CI 或者 CircleCI。那 GitHub Actions 相比它们有什么优劣势?

我整理了一张对比表:

对比项GitHub ActionsGitLab CIJenkinsCircleCI
配置语言YAMLYAMLGroovyYAML
托管方式云原生云/自托管自托管云原生
集成度GitHub 原生GitLab 原生需配置需配置
学习曲线
免费额度2000 分钟/月(私有库)400 分钟/月无限制(自托管)6000 分钟/月
公开仓库无限制无限制无限制无限制

GitHub Actions 的优势

1. 零配置集成

如果你的代码已经托管在 GitHub,用 GitHub Actions 是最顺的选择。不用额外配置 webhook、不用维护服务器、不用装插件。创建一个 YAML 文件,推上去就能跑。

2. Marketplace 生态

GitHub Marketplace 里有成千上万的 Actions,AWS、Azure、Google Cloud 都有官方 Actions。你需要什么功能,大概率别人已经写好了,直接 uses 调用。

3. 免费额度对个人开发者友好

公开仓库无限制使用,私有仓库每月 2000 分钟。对于个人项目或小团队,基本够用。

什么时候不选 GitHub Actions?

1. 你的代码不在 GitHub

如果你用 GitLab 或 Bitbucket,那就用它们自带的 CI/CD。虽然 GitHub Actions 也能通过 webhook 触发,但折腾一圈不如直接用原生方案。

2. 你需要完全控制运行环境

GitHub Actions 的 runner 环境是固定的(Ubuntu/Windows/macOS),你没法装自己的软件或配置特殊环境。这种情况下,Jenkins + 自托管 runner 更灵活。

3. 你对安全性有极端要求

GitHub Actions 的 runner 是 GitHub 托管的虚拟机。如果你的代码涉及高度敏感信息,可能需要自建 CI 系统。不过 GitHub 也支持 self-hosted runner,可以折中解决。

我的建议

对于大多数个人开发者和小团队:

  • 代码在 GitHub → 选 GitHub Actions
  • 代码在 GitLab → 选 GitLab CI
  • 需要高度定制 → Jenkins 或 self-hosted runner

没有绝对的最优解,适合自己的才是最好的。

总结

文章写到这,你大概已经知道 GitHub Actions 的 YAML 工作流是怎么回事了。

核心要点:

  • 四大核心字段:name 命名、on 触发、jobs 定义任务、steps 执行步骤
  • 八种常用触发器:用得最多的是 pushpull_requestschedule
  • 一个可复制的模板:拉代码 → 配环境 → 装依赖 → 跑测试
  • 四个常见坑:缩进、分支名、job-id、Secrets

接下来,你可以:

  1. 在自己的项目里创建第一个工作流(就复制本文的模板,改成你的项目配置)
  2. 读读系列的进阶文章《GitHub Actions 缓存策略:加速 CI/CD 流水线 5 倍》,了解如何让工作流跑得更快
  3. 去 GitHub Marketplace 逛逛,看看有什么好用的 Actions 能直接拿来用

自动化这件事,一旦尝到甜头,就回不去了。

12 分钟阅读 · 发布于: 2026年4月10日 · 修改于: 2026年4月11日

评论

使用 GitHub 账号登录后即可评论

相关文章