jenkinsgroovyjenkins-pipelinedryjenkins-shared-libraries

Can Jenkinsfile Stages be refactored for reuse/DRY


My jenkinsfile contains stages like these:

stages {
  stage('init'){
    steps {
      sh 'do-init'
    }
  }
  stage('region1') {
    stages {
      stage('build') {
        steps{
          script {
            dir("testing"){
              build(region:'region1', labels:"label1")
            }
          }
        }
      }
      stage('delete') {
        steps{
          script {
            dir ("testing"){
              delete('region1')
            }
          }
        }
      }
    }
  }
  stage('region2') {
    // repeat region1 stage for region2, label2 - edited for brevity
  }
}

Is it possible to refactor the inner "region stage" into a shared library, and then just call it twice in a script {} block?

My attempts so far have ended with the common DSL error "stages not found in steps"


Solution

  • Yes it is possible to achieve what you want, you just need to make sure that in the shared library function you are suing scripted pipeline syntax and not declarative syntax.
    For example in your pipeline you can do the following:

    stages {
      stage('init'){
        steps {
          sh 'do-init'
        }
      }
      stage('region1') {
        steps {
           buildAndDelete('region1', 'label1')
           // or using the Map version:
           // buildAndDelete region: 'region1', labels: 'label1'
        }
       
      stage('region2') {
        steps {
           buildAndDelete('region2', 'label2')
        }
      }
    }
    

    Now in you shared library vars folder you will have a file called buildAndDelete.groovy, and its contents will be:

    def call(Map params) {
        call(params.region, params.labels)
    }
    
    def call(String region, String labels) {
       stage('build') {
           dir("testing"){
               build(region: region, labels:labels)
           }
       }
       stage('delete') {
           dir("testing"){
               delete(region)
           }
       }
    }
    

    You can of course change the input parameters as needed.