Pipeline Groovy脚本如何支持含$的SonarQube分支名?
问题:SonarQube含$的分支名在Pipeline脚本中被截断
我的Groovy Pipeline脚本用于获取SonarQube分支及对应代码行数,运行正常,但遇到名为branch-$branch的分支时,遍历分支列表时该分支的curl请求里分支名被截断为branch-,无法获取数据。已经尝试branch_name = p_branches.name.toString()但无效,且无法修改分支名称,求解决方法。
原脚本
stage('Extract Output') { steps { script { // Sonar branches API Endpoint String branches_url = base_url+"/api/project_branches/list" String sonar_branches = sh(script: 'curl -s -u user:pswd -X GET -F "project=sonar.project" '+branches_url, returnStdout: true).trim() def jsonSonarBranches = readJSON text: sonar_branches p_branches = jsonSonarBranches.branches branch_name = p_branches.name branch_LAD = p_branches.analysisDate echo "${branch_name}" echo "------------------" // LOC API Endpoint String measures_url = base_url+"/api/measures/component" int index = 0 for(String branch: branch_name){ brnch_lad = branch_LAD.get(index) String project_measures = sh(script: 'curl -s -u usr:paswd -X GET -F "component=sonar.project" -F "metricKeys=ncloc" -F "branch='+branch+'" '+measures_url, returnStdout: true).trim() def jsonProjectMeasures = readJSON text: project_measures // components json: value = loc proj_component = jsonProjectMeasures.component.measures p_measures = proj_component.value if(brnch_lad == null){ brnch_lad = 'N/A' p_measures = 'N/A' echo "PROJECT_KEY:sonar.project BRANCH:${branch} LAD:${brnch_lad} LOC:${p_measures}" } else if(p_measures.isEmpty()) { p_measures = 'N/A' echo "PROJECT_KEY:sonar.project BRANCH:${branch} LAD:${brnch_lad} LOC:${p_measures}" } else if(p_measures == null){ p_measures = 'N/A' echo "PROJECT_KEY:sonar.project BRANCH:${branch} LAD:${brnch_lad} LOC:${p_measures}" } else { int index_measures = 0 p_loc = p_measures.get(index_measures) echo "PROJECT_KEY:sonar.project BRANCH:${branch} LAD:${brnch_lad} LOC:${p_loc}" index_measures++ } index++ } echo "--------------------------------------------------------------------------------------------------------" } } }
执行结果
echo "${branch_name}"输出:
[branch-123, branch-master, branch-origin/pr, branch-$branch]
branch-$branch分支对应的curl请求输出:
+ curl -s -u **** -X GET -F component=sonar.project -F metricKeys=ncloc -F branch=branch- https://sonarqube.com/api/measures/component
原因分析
问题出在shell命令的字符串拼接上:当用单引号包裹shell脚本时,branch='+branch+'会把branch-$branch中的$branch解析为shell环境变量,但这个变量不存在,所以被替换为空字符串,最终分支名变成branch-。
解决方案
有两种可靠的处理方式,推荐第二种(更通用,能处理所有特殊字符):
方法1:转义分支名中的$符号
在拼接shell命令前,把分支名里的$替换为\$,让shell把它当作普通字符处理:
// 替换分支名中的$为\$ def escapedBranch = branch.replace('$', '\\$') String project_measures = sh(script: 'curl -s -u usr:paswd -X GET -F "component=sonar.project" -F "metricKeys=ncloc" -F "branch='+escapedBranch+'" '+measures_url, returnStdout: true).trim()
方法2:使用curl的--data-urlencode参数(推荐)
--data-urlencode会自动处理所有URL特殊字符(包括$、/、&等),无需手动转义:
String project_measures = sh(script: "curl -s -u usr:paswd -X GET ${measures_url} -F 'component=sonar.project' -F 'metricKeys=ncloc' --data-urlencode 'branch=${branch}'", returnStdout: true).trim()
注意这里用双引号包裹整个shell命令,让Groovy先解析${branch}变量,再传递给curl处理。
修改后的完整脚本片段
stage('Extract Output') { steps { script { // Sonar branches API Endpoint String branches_url = base_url+"/api/project_branches/list" String sonar_branches = sh(script: 'curl -s -u user:pswd -X GET -F "project=sonar.project" '+branches_url, returnStdout: true).trim() def jsonSonarBranches = readJSON text: sonar_branches p_branches = jsonSonarBranches.branches branch_name = p_branches.name branch_LAD = p_branches.analysisDate echo "${branch_name}" echo "------------------" // LOC API Endpoint String measures_url = base_url+"/api/measures/component" int index = 0 for(String branch: branch_name){ brnch_lad = branch_LAD.get(index) // 使用--data-urlencode处理特殊字符 String project_measures = sh(script: "curl -s -u usr:paswd -X GET ${measures_url} -F 'component=sonar.project' -F 'metricKeys=ncloc' --data-urlencode 'branch=${branch}'", returnStdout: true).trim() def jsonProjectMeasures = readJSON text: project_measures // components json: value = loc proj_component = jsonProjectMeasures.component?.measures ?: [] p_measures = proj_component.value ?: [] if(brnch_lad == null){ brnch_lad = 'N/A' p_measures = 'N/A' echo "PROJECT_KEY:sonar.project BRANCH:${branch} LAD:${brnch_lad} LOC:${p_measures}" } else if(p_measures.isEmpty()) { p_measures = 'N/A' echo "PROJECT_KEY:sonar.project BRANCH:${branch} LAD:${brnch_lad} LOC:${p_measures}" } else { p_loc = p_measures[0] ?: 'N/A' echo "PROJECT_KEY:sonar.project BRANCH:${branch} LAD:${brnch_lad} LOC:${p_loc}" } index++ } echo "--------------------------------------------------------------------------------------------------------" } } }
(额外优化了空指针判断,避免脚本因API返回异常失败)
内容的提问来源于stack exchange,提问作者ckmb
相关产品推荐
相关产品推荐

