Willemoes
Willemoes

Reputation: 6367

Jenkins pipeline when condition for closed pull request

I need some help with detecting PR events in a multibranch pipeline, I've searched a lot around google, but I cannot find anything. I've been trying to trigger a build on a closed PR event. This is different to triggering the branch that was merged to.

I have these conditions that are working fine

when {
  branch "master"
}

or

when {
  changeRequest()
}

But I'm missing something like:

when {
  changeRequest(status = "merged")  // or "closed"
}

Any idea how to do this? My objective is to do some cleanup of preview environments, in order to do this I need to know the PR ID.

I'm using bitbucket post webhook and in Jenkins I use "Bitbucket Branch Source Plugin". I know that the "event" is being sent to Jenkins because it is checked in the webhook. Any suggestions?

Regards!

Upvotes: 8

Views: 3081

Answers (2)

ycr
ycr

Reputation: 14584

AFAIK you can't achieve this only with the Bitbucket Branch Source Plugin. How the Plugin behaves is, that once you receive the Merge or Decline event for a PR Jenkins will consider this as an orphaned Job and it will remove or disable the Job. (Based on your Orphaned Item Strategy configurations).

Since you need full control over the Webhook triggers, the best way to handle this is by intercepting the Webhook and deciding what you want to do with it based on the event. So first remove the Webhook trigger from the Multibranch Pipeline. Then create a second Job to receive a Generic-webhook, which will intercept the web-hook request and then trigger the Multibranch Pipeline after analyzing the request. For this you can use the Generic Webhook Trigger Plugin. The request flow will be something like below.

Bitbucket ====web-hook===> WebHookInterceptorPipeline ====> Multibranch Pipeline

Once you receive the Webhook request first you need to check whether it's originating from a PR, if so you should have all the details related to the PR to perform whatever task you need. You can read more about the webhook messages Bitbucket will send from here. The webhook URL will look something like the below.

JENKINS_URL/generic-webhook-trigger/invoke?token=12345678

Following is a basic Pipeline you can refer to build your Interceptor Pipeline, As you can see below you can extract whatever details from the Webhook request using JSONPath expressions. [key: 'PR_ID', value: '$.pullrequest.id', defaultValue: 'null'], I have added comments to the Pipeline itself.

Jenkins Pipeline.

pipeline {
  agent any
  triggers {
    GenericTrigger(
     genericVariables: [
      [key: 'PR_ID', value: '$.pullrequest.id', defaultValue: 'null'],
      [key: 'PR_TYPE', value: '$.pullrequest.type', defaultValue: 'null'],
      [key: 'PR_TITLE', value: '$.pullrequest.title', defaultValue: 'null'],
      [key: 'PR_STATE', value: '$.pullrequest.state', defaultValue: 'null'],
      [key: 'PUSH_DETAILS', value: '$.push', defaultValue: 'Null']
     ],

     causeString: 'Triggered By Bitbucket',
     token: '12345678',
     tokenCredentialId: '',
     printContributedVariables: true,
     printPostContent: true,
     silentResponse: false
    )
  }
  stages {
    stage('ProcessWebHook') {
      steps {
          script {
            echo "Received a Webhook Request from Bitbucket."
            if(PR_ID != "null") {
                echo "Received a PR with following Details"
                echo "PR_ID: $PR_ID ; PR_TYPE: $PR_TYPE ; PR_TITLE: $PR_TITLE ; PR_STATE: $PR_STATE"
                // If the PR state is either MERGED or DECLINED we have to do some cleanup or else call Multibrach Pipeline
                // After the clean up we will again call the Multibranch pipeline to make sure Orphaned Jobs are removed/disabled.

                if(PR_STATE == "DECLINED" || PR_STATE == "MERGED") {
                  // Do your cleanup here, You should have all the PR Details to figure out what to clean
                  echo "Cleaning UP!!!!!!"
                }
                
            } else if(PUSH_DETAILS != "null") {
              // This check is not really required in your case. But in case you want to do something if this is a push I added this. 
              echo "This is a commit. Let's trigger the MultiBranch Pipeline"
            }
            // Always we will call the Multibranch pipeline
            echo "Triggering the Multibranch Pipeline"
            build job: "MultiYCRPipeline", wait: false
          }
      }
    }
  }
}

Upvotes: 1

Mickael Rahmine
Mickael Rahmine

Reputation: 447

I have the same utility as you and this is what we do.

You probably have a multi-branch pipeline to deploy the environment of your PR, and that is configured to detect new PR and delete the job when the PR is merged.

In such a case we use the 'MultiBranch Action Triggers' plugin which allows us to run another job if one of the jobs is deleted.

This plugin enables building/triggering other jobs when a Pipeline job is created or deleted, or when a Run (also known as Build) is deleted by a Multi Branch Pipeline Job.

So what happens is that when we merge a PR, the job disappears in the multi-branch pipeline and if it disappears, it triggers another job that will destroy the environment.

As you can see on the picture we configured it to run two job when PR is merged : delete_docker_images_for_branch & destroy_environment.

Upvotes: 1

Related Questions