Search code examples
jenkinsjenkins-pluginsjenkins-pipelinecontinuous-deliveryjenkins-2

Jenkins 2 Pipelines - How to model a continuous delivery pipeline


I am completely new to Jenkins 2 pipelines.

I had played with Jenkins 1 pipelines with the following view:

enter image description here

You could start a certain stage directly, let's say that I could choose to start running from the release stage, skipping Test.

I have a pretty simple Jenkins 2 pipeline definition:

stage('Preparation'){
    echo """
         Preparing
         something
         """
}
stage('Greeting') { 
    parallel 'hello1':{
        node{
            echo 'hello world 1'
        }
    }, 'hello2':{
        node{
            echo 'hello world 2'
        }
    }
}

In the pipeline page I have "Build now" which runs all stages starting from Preparation.

My questions are:

  1. How can I run the stage I prefer? For instance Greeting instead of starting from Preparation?
  2. How do you define the dependencies between stages? I mean the stage called after another one completes
  3. Is there a way to limit the stages that a certain user can start? Imagine that I only want a specific user to launch the Greeting stage.
  4. How do you setup manual stages?

UPDATE: The real goal behind my questions is the modelling of a continuous delivery pipeline like the following with Jenkins 2 pipelines:

Build stage --> AUTO --> Acceptance Stage --> MANUAL --> Production Stage
                                          --> MANUAL --> QA Stage

This is the behaviour I want:

Build Stage (any user can start it) when it finishes it triggers automatically the Acceptance Stage. This one can't be lauched manually, only automatically after succesfully finishing the Build Stage.

From Acceptance Stage I need that only authorized users can manually trigger QA Stage and Production Stage.

The business flow would be: a developer hits Build Stage, its code is built and packaged. Acceptance Stage begins, using the packaged code to run a bunch of automated tests.

At this point, when Acceptance Stage has finished OK, two things can happen:

  1. Maybe QA Stage is needed to run more tests (Cucumber, manual, etc.). Some some authorized user would fire this stage.
  2. When the product owner is happy, he can decice to launch the Production Stage to deploy the code in a production environment.

I am struggling to model this with Jenkins 2 pipelines.


Solution

  • There is no direct answer to some of your questions but they can be achieved with some additional coding. While certain people might find some other way to achieve but let me try with what I have in my mind:

    1) How can I run the stage I prefer? For instance Greeting instead of starting from Preparation?
    

    This could be achieved by adding a Boolean parameter FASTFORWARD_TO_GREETING and than using the value provided while executing build to manipulate the flow of your build. So your code will now look like :

    if (FASTFORWARD_TO_GREETING == 'false') {
    stage('Preparation'){
        echo """
             Preparing
             something
             """
    }
    }
    
    stage('Greeting') { 
        parallel 'hello1':{
            node{
                echo 'hello world 1'
            }
        }, 'hello2':{
            node{
                echo 'hello world 2'
            }
        }
    }
    
    
    2) How do you define the dependencies between stages? I mean the stage called after another one completes
    

    Stages are executed serially, so if a stage is defined first it'll be started and completed first before moving to the next stage. However in parallel step this does not hold true, as all the steps will be executed in parallel. So in your example code the dependency you have defined is that stage "Preparation" will be executed first and than only "hello1" and "hello2" step will be executed in parallel. However there is no guarantee as to which "hello world1" or "hello world 2" would be printed.

    3) Is there a way to limit the stages that a certain user can start? Imagine that I only want a specific user to launch the Greeting stage.
    

    You can have an manual approval step just before some stage. For example, in your code you want stage Preparation to be executed and than you want it to go with manual approval before executing stage Greeting, your code will look something like this:

    stage('Preparation'){
        echo """
             Preparing
             something
             """
    }
    stage concurrency: 1, name: 'approve-greeting'
    input id: 'greeting-deploy', message: 'Proceed to Greeting?', ok: 'Deploy'
    
    stage('Greeting') { 
        parallel 'hello1':{
            node{
                echo 'hello world 1'
            }
        }, 'hello2':{
            node{
                echo 'hello world 2'
            }
        }
    }
    

    What will happen after this is when you execute the build the stage preparation will get executed but after that the job would wait for a manual approval to proceed. In the Jenkins Pipeline view the stage would be called "approve-greeting" and it'll wait until someone approves the build by clicking on it in the view.

    4) How do you setup manual stages?
    

    I believe this is answered in answer 3?

    Please let me know in case you need further information/explanation.

    EDIT:: Please find the further answers below:

    Build Stage (any user can start it) when it finishes it triggers automatically the Acceptance Stage.

    Clearly Both the Build Stage and Acceptance Stage will be defined as normal stage in Jenkins pipeline. So your code would be simple like :

    node {
        //define any variable here
        // Get source code from repo using checkout to directory say stackoverflow
        // Get source code from repo for acceptance test using checkout to directory say stackoverflow-test
        //Define any tool like Maven etc. location if required.
        dir('stackoverflow') {
          stage name: 'build'
            //Do required steps
        }
        dir('stackoverflow-test') {
          stage name: 'Acceptance'
            //Do required steps here 
        }
    

    At this point, when Acceptance Stage has finished OK, two things can happen:

    1. Maybe QA Stage is needed to run more tests (Cucumber, manual, etc.). Some some authorized user would fire this stage.

    2. When the product owner is happy, he can decide to launch the Production Stage to deploy the code in a production environment.

    This you can do by having input option so after the above piece of code you could now write:

        stage 'promotion'
          def userInput = input(
          id: 'userInput', message: 'Let\'s promote?', parameters: [
          [$class: 'BooleanParameterDefinition', defaultValue: false, description: 'Production', name: 'prod'],
          [$class: 'BooleanParameterDefinition', defaultValue: false, description: 'ManualQA', name: 'qa']
          ])
          echo ("Env: "+userInput['prod'])
          echo ("Target: "+userInput['qa'])
    

    Than you can take the value from above and manipulate the flow again. Like :

    If the value of prod is true than proceed to Production stage, If the value of qa is true than proceed to QA-Manual stage much like my above example code of FASTFORWARD_TO_GREETING.

    EDIT 2

    Further answering questions on the comment section:

    1) How or where do I specify parameters like FASTFORWARD_TO_GREETING

    Parameters like FASTFORWARD_TO_GREETING will be defined as Job level parameter

    2) In the promotion stage you have to choose between ManualQA and Production. If the user chooses ManualQA it runs that Stage skipping Production. After it I want the user to be promted if he wants to promote to production stage. If you could provide a full definition of the pipeline it'd be great.

    This you could manipulate after MaualQA stage with another input step but this time with only one parameter. So after stage Promotion, there would be stage ManualQA and than after that this below input step:

    def userInput1 = input(
     id: 'userInput', message: 'Let\'s promote?', parameters: [
     [$class: 'BooleanParameterDefinition', defaultValue: false, description: 'Production', name: 'prod']
    ])
    

    3) How can I determine if a user has permissions to run a stage or not. Ideally I would like to do it based on roles

    I am not sure about how to do it with roles but I believe anyone with administrator access or running that job would have access to run/approve that stage, but I am not 100% sure if it could be somehow modified.