How to configure a Jenkins 2 Pipeline so that Jenkinsfile uses a predefined variable
Asked Answered
J

2

1

I have several projects that use a Jenkinsfile which is practically the same. The only difference is the git project that it has to checkout. This forces me to have one Jenkinsfile per project although they could share the same one:

node{
    def mvnHome = tool 'M3'
    def artifactId
    def pomVersion

    stage('Commit Stage'){
        echo 'Downloading from Git...'
        git branch: 'develop', credentialsId: 'xxx', url: 'https://bitbucket.org/xxx/yyy.git'
        echo 'Building project and generating Docker image...'
        sh "${mvnHome}/bin/mvn clean install docker:build -DskipTests"
    ...

Is there a way to preconfigure the git location as a variable during the job creation so I can reuse the same Jenkinsfile?

...
    stage('Commit Stage'){
        echo 'Downloading from Git...'
        git branch: 'develop', credentialsId: 'xxx', url: env.GIT_REPO_LOCATION
    ...

I know I can set it up this way:

This project is parameterized -> String Parameter -> GIT_REPO_LOCATION, default= http://xxxx, and access it with env.GIT_REPO_LOCATION.

The downside is that the user is promted to start the build with the default value or change it. I would need that it were transparent to he user. Is there a way to do it?

Jocularity answered 7/4, 2017 at 12:26 Comment(0)
A
1

You can use the Pipeline Shared Groovy Library plugin to have a library that all your projects share in a git repository. In the documentation you can read about it in detail.

If you have a lot of Pipelines that are mostly similar, the global variable mechanism provides a handy tool to build a higher-level DSL that captures the similarity. For example, all Jenkins plugins are built and tested in the same way, so we might write a step named buildPlugin:

// vars/buildPlugin.groovy
def call(body) {
    // evaluate the body block, and collect configuration into the object
    def config = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()

    // now build, based on the configuration provided
    node {
        git url: "https://github.com/jenkinsci/${config.name}-plugin.git"
        sh "mvn install"
        mail to: "...", subject: "${config.name} plugin build", body: "..."
    }
}

Assuming the script has either been loaded as a Global Shared Library or as a Folder-level Shared Library the resulting Jenkinsfile will be dramatically simpler:

Jenkinsfile (Scripted Pipeline)

buildPlugin {
    name = 'git'
}

The example shows how a jenkinsfile passes name = git to the library. I currently use a similar setup and am very happy with it.

Addendum answered 7/4, 2017 at 14:13 Comment(2)
Thanks for the suggestion, I'll try it in the next days and come back with some feedback.Jocularity
Consider using multibranch pipeline. Then jenkins will show a separate subjob for each branch. It's a nicer visualization and you can start manual build for each branch.Addendum
S
0

Instead of having a Jenkinsfile in each Git repository, you can have an additional git repository from where you get the common Jenkinsfile - this works when using Pipeline type Job and selecting the option Pipeline script from SCM. This way Jenkins checks out the repo where you have the common Jenkinsfile before checking out the user repo.

In case the job can be triggered automatically, you can create a post-receive hook in each git repo that calls the Jenkins Pipeline with the repo as a parameter, so that the user does not have to manually run the job entering the repo as a parameter (GIT_REPO_LOCATION).

In case the job cannot be triggered automatically, the least annoying method I can think of is having a Choice parameter with a list of repositories instead of a String parameter.

Shatter answered 7/4, 2017 at 14:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.