ZakTaccardi
ZakTaccardi

Reputation: 12467

How can I import a shared groovy script into a pipeline from the same Git repo?

I have the following two pipelines in my repository

@Field String ANDROID_EMULATOR = "android-emulator"

pipeline {
    agent { label "android-emulator" }
    stages {
        stage("build") {
            steps {
                gradlew (":build")
            }
        }
    }
}

void gradlew(String tasks) {
    sh "./gradlew $tasks --profile"
}
@Field String ANDROID_EMULATOR = "android-emulator"

pipeline {
    agent none
    stages {
        stage("PR checks") {
            parallel {
                stage("build 1") {
                    agent { label ANDROID_EMULATOR }
                    steps {
                        gradlew(":one:build")
                    }
                }
                stage("build 2") {
                    agent { label ANDROID_EMULATOR }
                    steps {
                        gradlew(":two:build")
                    }
                }
            }
        }
    }
}

void gradlew(String tasks) {
    sh "./gradlew $tasks --profile"
}

As you can see, there is some code duplication between the two - ANDROID_EMULATOR and void gradlew(..).

I would like to move them into their own shared.groovy file:

@Field String ANDROID_EMULATOR = "android-emulator"

void gradlew(String tasks) {
    sh "./gradlew $tasks --profile"
}

And be able to import it into my other pipelines with a single line of code. Gradle allows this to be done with apply('shared.groovy').

Jenkins seems to allow only shared libraries (which are global), and load statements (which need to be loaded as a part of a node, which does not scale well). Does Jenkins lack support for this basic style of code sharing here?

Upvotes: 0

Views: 1623

Answers (2)

yong
yong

Reputation: 13712

You can use the pipeline load which is more simple than using shared library, especially when you hope the shared.groovy in the same repo as your Jenkinsfiles.

// shared.groovy

def gradlew(String tasks) {
    sh "./gradlew $tasks --profile"
}

return this // the return this must be have
// pipeline 1

pipeline {
    agent { label "android-emulator" }
    stages {
        stage("build") {
            steps {
                scripts {
                     shared = load 'shared.groovy'
                     shared.gradlew (":build")
                }
                
            }
        }
    }
}
// pipeline 2

pipeline {
    agent { label "android-emulator" }
    stages {
        stage("build") {
            steps {
                scripts {
                     shared = load 'shared.groovy'
                     shared.gradlew ("one:build")
                }
                
            }
        }
    }
}

Upvotes: 2

Yuri G.
Yuri G.

Reputation: 4648

Jenkins shared libraries have a well defined folder structure https://www.jenkins.io/doc/book/pipeline/shared-libraries/#directory-structure

You can try:

  • to implement this folder structure in a subfolder in your repo
  • to use a Dynamic Retrieval with a scm config that will check out the specific folder

I afraid it is too complicated and even not possible

I think the best approach is to create global shared libraries repo and to implement a gradleBuild custom step . In that case your code will be like

Pipeline 1:

@Library('somelib')
@Field String ANDROID_EMULATOR = "android-emulator"

pipeline {
   agent { label "android-emulator" }
   stages {
     stage("build") {
        steps {
            gradleBuild ":build"
        }
     }
  }
}

Pipeline 2:

@Library('somelib')
@Field String ANDROID_EMULATOR = "android-emulator"

pipeline {
  agent none
  stages {
     stage("PR checks") {
        parallel {
            stage("build 1") {
                agent { label ANDROID_EMULATOR }
                steps {
                    gradlew(":one:build")
                }
            }
            stage("build 2") {
                agent { label ANDROID_EMULATOR }
                steps {
                    gradlew(":two:build")
                }
            }
        }
     }
   }
}

Shared libraries vars/gradeBuild.groovy file:

def call(String tasks) {
   sh "./gradlew $tasks --profile"
}

Upvotes: 0

Related Questions