我正在尝试更换' /'来自Git分支名称' _'在我的jenkinsfile中,以便我可以用分支名称标记我的docker镜像。在bash中,下面的命令工作正常
echo "${git_branch_name//\//_}"
但是当在jenkinsfile中使用上面的命令时会抛出错误。
#!/usr/bin/env groovy
def commit_id
def imagetag
def branch_name
def git_branch_name
node('Nodename') {
stage('checkout') {
checkout (scm).$Branch_Param
sh "git rev-parse --short HEAD > .git/commit-id"
commit_id = readFile('.git/commit-id').trim()
sh "git rev-parse --abbrev-ref HEAD > .git/branch-name"
git_branch_name = readFile('.git/branch-name').trim()
branch_name= sh "echo ${git_branch_name//\//_}"
sh "echo ${commit_id}"
sh "echo ${branch_name}"
sh "echo Current branch is ${branch_name}"
}
}
WorkflowScript: 15: end of line reached within a simple string 'x' or "x" or /x/;
solution: for multi-line literals, use triple quotes '''x''' or """x""" or /x/ or $/x/$ @ line 15, column 28.
sh "branch_name = echo ${git_branch_name//\//_}"
我在这里做错了什么?我应该使用Groovy正则表达式而不是shell吗?为什么shell没有被正确解释?
谢谢
答案 0 :(得分:1)
问题是您要让Groovy本身解释表达式${git_branch_name//\//_}
,而不是shell。导致该问题的原因是,您在传递给sh
步骤的字符串周围使用双引号。因此,如果您改写以下内容,则第一个错误将消失:
sh 'echo ${git_branch_name//\\//_}' // <- Note the single-quotes
基本上,除非您特别需要使用 groovy的字符串插值,否则请始终使用单引号(请参阅此答案底部的最后一个echo
)。
有趣的是,似乎我在测试时不需要shebang(#!/bin/bash
)来指定bash,正如一些评论所建议的那样;此${variable//x/y}
替换语法按原样在sh步骤中起作用。我猜它生成的外壳是bash。我不知道是否总是这样,还是我们的Jenkins盒子是专门设置的。
还请注意,您需要转义转义序列('\\/'
),因为传递给sh步骤的是groovy代码中的字符串文字。如果不添加额外的反斜杠,则传递给外壳的行将由echo ${git_branch_name////_}
解释,这是行不通的。
但是还有其他问题。首先,像您所做的那样将sh步骤的输出分配给branch_name
意味着branch_name
将始终等于null。要从一行shell代码中获取标准输出,您需要将额外的参数returnStdout: true
传递给sh:
branch_name = sh (
script: 'echo ${git_branch_name//\\//_}',
returnStdout: true
).trim () // You basically always need to use trim, because the
// stdout will have a newline at the end
要获得奖励积分,我们可以将该sh调用包装在closure中。我发现自己经常使用它来使它成为一个好主意。
// Get it? `sh` out, "shout!"
def shout = { cmd -> sh (script: cmd, returnStdout: true).trim () }
//...
branch_name = shout 'echo ${git_branch_name//\\//_}'
但是,最后,主要的问题是bash(或实际生成的任何shell)都无法访问常规变量。据了解,echo ${git_branch_name}
输出一个空字符串,因此echo ${git_branch_name//\//_}
也输出一个空字符串。
您有两种选择。您可以跳过.git/branch-name
的创建,而只是立即输出git rev-parse
的字符串替换结果:
branch_name = shout 'name=$(git rev-parse --abbrev-ref HEAD) && echo ${name//\\//_}'
或者为了进一步简化,您可以使用groovy的字符串替换函数而不是bash语法:
branch_name = shout ('git rev-parse --abbrev-ref HEAD').replace ('/', '_')
就个人而言,我发现后者更具可读性。 YMMV。因此,最后将它们整合在一起:
#!groovy
def shout = { cmd -> sh (script: cmd, returnStdout: true).trim () }
// Note that I'm not declaring any variables up here. They're not needed.
// But you can if you want, just to clearly declare the environment for
// future maintainers.
node ('Nodename') {
stage ('checkout') {
checkout (scm).$Branch_Param
commit_id = shout 'git rev-parse --short HEAD'
branch_name = shout ('git rev-parse --abbrev-ref HEAD').replace ('/', '_')
echo commit_id
echo branch_name
echo "The most recent commit on branch ${branch_name} was ${commit_id}"
}
}