Skip to content

Commit

Permalink
Use CANCELLED build state in Bitbucket Data Center and Server 8.0 (#606
Browse files Browse the repository at this point in the history
…) (#906)

Add an options to BitbucketBuildStatusNotificationsTrait to determine which notification to send to Bitbucket based on the Jenkins build result.
Revert the default behaviour for NOT_BUILT notification from SUCCESS to FAILED (configurable to STOPPED) for Bitbucket Cloud, the SUCCESS status was erroneously introduced in 2022 as default instead of STOPPED with the disableNotificationForNotBuildJob (which can be misunderstood) configurable option.
Add help description for all current configurable options for the build status notification trait
  • Loading branch information
nfalco79 authored Nov 14, 2024
1 parent 35872b2 commit 200b56c
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class BitbucketBuildStatusNotifications {
private static String getRootURL(@NonNull Run<?, ?> build) {
JenkinsLocationConfiguration cfg = JenkinsLocationConfiguration.get();

if (cfg == null || cfg.getUrl() == null) {
if (cfg.getUrl() == null) {

Check warning on line 64 in src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketBuildStatusNotifications.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 64 is only partially covered, one branch is missing
throw new IllegalStateException("Could not determine Jenkins URL.");
}

Expand Down Expand Up @@ -118,6 +118,8 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener
return;
}

BitbucketSCMSourceContext context = new BitbucketSCMSourceContext(null, SCMHeadObserver.none())
.withTraits(source.getTraits()); // NOSONAR
final Result result = build.getResult();
final String name = build.getFullDisplayName(); // use the build number as the display name of the status
String buildDescription = build.getDescription();
Expand All @@ -128,7 +130,6 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener
state = BitbucketBuildStatus.Status.SUCCESSFUL;
} else if (Result.UNSTABLE.equals(result)) {
statusDescription = StringUtils.defaultIfBlank(buildDescription, "This commit has test failures.");
BitbucketSCMSourceContext context = new BitbucketSCMSourceContext(null, SCMHeadObserver.none()).withTraits(source.getTraits());
if (context.sendSuccessNotificationForUnstableBuild()) {
state = BitbucketBuildStatus.Status.SUCCESSFUL;
} else {
Expand All @@ -138,17 +139,21 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener
statusDescription = StringUtils.defaultIfBlank(buildDescription, "There was a failure building this commit.");
state = BitbucketBuildStatus.Status.FAILED;
} else if (Result.NOT_BUILT.equals(result)) {
// Bitbucket Cloud and Server support different build states.
statusDescription = StringUtils.defaultIfBlank(buildDescription, "This commit was not built (probably the build was skipped)");
BitbucketSCMSourceContext context = new BitbucketSCMSourceContext(null, SCMHeadObserver.none()).withTraits(source.getTraits());
if (context.disableNotificationForNotBuildJobs()) {
state = (bitbucket instanceof BitbucketCloudApiClient) ? BitbucketBuildStatus.Status.STOPPED : null;
// Bitbucket Cloud and Server support different build states.
state = (bitbucket instanceof BitbucketCloudApiClient) ? BitbucketBuildStatus.Status.STOPPED : BitbucketBuildStatus.Status.CANCELLED;
} else {
state = BitbucketBuildStatus.Status.SUCCESSFUL;
state = BitbucketBuildStatus.Status.FAILED;
}
} else if (result != null) { // ABORTED etc.
statusDescription = StringUtils.defaultIfBlank(buildDescription, "Something is wrong with the build of this commit.");
state = BitbucketBuildStatus.Status.FAILED;
if (context.sendStopNotificationForAbortBuild()) {
// Bitbucket Cloud and Server support different build states.
state = (bitbucket instanceof BitbucketCloudApiClient) ? BitbucketBuildStatus.Status.STOPPED : BitbucketBuildStatus.Status.CANCELLED;
} else {
state = BitbucketBuildStatus.Status.FAILED;
}
} else {
statusDescription = StringUtils.defaultIfBlank(buildDescription, "The build is in progress...");
state = BitbucketBuildStatus.Status.INPROGRESS;
Expand Down Expand Up @@ -187,7 +192,7 @@ private static void sendNotifications(BitbucketSCMSource source, Run<?, ?> build
}
boolean shareBuildKeyBetweenBranchAndPR = sourceContext
.filters().stream()
.anyMatch(filter -> filter instanceof ExcludeOriginPRBranchesSCMHeadFilter);
.anyMatch(ExcludeOriginPRBranchesSCMHeadFilter.class::isInstance);

String key;
BitbucketApi bitbucket;
Expand Down Expand Up @@ -239,7 +244,7 @@ private static String getBuildKey(@NonNull Run<?, ?> build, String branch,
* Sends notifications to Bitbucket on Checkout (for the "In Progress" Status).
*/
@Extension
public static class JobCheckOutListener extends SCMListener {
public static class JobCheckoutListener extends SCMListener {

@Override
public void onCheckout(Run<?, ?> build, SCM scm, FilePath workspace, TaskListener listener, File changelogFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,17 @@
public class BitbucketBuildStatusNotificationsTrait extends SCMSourceTrait {

/**
* Should unstable builds be communicated as success to Bitbucket
* Should unstable builds be communicated as success to Bitbucket.
*/
private boolean sendSuccessNotificationForUnstableBuild;

/**
* Should not build jobs be communicated to Bitbucket
* Aborted jobs must be communicated as stopped to Bitbucket.
*/
private boolean sendStoppedNotificationForAbortBuild;

/**
* Should not build jobs be communicated to Bitbucket.
*/
private boolean disableNotificationForNotBuildJobs;

Expand All @@ -73,6 +78,27 @@ public boolean getSendSuccessNotificationForUnstableBuild() {
return this.sendSuccessNotificationForUnstableBuild;
}

/**
* Set if aborted builds will be communicated as stopped.
*
* @param sendStop comunicate Stop/Cancelled build status to Bitbucket for
* aborted build.
*/
@DataBoundSetter
public void setSendStoppedNotificationForAbortBuild(boolean sendStop) {
sendStoppedNotificationForAbortBuild = sendStop;
}

/**
* Return if aborted builds will be communicated as stopped.
*
* @return true will be comunicate to Bitbucket as Stopped/Cancelled build
* failed otherwise.
*/
public boolean getSendStoppedNotificationForAbortBuild() {
return this.sendStoppedNotificationForAbortBuild;
}

@DataBoundSetter
public void setDisableNotificationForNotBuildJobs(boolean isNotificationDisabled) {
disableNotificationForNotBuildJobs = isNotificationDisabled;
Expand All @@ -92,6 +118,7 @@ public boolean getDisableNotificationForNotBuildJobs() {
protected void decorateContext(SCMSourceContext<?, ?> context) {
((BitbucketSCMSourceContext) context).withDisableNotificationForNotBuildJobs(getDisableNotificationForNotBuildJobs());
((BitbucketSCMSourceContext) context).withSendSuccessNotificationForUnstableBuild(getSendSuccessNotificationForUnstableBuild());
((BitbucketSCMSourceContext) context).withSendStoppedNotificationForAbortBuild(getSendStoppedNotificationForAbortBuild());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public class BitbucketSCMSourceContext extends SCMSourceContext<BitbucketSCMSour
*/
@NonNull
private WebhookConfiguration webhookConfiguration = new WebhookConfiguration();

/**
* {@code true} if notifications should be disabled in this context.
*/
Expand All @@ -92,7 +93,12 @@ public class BitbucketSCMSourceContext extends SCMSourceContext<BitbucketSCMSour
private boolean sendSuccessNotificationForUnstableBuild;

/**
* {@code false} if not build jobs should be send to Bitbucket.
* {@code true} if aborted builds will be communicated as stopped/cancelled.
*/
private boolean sendStoppedNotificationForAbortBuild;

/**
* {@code false} if not built jobs should be send to Bitbucket.
*/
private boolean disableNotificationForNotBuildJobs;

Expand Down Expand Up @@ -208,7 +214,15 @@ public final WebhookConfiguration webhookConfiguration() {
*/
public final boolean notificationsDisabled() {
return notificationsDisabled;
}

/**
* Returns if aborted builds should be passed as stopped/cancelled to Bitbucket.
*
* @return {@code true} if aborted builds should be passed as stopped/cancelled to Bitbucket.
*/
public final boolean sendStopNotificationForAbortBuild() {
return sendStoppedNotificationForAbortBuild;
}

/**
Expand Down Expand Up @@ -366,6 +380,18 @@ public final BitbucketSCMSourceContext withSendSuccessNotificationForUnstableBui
return this;
}

/**
* Defines behaviour of unstable builds in Bitbucket.
*
* @param sendStopped {@code true} to consider aborted builds as stopped when notifying Bitbucket.
* @return {@code this} for method chaining.
*/
@NonNull
public final BitbucketSCMSourceContext withSendStoppedNotificationForAbortBuild(boolean sendStopped) {
this.sendStoppedNotificationForAbortBuild = sendStopped;
return this;
}

/**
* Defines behaviour of not-built jobs in Bitbucket.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ public class BitbucketBuildStatus {
public enum Status {
INPROGRESS("INPROGRESS"),
FAILED("FAILED"),
// available only in Cloud
STOPPED("STOPPED"),
// available only in Data Center
CANCELLED("CANCELLED"),
SUCCESSFUL("SUCCESSFUL");

private final String status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
<f:entry title="${%Communicate unstable builds to Bitbucket as successful}" field="sendSuccessNotificationForUnstableBuild">
<f:checkbox/>
</f:entry>
<f:entry title="${%Do not communicate not-built jobs to Bitbucket}" field="disableNotificationForNotBuildJobs">
<f:entry title="${%Communicate not-built jobs to Bitbucket as stopped}" field="disableNotificationForNotBuildJobs">
<f:checkbox/>
</f:entry>
<f:entry title="${%Communicate abort build to Bitbucket as stopped}" field="sendStoppedNotificationForAbortBuild">
<f:checkbox/>
</f:entry>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div>
Not-built result by default is notificated as FAILED status to Bitbucket.
If this option is enabled than not-built result is notified as STOPPED for Bitbucket Cloud or as CANCELLED for Bitbucket Data Center.
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div>
Aborted build by default is notificated as FAILED status to Bitbucket.
If this option is enabled than aborted build is notified as STOPPED for Bitbucket Cloud or as CANCELLED for Bitbucket Data Center.
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div>
Unstable build by default is notificated as FAILED status to Bitbucket.
If this option is enabled than unstable build is notified as SUCCESS to Bitbucket.
</div>
Loading

0 comments on commit 200b56c

Please sign in to comment.