Skip to content

过滤器教程

过滤器决定哪些 Webhook 事件会被路由转发。只有当路由 filters 数组中的每一个过滤器都匹配时,路由才会触发(AND 逻辑)。本页是一份上手教程:解释每种过滤器类型的行为,以及如何组合它们实现真实场景的路由规则。

参考表格见配置指南的过滤器类型,完整事件列表见支持的事件

匹配机制

  • 路由中所有过滤器都必须匹配,否则该路由被跳过。
  • 每个过滤器将事件与 Webhook 载荷的某个字段进行匹配。
  • 所有过滤器类型都不区分大小写
  • match 值可以是单个字符串,也可以是字符串数组。数组相当于 OR——只要其中一个值匹配,该过滤器即匹配。
  • 设置 "exclude": true 会反转结果(NOT 逻辑):当值匹配时,该过滤器才匹配。
json
{
  "type": "event",
  "match": ["push", "pull_request"],
  "exclude": false
}

上面这条路由同时匹配 pushpull_request 事件。

模式语法

所有过滤器类型共享以下三种模式写法:

模式含义
纯文本字段过滤器:完全相等匹配;keyword:在载荷中任意位置搜索。
* / ?通配符(glob)——* 任意长度、? 恰好一个字符。
/正则表达式/正则表达式编译(忽略大小写标志)。
  • 字段过滤器(event/repo/actor/action/branch)的纯文本与通配符匹配整个值;keyword 则在载荷中任意位置搜索。
  • 正则表达式始终是搜索语义:/^feat/ 匹配以 feat 开头的值,/feat/ 匹配任意位置出现 feat 的值。

示例:

json
{ "type": "event", "match": "pull_*" }

匹配 pull_requestpull_request_reviewpull_request_review_comment 等。

json
{ "type": "repo", "match": "myorg/*" }
json
{ "type": "branch", "match": "feature-?" }

匹配 feature-xfeature-1,但不匹配 feature-xy

json
{ "type": "branch", "match": "/^feat/" }

匹配任何以 feat 开头的分支名。

TIP

通配符和正则同样不区分大小写,且 * 可以跨过仓库名中的 /myorg/* 也能匹配 myorg/sub/backend)。

各过滤器类型详解

event — 事件类型

匹配 GitHub 事件名称,如 pushpull_requestissuesrelease。它是每条路由的主干。

json
{ "type": "event", "match": "release" }

用数组匹配多种事件:

json
{ "type": "event", "match": ["create", "delete"] }

repo — 仓库

匹配仓库全名owner/name)。不区分大小写。

json
{ "type": "repo", "match": "myorg/backend" }

将多个仓库路由到同一频道:

json
{ "type": "repo", "match": ["myorg/backend", "myorg/frontend"] }

actor — 发送者

匹配触发事件的 GitHub 发送者登录名(载荷中的 sender.login)。常用于忽略机器人。

json
{ "type": "actor", "match": "dependabot[bot]", "exclude": true }

上面这条路由对 Dependabot 触发之外的所有事件都会触发。

action — 事件操作

匹配载荷中的 action 字段,如 openedclosedpublishedcompleted。并非所有事件都带有 action——参见过滤器兼容性。与 event 组合可精确到某个生命周期步骤:

json
{
  "type": "event",
  "match": "pull_request",
  "exclude": false
},
{
  "type": "action",
  "match": ["opened", "reopened"]
}

上面的规则在拉取请求被打开或重新打开时触发(合并/关闭/编辑时不触发)。

branch — 分支

匹配事件涉及的分支。何种字段算作「分支」取决于事件类型:

事件提取的分支
push推送到的目标分支
pull_request(及 review)拉取请求的 head(源)分支
create / delete创建/删除的分支或标签
workflow_run工作流运行所在的 head_branch
workflow_job作业运行所在的 head_branch
check_suite检查套件的 head_branch
deployment部署引用(去除 refs/heads/ 前缀)
code_scanning_alert告警所属的分支
json
{
  "type": "event",
  "match": "push"
},
{
  "type": "branch",
  "match": "main"
}

仅当推送到 main 时触发。要关注多个长期分支:

json
{ "type": "branch", "match": ["main", "develop"] }

NOTE

branch 匹配不区分大小写。需要前缀或通配符式匹配时,可直接使用通配符(feature/*)或用 / 包裹正则(/^release-/)。

keyword — 载荷中的文本

匹配整个 JSON 载荷(转为小写)。它是最灵活的过滤器:纯文本在任意位置搜索,*/? 通配符带通配搜索,// 包裹的模式按正则表达式编译(带 i 标志)。

