如何配置GitHub Action:仅特定路径变更触发,排除master分支合并
解决思路与方案
问题出在GitHub的on.push.paths过滤逻辑上:它是对比当前分支和上一次推送该分支时的状态来判断路径是否变更。当你把带some/path变更的master合并到其他分支时,目标分支的状态和上一次推送的差异会包含master里的some/path内容,所以触发了Action,但这并不是你要的「该路径有新修改」的场景。
下面是几种可行的解决方案:
方案一:在Workflow内检查本次提交的实际变更
这是最可靠的方法——保留GitHub的路径过滤做初步筛选,在Job里直接检查本次推送的提交是否真的修改了some/path下的文件,只有确认有新修改时才执行构建。
修改后的配置示例:
on: push: paths: - 'some/path/**' jobs: build-resources: runs-on: ubuntu-latest steps: - name: 拉取代码 uses: actions/checkout@v4 with: fetch-depth: 2 # 只拉最近2次提交,足够对比本次变更 - name: 检查本次提交是否修改了some/path id: check_changes run: | # 对比当前提交和上一次提交的文件变更 CHANGED=$(git diff --name-only HEAD^ HEAD | grep "^some/path/") if [ -n "$CHANGED" ]; then echo "has_changes=true" >> $GITHUB_OUTPUT else echo "has_changes=false" >> $GITHUB_OUTPUT fi - name: 执行资源构建 if: steps.check_changes.outputs.has_changes == 'true' run: | # 这里替换成你的构建命令 echo "开始构建some/path下的资源..."
原理很简单:不管分支合并带来的差异,只看本次推送的提交(也就是合并提交或普通提交)本身是否修改了some/path的文件。如果是合并master的操作,本次提交本身不会有some/path的新修改,就会跳过构建。
方案二:排除从master分支合并的推送
如果你想直接拦截从master合并的操作,可以通过检查提交的父分支来实现,但这种方法依赖Git的提交结构,可靠性稍弱(比如自定义合并信息或合并master的衍生分支时可能误判)。
示例配置:
on: push: paths: - 'some/path/**' jobs: build-resources: runs-on: ubuntu-latest steps: - name: 拉取完整代码历史 uses: actions/checkout@v4 with: fetch-depth: 0 # 需要完整历史来识别合并源分支 - name: 检查是否是从master合并的提交 id: check_merge run: | # 先判断是否是合并提交(有两个父提交) if git rev-parse --verify -q HEAD^2 > /dev/null; then # 获取合并的源分支名称 MERGE_SOURCE=$(git name-rev --name-only $(git show -s --pretty=format:%P HEAD | awk '{print $2}')) if [[ "$MERGE_SOURCE" == "refs/heads/master" ]]; then echo "is_merge_from_master=true" >> $GITHUB_OUTPUT else echo "is_merge_from_master=false" >> $GITHUB_OUTPUT fi else echo "is_merge_from_master=false" >> $GITHUB_OUTPUT fi - name: 执行资源构建 if: steps.check_merge.outputs.is_merge_from_master == 'false' run: | # 替换成你的构建命令 echo "开始构建some/path下的资源..."
方案三:结合Pull Request事件优化
如果你的代码合并都是通过PR完成的,可以改用pull_request事件——GitHub对PR的路径过滤是基于PR中实际新增/修改的文件,而不是分支整体差异。这样合并master到其他分支的PR如果没有修改some/path,就不会触发Action。
示例配置:
on: push: paths: - 'some/path/**' pull_request: paths: - 'some/path/**' jobs: build-resources: runs-on: ubuntu-latest steps: - name: 执行资源构建 run: | # 替换成你的构建命令 echo "开始构建some/path下的资源..."
注意:这个方案只解决PR场景的问题,直接推送分支的情况还是需要结合方案一处理。
内容的提问来源于stack exchange,提问作者Ecuador
相关产品推荐
相关产品推荐

