psychotiq
psychotiq

Reputation: 613

Declarative pipeline when condition in post

As far as declarative pipelines go in Jenkins, I'm having trouble with the when keyword.

I keep getting the error No such DSL method 'when' found among steps. I'm sort of new to Jenkins 2 declarative pipelines and don't think I am mixing up scripted pipelines with declarative ones.

The goal of this pipeline is to run mvn deploy after a successful Sonar run and send out mail notifications of a failure or success. I only want the artifacts to be deployed when on master or a release branch.

The part I'm having difficulties with is in the post section. The Notifications stage is working great. Note that I got this to work without the when clause, but really need it or an equivalent.

pipeline {
  agent any
  tools {
    maven 'M3'
    jdk 'JDK8'
  }
  stages {
    stage('Notifications') {
      steps {
        sh 'mkdir tmpPom'
        sh 'mv pom.xml tmpPom/pom.xml'
        checkout([$class: 'GitSCM', branches: [[name: 'origin/master']], doGenerateSubmoduleConfigurations: false, submoduleCfg: [], userRemoteConfigs: [[url: 'https://repository.git']]])
        sh 'mvn clean test'
        sh 'rm pom.xml'
        sh 'mv tmpPom/pom.xml ../pom.xml'
      }
    }
  }
  post {
    success {
      script {
        currentBuild.result = 'SUCCESS'
      }
      when { 
        branch 'master|release/*' 
      }
      steps {
        sh 'mvn deploy'
      }     
      sendNotification(recipients,
        null,             
        'https://link.to.sonar',
        currentBuild.result,
      )
    }
    failure {
      script {
        currentBuild.result = 'FAILURE'
      }    
      sendNotification(recipients,
        null,             
        'https://link.to.sonar',
        currentBuild.result
      )
    }
  }
}

Upvotes: 49

Views: 64380

Answers (3)

sirineBEJI
sirineBEJI

Reputation: 1220

In the documentation of declarative pipelines, it's mentioned that you can't use when in the post block. when is allowed only inside a stage directive. So what you can do is test the conditions using an if in a script:

post {
success {
  script {
    if (env.BRANCH_NAME == 'master')
        currentBuild.result = 'SUCCESS'
  }
 }
// failure block
}

Upvotes: 73

Shane Gannon
Shane Gannon

Reputation: 7738

Ran into the same issue with post. Worked around it by annotating the variable with @groovy.transform.Field. This was based on info I found in the Jenkins docs for defining global variables.

e.g.

#!groovy

pipeline {
    agent none
    stages {
        stage("Validate") {
            parallel {
                stage("Ubuntu") {
                    agent {
                        label "TEST_MACHINE"
                    }
                    steps {{
                        sh "run tests command"
                        recordFailures('Ubuntu', 'test-results.xml')
                        junit 'test-results.xml'
                    }
                }
            }
        }
    }
    post { 
        unsuccessful { 
            notify()
        }
    }
}

// Make testFailures global so it can be accessed from a 'post' step
@groovy.transform.Field
def testFailures = [:]

def recordFailures(key, resultsFile) {
    def failures = ... parse test-results.xml script for failures ...
    if (failures) {
        testFailures[key] = failures
    }
}

def notify() {
    if (testFailures) {
        ... do something here ...
    }
}

Upvotes: 0

Nagev
Nagev

Reputation: 13295

Using a GitHub Repository and the Pipeline plugin I have something along these lines:

pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        sh '''
          make
        '''
      }
    }
  }
  post {
    always {
      sh '''
        make clean
      '''
    }
    success {
      script {
        if (env.BRANCH_NAME == 'master') {
          emailext (
            to: '[email protected]',
            subject: "${env.JOB_NAME} #${env.BUILD_NUMBER} master is fine",
            body: "The master build is happy.\n\nConsole: ${env.BUILD_URL}.\n\n",
            attachLog: true,
          )
        } else if (env.BRANCH_NAME.startsWith('PR')) {
          // also send email to tell people their PR status
        } else {
          // this is some other branch
        } 
      }
    }     
  }
}

And that way, notifications can be sent based on the type of branch being built. See the pipeline model definition and also the global variable reference available on your server at http://your-jenkins-ip:8080/pipeline-syntax/globals#env for details.

Upvotes: 21

Related Questions