Skip to content

Latest commit

 

History

History
247 lines (191 loc) · 18 KB

approvals-post-cb-core.md

File metadata and controls

247 lines (191 loc) · 18 KB

Pipeline Approvals, Post Actions and Notifications with CloudBees Core

In this set of exercises, we will see how you can capture interactive input in your Jenkins Pipeline while it is running, get an introduction to the Declarative post sections and use a post-condition block to send a notification. We will also see how CloudBees Core enables easy simultaneous updates of all of our Team Masters and will use this capability to add the Slack plugin and necessary configuration to send a Slack notification from our Pipeline job.

Interactive Input

For this exercise we are going to add a new stage after the Build and Push Image stage that will demonstrate how to pause a Pipeline job and prompt for interactive input.

NOTE: The Declarative input directive blocks the stage from acquiring an agent and that is why it is configured outside the steps block as a directive. You could use the pre-exsiting input step directly in the steps block but that would hold whatever agent is assigned to that stage for as long it takes for the input to be submitted.

  1. Use the GitHub file editor to update the nodejs-app/Jenkinsfile.template file in your forked custom-marker-pipelines repository - adding the following stage to your Pipeline after the Build and Push Image stage and commit the change:
    stage('Deploy') {
      when {
        beforeAgent true
        branch 'master'
      }
      input {
        message "Should we continue?"
      }
      steps {
        echo "Continuing with deployment"
      }
    }
  1. Run your updated Pipeline job in Blue Ocean and note the input prompt during the Deploy stage. This input prompt is also available in the Console log and classic Stage View.

  2. Your Team Master will wait indefinitely for a user response to an input step. Let's fix that by setting a timeout. Earlier we used options at the global pipeline level to set the Discard old builds strategy for your Team Master with the buildDiscarder option. Now we will configure options at the stage level. We will add a timeout option for the Deploy stage using the stage options directive. Update the Deploy stage to match the following and then commit the changes:

    stage('Deploy') {
      when {
        beforeAgent true
        branch 'master'
      }
      options {
        timeout(time: 30, unit: 'SECONDS') 
      }
      input {
        message "Should we continue?"
      }
      steps {
        echo "Continuing with deployment"
      }
    }
  1. Run your updated Pipeline job in Blue Ocean and wait at least 30 seconds once it reaches the 'Deploy' stage. Your pipeline will be automatically aborted 30 seconds after the 'Deploy' stage starts.

    Run it again if you would like - but this time approving it before 30 seconds expires - the job will complete successfully.

Input Approval for Team Members

The input directive supports a number of interesting configuration options. In this exercise we are going to use the submitter option to control what Team Master member is allowed to submit the input directive. But first you need to add another member to your CloudBees Team Master. Team Masters provide an easy to use authorization model right out-of-the-box. The following roles are available (there is a CLI to add or modify roles):

  • Team Admin: administrator of the Team Master.
  • Team Member: read, write and execute permission on the pipelines.
  • Team Guest: read only.

We want to add a Team Guest to our Team Masters and then set that Team member as the submitter for our input directive. Before you begin, pick a person near you to pair up with. The two of you will share each other's Jenkins account names. You will use that account name when adding a new member to your Team Master below:

  1. On your Team Master, navigate to the Team list by clicking on the Administration link on the top right (this link is available on all Blue Ocean pages except for the Pipeline Run Details view).

  2. Next, click on the cog icon for your team.

  3. Click on the Members link in the left menu and then click on the Add a user or group link.

  4. Select Team Guest from the role drop-down, enter the account name for the person next to you in the Add user or group input (I will use beedemo-ops), press your enter/return key, and then click the Save changes button.

  5. Click on the Pipelines link in the top menu.

