脚本:"git rev-parse ${latestTag}^{commit}" 在 Jenkinsfile 中失败

script: "git rev-parse ${latestTag}^{commit}" fails in Jenkinsfile

Jenkinsfile 中的下一行

latestTagSHA1 = sh(returnStdout: true, script: "git rev-parse ${latestTag}^{commit}")

导致 script.sh: ^{commit}: not found 错误。

有没有办法逃避 ^{commit} 部分?

我试过 ^\{commit\} 没用。

重要的是要注意我实际上想要 运行 命令

git rev-parse ${latestTag}^{commit},例如 git rev-parse 2.0.0^{commit} 其中 latestTag 等于 2.0.0.

此命令 returns git 标签的 SHA1。例如,对于现有的带有标记 1.0 的标记提交 850d25580a894befbce6d922bee954c7669cf70c,下面的命令将 return 标记的 SHA1

git rev-parse 1.0^{commit}
850d25580a894befbce6d922bee954c7669cf70c

使用失败行添加了完整 Jenkinsfile

pipeline {
    agent  {
        node {
            label 'some_label'
            customWorkspace "workspace/${JOB_NAME}/${params.PROJECT}/${params.REPO_NAME}/${BUILD_NUMBER}/"
        }
    }

    parameters {
        string defaultValue: "${REPO_NAME}", name: 'REPO_NAME', trim: true
        string defaultValue: "${PROJECT}", name: 'PROJECT', trim: true
        string defaultValue: "${SRC_BRANCH_NAME}", name: 'SRC_BRANCH_NAME', trim: true
        string defaultValue: "${PR_MERGER_EMAIL}", name: 'PR_MERGER_EMAIL', trim: true
        string defaultValue: "${SHA1}", name: 'SHA1', trim: true
    }
    options {
        lock resource: "${params.REPO_NAME}" // lock on repo to avoid concurrent releases on the same repo
    }

    stages {
        stage("package") {
            steps {
                dir("/tmp/${params.PROJECT}/${params.REPO_NAME}") {                    
                    checkout(
                        [
                            $class: 'GitSCM',
                            branches: [[name: 'refs/heads/master']],
                            extensions: [
                                            [$class: 'LocalBranch', localBranch: "master"]
                                        ],
                            userRemoteConfigs: [[
                                    url: env.GIT_URL, credentialsId: "smth"
                                ]]
                        ]
                    )
                    script {                    
                        sh "cd /tmp/${params.PROJECT}/${params.REPO_NAME}"                    
                        latestTag = sh(returnStdout: true, script: "git describe --tags `git rev-list --tags --max-count=1`")
                        latestTagSHA1 = sh(returnStdout: true, script: "git rev-parse ${latestTag}^{commit}")
                        latestSHA1Timestamp = sh(returnStdout: true, script: "git show -s  --format='%ct' ${latestTagSHA1}")
                        currentCommitSHA1Timestamp = sh(returnStdout: true, script: "git show -s  --format='%ct' ${params.SHA1}")
                        if (latestSHA1Timestamp > currentCommitSHA1Timestamp) {
                            currentBuild.result = 'ABORTED'
                            error('some')
                        }
                    }
                }
            }
        }
    }
}

你可以尝试:“git rev-parse ${latestTag}”^${commit}”

您需要为要调用的所有变量添加 $

您不必转义任何引发错误的行。问题是 sh 步骤 return 的输出带有尾随换行符。

returnStdout (optional)
If checked, standard output from the task is returned as the step value as a String, rather than being printed to the build log. (Standard error, if any, will still be printed to the log.) You will often want to call .trim() on the result to strip off a trailing newline.


Source: https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script

这就是为什么 Jenkins 试图在您的案例中执行的是:

git rev-parse 1.0.0
^{commit}

而不是

git rev-parse 1.0.0^{commit}

这个问题的解决方案很简单:当您 return 输出 sh 步骤时,最后调用 trim() 以删除结尾的换行符。

latestTag = sh(returnStdout: true, script: "git describe --tags `git rev-list --tags --max-count=1`").trim()

请记住,您必须 trim 所有变量的输出,这些变量稍后将用作下一个命令的一部分。