首页 > 解决方案 > Jenkins 声明性管道在使用 try catch 时失败,脚本标签中的最终块也在发布时

问题描述

我一直在尝试在我的声明性 jenkins 管道中使用 try catch 块,但它在执行 post 语句时一直失败,但没有出现 try catch 块的执行。

执行总是后置条件时出错:

*Error when executing always post condition:
00:44:07  groovy.lang.MissingPropertyException: No such property: subject for class: groovy.lang.Binding
00:44:07    at groovy.lang.Binding.getVariable(Binding.java:63)
00:44:07    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:270)
00:44:07    at org.kohsuke.groovy.sandbox.impl.Checker$7.call(Checker.java:353)
00:44:07    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:357)
00:44:07    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
00:44:07    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
00:44:07    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:333)
00:44:07    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
00:44:07    at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
00:44:07    at WorkflowScript.run(WorkflowScript:91)
00:44:07    at ___cps.transform___(Native Method)*

这是我的管道代码

 @Library('akci@feature/TRE-168-notify-build-status-from-jenkins-to-gchat')

import groovy.transform.Field
import com.kaercher.pre.Definitions

def git_commit = ""
def host_name = "localhost"
def docker_vm_name = "terraform-mce-vm"
def docker_image_name = "terraform-mce-iac"
def virtual_nework = "192.168.61.3/24"
def docker_image = ""
def docker_image_version_tag = ""

addCiParameter(
    logRotator(artifactDaysToKeepStr: '8', artifactNumToKeepStr: '3', daysToKeepStr: '8', numToKeepStr: '3'),
    [booleanParam(defaultValue: false, description: 'Deploy the Docker container', name: 'deploy')]
)

pipeline {
    agent {label 'linux'}
    stages {
        stage('Prepare Build'){
            steps {
                sh "git clean -fdx"
                script {
                    git_commit = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
                    host_name = sh(returnStdout: true, script: 'hostname').trim()
                    
                    echo "Build Prepared"
                }
            }
        }
         stage('Build') {
            steps {
                 
                script {
                
                try {
                echo "Build-Started"
                
                dir ('docker') 
                
                        { 
                        def docker_image_version = (readFile("Dockerfile") =~ ~/version=\"(\d+\.\d+\.\d+)/)[0][1]
                        docker_image_version_tag = (params.revision == "master") ? docker_image_version : "${docker_image_version}-${params.revision.replaceAll("-","_").replaceAll("/","_").replaceAll("[^A-Za-z0-9_]", "")}"
                        docker_image = docker.build("iac-docker.artifactory.kws.kaercher.com/$docker_image_name:${docker_image_version_tag}", "--build-arg http_proxy='http://$host_name:3128' --build-arg https_proxy='http://$host_name:3128' -f Dockerfile .")
                        }
                        
                        notifyBuild('STARTED')
                        
                        }
                    catch (e) {
    // If there was an exception thrown, the build failed
    currentBuild.result = "FAILED"
    throw e
  }
    
    finally {
    notifyBuild(currentBuild.result)
    }
    
                        
           }
        }
    
     }
  }


post {
        always {
            script {notifyBuildEnded(git_commit)}
          script {
          googlechatnotification(
          url: 'https://chat.googleapis.com/v1/spaces/AAAAjU4cyQU/messages?key=MY_API_KEY&token=MY_TOKEN',
          message: "*${subject}* ${summary} *${commitRef}* ${details}* ${env.BUILD_URL}",
          sameThreadNotification: true
        )
        }
      }
    }
    
}

我还创建了一个函数作为共享库,如 notifyBuild.groovy

void call(String buildStatus = 'STARTED') {
  // build status of null means successful
  buildStatus = buildStatus ?: 'SUCCESS'

  // Default values
  def colorName = 'RED'
  def colorCode = '#FF0000'
  def subject = "${buildStatus}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'"
  def summary = "${subject} (${env.BUILD_URL})"
  def details = """<p>STARTED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]':</p>
    <p>Check console output at &QUOT;<a href='${env.BUILD_URL}'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a>&QUOT;</p>"""

  // Override default values based on build status
  if (buildStatus == 'STARTED') {
    color = 'YELLOW'
    colorCode = '#FFFF00'
  } else if (buildStatus == 'SUCCESS') {
    color = 'GREEN'
    colorCode = '#00FF00'
  } else {
    color = 'RED'
    colorCode = '#FF0000'
  }
  }

标签: jenkinsgroovyjenkins-pipeline

解决方案


由于以下行,您的管道失败:

   message: "*${subject}* ${summary} *${commitRef}* ${details}* ${env.BUILD_URL}",

subject参数未在任何地方定义,因此您会收到异常:

groovy.lang.MissingPropertyException: No such property: subject for class: groovy.lang.Binding`

尽管subjectsummary是在共享库中定义的,但它是一个完全不同的上下文,与主声明性管道无关。此外commitRef,并且details 根本没有在任何地方定义。定义这些参数或用值替换它们,它应该可以工作。


推荐阅读