Now that we all have a new team member, you can add them as a submitter for the input directive in your nodejs-app/Jenkinsfile.template Pipeline script.

  1. Use the GitHub file editor to update your nodejs-app/Jenkinsfile.template Pipeline script in your forked custom-marker-pipelines repository - updating the input directive of the Deploy stage with the following changes (replacing beedemo-ops with Jenkins username of your new Team Guest member). Also, update the timeout duration to give your approver plenty of time to submit the input:
      options {
        timeout(time: 60, unit: 'SECONDS') 
      }
      input {
        message "Should we deploy?"
        submitter "beedemo-ops"
        submitterParameter "APPROVER"
      }
  1. So, we added one additonal configuration option for our input directive: submitterParameter. Setting the submitterParameter option will result in a Pipeline environmental variable named APPROVER being set with the value being the username of the user that submitted the input. In the example above it will either be beedemo-ops. Update the steps section so the echo step in your nodejs-app/Jenkinsfile.template Pipeline script will print the APPROVER environmental variable and then commit the changes:
      steps {
        echo "Continuing with deployment - approved by ${APPROVER}"
      }
  1. Navigate to the master branch of your helloworld-nodejs job in Blue Ocean on your Team Master and run the job. If you attempt to approve the input you will get an error:

  2. The submitter needs to navigate to the master branch of your helloworld-nodejs job on your Team Master to approve the input of your helloworld-nodejs Pipeline. You can use the Team switcher to quickly navigate to another Team Master that you are a member. The Team switcher drop-down will appear in the top right of your screen once you have been added as a member to another Team Master. The submitter needs to switch to the Team where they are a Team Guest member by selecting that team from the Team switcher drop-down.

  3. As the submitter navigate to the helloworld-nodejs job on your new team and approve the input. Note the output of the echo step.

NOTE: If you select a Pipeline job as a favorite you will be able to see things like jobs awaiting input submission in the Blue Ocean Dashboard.

Declarative Post Section

What happens if your input step times out or if the approver clicks the Abort button? There is a special post section for Delcarative Pipelines that allows you to define one or more additional steps that are run upon the completion of the entire pipeline or an individual stage execution and are designed to handle a variety of conditions (not only aborted) that could occur outside the standard Pipeline flow.

In this example we will add a post section to our Deploy stage to handle a timeout or disapproval by our submitter (aborted run).

  1. Add the following post section just below the options directive a the root of your Pipeline using the GitHub editor and commit your changes:
