4. 工作流触发器详解

工作流触发器决定了 GitHub Actions 在什么条件下被唤醒。一个工作流可以同时监听多个事件,每个事件又可以叠加分支过滤、路径过滤、活动类型过滤和参数约束。理解触发器的关键,不是记住事件名称,而是建立“事件源 → 过滤条件 → 触发结果”的判断链:谁产生了事件、事件携带了哪些字段、哪些字段会被 on 下的过滤器拦截、最终哪些作业会进入运行队列。

GitHub Actions 的触发器大致分为四类:代码托管事件(push、pull_request、create、release 等)、定时事件(schedule)、手动事件(workflow_dispatch)和外部事件(repository_dispatch、workflow_call)。本节重点讨论最常用的五种:push、pull_request、schedule、workflow_dispatch、repository_dispatch。

push:最基础的代码推送触发

push 在提交被推送到仓库时触发。默认情况下,任何分支的推送都会触发工作流,这通常不是我们想要的。通过 branches 和 branches-ignore 可以限定分支,通过 paths 和 paths-ignore 可以限定文件路径。需要注意:branches 与 branches-ignore 不能同时出现在同一个事件下,paths 与 paths-ignore 同理。

on:
  push:
    branches:
      - main
      - 'release/**'
    paths:
      - 'src/**'
      - 'package.json'
      - '!src/**/*.md'
    tags:
      - 'v*'

上面的配置表示:只有推送到 main 或 release/ 开头的分支,且改动涉及 src/ 或 package.json,同时排除 src/ 下的 Markdown 文件时,工作流才会运行;此外,推送 v 开头的标签也会触发。路径过滤使用 glob 语法,! 前缀表示排除,多个模式按顺序匹配,后面的规则可以覆盖前面的规则。

一个常见误区是:paths 过滤基于两次提交之间的差异文件列表。如果一次推送包含多个提交,GitHub 会计算推送前后的差异,而不是逐个提交判断。因此,合并分支时即使只改了一个文件,也可能因为合并带来的差异范围较大而触发工作流。

pull_request:PR 生命周期触发

pull_request 在 PR 被打开、同步、重新打开、标记为可审查等时刻触发。它比 push 多了一个关键概念:活动类型(types)。默认活动类型是 opened、synchronize、reopened,如果显式指定 types,默认值会被覆盖。

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
    branches:
      - main
    paths:
      - 'src/**'
      - 'tests/**'

这里 branches 过滤的是 PR 的目标分支,而不是源分支。也就是说,只有目标为 main 的 PR 才会触发。如果希望过滤源分支,需要使用 head 字段(部分场景支持)。pull_request 还有一个重要变体 pull_request_target,它在目标分支的上下文中运行,拥有写权限和 secrets,适合做标签、评论等操作,但绝不能直接检出并执行 PR 中的不可信代码,否则会造成严重的安全风险。

schedule:定时触发

schedule 使用 POSIX cron 语法,时间基准是 UTC。它只会在默认分支上运行,且最短间隔为 5 分钟。GitHub 的定时任务在高峰期可能延迟,因此不适合对时间精度要求极高的场景。

on:
  schedule:
    - cron: '0 2 * * 1-5'   # 工作日 UTC 02:00
    - cron: '30 14 * * 0'   # 周日 UTC 14:30

上面的配置表示工作日每天 UTC 02:00 以及周日 UTC 14:30 各触发一次。如果团队在北京时间工作,需要把本地时间减去 8 小时换算成 UTC。例如希望北京时间每天 10:00 运行,应写成 0 2 * * *。定时工作流常用于夜间构建、依赖扫描、数据同步等场景。

workflow_dispatch:手动触发与参数

workflow_dispatch 允许在 GitHub 界面或通过 API 手动触发工作流,并支持定义输入参数。参数类型包括 string、boolean、choice 和 environment。

on:
  workflow_dispatch:
    inputs:
      environment:
        description: '部署环境'
        required: true
        default: 'staging'
        type: choice
        options: [staging, production]
      dry_run:
        description: '仅演练不实际部署'
        required: false
        default: true
        type: boolean
      version:
        description: '版本号'
        required: true
        type: string

在作业中通过 github.event.inputs.environment 或 inputs.environment 读取参数。布尔类型在 github.event.inputs 中会变成字符串 'true' 或 'false',而在 inputs 上下文中保持布尔值,因此推荐使用 inputs 上下文。手动触发非常适合发布、回滚、数据修复等需要人工确认的操作。

repository_dispatch:外部系统触发

repository_dispatch 允许通过 REST API 从外部系统触发工作流,常用于跨仓库联动、第三方服务回调等。它需要指定一个自定义的 event_type,并可携带 client_payload 作为数据载荷。

on:
  repository_dispatch:
    types: [build-request, cache-invalidate]

触发方式为向 POST /repos/{owner}/{repo}/dispatches 发送请求,请求体包含 event_type 和可选的 client_payload。工作流中通过 github.event.client_payload 读取载荷。注意:repository_dispatch 只在默认分支上触发,且需要具有 repo 权限的 token。

触发器组合与过滤优先级

当多个事件同时配置时,任意一个事件满足条件都会触发工作流。过滤条件的判断顺序是:先判断事件类型是否匹配,再判断活动类型是否在 types 列表中,然后判断分支/标签是否匹配,最后判断路径是否匹配。只有全部通过,工作流才会进入运行队列。

工作流触发器判断链:事件源 → 过滤条件 → 触发结果 push pull_request schedule workflow_dispatch repository_dispatch branches / tags 分支与标签过滤 types 活动类型过滤 paths / paths-ignore 文件路径过滤 inputs 手动参数校验 client_payload 外部载荷 全部条件 是否通过? AND 逻辑 ✓ 触发 进入运行队列 ✗ 跳过 不创建运行 通过 拦截 关键约束速查 • branches 与 branches-ignore 互斥;paths 与 paths-ignore 互斥 • pull_request 的 branches 过滤的是目标分支,不是源分支 • schedule 使用 UTC,最短间隔 5 分钟,仅在默认分支运行 • repository_dispatch 仅在默认分支触发,需 repo 权限 token

实践建议与常见排障

配置触发器时,建议遵循“最小触发面”原则:能用路径过滤就不要全仓库触发,能用分支过滤就不要全分支触发。对于 pull_request,如果只需要在 PR 合并前做检查,使用默认活动类型即可;如果需要在 PR 被标记为可审查时才运行,显式添加 ready_for_review。

常见问题包括:工作流没有触发,通常是因为分支名或路径 glob 写错、types 覆盖了默认值、或者事件发生在非默认分支而 schedule 和 repository_dispatch 不支持。排查时可以在仓库的 Actions 页面查看事件日志,确认事件是否被接收、过滤条件是否匹配。另一个高频问题是 paths 过滤在合并提交上表现不符合预期,此时可以改用 paths-ignore 或结合 dorny/paths-filter 等 action 做更精细的判断。

提示:在调试触发器时,可以临时把 on 配置为 on: [push, pull_request, workflow_dispatch],先确认工作流本身能正常运行,再逐步加上分支、路径和活动类型过滤,避免一次性配置过复杂导致难以定位问题。
安全提醒:pull_request_target 拥有目标分支的 secrets 和写权限,如果直接检出并执行 PR 中的代码,攻击者可以通过修改 PR 内容窃取 secrets。使用该触发器时,应只做标签、评论、状态更新等不执行不可信代码的操作。

掌握这五类触发器后,就可以根据团队的实际交付节奏组合使用:日常开发用 push 和 pull_request 做持续集成,夜间用 schedule 做定时任务,发布用 workflow_dispatch 做人工确认,跨系统协作用 repository_dispatch 做事件驱动。触发器的设计质量,直接决定了 CI/CD 流水线是否既灵敏又可控。