CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
GitHub Actions CI/CD/课时/Workflow 文件结构
RawBlame
课时目录12 节

GitHub Actions CI/CD

  1. 01CI/CD 与 GitHub Actions
  2. 02Workflow 文件结构
  3. 03Jobs 与运行器
  4. 04Steps 与 Actions
  5. 05Secrets 与环境
  6. 06依赖缓存
  7. 07构建 Spring Boot
  8. 08构建 Next.js platform
  9. 09构建推送镜像
  10. 10部署策略
  11. 11PR 检查与分支保护
  12. 12综合练习

Workflow 文件结构

.github/workflows、on 触发器、name、permissions。

30 分钟

Workflow 文件结构

这一课你将能做到

  1. 在仓库创建 .github/workflows/ci.yml,用 on 配置 push / pull_request / workflow_dispatch 三种触发器
  2. 读懂最小 workflow 的骨架:name、on、permissions、jobs、runs-on、steps 各管什么
  3. 在 GitHub Actions 页手动触发一次 run,并对照日志确认 echo 输出

为什么要学

概念课说过「自动工头」;工头的说明书就是 workflow YAML。路径约定死在 .github/workflows/*.yml(或 .yaml)——放错目录等于没装,GitHub 根本不扫描。

触发器写错时,最常见的懵是:「我 push 了为什么没跑?」或「只想手动跑一次,结果每次 push 都在烧分钟数。」这些都不是玄学,是 on 的语义没吃透。

本课把文件骨架钉牢:何时跑、权限多大、里面有哪些 job。Job 并行/串行、step 细节下一课再拆。

先建立图像

仓库根目录
└─ .github/
   └─ workflows/
      ├─ ci.yml          ← 名称随意,扩展名必须是 yml/yaml
      ├─ docker.yml
      └─ …

一个 workflow 文件 ≈
  name: 页面上显示的名字
  on:   何时启动(触发器)
  permissions: 这次 run 的 GITHUB_TOKEN 能做什么
  jobs:
    job-id:
      runs-on: 哪种虚拟机
      steps:   具体命令 / action

人话:workflow 像一份「外卖单」——写清什么时候下单(on)、厨房在哪(runs-on)、做哪几道菜(jobs/steps)。单子本身也进 Git,改单子要 PR。

键人话初学必填?
nameActions 列表里的标题建议填
on触发条件必须
permissionstoken 能力上限强烈建议显式写
jobs要跑的任务集合必须
concurrency同名 run 互斥/取消旧的进阶可选

跟着做

步骤 1:创建目录与文件

在本地仓库(或 GitHub 网页 Add file)新建:

.github/workflows/ci.yml

注意是 workflows 复数,不是 workflow。若目录不存在就整条路径新建。提交到一个 feature 分支试水——YAML 语法严重错误时,Actions 页会直接出现醒目的解析失败。

步骤 2:粘贴最小可运行示例

写入:

# 在 Actions 列表里显示的名字
name: CI

# 何时启动这份流水线
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  # 允许在网页上点「Run workflow」手动跑
  workflow_dispatch:

# 默认只读代码,符合最小权限
permissions:
  contents: read

jobs:
  hello:
    # GitHub 托管的 Ubuntu 虚拟机
    runs-on: ubuntu-latest
    steps:
      - name: 打个招呼
        run: echo "Hello CodeRoadMap"

推上去后:对 main 的 push/PR 应出现 run;也可在 Actions 页点 Run workflow 手动运行。

步骤 3:在 UI 里核对一次 run

Actions → 点进本次 CI → 点 job hello → 展开 step「打个招呼」。日志里应有 Hello CodeRoadMap。

若没出现 run:检查分支名是否真是 main(有的仓库是 master)、文件路径是否在 .github/workflows/、是否 push 到了远端。

步骤 4:改触发器做对照实验

临时改成只手动:

on:
  workflow_dispatch:

再 push 一次普通提交——不应自动跑;回到 Actions 页点 Run workflow 才跑。改回 push + pull_request 后,确认 PR 会再次触发。笔记写:「on 决定烧不烧分钟数。」

步骤 5:认识常用触发器表

on场景备注
push分支收到提交可按 branches / paths 过滤
pull_requestPR 打开/同步/重开面试最常问的场景
workflow_dispatch人手点运行或 API 触发排错利器
schedulecron 定时注意时区是 UTC
workflow_call被其它 workflow 复用可复用流水线(进阶)

本站主路径常用:push + pull_request 到 main,外加 workflow_dispatch 方便排错。

步骤 6:把流水线当代码审一遍

改 ci.yml 也开 PR,请人看三件事:

  • 触发是否过宽(是否在所有分支狂跑制造噪音)
  • permissions 是否过大(无必要的 write)
  • job 名是否与日后分支保护里要勾的 check 名一致(第 11 课)

讲清楚要点

  1. 因为 GitHub 只扫描固定目录,所以文件必须放在 .github/workflows/——放 scripts/ci.yml 不会自动变成 Actions。
  2. 因为 on 决定何时占用 runner,所以先写准触发器再堆步骤——省分钟数从「少跑冤枉流水线」开始。
  3. 因为 GITHUB_TOKEN 默认能力随 permissions 变,所以显式写最小权限——纯 CI 常用 contents: read;推 GHCR 才加 packages: write。
  4. 因为 workflow 版本化在 Git,所以改流水线与改业务一样走 review——避免「某天 main 上的 CD 被悄悄改掉」。
  5. 因为一个仓库可有多个 workflow 文件,所以按职责拆分更清晰——ci.yml 测代码、docker.yml 推镜像,失败域分离。
  6. 因为 YAML 对缩进敏感,所以用空格对齐、先跑通最小 echo 再加复杂步骤——Tab 与空格混用是解析失败的常见根因。

你可能会懵的地方

  1. 「name 和 job 的 id 哪个出现在分支保护里?」 分支保护勾选的是 job 级 check(默认用 job 的 key,或 job 上的 name: 字段)。workflow 顶层 name 只是列表标题。第 11 课会再钉一次。

  2. 「push 和 pull_request 会不会跑两次?」 开 PR 时跑 pull_request;往 PR 分支再 push 会再触发一轮;合并进 main 的 push 再跑一次——这是预期行为。可用 paths 过滤减轻(第 11 课)。

  3. 「permissions 不写行不行?」 能跑,但默认权限随仓库/组织设置变化,可读性差、可审计性差。显式写出「这份 CI 只需读代码」更安全也更好审。

  4. 「workflow_dispatch 按钮为什么有时不出现?」 该触发器必须存在于默认分支上的 workflow 文件里,按钮才会出现。在 feature 分支加了 workflow_dispatch 但没合进默认分支时,Actions 列表里看不到「Run workflow」入口。

  5. 「on: 后面直接跟数组是什么写法?」 on: [push, pull_request] 是简写,等价于对两个事件都用默认配置(所有分支)。需要 branches/paths 过滤时必须用映射写法。

错法对照

错法问题正解
文件放在 .github/ci.ymlGitHub 不加载.github/workflows/ci.yml
on: [push] 无分支过滤,所有分支狂跑浪费分钟、噪音大限制 branches,需要时再加 paths
默认给 contents: write「方便以后用」token 能力过大CI 只读;写权限按 job 需要再开
用 Tab 缩进 YAML解析失败或报错难懂统一空格,编辑器配置 show invisibles
只在网页点 Generate 从不提交 YAML无法复现、无法 reviewYAML 进仓库,PR 合并

卡点急救

  1. workflow 完全不触发:按顺序查四点——① 文件在不在 .github/workflows/;② 触发的分支名与 on.push.branches 是否匹配;③ 该文件是否已存在于默认分支(新加在 feature 分支的 workflow 不响应本分支的 push);④ 仓库 Actions 是否被 Settings 禁用。
  2. YAML 报错 Unexpected value 或整个文件不解析:九成是缩进错误或 Tab 字符。用编辑器「显示空白字符」逐行查;也可本地用 yamllint 或 VS Code 的 YAML 插件先校验再 push。
  3. 手动 Run workflow 按钮不见了:确认默认分支上的文件仍含 workflow_dispatch:;确认你在 Actions 左侧列表选中了正确的 workflow;还要注意按钮只在页面右上角,容易看漏。

面试常问

  • GitHub Actions 的 workflow 文件放在哪?有哪些常见触发事件? 放在仓库 .github/workflows/ 目录,扩展名 yml/yaml。常见触发:push、pull_request、workflow_dispatch(手动)、schedule(cron)、release、workflow_call(被复用)。可以按 branches、paths 精细过滤,比如 monorepo 里只改 backend/** 才跑 Java 检查。

  • permissions 字段为什么重要? 它控制这次 run 里 GITHUB_TOKEN 的能力上限。GitHub 默认 token 权限可能偏宽(取决于仓库设置),显式声明最小权限(如 contents: read)能缩小「workflow 被注入恶意命令后能造成的破坏面」。这是 Actions 安全加固的第一课,也是供应链安全面试题的得分点。

  • 一个仓库多个 workflow 文件怎么组织? 按职责拆:CI 检查一个文件(高频、PR 触发)、镜像构建一个文件(main 触发)、定时任务一个文件。好处是失败域分离、权限各配、日志各看;坏处是触发条件要写清楚,避免同一改动重复跑多个流水线。

自测三问

  1. 写出最小 workflow 必须有的两个顶层键(除 name 外)。
  2. 如何做到「代码 push 不自动跑、只在网页手动跑」?
  3. 为什么建议写 permissions: contents: read?

小结一句话

一个 workflow = 触发器 +(可选)权限声明 + jobs 集合;文件必须在 .github/workflows/。

延伸

  • Workflow syntax for GitHub Actions
  • Events that trigger workflows
  • 下一课:Jobs 与运行器——一个 workflow 里多台机器怎么并行、怎么排队。
加载本节练习…
← 上一课CI/CD 与 GitHub Actions下一课 →Jobs 与运行器