pipeline {
  agent { label 'nodejs-app' }
  options { 
    buildDiscarder(logRotator(numToKeepStr: '2'))
  }
  post {
    aborted {
      echo "Why didn't you push my button?"
    }
  }

NOTE: Even though we are putting the post section near the top of our Pipeline it will still run after all the stages are complete.

  1. Run your pipeline from the Branches view of the Blue Ocean Activity View for your pipeline.
  2. Let the job timeout or have your submitter click the Abort button. You will see the following output:

  3. In order to speed up the rest of the workshop, remove the the submitter option for the input directive by editing the nodejs-app/Jenkinsfile.template file in your forked custom-marker-pipelines repository and then commit the changes. Your Deploy stage should match the following and you will now be able to approve your own job:
    stage('Deploy') {
      when {
        beforeAgent true
        branch 'master'
      }
      options {
        timeout(time: 60, unit: 'SECONDS') 
      }
      input {
        message "Should we deploy?"
        submitterParameter "APPROVER"
      }
      steps {
        echo "Continuing with deployment - approved by ${APPROVER}"
      }
    }

More Options - Skip Default Checkout

By default, when a global agent - that is an agent at the pipeline level - is used and there aren't any agents defined at the individual stage levels, then that same agent is shared across all the stages and the source code repository associated with the Jenkins job is automatically checked out only once. But you will typically want to use different agents for different stages. And sometimes you don't need to checkout the source code for every stage. That is the case for our Pipeline for the helloworld-nodejs repository - we will eventually have different Kubernetes Pod Template based agents for each stage. So we are going to revisit the automatic code checkout for Declarative Pipelines that was mentioned in the Basic Declarative Syntax Structure lesson. Declarative Pipeline checks out source code by default as part of the agent directive. However, we don't need all of the files in the helloworld-nodejs repository in all of the stages. The skipDefaultCheckout option is a global level options to disable automatic checkouts.

  1. First, update the global options directive by adding the skipDefaultCheckout job setting below the buildDiscarder setting:
pipeline {
  agent none
  options { 
    buildDiscarder(logRotator(numToKeepStr: '2'))
    skipDefaultCheckout true
  }
  1. Next, we need to add a checkout step - checkout scm to the Test stage, we don't want to do a full checkout in any of the other stages but we do need a checkout in this stage:
    stage('Test') {
      agent { label 'nodejs-app' }
      steps {
        checkout scm
        container('nodejs') {
          echo 'Hello World!'   
          sh 'node --version'
        }
      }
    }
  1. Navigate to the master branch of your helloworld-nodejs job in Blue Ocean on your Team Master and run the job.

NOTE: The scm part of the checkout scm step is a special environment variable that is created for all Pipelines configured to load their Pipeline script from source control such as our helloworld-nodejs Multibranch Pipeline project.

Send Notification

Typically if you are using the input step with your Jenkins Pipeline you will want to send out a notification to the targeted approvers before the input step pauses the job. In this exercise we will send a notification using the Slack plugin slackSend step. But before that, we must update everyone's Team Master by installing and configuring the Slack plugin. Rather than have everyone do that manually on their own, we will take advantage of the CloudBees Core Operations Center Cluster Operations to bulk upgrade everyone's Team Master.

Bulk-upgrading Team Masters

For the first part of this exercise everyone will just follow along as it is the Operations Center administrator that would perform this task for all the Teams across your organization. Most of the tasks required to complete this task have already been done, but we will review all of the components of the bulk-upgrade to enable Slack notifications across all Team Masters.

  1. For this workshop we have created a custom container (Docker) image for our Team Masters. Among other things, this custom image allows us to manage the automatic installation of additional plugins. So the first thing we will need to do is add the Slack plugin to this custom image. To do that, we just have to add a text entry to the plugin.txt file which is utilized by the plugin.sh script to install every plugin in the list and their dependencies:
configuration-as-code:1.3
configuration-as-code-support:1.3
notification-api:1.1
operations-center-notification:1.0
aws-credentials:1.23
artifact-manager-s3:1.1
aws-global-configuration:1.0
devoptics:1.1561
slack:2.4
  1. Next we want to add the necessary configuration for the Slack plugin so that every Team can start using it right away. Fot that, we turn to the Jenkins Configuration as Code plugin. The CasC plugin allows us to define configuration for all the Team Masters in a simple yaml file that we copy into the custom container image. Here is the configuration snippet for the Slack plugin:
  slackNotifier:
    teamDomain: beedemo-team
    tokenCredentialId: beedemo-slack
    room: "#ci"
  1. After those changes are made for our custom container image, we need to build the image and push it to a container registry. We have already done that and the image has been pushed to an AWS Elastic Container Registry (ECR) as 946759952272.dkr.ecr.us-east-1.amazonaws.com/kypseli/cb-core-mm:2.138.3.1-kube-workshop-slack-2.
  2. Next, we need to update what Docker Image is the default for our Team Masters on Operations Center:

  3. Now all we have to do is run a Cluster Operation job on CloudBees Core Operations Center that has been configured to reprovision all of the Team Masters resulting in each Team Master using the new container image. Once your Team Master has been restarted the Slack plugin will be installed and cofigured:

That's it, once everyone's Team Master is restarted they will have the updated plugins and configuration provided by the updated container image.

Send a Slack Notification

Now all you have to do to send a Slack message is add the slackSend step to your Pipeline. We will add it to the success post block of the Build and Push Image stage.

  1. Use the GitHub file editor to update your nodejs-app/Jenkinsfile.template Pipeline script in your forked custom-marker-pipelines repository and add the following post block after the steps block of the Build and Push Image stage and then commit the changes:
    stage('Build and Push Image') {
      agent any
      when {
        beforeAgent true
        branch 'master'
      }
      steps {
        echo "TODO - build and push image"
      }
      post {
        success {
          slackSend "${JOB_NAME} pipeline job is awaiting approval at: ${RUN_DISPLAY_URL}"
        }
      }
    }

NOTE: The global environmental variables - JOB_NAME and RUN_DISPLAY_URL that we are including in our Slack message are very handy for including in messages, providing a link to navigate directly to the job.

  1. Navigate to the master branch of your helloworld-nodejs job in Blue Ocean on your Team Master and run the job.
  2. After your Pipeline job completes the steps in the Build and Push Image stage a message from your Team Master in the beedemo-team #ci Slack channel as below:

Next Lesson

Before moving on to the next lesson you can make sure that your nodejs-app/Jenkinsfile.template Pipeline script is correct by comparing to or copying from the after-approvals branch of your forked custom-marker-pipelines repository.

You may proceed to the next set of exercises - Pipeline Artifacts and Restartable, Parallel and Sequential Stages with CloudBees Core - when your instructor tells you.