GitHub Actions 路径过滤器使用指南
问题描述
在 Git 仓库中,我们经常需要根据文件变更的位置来控制 CI/CD 流程的执行。常见的情景是:当只有特定目录下的文件发生变化时,才触发对应的 GitHub Actions 工作流程。
例如,假设项目结构如下:
- folder1
- file1
- *其他文件*
- folder2
- file1
- *其他文件*
- .gitignore
- package.json
- *其他文件*
当只有 folder1
目录下的文件发生变化时,才触发相应的工作流程。
解决方案
基本路径过滤
GitHub Actions 提供了原生的路径过滤功能,可以在工作流程配置中使用 paths
或 paths-ignore
来指定触发条件:
on:
push:
paths:
- 'folder1/**'
上述配置表示只有当 push
操作涉及 folder1
目录下的文件时,工作流程才会触发。
同时监听多个路径
你可以指定多个路径模式:
on:
push:
paths:
- 'folder1/**'
- 'folder2/subfolder/**'
排除特定路径
如果需要排除某些路径,可以使用 !
前缀的否定模式:
on:
push:
paths:
- 'sub-project/**'
- '!sub-project/docs/**' # 排除子项目中的 docs 目录
注意
否定模式必须与至少一个肯定模式一起使用,且模式的顺序很重要(按列出的顺序进行评估)。
使用 paths-ignore 排除路径
另一种排除路径的方法是使用 paths-ignore
:
on:
push:
paths-ignore:
- 'folder1/**'
重要限制
不能对同一事件同时使用 paths
和 paths-ignore
,必须选择其中一种方式。
结合分支过滤
路径过滤可以与其他触发条件(如分支过滤)结合使用:
on:
push:
branches: ['main']
paths: ['folder1/**']
监听 Pull Request 事件
同样的路径过滤语法也适用于 pull_request
事件:
on:
push:
paths:
- 'folder1/**'
pull_request:
paths:
- 'folder1/**'
包含工作流程文件自身变更
如果工作流程配置文件的变更也应该触发工作流程执行,需要将工作流程目录加入路径:
on:
push:
paths:
- 'my-nodejs-application-directory/**'
- '.github/workflows/**' # 包含工作流程文件变更
高级用法
作业级别的路径过滤
原生的路径过滤只能在工作流程级别使用。如果需要在作业级别进行更精细的控制,可以使用第三方 Action,如 changed-files
:
jobs:
my-job:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v41
- name: Run conditional step
if: contains(steps.changed-files.outputs.all_changed_files, 'folder1/')
run: echo "Folder1 files were changed!"
复杂路径模式
路径模式支持 glob 模式匹配:
*
匹配零个或多个非/
字符**
匹配零个或多个任意字符(包括/
)?
匹配单个非/
字符[abc]
匹配指定字符集中的单个字符
最佳实践
- 明确指定分支:结合分支过滤和路径过滤,提高精确度
- 包含工作流程文件:如果需要工作流程自身的变更也能触发执行
- 测试模式:使用 GitHub 提供的路径过滤器测试工具验证模式是否正确
- 避免过度使用:过于复杂的路径模式可能会影响性能和维护性
总结
GitHub Actions 的原生路径过滤功能提供了简单而强大的方式来实现条件触发工作流程。通过合理使用 paths
和 paths-ignore
,可以精确控制工作流程的执行条件,提高 CI/CD 流程的效率。
对于更复杂的场景,可以考虑结合第三方 Action 实现作业级别的精细控制。无论选择哪种方式,清晰的路径模式和充分的测试都是确保工作流程按预期执行的关键。