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

Fix #77 approve bitbucket PRs when configured. #541

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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 @@ -58,6 +58,7 @@
public class CommunityBranchPlugin implements Plugin, CoreExtension {

public static final String IMAGE_URL_BASE = "com.github.mc1arke.sonarqube.plugin.branch.image-url-base";
public static final String PULL_REQUEST_APPROVE_ENABLED = "com.github.mc1arke.sonarqube.plugin.branch.pullrequest.approve.enabled";

@Override
public String getName() {
Expand Down Expand Up @@ -134,7 +135,14 @@ public void load(CoreExtension.Context context) {
.description("Base URL used to load the images for the PR comments (please use this only if images are not displayed properly).")
.type(PropertyType.STRING)
.build());

context.addExtensions(PropertyDefinition.builder(PULL_REQUEST_APPROVE_ENABLED)
.category(CoreProperties.CATEGORY_ALM_INTEGRATION)
.subCategory("bitbucket")
.type(PropertyType.BOOLEAN)
.defaultValue(String.valueOf(false))
.name("Enable approving pull requests")
.description("This approve pull request when quality gate is passed (if implemented).")
.build());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,12 @@ CodeInsightsReport createCodeInsightsReport(List<ReportData> reportData,
*/
Repository retrieveRepository(String project, String repo) throws IOException;

/**
* Marks the specified pull request as approved by logged user.
* @param approve or not the pull request
* @param project the project as resolved from {@link #resolveProject(AlmSettingDto, ProjectAlmSettingDto)}
* @param repo the repository as resolved from {@link #resolveRepository(AlmSettingDto, ProjectAlmSettingDto)}
* @param prId the branch name
*/
void setApproval(boolean approve, String project, String repository, String prId) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,45 @@ public void uploadReport(String project, String repository, String commit, CodeI
}
}

public void setApproval(boolean approve, String project, String repository, String prId) throws IOException {
if (prId == null) {
return;
}

String reqURL = format("https://api.bitbucket.org/2.0/repositories/%s/%s/pullrequests/%s/approve", project, repository, prId);
// relying on approve response error code we can understand if already
// approved without extra calls on activity resource
if (!approve) {
Request req = new Request.Builder()
.delete()
.url(reqURL)
.build();
try (Response response = okHttpClient.newCall(req).execute()) {
if (response.code() == 404) {
// it is already not approved
LOGGER.info("Pull request {} already disapproved", prId);
} else {
validate(response);
LOGGER.debug("Pull request {} disapproved", prId);
}
}
} else {
Request req = new Request.Builder()
.post(RequestBody.create(new byte[0]))
.url(reqURL)
.build();
try (Response response = okHttpClient.newCall(req).execute()) {
if (response.code() == 409) {
// it is already approved nothing to do
LOGGER.info("Pull request {} already approved", prId);
} else {
validate(response);
LOGGER.debug("Pull request {} approved", prId);
}
}
}
}

@Override
public boolean supportsCodeInsights() {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,45 @@ void validate(Response response) throws IOException {
throw new BitbucketException(response.code(), errors);
}
}
}

@Override
public void setApproval(boolean approve, String project, String repository, String prId) throws IOException {
if (prId == null) {
return;
}

String reqURL = format("%s/rest/api/1.0/projects/%s/repos/%s/pull-requests/%s/approve", config.getUrl(), project, repository, prId);
// relying on approve response error code we can understand if already
// approved without extra calls on activity resource
if (!approve) {
Request req = new Request.Builder()
.delete()
.url(reqURL)
.build();
try (Response response = okHttpClient.newCall(req).execute()) {
if (response.code() == 404) {
// it is already not approved
LOGGER.info("Pull request {} already disapproved", prId);
} else {
validate(response);
LOGGER.debug("Pull request {} disapproved", prId);
}
}
} else {
Request req = new Request.Builder()
.post(RequestBody.create(new byte[0]))
.url(reqURL)
.build();
try (Response response = okHttpClient.newCall(req).execute()) {
if (response.code() == 409) {
// it is already approved nothing to do
LOGGER.info("Pull request {} already approved", prId);
} else {
validate(response);
LOGGER.debug("Pull request {} approved", prId);
}
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ public Map<RuleType, Long> countRuleByType() {
.filter(i -> k == i.type()).count()));
}

public boolean getApproval() {
return configuration.getBoolean(CommunityBranchPlugin.PULL_REQUEST_APPROVE_ENABLED).orElse(false);
}

private static String pluralOf(long value, String singleLabel, String multiLabel) {
return value + " " + (1 == value ? singleLabel : multiLabel);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ public DecorationResult decorateQualityGateStatus(AnalysisDetails analysisDetail
analysisDetails.getCommitSha(), codeInsightsReport);

updateAnnotations(client, project, repo, analysisDetails);

if (analysisDetails.getApproval()) {
String prId = analysisDetails.getBranchName();
client.setApproval(QualityGate.Status.ERROR != analysisDetails.getQualityGateStatus(), project, repo, prId);
}
} catch (IOException e) {
LOGGER.error("Could not decorate pull request for project {}", analysisDetails.getAnalysisProjectKey(), e);
}
Expand Down