jenkins - 如何在jenkinsfile中使用shell正则表达式进行jenkins管道?

标签 jenkins sh jenkins-pipeline

我正在尝试将 Git 分支名称中的“/”替换为 jenkins 文件中的“_”,以便我可以使用分支名称标记我的 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 没有被正确解释?

谢谢

最佳答案

问题是您要求 Groovy 本身解释表达式 ${git_branch_name//\//_} ,不是外壳。在传递给 sh 的字符串周围使用双引号步骤就是造成这种情况的原因。因此,如果您编写以下内容,第一个错误就会消失:

    sh 'echo ${git_branch_name//\\//_}' // <- Note the single-quotes

基本上,始终使用单引号,除非您特别需要使用groovy字符串插值(请参阅本答案底部的最后一个echo)。

有趣的是,当我测试时,我似乎不需要 shebang ( #!/bin/bash ) 来指定 bash,正如一些评论所建议的那样;这个${variable//x/y}替换语法按原样在 sh 步骤中工作。我猜生成的 shell 是 bash。我不知道情况是否总是如此,或者我们的 Jenkins 盒子是否是专门这样设置的。

另请注意,您需要转义转义序列 ( '\\/' ),因为您传递给 sh 步骤的是 groovy 代码中的字符串文字。如果不添加额外的反斜杠,则传递给 shell 并由其解释的行将是 echo ${git_branch_name////_} ,它无法理解。

但还有其他问题。首先,将 sh 步骤的输出分配给 branch_name正如你所做的那样意味着 branch_name将始终等于 null。要从一行 shell 代码获取标准输出,您需要传递额外的参数 returnStdout: true致:

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)无法访问 groovy 变量。据了解,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}"
    }
}

关于jenkins - 如何在jenkinsfile中使用shell正则表达式进行jenkins管道?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50373682/

相关文章:

docker - 使用Docker镜像安装Jenkins插件

jenkins - 如何在 Jenkins 中使用作业参数或环境变量来归档工件?

jenkins - 从Jenkins服务器部署到另一台服务器: Host key verification failed

java - 将 Jenkins Java 版本从 8 升级到 11

bash - 为什么正确的 shell 脚本会给出包装/截断/损坏的错误消息?

Jenkins 管道 bat 多行

c - 在带有 busybox 的嵌入式 linux 上使用 system() 时,SIGHUP 信号处理程序重置为默认值

linux - mv 来自文本板的包含空格和特殊字符的文件

jenkins - Jenkins 的工作可以因成功而中止吗?

Jenkins 和 Kubernetes 与 Helm 的集成