Setup
Make sure that you have the Bitbucket plug-in for Jenkins installed.
Add a new webhook in Bitbucket by navigating to your project and select Webhooks > Add webhook.
Leave the Secret field empty and use https://${JENKINS_URL}/bitbucket-hook/ (note the trailing slash) as URL

Matching Bitbucket webhooks with a Jenkins project
When Bitbucket Cloud sends a request to Jenkins, the Bitbucket plugin uses the HTTP headers User-Agent: Bitbucket-Webhooks/2.0 and X-Event-Key: repo:push to identify a new push.
For Bitbucket Server or older webhooks other checks are done, see BitbucketPayloadProcessor.java.
In case your Bitbucket project is located at https://bitbucket.org/my-org/my-project, that URL must match with your checkout URL in Jenkins. This may not be the case if you have to do a checkout via SSH instead of HTTPS.
Job configuration
Pipeline job
When using the JobDSL plug-in, you have to specify the overrideUrl:
pipelineJob("my-job") {
// listen for Bitbucket WebHook
properties {
pipelineTriggers {
triggers {
// see https://github.com/jenkinsci/job-dsl-plugin/wiki/Migration
bitbucketPush {
overrideUrl: 'https://bitbucket.org/my-org/my-project'
}
}
}
}
definition {
cpsScm {
lightweight(true)
scm {
git {
branch('*/main')
remote {
name('origin')
url('git@bitbucket.org:my-org/my-project.git')
}
}
}
}
}
}
Please use properties.pipelineTriggers.triggers instead of triggers. The later one is deprecated and will be removed in the future.
Multibranch pipeline job
For a multibranch pipeline job, you have to configure the Bitbucket trigger listener in a different way. First of all, the Jenkins DSL extension bitbucketPush has no effect in a multibranch pipeline.
Instead, the configure block has to be used to set the correct configuration.
multibranchPipelineJob('Test feature branches') {
// for a multibranch-project `triggers { bitbucketPush }` does not work
configure { project ->
project / triggers / 'com.cloudbees.jenkins.plugins.BitBucketMultibranchTrigger' {
spec()
overrideUrl('https://bitbucket.org/my-org/my-project')
}
}
branchSources {
branchSource {
source {
git {
// IMPORTANT: use a constant and unique identifier
id('my-feature-branches')
remote('git@bitbucket.org:my-org/my-project')
credentialsId('my-credential-id-for-bitbucket')
traits {
// scan git branches; without this trait, no branch is detected
gitBranchDiscovery()
headWildcardFilter {
includes('*')
// we are interested in everything bot not in those branches
excludes('main master develop')
}
}
}
}
}
}
}
With that JobDSL configuration, each commit to a branch which is not main,master or develop, triggers a new build.
You may not want to build all branches on first indexing of the Git project. Make sure that you have installed the basic-branch-build-strategies plug-in. Then add the following section to your JobDSL configuration:
multibranchPipelineJob('Test feature branches') {
// ...
branchSources {
branchSource {
source {
// ...
}
buildStrategies {
buildAllBranches {
strategies {
// do not trigger initial builds when first branch indexing happens
skipInitialBuildOnFirstBranchIndexing()
}
}
}
}
}
}
Debugging webhooks
Bitbucket only sends webhooks when doing a non-forced Git push. To not mess up your project's Git history, you can use the following wrapper script:
#!/bin/bash
curl -o - \
-X POST https://${JENKINS_URL}/bitbucket-hook/ \
-H "User-Agent: Bitbucket-Webhooks/2.0" \
-H "X-Event-Key: repo:push" -H "Content-Type: application/json" \
-d '${SAMPLE_REQUEST_FROM_BITBUCKET}'
You can get the ${SAMPLE_REQUEST_FROM_BITBUCKET} from Bitbucket by navigating to Webhooks > ${YOUR_WEBHOOK} > View requests > ${REQUEST} > View details > Body > Copy as raw string.

Enabling the Bitbucket plugin log
In Jenkins click on Manage Jenkins > System log > Add recorder and add the following loggers with priority ALL:
com.cloudbees.jenkins.plugins.BitbucketHookReceivercom.cloudbees.jenkins.plugins.BitbucketPayloadProcessorcom.cloudbees.jenkins.plugins.BitbucketJobProbe

When you now triggering the webhook, all internal actions are added to the log. That should make it easier to debug your non-working webhook.