Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JENKINS-65741: Implement a new option that will allow to include jenkins url to the commit status #454

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ public class BitbucketBuildStatusNotifications {
private static final String STOPPED_STATE = "STOPPED";
private static final String INPROGRESS_STATE = "INPROGRESS";

private static String getRootURL(@NonNull Run<?, ?> build) {
private static String getRootURL() {
return DisplayURLProvider.get().getRoot();
}

private static String getRunURL(@NonNull Run<?, ?> build) {
Copy link
Contributor Author

@dee-kryvenko dee-kryvenko May 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method was confusing - it was returning job url but saying it was returning root url, and since I needed a new method that would return a root url - I had to rename this.

This method also never actually uses build and cfg so I am not sure what's the purpose of everything in there except for the last line.

JenkinsLocationConfiguration cfg = JenkinsLocationConfiguration.get();

if (cfg == null || cfg.getUrl() == null) {
throw new IllegalStateException("Could not determine Jenkins URL.");
throw new IllegalStateException("Could not determine job URL.");
}

return DisplayURLProvider.get().getRunURL(build);
Expand Down Expand Up @@ -110,9 +114,11 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener
return;
}

String url;
String rootUrl, url;
try {
url = getRootURL(build);
rootUrl = getRootURL();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Root URL does not need a checkURL. There is no requirements for the text fields it is used in, and we want to keep whatever the user have put in there.


url = getRunURL(build);
checkURL(url, bitbucket);
} catch (IllegalStateException e) {
listener.getLogger().println("Can not determine Jenkins root URL " +
Expand All @@ -123,10 +129,15 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener
return;
}

BitbucketSCMSource source = (BitbucketSCMSource) s;
BitbucketSCMSourceContext sourceContext = new BitbucketSCMSourceContext(null, SCMHeadObserver.none())
.withTraits(source.getTraits());

String name = build.getFullDisplayName(); // use the build number as the display name of the status
BitbucketBuildStatus status;
Result result = build.getResult();
String buildDescription = build.getDescription();
String statusDescriptionSuffix = "";
String statusDescription;
String state;
if (Result.SUCCESS.equals(result)) {
Expand All @@ -135,9 +146,6 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener
} else if (Result.UNSTABLE.equals(result)) {
statusDescription = StringUtils.defaultIfBlank(buildDescription, "This commit has test failures.");

BitbucketSCMSource source = (BitbucketSCMSource) s;
BitbucketSCMSourceContext sourceContext = new BitbucketSCMSourceContext(null, SCMHeadObserver.none())
.withTraits(source.getTraits());
if (sourceContext.sendSuccessNotificationForUnstableBuild()) {
state = SUCCESSFUL_STATE;
} else {
Expand All @@ -157,7 +165,10 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener
statusDescription = StringUtils.defaultIfBlank(buildDescription, "The build is in progress...");
state = INPROGRESS_STATE;
}
status = new BitbucketBuildStatus(hash, statusDescription, state, url, key, name);
if (sourceContext.buildStatusIncludeJenkinsURL()) {
statusDescriptionSuffix = "\n" + rootUrl;
}
status = new BitbucketBuildStatus(hash, statusDescription + statusDescriptionSuffix, state, url, key, name);
new BitbucketChangesetCommentNotifier(bitbucket).buildStatus(status);
if (result != null) {
listener.getLogger().println("[Bitbucket] Build result notified");
Expand All @@ -171,6 +182,8 @@ private static void createStatus(@NonNull Run<?, ?> build, @NonNull TaskListener

private static void sendNotifications(BitbucketSCMSource source, Run<?, ?> build, TaskListener listener)
throws IOException, InterruptedException {
String rootUrl = getRootURL();

BitbucketSCMSourceContext sourceContext = new BitbucketSCMSourceContext(null,
SCMHeadObserver.none()).withTraits(source.getTraits());
if (sourceContext.notificationsDisabled()) {
Expand All @@ -193,11 +206,13 @@ private static void sendNotifications(BitbucketSCMSource source, Run<?, ?> build
if (r instanceof PullRequestSCMRevision) {
listener.getLogger().println("[Bitbucket] Notifying pull request build result");
PullRequestSCMHead head = (PullRequestSCMHead) r.getHead();
key = getBuildKey(build, head.getOriginName(), shareBuildKeyBetweenBranchAndPR);
key = getBuildKey(build, rootUrl, head.getOriginName(),
shareBuildKeyBetweenBranchAndPR, sourceContext.buildStatusIncludeJenkinsURL());
bitbucket = source.buildBitbucketClient(head);
} else {
listener.getLogger().println("[Bitbucket] Notifying commit build result");
key = getBuildKey(build, r.getHead().getName(), shareBuildKeyBetweenBranchAndPR);
key = getBuildKey(build, rootUrl, r.getHead().getName(),
shareBuildKeyBetweenBranchAndPR, sourceContext.buildStatusIncludeJenkinsURL());
bitbucket = source.buildBitbucketClient();
}
createStatus(build, listener, bitbucket, key, hash);
Expand All @@ -215,8 +230,8 @@ private static String getHash(@CheckForNull SCMRevision revision) {
return null;
}

private static String getBuildKey(@NonNull Run<?, ?> build, String branch,
boolean shareBuildKeyBetweenBranchAndPR) {
private static String getBuildKey(@NonNull Run<?, ?> build, String rootUrl, String branch,
boolean shareBuildKeyBetweenBranchAndPR, boolean includeJenkinsURL) {

// When the ExcludeOriginPRBranchesSCMHeadFilter filter is active, we want the
// build status key to be the same between the branch project and the PR project.
Expand All @@ -231,6 +246,10 @@ private static String getBuildKey(@NonNull Run<?, ?> build, String branch,
key = build.getParent().getFullName(); // use the job full name as the key for the status
}

if (includeJenkinsURL) {
key = rootUrl + "/" + key;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be double / depending on the user input - but I figured it doesn't makes any difference, the string is just a seed for a hash - as long as it's consistent, we're good.

}

return key;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public class BitbucketBuildStatusNotificationsTrait extends SCMSourceTrait {
*/
private boolean sendSuccessNotificationForUnstableBuild;

/**
* Include Jenkins URL as a status key/name
*/
private boolean includeJenkinsURL;

/**
* Constructor.
*
Expand All @@ -68,12 +73,26 @@ public boolean getSendSuccessNotificationForUnstableBuild() {
return this.sendSuccessNotificationForUnstableBuild;
}

@DataBoundSetter
public void setIncludeJenkinsURL(boolean isIncludeJenkinsURL) {
includeJenkinsURL = isIncludeJenkinsURL;
}

/**
* @return {@code true} if commit status should include Jenkins URL
*/
public boolean getIncludeJenkinsURL() {
return this.includeJenkinsURL;
}

/**
* {@inheritDoc}
*/
@Override
protected void decorateContext(SCMSourceContext<?, ?> context) {
((BitbucketSCMSourceContext) context).withSendSuccessNotificationForUnstableBuild(getSendSuccessNotificationForUnstableBuild());
((BitbucketSCMSourceContext) context)
.withSendSuccessNotificationForUnstableBuild(getSendSuccessNotificationForUnstableBuild())
.withBuildStatusIncludeJenkinsURL(getIncludeJenkinsURL());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ public class BitbucketSCMSourceContext extends SCMSourceContext<BitbucketSCMSour
*/
private boolean sendSuccessNotificationForUnstableBuild;

/**
* {@code true} if need to include Jenkins URL to the build status name and key.
*/
private boolean buildStatusIncludeJenkinsURL;

/**
* Constructor.
*
Expand Down Expand Up @@ -215,6 +220,15 @@ public final boolean sendSuccessNotificationForUnstableBuild() {
return sendSuccessNotificationForUnstableBuild;
}

/**
* Returns {@code true} if should include Jenkins URL to a build status name and key.
*
* @return {@code false} if should NOT include Jenkins URL to a build status name and key.
*/
public final boolean buildStatusIncludeJenkinsURL() {
return buildStatusIncludeJenkinsURL;
}

/**
* Adds a requirement for branch details to any {@link BitbucketSCMSourceRequest} for this context.
*
Expand Down Expand Up @@ -352,6 +366,18 @@ public final BitbucketSCMSourceContext withSendSuccessNotificationForUnstableBui
return this;
}

/**
* Defines behaviour of build status name and key.
*
* @param buildStatusIncludeJenkinsURL {@code true} to inluce Jenkins URL to the build status key/name.
* @return {@code this} for method chaining.
*/
@NonNull
public final BitbucketSCMSourceContext withBuildStatusIncludeJenkinsURL(boolean buildStatusIncludeJenkinsURL) {
this.buildStatusIncludeJenkinsURL = buildStatusIncludeJenkinsURL;
return this;
}

/**
* {@inheritDoc}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
<f:entry title="${%Communicate Unstable builds to Bitbucket as Successful}" field="sendSuccessNotificationForUnstableBuild">
<f:checkbox/>
</f:entry>
<f:entry title="${%Include Jenkins URL}" field="includeJenkinsURL">
<f:checkbox/>
</f:entry>
</j:jelly>