Jenkins流水线中如何追踪Git子模块中含指定分支的子模块?
问题描述
现有Git项目包含多个子模块,其中只有部分子模块(比如module2、module4)存在feature/jira-123-new-feature分支,其余子模块没有这个分支。需要在Jenkins流水线里实现这么个逻辑:遍历所有子模块,要是子模块有目标分支就把它加到childModules列表里,没有就跳过。目前已经写了部分流水线代码,需要补全<add child module to childModules list>的逻辑,或者找更优的实现方案。现有代码示例如下:
node("buildNode") { stage("Run Git") { List<String> childModules = [] sh """ git submodule foreach 'git checkout feature/jira-123-new-feature && <add child module to childModules list> || :' """ } }
解决方案
方案一:逐个遍历子模块,检查分支后加入列表
这种方式更贴合Jenkins流水线的Groovy逻辑,避开Shell和Groovy变量交互的麻烦:
node("buildNode") { stage("Run Git") { List<String> childModules = [] // 获取所有子模块的路径列表 def submodulePaths = sh( script: 'git submodule foreach --quiet echo "$path"', returnStdout: true ).trim().split('\n') submodulePaths.each { path -> // 远程检查目标分支是否存在(比本地checkout更可靠) def branchExists = sh( script: "cd ${path} && git ls-remote --heads origin feature/jira-123-new-feature | grep -q feature/jira-123-new-feature", returnStatus: true ) if (branchExists == 0) { // 分支存在就切换并加入列表 sh "cd ${path} && git checkout feature/jira-123-new-feature" childModules.add(path) } } // 可选:打印结果验证 echo "符合条件的子模块:${childModules}" } }
方案说明
- 用
git submodule foreach --quiet echo "$path"获取所有子模块的路径,过滤掉默认的冗余输出 - 遍历每个子模块,通过
git ls-remote检查远程仓库是否有目标分支,避免本地分支缓存带来的误差 - 分支存在时执行checkout,并将子模块路径加入列表
方案二:通过Shell输出捕获符合条件的子模块
如果更习惯用git submodule foreach的写法,可以让Shell直接输出符合条件的子模块路径,再把结果捕获到Groovy列表里:
node("buildNode") { stage("Run Git") { List<String> childModules = [] // 执行Shell命令,输出存在目标分支的子模块路径 def validModules = sh( script: """ git submodule foreach ' if git ls-remote --heads origin feature/jira-123-new-feature | grep -q feature/jira-123-new-feature; then git checkout feature/jira-123-new-feature echo "\$path" fi ' | grep -v "^Entering" """, returnStdout: true ).trim().split('\n') // 把结果转成Groovy列表 childModules.addAll(validModules) echo "符合条件的子模块:${childModules}" } }
方案说明
- 在
git submodule foreach的脚本里,先检查远程分支是否存在,存在就执行checkout并输出子模块路径 - 用
grep -v "^Entering"过滤掉git submodule foreach默认输出的Entering 'xxx'提示行 - 捕获Shell输出后分割成数组,添加到
childModules列表中
注意事项
- 优先用
git ls-remote检查远程分支,避免本地分支不存在但远程存在、或者本地分支过时的问题 - Jenkins流水线里,
sh步骤的returnStdout(捕获输出)和returnStatus(获取执行状态码)是实现Shell与Groovy变量交互的核心 - 如果只需要检查本地已有的分支,可以把
git ls-remote换成git show-ref --verify --quiet refs/heads/feature/jira-123-new-feature
内容的提问来源于stack exchange,提问作者Chris F
相关产品推荐
相关产品推荐

