GitLab CI默认分支(Production)部署流水线未触发问题求助
问题背景与现象
我在GitLab仓库维护了uat和production两个分支,各自存放专属的.gitlab-ci.yml配置文件,其中production是默认分支。两个分支的部署任务规则完全一致:仅当dir/目录下文件变更时触发,且排除定时流水线。
但实际运行时,uat分支的deploy_to_uat任务表现正常——直接推代码、合并PR到uat都能正确触发;而配置几乎一模一样的production分支的deploy_to_production任务,无论怎么操作都毫无反应。
核心误区:默认分支的changes检测逻辑差异
你踩了GitLab CI一个容易忽略的坑:默认分支的changes规则判断逻辑和普通分支不一样。
对于非默认分支(比如uat),GitLab会对比当前提交和分支的上一个提交,检查dir/目录是否有变更。但对于默认分支(production),GitLab默认的对比基准是上一次成功运行的流水线对应的提交,而不是分支的上一个提交。
举个例子:如果之前production分支的某次流水线因为没有dir/变更而跳过了部署任务,或者流水线历史有异常,那么新的提交即使修改了dir/下的文件,GitLab也会拿它和上一次成功流水线的提交对比,可能判断为没有变更,从而不触发任务。
修复方案
这里给你三个可行的解决办法,按推荐度排序:
1. 改用rules替代only/except(推荐)
rules是GitLab CI更现代、逻辑更清晰的语法,能避开only/except在默认分支上的判断陷阱。把production分支的配置改成下面这样:
deploy_to_production: rules: # 先排除定时流水线 - if: '$CI_PIPELINE_SOURCE == "schedule"' when: never # 仅当是production分支且dir/有变更时触发 - if: '$CI_COMMIT_BRANCH == "production"' changes: - dir/* when: always script: # upload to prod
你也可以把uat分支的配置同步改成这种写法,保持两个分支的配置逻辑一致,后续更易维护。
2. 给changes指定明确的对比基准
如果不想替换语法,可以在only的changes里加上compare_to参数,强制GitLab和分支的上一个提交对比,而不是上一次成功流水线:
deploy_to_production: only: refs: - production changes: - dir/* compare_to: 'HEAD~1' # 明确对比上一个提交 except: - schedules script: # upload to prod
3. 手动触发一次基准流水线
如果暂时不想修改配置,可以先手动触发production分支的流水线:进入分支的"CI/CD" -> "Pipelines"页面,点击"Run pipeline",直接运行一次全量流水线。这会更新GitLab默认分支的对比基准,之后正常提交的dir/变更就能被正确检测到了。
总结
本质问题是你没意识到默认分支和普通分支在changes检测上的逻辑差异,改用rules语法是最稳妥的长期解决方案,能避免后续再踩类似的坑。
内容的提问来源于stack exchange,提问作者Thomas Koch

