Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-33507

Bitbucket Server webhooks and Bitbucket Cloud build status notifications

      Auto-register webhooks for Bitbucket Server and build status notifications for Bitbucket Cloud (only PR comments are sent currently).

          [JENKINS-33507] Bitbucket Server webhooks and Bitbucket Cloud build status notifications

          Nenad Miksa added a comment -

          We actually have solved this way: we created a webhook on BitBucket which every time there is a push to repository or pull request is created or updated, it calls this URL: http://jenkins.server/job/MyPipelineJob/build

          MyPipelineJob is multibranch pipeline job which only enumerates changes in pull requests and feature branches and triggers builds if necessary. However, we are missing Build status badges from BitBucket BuildStatus API.

          Nenad Miksa added a comment - We actually have solved this way: we created a webhook on BitBucket which every time there is a push to repository or pull request is created or updated, it calls this URL: http://jenkins.server/job/MyPipelineJob/build MyPipelineJob is multibranch pipeline job which only enumerates changes in pull requests and feature branches and triggers builds if necessary. However, we are missing Build status badges from BitBucket BuildStatus API.

          Mark Ottaviani added a comment - Is https://marketplace.atlassian.com/plugins/com.atlassian.stash.plugin.stash-web-post-receive-hooks-plugin/server/overview a viable option?

          Nenad Miksa added a comment -

          For BitBucket status API notifications, we have the following workaround:

          def obtainBitbucketToken() {
              try {
                  echo "Obtaining BitBucket Access Token"
                  sh "curl -s -X POST https://bitbucket.org/site/oauth2/access_token -u \"${getBitbucketOAuthKey()}:${getBitbucketOAuthSecret()}\" -d grant_type=client_credentials | jsawk 'return this.access_token' | tr -d \"\\n\" > accessToken.txt"
          
                  def accessToken = readFile 'accessToken.txt'
          
                  echo "BitBucket Token request response: ${accessToken}"
          
                  return accessToken
              } catch (error) {
                  echo "Failed to obtain BitBucket access token!"
                  return null
              }
          }
          
          def notifyCommit(String accessToken, String commitHash, String repository, String buildKey, boolean inProgress, boolean runTests) {
              echo "Notifying commit"
              if (accessToken == null) {
                  echo "Failed to notify commit with null access token!"
                  return
              }
              try {
                  def state = null
                  def description = null
                  if (inProgress) {
                      state = 'INPROGRESS'
                      description = "Build in progress. Tests will run: ${runTests}"
                  } else {
                      if (currentBuild.result == 'SUCCESS') {
                          state = 'SUCCESSFUL'
                          if (runTests) {
                              description = 'Build has succeeded and all tests have passed!'
                          } else {
                              description = 'Build has succeeded but tests were not run!'
                          }
                      } else {
                          state = 'FAILED'
                          if (currentBuild.result == 'UNSTABLE') {
                              description = 'Build has succeeded, but some tests have failed!'
                          } else {
                              description = "Build has failed. Jenkins result is: ${currentBuild.result}"
                          }
                      }
                  }
                  def payload = "{\"state\": \"${state}\", \"key\": \"Jenkins ${buildKey}\", \"name\": \"Jenkins ${buildKey}\", \"url\": \"${env.BUILD_URL}\", \"description\": \"${description}\"}"
                  sh "curl -s -X POST https://api.bitbucket.org/2.0/repositories/microblink/${repository}/commit/${commitHash}/statuses/build -H \"Content-Type: application/json\" -H \"Authorization: Bearer ${accessToken}\" -d '${payload}'"
              } catch(error) {
                  echo "There has been an error with notifying BitBucket!. Error: ${error}"
              }
          }
          

          So, at the beginning of my pipeline script, after checkout and resolving of git commit, I call it this way:

          def accessToken = obtainBitbucketToken()
          notifyCommit(accessToken, commitHash, repository, keyPullRequestBuild, true, runTests) // runTests is variable in my pipeline telling me whether tests should be run
          

          After the build finishes, I just need to call:

          def accessToken = obtainBitbucketToken()
          notifyCommit(accessToken, commitHash, repository, keyPullRequestBuild, false, runTests)
          

          This code needs to be run on unix node which has curl and jsawk tools installed (I tried JsonSlurper which should be built into the Groovy, but it kept crashing with serialization exceptions, even when used only from functions marked with @NonCPS).

          Nenad Miksa added a comment - For BitBucket status API notifications, we have the following workaround: def obtainBitbucketToken() { try { echo "Obtaining BitBucket Access Token" sh "curl -s -X POST https: //bitbucket.org/site/oauth2/access_token -u \" ${getBitbucketOAuthKey()}:${getBitbucketOAuthSecret()}\ " -d grant_type=client_credentials | jsawk ' return this .access_token' | tr -d \" \\n\ " > accessToken.txt" def accessToken = readFile 'accessToken.txt' echo "BitBucket Token request response: ${accessToken}" return accessToken } catch (error) { echo "Failed to obtain BitBucket access token!" return null } } def notifyCommit( String accessToken, String commitHash, String repository, String buildKey, boolean inProgress, boolean runTests) { echo "Notifying commit" if (accessToken == null ) { echo "Failed to notify commit with null access token!" return } try { def state = null def description = null if (inProgress) { state = 'INPROGRESS' description = "Build in progress. Tests will run: ${runTests}" } else { if (currentBuild.result == 'SUCCESS' ) { state = 'SUCCESSFUL' if (runTests) { description = 'Build has succeeded and all tests have passed!' } else { description = 'Build has succeeded but tests were not run!' } } else { state = 'FAILED' if (currentBuild.result == 'UNSTABLE' ) { description = 'Build has succeeded, but some tests have failed!' } else { description = "Build has failed. Jenkins result is: ${currentBuild.result}" } } } def payload = "{\" state\ ": \" ${state}\ ", \" key\ ": \" Jenkins ${buildKey}\ ", \" name\ ": \" Jenkins ${buildKey}\ ", \" url\ ": \" ${env.BUILD_URL}\ ", \" description\ ": \" ${description}\ "}" sh "curl -s -X POST https: //api.bitbucket.org/2.0/repositories/microblink/${repository}/commit/${commitHash}/statuses/build -H \" Content-Type: application/json\ " -H \" Authorization: Bearer ${accessToken}\ " -d '${payload}' " } catch (error) { echo "There has been an error with notifying BitBucket!. Error: ${error}" } } So, at the beginning of my pipeline script, after checkout and resolving of git commit, I call it this way: def accessToken = obtainBitbucketToken() notifyCommit(accessToken, commitHash, repository, keyPullRequestBuild, true , runTests) // runTests is variable in my pipeline telling me whether tests should be run After the build finishes, I just need to call: def accessToken = obtainBitbucketToken() notifyCommit(accessToken, commitHash, repository, keyPullRequestBuild, false , runTests) This code needs to be run on unix node which has curl and jsawk tools installed (I tried JsonSlurper which should be built into the Groovy, but it kept crashing with serialization exceptions, even when used only from functions marked with @NonCPS).

          Nenad Miksa added a comment -

          I forgot to mention - you need to define functions getBitbucketOAuthKey() and getBitbucketOAuthSecret() which return OAuth key and secret for OAuth consumer.

          Nenad Miksa added a comment - I forgot to mention - you need to define functions getBitbucketOAuthKey() and getBitbucketOAuthSecret() which return OAuth key and secret for OAuth consumer.

          Another alternative for webhooks in BB Server. And the author has sent a PR to support it. I could not test it yet.

          Maybe this plugin could expose an API to register the webhook in the repository.

          Antonio Muñiz added a comment - Another alternative for webhooks in BB Server . And the author has sent a PR to support it . I could not test it yet. Maybe this plugin could expose an API to register the webhook in the repository.

          I'm currently creating this api. Its almost done, just need some more testing and re-approval by Atlassian when its done.

          Erwin Oldenkamp added a comment - I'm currently creating this api. Its almost done, just need some more testing and re-approval by Atlassian when its done.

          Aaron Trout added a comment -

          +1 for webhooks on Bitbucket Server. Could it just enable the proper Jenkins hook plugin?

          Aaron Trout added a comment - +1 for webhooks on Bitbucket Server. Could it just enable the proper Jenkins hook plugin?

          Webhooks support for BB Server merged into master (not released yet).

          For the records: the plugin required at BB Server side is https://marketplace.atlassian.com/plugins/nl.topicus.bitbucket.bitbucket-webhooks/server/overview

          Antonio Muñiz added a comment - Webhooks support for BB Server merged into master (not released yet). For the records: the plugin required at BB Server side is https://marketplace.atlassian.com/plugins/nl.topicus.bitbucket.bitbucket-webhooks/server/overview

          Itai Sanders added a comment -

          does this mean we also have the build status notification fixed?

          Itai Sanders added a comment - does this mean we also have the build status notification fixed?

          amuniz When do you plan to release this ? Is there a way i can test this now ?

          Mihai Marinescu added a comment - amuniz When do you plan to release this ? Is there a way i can test this now ?

            amuniz Antonio Muñiz
            amuniz Antonio Muñiz
            Votes:
            21 Vote for this issue
            Watchers:
            30 Start watching this issue

              Created:
              Updated:
              Resolved: