Revisit Build Status Notifications to support Manual Stages in Bamboo

XMLWordPrintable

    • 2
    • 1

      Issue Summary

      When using manual stages in Bamboo, additional build status notifications are delivered to Bitbucket. Specifically, Bamboo sends "In Progress" and "Success" notifications upon reaching a manual stage and again when the manual stage is initiated. This behavior allows premature merging of pull requests. 

      Steps to Reproduce

      1. Creat a build plan in Bamboo with two standard stages:
        • Received two build notifications for the entire plan execution:
          • one for 'in progress' and one for 'success.'
      2. Update the second stage to be a manual stage:
        • Received four build notifications for the entire plan execution: 
          • One for 'in progress' and one for 'success' for the first(standard) stage, 
          • One for 'in progress' and one for 'success' for the second (manual) stage.

      Expected Results

      1. Option A: Modify Bamboo to send a different build status to Bitbucket for builds with manual stages, such as "Continuable" instead of "Success."
      2. Option B: Introduce a setting in Bitbucket to prevent merges on pull requests with pending manual stages

      Actual Results

      Bamboo sends an "In Progress" notification when initiating the build and a "Success" notification when reaching the manual stage. After initiating the manual stage, the two 'In Progress' notifications are delivered again, along with the 'Success' notification once the manual stage is completed. 

      Workaround

      Install a merge check script to the Bitbucket Repository similar to:

      import java.util.Listimport java.lang.Iterableimport com.atlassian.bitbucket.commit.Commitimport groovy.json.JsonSlurperimport com.atlassian.sal.api.net.Responseimport com.atlassian.applinks.api.ApplicationLinkResponseHandlerimport com.atlassian.applinks.api.application.bamboo.BambooApplicationTypeimport com.atlassian.applinks.api.ApplicationLinkServiceimport com.atlassian.applinks.api.ApplicationLinkimport com.atlassian.bitbucket.pull.PullRequestServiceimport com.atlassian.bitbucket.repository.RepositoryServiceimport com.atlassian.sal.api.component.ComponentLocatorimport com.atlassian.bitbucket.pull.PullRequestimport com.atlassian.bitbucket.internal.build.status.SimpleBuildStatusimport com.spacex.scriptrunner.RepositoryBuildsimport com.atlassian.sal.api.net.Responseimport com.atlassian.sal.api.net.ResponseExceptionimport static com.atlassian.sal.api.net.Request.MethodType.GETimport com.atlassian.bitbucket.hook.repository.RepositoryHookResult
      
      def appLinkService = ComponentLocator.getComponent(ApplicationLinkService)
      def appLink = appLinkService.getPrimaryApplicationLink(BambooApplicationType)
      def applicationLinkRequestFactory
      def request
      def sessionDetails// returns if the build is still pending manual stepsdef continuable
      def buildStatus
      def buildKey
      
      RepositoryBuilds repoBuilds = new RepositoryBuilds()
      Iterable<Commit> prCommits = pr.getCommits()
      
      def handler = new ApplicationLinkResponseHandler<Map>() {
          @Override
          Map credentialsRequired(Response response) throws ResponseException {        null    }
      
          @Override
          Map handle(Response response) throws ResponseException {        assert response.statusCode == 200        new JsonSlurper().parseText(response.getResponseBodyAsString()) as Map
          }
      }
      
      List<SimpleBuildStatus> filteredBuilds = [];
      
      prCommits.each { commit ->
          repoBuilds = new RepositoryBuilds()
          List<SimpleBuildStatus> allBuilds = repoBuilds.getBuilds(pr, commit.getId())
          allBuilds.each { build ->
              buildKey = build.url        if (buildKey.contains("bamboo"))\{
                  filteredBuilds.add(build)
              }
          }
      }// look at the latest commit that has a builddef latestBuild = filteredBuilds.max \{ it.createdDate }
      buildKey = latestBuild.getUrl().substring(buildKey.lastIndexOf("browse/")).replace("browse/","")
      
      applicationLinkRequestFactory = appLink.createAuthenticatedRequestFactory()
      request = applicationLinkRequestFactory.createRequest(GET, "/rest/api/latest/result/${buildKey}")
      request.setHeader("Accept","application/json")
      sessionDetails = request.execute(handler)
      continuable = sessionDetails.continuable
      buildStatus = sessionDetails.buildStateif (buildStatus != "Successful"){
          RepositoryHookResult.rejected("Builds not successful", "Build ${buildKey} in commit ${latestBuild.commitId} failed.")
      }else if (continuable){
          RepositoryHookResult.rejected("Manual Stage Pending", "Build ${buildKey} in commit ${latestBuild.commitId} requires manual stage to finish before merging.")
      }
      

            Assignee:
            Unassigned
            Reporter:
            Abhi Phull
            Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: