-
Type:
Suggestion
-
Resolution: Unresolved
-
None
-
Component/s: Integration – Build Status
-
None
-
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
- 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.'
- Received two build notifications for the entire plan execution:
- 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.
- Received four build notifications for the entire plan execution:
Expected Results
- Option A: Modify Bamboo to send a different build status to Bitbucket for builds with manual stages, such as "Continuable" instead of "Success."
- 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.") }