6

I am currently working on a generic pipeline which is going to be used via shared library to replace existing jobs so that it's easier to manage all jobs from a more centralized place. Most of the existing jobs have these three stages:

  1. allocates a node
  2. checks out the code from git repository and builds it
  3. deploys the code to a testing repository

Some of the jobs have a few if/elses in their stages which do things based on parameters or environment variables, but overall the jobs are quite similar otherwise. The solution which comes to my mind is to use Closures to allow for additional logic code to be executed in those stages, but I am having difficulties figuring out how to secure this so that the only possible "steps" you can execute are sh and bat.

Here is an oversimplified example vars/genericPipeline.groovy to illustrate what I'm talking about:

def call(body)
{
    def config = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()

    String AGENT_LABEL = config.getOrDefault('label', 'mvn3')

    Closure MVN_BUILD = config.getOrDefault('build', {
        sh "mvn clean install"
    })

    Closure MVN_DEPLOY = config.getOrDefault('deploy', { BRANCH_NAME, ARTIFACT_COORDINATES, SERVER_ID, REPO, TMP_REPO ->
        def SERVER_URL = REPO

        if (BRANCH_NAME != 'master')
        {
            SERVER_URL = TMP_REPO
        }

        sh label: "Deploying ${ARTIFACT_COORDINATES}",
           script: "mvn deploy" +
                   " -DskipTests" +
                   " -DaltDeploymentRepository=${SERVER_ID}::default::${SERVER_URL}"
    })

    pipeline {
        agent {
            node {
                label AGENT_LABEL
            }
        }
        environment {
            GROUP_ID = readMavenPom().getGroupId()
            ARTIFACT_ID = readMavenPom().getArtifactId()
            VERSION = readMavenPom().getVersion()
            ARTIFACT_COORDINATES = "${readMavenPom().getGroupId()}:${readMavenPom().getArtifactId()}:${readMavenPom().getVersion()}"
        }
        stages {
            stage('Building...') {
                steps {
                    MVN_BUILD()
                }
            }
            stage('Deploying...') {
                steps {
                    MVN_DEPLOY(BRANCH_NAME, env.ARTIFACT_COORDINATES, config.serverId, config.repo, config.tmpRepo)
                }
            }
        }
    }
}

This could later be used in the jobs as:

genericPipeline {
   build = {
       sh "mvn clean install"
   }
   // could be set for the "corner cases" or could skipped to use the 
   // default deploy closure for all other cases.
   deploy = {
       sh "mvn deploy"
   }
}

As you can see, the deploy uses two different repositories to deploy to, based on the branch name. I am aware I could simply just put the logic in the stage, but the problem is that some of the jobs are not multi-branch and they would not have this if/else logic. However they would still have the same pipeline structure without any other changes and I would prefer to have to maintain one pipeline than 5 relatively similar pipes for all the different if/else cases which could occur in the deploy stage. :)

So, the question here - is it possible to only white-list the execution of specific steps (i.e. sh/bat) in the MVN_BUILD and MVN_DEPLOY closures? Or if there is another, perhaps even better way to handle this case?

tftd
  • 16,203
  • 11
  • 62
  • 106

0 Answers0