2323 */
2424package com .cloudbees .jenkins .plugins .bitbucket ;
2525
26+ import com .cloudbees .jenkins .plugins .bitbucket .BranchDiscoveryTrait .ExcludeOriginPRBranchesSCMHeadFilter ;
2627import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketApi ;
2728import com .cloudbees .jenkins .plugins .bitbucket .api .BitbucketBuildStatus ;
2829import com .cloudbees .jenkins .plugins .bitbucket .client .BitbucketCloudApiClient ;
@@ -97,7 +98,7 @@ static String checkURL(@NonNull String url, BitbucketApi bitbucket) {
9798 }
9899
99100 private static void createStatus (@ NonNull Run <?, ?> build , @ NonNull TaskListener listener ,
100- @ NonNull BitbucketApi bitbucket , @ NonNull String hash )
101+ @ NonNull BitbucketApi bitbucket , @ NonNull String key , @ NonNull String hash )
101102 throws IOException , InterruptedException {
102103
103104 String url ;
@@ -112,7 +113,6 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener
112113 return ;
113114 }
114115
115- String key = build .getParent ().getFullName (); // use the job full name as the key for the status
116116 String name = build .getFullDisplayName (); // use the build number as the display name of the status
117117 BitbucketBuildStatus status ;
118118 Result result = build .getResult ();
@@ -153,24 +153,36 @@ private static void sendNotifications(Run<?, ?> build, TaskListener listener)
153153 return ;
154154 }
155155 BitbucketSCMSource source = (BitbucketSCMSource ) s ;
156- if ( new BitbucketSCMSourceContext (null , SCMHeadObserver . none ())
157- . withTraits (source .getTraits ())
158- .notificationsDisabled ()) {
156+ BitbucketSCMSourceContext sourceContext = new BitbucketSCMSourceContext (null ,
157+ SCMHeadObserver . none ()). withTraits (source .getTraits ());
158+ if ( sourceContext .notificationsDisabled ()) {
159159 return ;
160160 }
161161 SCMRevision r = SCMRevisionAction .getRevision (s , build );
162+ if (r == null ) {
163+ return ;
164+ }
162165 String hash = getHash (r );
163166 if (hash == null ) {
164167 return ;
165168 }
169+ boolean shareBuildKeyBetweenBranchAndPR = sourceContext
170+ .filters ().stream ()
171+ .anyMatch (filter -> filter instanceof ExcludeOriginPRBranchesSCMHeadFilter );
172+
173+ String key ;
174+ BitbucketApi bitbucket ;
166175 if (r instanceof PullRequestSCMRevision ) {
167176 listener .getLogger ().println ("[Bitbucket] Notifying pull request build result" );
168- createStatus (build , listener , source .buildBitbucketClient ((PullRequestSCMHead ) r .getHead ()), hash );
169-
177+ PullRequestSCMHead head = (PullRequestSCMHead ) r .getHead ();
178+ key = getBuildKey (build , head .getOriginName (), shareBuildKeyBetweenBranchAndPR );
179+ bitbucket = source .buildBitbucketClient (head );
170180 } else {
171181 listener .getLogger ().println ("[Bitbucket] Notifying commit build result" );
172- createStatus (build , listener , source .buildBitbucketClient (), hash );
182+ key = getBuildKey (build , r .getHead ().getName (), shareBuildKeyBetweenBranchAndPR );
183+ bitbucket = source .buildBitbucketClient ();
173184 }
185+ createStatus (build , listener , bitbucket , key , hash );
174186 }
175187
176188 @ CheckForNull
@@ -189,6 +201,25 @@ private static String getHash(@CheckForNull SCMRevision revision) {
189201 return null ;
190202 }
191203
204+ private static String getBuildKey (@ NonNull Run <?, ?> build , String branch ,
205+ boolean shareBuildKeyBetweenBranchAndPR ) {
206+
207+ // When the ExcludeOriginPRBranchesSCMHeadFilter filter is active, we want the
208+ // build status key to be the same between the branch project and the PR project.
209+ // This is to avoid having two build statuses when a branch goes into PR and
210+ // it was already built at least once as a branch.
211+ // So the key we use is the branch name.
212+ String key ;
213+ if (shareBuildKeyBetweenBranchAndPR ) {
214+ String folderName = build .getParent ().getParent ().getFullName ();
215+ key = String .format ("%s/%s" , folderName , branch );
216+ } else {
217+ key = build .getParent ().getFullName (); // use the job full name as the key for the status
218+ }
219+
220+ return key ;
221+ }
222+
192223 /**
193224 * Sends notifications to Bitbucket on Checkout (for the "In Progress" Status).
194225 */
0 commit comments