Skip to content

Commit

Permalink
Issue jenkinsci#290: Implement compatibility with new Bitbucket rest …
Browse files Browse the repository at this point in the history
…api and fix missing "parent" property in JSON for required builds
  • Loading branch information
BUGinator86pA committed Oct 3, 2023
1 parent dfba29a commit 04cf2f9
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ public class BuildStatusUriFactory {
private BuildStatusUriFactory() {
}

public static URI create(String baseUri, String commit) {
public static URI create(String baseUri, String projectKey, String slug, String commit) {
String tidyBase = StringUtils.removeEnd(baseUri, "/");
String uri = String.join("/", tidyBase, "rest/build-status/1.0/commits", commit);

String uri;
if(projectKey == null || slug == null || projectKey.isEmpty() || slug.isEmpty()) {
uri = String.join("/", tidyBase, "rest/build-status/1.0/commits", commit);
}
else {
uri = String.join("/", tidyBase, "rest/api/latest/projects", projectKey, "repos", slug, "commits", commit, "builds");
}
return URI.create(uri);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class DefaultApacheHttpNotifier implements HttpNotifier {
try (CloseableHttpClient client = getHttpClient(logger, uri, settings.isIgnoreUnverifiedSSL())) {
HttpPost req = createRequest(uri, payload, settings.getCredentials(), context);
HttpResponse res = client.execute(req);

if (res.getStatusLine().getStatusCode() != 204) {
return NotificationResult.newFailure(EntityUtils.toString(res.getEntity()));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static NotificationResult newFailure(String message) {
* @param initSuccess success flag
* @param initMessage message in case notification was not successful
*/
protected NotificationResult(
NotificationResult(
final boolean initSuccess,
final String initMessage) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,22 @@ public class StashNotifier extends Notifier implements SimpleBuildStep {
private boolean includeBuildNumberInKey;

/**
* specify project key manually
* specify Bitbucket project key
*/
private String bbProjectKey;

/**
* specify Bitbucket repository slug
*/
private String repositorySlug;

/**
* specify Jenkins project key manually
*/
private String projectKey;

/**
* append parent project key to key formation
* append parent Jenkins project key to key formation
*/
private boolean prependParentProjectKey;

Expand All @@ -172,7 +182,7 @@ public class StashNotifier extends Notifier implements SimpleBuildStep {
*/
private boolean considerUnstableAsSuccess;

private JenkinsLocationConfiguration globalConfig;
private final JenkinsLocationConfiguration globalConfig;

/**
* gives us the desired {@link HttpNotifier}. Transient because
Expand All @@ -190,6 +200,8 @@ public BuildStepMonitor getRequiredMonitorService() {
StashNotifier(
String stashServerBaseUrl,
String credentialsId,
String bbProjectKey,
String repositorySlug,
boolean ignoreUnverifiedSSLPeer,
String commitSha1,
String buildStatus,
Expand All @@ -205,6 +217,8 @@ public BuildStepMonitor getRequiredMonitorService() {
this.globalConfig = globalConfig;
setStashServerBaseUrl(stashServerBaseUrl);
setCredentialsId(credentialsId);
setBbProjectKey(bbProjectKey);
setRepositorySlug(repositorySlug);
setIgnoreUnverifiedSSLPeer(ignoreUnverifiedSSLPeer);
setCommitSha1(commitSha1);
setBuildStatus(buildStatus);
Expand Down Expand Up @@ -304,6 +318,15 @@ public void setIncludeBuildNumberInKey(boolean includeBuildNumberInKey) {
this.includeBuildNumberInKey = includeBuildNumberInKey;
}

public String getBbProjectKey() { return bbProjectKey; }

@DataBoundSetter
public void setBbProjectKey(String bbProjectKey) { this.bbProjectKey = bbProjectKey; }

public String getRepositorySlug() { return repositorySlug; }

@DataBoundSetter
public void setRepositorySlug(String repositorySlug) { this.repositorySlug = repositorySlug; }
public String getProjectKey() {
return projectKey;
}
Expand Down Expand Up @@ -452,6 +475,7 @@ private boolean processJenkinsEvent(
try {
NotificationResult result
= notifyStash(logger, run, commitSha1, listener, state);

if (result.indicatesSuccess) {
logger.println("Notified Bitbucket for commit with id " + commitSha1);
} else {
Expand Down Expand Up @@ -851,14 +875,15 @@ protected NotificationResult notifyStash(

String stashURL = expandStashURL(run, listener);

logger.println("Notifying Bitbucket at \"" + stashURL + "\"");

Credentials usernamePasswordCredentials
= getCredentials(UsernamePasswordCredentials.class, run.getParent());
Credentials stringCredentials
= getCredentials(StringCredentials.class, run.getParent());

URI uri = BuildStatusUriFactory.create(stashURL, commitSha1);
URI uri = BuildStatusUriFactory.create(stashURL, bbProjectKey, repositorySlug, commitSha1);

logger.println("Sending notification to \"" + uri + "?key=" + abbreviate(getBuildKey(run, listener), MAX_FIELD_LENGTH) + "\"");

NotificationSettings settings = new NotificationSettings(
ignoreUnverifiedSSLPeer || getDescriptor().isIgnoreUnverifiedSsl(),
stringCredentials != null ? stringCredentials : usernamePasswordCredentials
Expand Down Expand Up @@ -923,48 +948,6 @@ protected StashBuildState getPushedBuildStatus(StashBuildState currentBuildStatu
}
}

/**
* Returns the HTTP POST request ready to be sent to the Bitbucket build API for
* the given run and change set.
*
* @see DefaultApacheHttpNotifier#createRequest(URI, JSONObject, Credentials, NotificationContext)
* @deprecated in favor of method overload
* @param stashBuildNotificationEntity a entity containing the parameters for Bitbucket
* @param commitSha1 the SHA1 of the commit that was built
* @param url Bitbucket URL
* @return the HTTP POST request to the Bitbucket build API
*/
protected HttpPost createRequest(
final HttpEntity stashBuildNotificationEntity,
final Item project,
final String commitSha1,
final String url) throws AuthenticationException {

HttpPost req = new HttpPost(
url
+ "/rest/build-status/1.0/commits/"
+ commitSha1);

// If we have a credential defined then we need to determine if it
// is a basic auth
UsernamePasswordCredentials usernamePasswordCredentials
= getCredentials(UsernamePasswordCredentials.class, project);

if (usernamePasswordCredentials != null) {
req.addHeader(new BasicScheme().authenticate(
new org.apache.http.auth.UsernamePasswordCredentials(
usernamePasswordCredentials.getUsername(),
usernamePasswordCredentials.getPassword().getPlainText()),
req,
null));
}

req.addHeader(HttpHeaders.CONTENT_TYPE, "application/json");
req.setEntity(stashBuildNotificationEntity);

return req;
}

private String expandStashURL(Run<?, ?> run, final TaskListener listener) {
String url = stashServerBaseUrl;
DescriptorImpl descriptor = getDescriptor();
Expand Down Expand Up @@ -1018,12 +1001,18 @@ private JSONObject createNotificationPayload(
final StashBuildState state,
TaskListener listener) {

String buildId = abbreviate(getBuildKey(run, listener), MAX_FIELD_LENGTH);

JSONObject json = new JSONObject();
json.put("key", buildId);
json.put("parent", buildId);
json.put("state", state.name());
json.put("key", abbreviate(getBuildKey(run, listener), MAX_FIELD_LENGTH));
json.put("url", abbreviate(getBuildUrl(run), MAX_URL_FIELD_LENGTH));
json.put("name", abbreviate(getBuildName(run), MAX_FIELD_LENGTH));
json.put("description", abbreviate(getBuildDescription(run, state), MAX_FIELD_LENGTH));
json.put("url", abbreviate(getBuildUrl(run), MAX_URL_FIELD_LENGTH));
json.put("buildNumber", run.getNumber());
json.put("duration", run.getDuration());

return json;
}

Expand Down Expand Up @@ -1076,9 +1065,7 @@ protected String getBuildKey(final Run<?, ?> run,
StringBuilder key = new StringBuilder();

if (prependParentProjectKey || getDescriptor().isPrependParentProjectKey()) {
if (null != run.getParent().getParent()) {
key.append(run.getParent().getParent().getFullName()).append('-');
}
key.append(run.getParent().getParent().getFullName()).append('-');
}

if (projectKey != null && projectKey.trim().length() > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
<f:entry title="${%Credentials}" field="credentialsId">
<c:select/>
</f:entry>
<f:entry title="Bitbucket project key" field="bbProjectKey">
<f:textbox />
</f:entry>
<f:entry title="Bitbucket Repository Slug" field="repositorySlug">
<f:textbox />
</f:entry>
<f:entry title="Commit SHA-1" field="commitSha1">
<f:textbox />
</f:entry>
Expand All @@ -22,10 +28,10 @@
<f:entry title="Keep repeated builds in Bitbucket" field="includeBuildNumberInKey">
<f:checkbox />
</f:entry>
<f:entry title="Override project key" field="projectKey">
<f:entry title="Override Jenkins project key" field="projectKey">
<f:textbox />
</f:entry>
<f:entry title="Prepend parent project name to key" field="prependParentProjectKey">
<f:entry title="Prepend parent Jenkins project name to key" field="prependParentProjectKey">
<f:checkbox />
</f:entry>
<f:entry title="Disable INPROGRESS notification" field="disableInprogressNotification">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,31 @@ public class BuildStatusUriFactoryTest {
public void shouldHandleTrailingSlash() {
String baseUri = "http://localhost:12345/";
URI expected = URI.create("http://localhost:12345/rest/build-status/1.0/commits/25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
URI actual = BuildStatusUriFactory.create(baseUri, "25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
URI actual = BuildStatusUriFactory.create(baseUri, "", "","25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
assertThat(actual, equalTo(expected));
}

@Test
public void shouldHandleNoTrailingSlash() {
String baseUri = "http://localhost:12345";
URI expected = URI.create("http://localhost:12345/rest/build-status/1.0/commits/25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
URI actual = BuildStatusUriFactory.create(baseUri, "25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
URI actual = BuildStatusUriFactory.create(baseUri, "","","25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
assertThat(actual, equalTo(expected));
}

@Test
public void shouldHandleBasePathTrailingSlash() {
String baseUri = "http://localhost:12345/some-path/";
URI expected = URI.create("http://localhost:12345/some-path/rest/build-status/1.0/commits/25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
URI actual = BuildStatusUriFactory.create(baseUri, "25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
URI actual = BuildStatusUriFactory.create(baseUri, "","","25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
assertThat(actual, equalTo(expected));
}

@Test
public void shouldHandleBasePathNoTrailingSlash() {
String baseUri = "http://localhost:12345/some-path";
URI expected = URI.create("http://localhost:12345/some-path/rest/build-status/1.0/commits/25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
URI actual = BuildStatusUriFactory.create(baseUri, "25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
URI actual = BuildStatusUriFactory.create(baseUri,"","","25a4b3c9b494fc7ac65b80e3b0ecce63f235f20d");
assertThat(actual, equalTo(expected));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public void before() {

private NotificationResult notifyStash(int statusCode) throws Exception {
PrintStream logger = mock(PrintStream.class);
URI uri = BuildStatusUriFactory.create("http://localhost", "df02f57eea1cda72fa2412102f061dd7f6188e98");
URI uri = BuildStatusUriFactory.create("http://localhost", "","", "df02f57eea1cda72fa2412102f061dd7f6188e98");
when(buildListener.getLogger()).thenReturn(logger);
CloseableHttpResponse resp = mock(CloseableHttpResponse.class);
StatusLine sl = mock(StatusLine.class);
Expand Down
Loading

0 comments on commit 04cf2f9

Please sign in to comment.