json
{ "type": "keyword", "match": "deploy" }

当载荷中任意位置包含 deploy 时触发。由于载荷已被转为小写,DeployDEPLOY 等都会匹配。

json
{ "type": "keyword", "match": "*release-*" }
json
{ "type": "keyword", "match": "/^(fix|hotfix)/" }
json
{ "type": "keyword", "match": "/release-[0-9]+/" }

行为细节:

  • 超过 200 个字符的模式编译为通配符/正则,回退为纯文本匹配。
  • / 包裹但不是合法正则的模式匹配任何内容都不命中(过滤器恒为 false),而不会报错。
  • 要搜索是通配符或正则特殊字符的文本(如 v1.2.3),使用纯文本形式即可——不含 *? 且未被 // 包裹的模式按字面匹配。
  • 搜索覆盖整个载荷:提交信息、PR 标题与正文、标签、引用,甚至仓库名和发送者名。

keywordexclude 组合

与其他过滤器一样,exclude 会反转关键词匹配:

json
{ "type": "keyword", "match": "/wip|draft/", "exclude": true }

跳过载荷中提及 wipdraft 的事件。

示例 1:PR 通知,跳过机器人和草稿

转发拉取请求动态,但忽略机器人作者和草稿 PR,发往 #prs 频道:

json
{
  "id": "pr-notices",
  "name": "PR Notices",
  "enabled": true,
  "groupId": "eng",
  "filters": [
    { "type": "event", "match": "pull_request" },
    { "type": "actor", "match": "dependabot[bot]", "exclude": true },
    { "type": "keyword", "match": "\"draft\": true", "exclude": true }
  ],
  "target": { "channelId": "111111111111111111" }
}

"draft": true 模式匹配 GitHub 在拉取请求载荷中包含的 draft 字段;配合 exclude: true 即可过滤掉草稿 PR。

示例 2:仅发布通知频道

只转发特定仓库的已发布 release:

json
{
  "id": "release-alerts",
  "name": "Release Alerts",
  "enabled": true,
  "groupId": "eng",
  "filters": [
    { "type": "event", "match": "release" },
    { "type": "action", "match": "published" },
    { "type": "repo", "match": "myorg/backend" }
  ],
  "target": { "channelId": "222222222222222222" }
}

示例 3:CI 失败

转发任意分支上以失败结束的 workflow run,发往 #ci 频道:

json
{
  "id": "ci-failures",
  "name": "CI Failures",
  "enabled": true,
  "groupId": "eng",
  "filters": [
    { "type": "event", "match": "workflow_run" },
    { "type": "action", "match": "completed" },
    { "type": "keyword", "match": "\"conclusion\":\"failure\"" }
  ],
  "target": { "channelId": "333333333333333333" }
}

常见陷阱

  • 通配符是 glob,不是正则。 repo: "myorg/*" 匹配 myorg 下的任意仓库(含 myorg/sub/backend),但 repo: "myorg/.*" 按字面匹配。需要正则请用 / 包裹:"/myorg\/.*/"
  • / 包裹的非法正则永远不匹配。 与纯文本不同——未包裹的非法模式按字面匹配。只有确定是真正的正则时才使用 // 包裹。
  • action 过滤器遇到无 action 的事件永远不匹配。 先确认该事件带有 action 字段(见过滤器兼容性)。
  • branch 过滤器遇到无分支的事件永远不匹配。issues 事件上使用 branch 过滤器恒为假。此时需要类似分支的匹配可用 keyword
  • keyword 会搜索一切。 因为它扫描整个载荷,"fix" 这样的模式可能同时匹配提交信息、issue 标题和仓库名。请尽量写得更具体。
  • 牢记 exclude 语义。 exclude: true 反转的是整个过滤器——数组中的一个值不匹配并不会「阻断」路由;只有当所有值都不匹配时,取反后的过滤器才匹配。

基于 MIT 许可发布。