Access BitBucket payload data in Jenkins pipeline

2020-08-26 04:09发布

问题:

I've got a Jenkins pipeline job; it is configured to build on remote trigger which is being called by a BitBucket webhook. This works and is triggering the build.

I also need to access the payload data sent by BitBucket (described here) to get details about the push such as the specific branch.

The BitBucket plugin would usually parse this payload and present it to the job as an environment variable, but I can't set the pipeline job as being connected to a specific repo for that plugin, so it doesn't help.

I tried testing to see if the data was available in a few different ways like so:

node {
    stage 'Desperation'

    echo "${params.push}"
    echo "${env.BITBUCKET_PAYLOAD}"
    echo "${env.push}"
}

These don't work (nor did I really expect them to).

Is there any way to get hold of this payload data? The only thing I can come up with is having a freestyle job and setting up the connection to BitBucket on that, then calling this job afterwards with the data reformatted. That seems horribly clunky though.

回答1:

Ultimately I had to settle for a workaround.

My final setup is a Pipeline job my-build and a Freestyle job my-build-trigger.

my-build-trigger is straightforward. It has a git repo set up in the SCM section and Build when a change is pushed to BitBucket checked in the build triggers section.

In post-build actions I selected Trigger parameterized build on other projects.

The above is important. Build other projects will not trigger a Pipeline job. It will simply say my-build is not buildable.

Pass your payload parameter onto your downstream (Pipeline) job under predefined parameters, entering as payload=${BITBUCKET_PAYLOAD}.

BITBUCKET_PAYLOAD is an environment variable populated by the BitBucket plugin from the BitBucket payload object. You can see payload documentation from BitBucket here

Your post-build will look like this:

On your pipeline job, you should then create a corresponding parameter called payload (String type).

In your Jenkinsfile you can use this payload like so:

node {
    stage 'Echo stuff pointlessly'
    def payload = new groovy.json.JsonSlurper().parseText("${params.payload}")
    // Echoes the new commit hash
    echo payload.push.changes[0].new.target.hash
}

Be warned, you may get a serialization error in your job (java.io.NotSerializableException: groovy.json.internal.LazyMap). That is explained in this question. In short, you need to nullify the payload and other JSONObject vars after use.

Any comments or improvements are always appreciated.



回答2:

Here is how we solved it:

  • we used the BitBucket webhook to receive the notifications we wanted.
  • to receive the payload, we installed https://plugins.jenkins.io/generic-webhook-trigger/

The latter allows you to receive data in the application/json format, which is what BitBucket sends.

In your job settings, make sure to enable the following options:

Also, make sure to check both:

  • Print post content
  • Print contributed variables

This will show in your jenkins console all the variables it receive, also decomposing the json and converting it to plain variables. After you see the variables names that you want, make sure to "register" them as normal variables for your project.

I know you asked about using Jenkins Pipeline and this explanation is using the WebUI. The documentation of generic-webhook-trigger covers code snippets for exactly your case. I decided to add WebUI explanation so you can understand the gist of it.