24

I am learning Jenkins Pipeline, and I tried to follow this Pipeline code. But my Jenkins always complains that def is not legal.

I am wondering did I miss any plugins? I already installed groovy, job-dsl, but it doesn't work.

informatik01
  • 16,038
  • 10
  • 74
  • 104
Ron
  • 6,037
  • 4
  • 33
  • 52
  • 2
    There are 2 types of pipelines: scripted and declarative. Certain things can't be used in part of the declarative pipeline. Learn the difference between the two and you should learn where `def` is valid. – Rob Hales Nov 10 '17 at 06:22
  • 2
    Thanks for your hints, it leads to the answer. `def` is used in scripted pipeline, which start with `node {...}`; while my file starts with `pipeline`, which is declarative, and `def` is not allowed, unless it is wrapped by `script {...}` – Ron Nov 10 '17 at 08:22

3 Answers3

29

As @Rob said, There are 2 types of pipelines: scripted and declarative. It is like imperative vs declarative. def is only allowed in scripted pipeline or wrapped in script {}.

Scripted pipeline (Imperative)

Start with node, and def or if is allowed, like below. It is traditional way.

node {
    stage('Example') {
        if (env.BRANCH_NAME == 'master') {
            echo 'I only execute on the master branch'
        } else {
            echo 'I execute elsewhere'
        }
    }
}

Declarative pipeline (Preferred)

Start with pipeline, and def or if is NOT allowed, unless it is wrapped in script {...}. Declarative pipeline make a lot things easy to write and read.

time trigger

pipeline {
    agent any
    triggers {
        cron('H 4/* 0 0 1-5')
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

when

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                branch 'production'
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

Parallel

pipeline {
    agent any
    stages {
        stage('Non-Parallel Stage') {
            steps {
                echo 'This stage will be executed first.'
            }
        }
        stage('Parallel Stage') {
            when {
                branch 'master'
            }
            failFast true
            parallel {
                stage('Branch A') {
                    agent {
                        label "for-branch-a"
                    }
                    steps {
                        echo "On Branch A"
                    }
                }
                stage('Branch B') {
                    agent {
                        label "for-branch-b"
                    }
                    steps {
                        echo "On Branch B"
                    }
                }
            }
        }
    }
}

embedded with scripted code

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'

                script {
                    def browsers = ['chrome', 'firefox']
                    for (int i = 0; i < browsers.size(); ++i) {
                        echo "Testing the ${browsers[i]} browser"
                    }
                }
            }
        }
    }
}

To read more declarative pipeline grammar, please refer the official doc here

Neuron
  • 5,141
  • 5
  • 38
  • 59
Ron
  • 6,037
  • 4
  • 33
  • 52
  • See my example of it above as an alternative way to use it on a declarative pipeline – krad Apr 02 '19 at 15:02
9

You can use def with a declarative pipeline, just not inside it eg

def agentLabel
if (BRANCH_NAME =~ /^(staging|master)$/)  {
    agentLabel = "prod"
} else {
    agentLabel = "master"
}

pipeline {
  agent { node { label agentLabel } } 
..
krad
  • 1,321
  • 1
  • 15
  • 12
-2

You can use def by using node like below:

node {
stage('Example') {
    if (env.BRANCH_NAME == 'master') {
        echo 'I only execute on the master branch'
    } else {
        echo 'I execute elsewhere'
    }
}

Another way : by using script{..}

    stage ('jon'){
steps{
script{                                                                                              
    def imageLine = 'chiducaff/user_containers:sonnginx'
}
    writeFile file: 'anchore_images', text: imageLine
    anchore name: 'anchore_images'
                           }}
chiducaf
  • 773
  • 5
  • 8
  • The latter form doesn't work. It seems you have to use the variable within the `script` block or you get `groovy.lang.MissingPropertyException` for it. – okapi Jun 24 '20 at 07:53