Skip to content

Commit

Permalink
#309: Add support for Sonarqube 8.7
Browse files Browse the repository at this point in the history
Sonarqube 8.7 removed the concept of the `OrganizationDto` and removed the reference to this class in the `BranchSupportDelegate` interface, so the `CommunityBranchSupportDelegate` implementation has had to update the relevant method signature, therefore making this version of the plugin binary incompatible with older versions of Sonarqube.

Alongside this, various webservice endpoints for configuring the global ALM definitions have been moved into the Community edition from the commercial Sonarqube editions, so have been removed from this plugin to prevent the bundled definitions conflicting with the plugin versions.

As Sonarqube Community Edition now has direct UI options for configuring Bitbucket Cloud, the relevant endpoints have been introduced for supporting this UI, and the Bitbucket Cloud client used for Pull Request decorating has been updated to use OAuth 2 credential negotiation for authenticating, rather than using the Basic authentication previously used on all requests.
  • Loading branch information
mc1arke committed Mar 6, 2021
1 parent 3d2bd86 commit 9970d5c
Show file tree
Hide file tree
Showing 66 changed files with 773 additions and 1,905 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Michael Clarke
* Copyright (C) 2020-2021 Michael Clarke
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -40,7 +40,7 @@ repositories {
}
}

def sonarqubeVersion = '8.5.0.37579'
def sonarqubeVersion = '8.7.0.41497'
def sonarqubeLibDir = "${projectDir}/sonarqube-lib"
def sonarLibraries = "${sonarqubeLibDir}/sonarqube-${sonarqubeVersion}/lib"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Michael Clarke
* Copyright (C) 2020-2021 Michael Clarke
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -27,25 +27,15 @@
import com.github.mc1arke.sonarqube.plugin.scanner.ScannerPullRequestPropertySensor;
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchFeatureExtension;
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchSupportDelegate;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.AlmSettingsWs;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.CountBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.DeleteAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.DeleteBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.GetBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.ListAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.ListDefinitionsAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.azure.CreateAzureAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.azure.SetAzureBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.azure.UpdateAzureAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.bitbucket.CreateBitbucketAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.bitbucket.SetBitbucketBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.bitbucket.UpdateBitbucketAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.github.CreateGithubAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.github.SetGithubBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.github.UpdateGithubAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.gitlab.CreateGitlabAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.gitlab.SetGitlabBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.gitlab.UpdateGitlabAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetAzureBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetBitbucketBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetBitbucketCloudBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetGithubBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetGitlabBindingAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.CreateBitbucketCloudAction;
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.UpdateBitbucketCloudAction;
import org.sonar.api.CoreProperties;
import org.sonar.api.Plugin;
import org.sonar.api.PropertyType;
Expand Down Expand Up @@ -74,18 +64,14 @@ public void load(CoreExtension.Context context) {
} else if (SonarQubeSide.SERVER == context.getRuntime().getSonarQubeSide()) {
context.addExtensions(CommunityBranchFeatureExtension.class, CommunityBranchSupportDelegate.class,

AlmSettingsWs.class, CountBindingAction.class, DeleteAction.class,
DeleteBindingAction.class, ListAction.class, ListDefinitionsAction.class,
GetBindingAction.class,
CountBindingAction.class,
DeleteBindingAction.class,
SetGithubBindingAction.class,
SetAzureBindingAction.class,
SetBitbucketBindingAction.class,
SetBitbucketCloudBindingAction.class,
SetGitlabBindingAction.class, CreateBitbucketCloudAction.class, UpdateBitbucketCloudAction.class,

CreateGithubAction.class, SetGithubBindingAction.class, UpdateGithubAction.class,

CreateAzureAction.class, SetAzureBindingAction.class, UpdateAzureAction.class,

CreateBitbucketAction.class, SetBitbucketBindingAction.class,
UpdateBitbucketAction.class,

CreateGitlabAction.class, SetGitlabBindingAction.class, UpdateGitlabAction.class,

/* org.sonar.db.purge.PurgeConfiguration uses the value for the this property if it's configured, so it only
needs to be specified here, but doesn't need any additional classes to perform the relevant purge/cleanup
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Michael Clarke
* Copyright (C) 2020-2021 Michael Clarke
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -22,10 +22,12 @@
import org.sonar.db.alm.setting.AlmSettingDto;
import org.sonar.db.alm.setting.ProjectAlmSettingDto;

import java.util.List;

public interface PullRequestBuildStatusDecorator {

DecorationResult decorateQualityGateStatus(AnalysisDetails analysisDetails, AlmSettingDto almSettingDto,
ProjectAlmSettingDto projectAlmSettingDto);

ALM alm();
List<ALM> alm();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Michael Clarke
* Copyright (C) 2020-2021 Michael Clarke
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -156,7 +156,7 @@ public void finished(Context context) {
projectAnalysis.getScannerContext());

PullRequestBuildStatusDecorator pullRequestDecorator = optionalPullRequestDecorator.get();
LOGGER.info("using pull request decorator " + pullRequestDecorator.alm().getId());
LOGGER.info("using pull request decorator " + pullRequestDecorator.getClass().getName());
DecorationResult decorationResult = pullRequestDecorator.decorateQualityGateStatus(analysisDetails, almSettingDto, projectAlmSettingDto);

decorationResult.getPullRequestUrl().ifPresent(pullRequestUrl -> persistPullRequestUrl(pullRequestUrl, projectAnalysis, optionalBranchName.get()));
Expand All @@ -168,7 +168,7 @@ private static Optional<PullRequestBuildStatusDecorator> findCurrentPullRequestS
ALM alm = almSetting.getAlm();

for (PullRequestBuildStatusDecorator pullRequestDecorator : pullRequestDecorators) {
if (alm == pullRequestDecorator.alm()) {
if (pullRequestDecorator.alm().contains(alm)) {
return Optional.of(pullRequestDecorator);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -392,7 +393,7 @@ private static String encodeURI(String uri) throws IOException {
}

@Override
public ALM alm() {
return ALM.AZURE_DEVOPS;
public List<ALM> alm() {
return Collections.singletonList(ALM.AZURE_DEVOPS);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Mathias Åhsberg
* Copyright (C) 2020-2021 Mathias Åhsberg, Michael Clarke
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -25,13 +25,11 @@
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.BitbucketClientFactory;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.BitbucketException;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.AnnotationUploadLimit;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.BitbucketConfiguration;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.CodeInsightsAnnotation;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.CodeInsightsReport;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.DataValue;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.ReportData;
import com.google.common.annotations.VisibleForTesting;

import org.sonar.api.ce.posttask.QualityGate;
import org.sonar.api.issue.Issue;
import org.sonar.api.measures.CoreMetrics;
Expand All @@ -47,6 +45,7 @@
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
Expand All @@ -70,19 +69,16 @@ public class BitbucketPullRequestDecorator implements PullRequestBuildStatusDeco

@Override
public DecorationResult decorateQualityGateStatus(AnalysisDetails analysisDetails, AlmSettingDto almSettingDto, ProjectAlmSettingDto projectAlmSettingDto) {
String project = projectAlmSettingDto.getAlmRepo();
String repo = projectAlmSettingDto.getAlmSlug();
String url = almSettingDto.getUrl();
String token = almSettingDto.getPersonalAccessToken();
BitbucketConfiguration bitbucketConfiguration = new BitbucketConfiguration(url, token, repo, project);

BitbucketClient client = createClient(bitbucketConfiguration);
BitbucketClient client = createClient(almSettingDto, projectAlmSettingDto);
try {
if (!client.supportsCodeInsights()) {
LOGGER.warn("Your Bitbucket instance does not support the Code Insights API.");
return DEFAULT_DECORATION_RESULT;
}

String project = client.resolveProject(almSettingDto, projectAlmSettingDto);
String repo = client.resolveRepository(almSettingDto, projectAlmSettingDto);

CodeInsightsReport codeInsightsReport = client.createCodeInsightsReport(
toReport(client, analysisDetails),
reportDescription(analysisDetails),
Expand All @@ -104,13 +100,13 @@ public DecorationResult decorateQualityGateStatus(AnalysisDetails analysisDetail
}

@VisibleForTesting
BitbucketClient createClient(BitbucketConfiguration bitbucketConfiguration) {
return BitbucketClientFactory.createClient(bitbucketConfiguration);
BitbucketClient createClient(AlmSettingDto almSettingDto, ProjectAlmSettingDto projectAlmSettingDto) {
return BitbucketClientFactory.createClient(almSettingDto, projectAlmSettingDto);
}

@Override
public ALM alm() {
return ALM.BITBUCKET;
public List<ALM> alm() {
return Arrays.asList(ALM.BITBUCKET, ALM.BITBUCKET_CLOUD);
}

private List<ReportData> toReport(BitbucketClient client, AnalysisDetails analysisDetails) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Marvin Wichmann
* Copyright (C) 2020-2021 Marvin Wichmann, Michael Clarke
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -24,6 +24,8 @@
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.DataValue;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.ReportData;
import org.sonar.api.ce.posttask.QualityGate;
import org.sonar.db.alm.setting.AlmSettingDto;
import org.sonar.db.alm.setting.ProjectAlmSettingDto;

import java.io.IOException;
import java.time.Instant;
Expand Down Expand Up @@ -101,4 +103,24 @@ CodeInsightsReport createCodeInsightsReport(List<ReportData> reportData,
*/
AnnotationUploadLimit getAnnotationUploadLimit();

/**
* Extract the name of the project from the relevant configuration. The project is
* the value that should be used in the calls that take a `project` parameter.
*
* @param almSettingDto the global `AlmSettingDto` containing the global configuration for this ALM
* @param projectAlmSettingDto the `ProjectAlmSettingDto` assigned to the current project
* @return the resolved project name.
*/
String resolveProject(AlmSettingDto almSettingDto, ProjectAlmSettingDto projectAlmSettingDto);

/**
* Extract the name of the repository from the relevant configuration. The project is
* the value that should be used in the calls that take a `repository` parameter.
*
* @param almSettingDto the global `AlmSettingDto` containing the global configuration for this ALM
* @param projectAlmSettingDto the `ProjectAlmSettingDto` assigned to the current project
* @return the resolved repository name.
*/
String resolveRepository(AlmSettingDto almSettingDto, ProjectAlmSettingDto projectAlmSettingDto);

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 Marvin Wichmann
* Copyright (C) 2020-2021 Marvin Wichmann, Michael Clarke
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -21,17 +21,21 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.BitbucketConfiguration;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.cloud.BitbucketCloudConfiguration;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.client.model.server.BitbucketServerConfiguration;
import org.sonar.db.alm.setting.ALM;
import org.sonar.db.alm.setting.AlmSettingDto;
import org.sonar.db.alm.setting.ProjectAlmSettingDto;

public final class BitbucketClientFactory {
private BitbucketClientFactory() {
}

public static BitbucketClient createClient(BitbucketConfiguration bitbucketConfiguration) {
if (bitbucketConfiguration.isCloud()) {
return new BitbucketCloudClient(bitbucketConfiguration, createObjectMapper());
public static BitbucketClient createClient(AlmSettingDto almSettingDto, ProjectAlmSettingDto projectAlmSettingDto) {
if (almSettingDto.getAlm() == ALM.BITBUCKET_CLOUD) {
return new BitbucketCloudClient(new BitbucketCloudConfiguration(almSettingDto.getAppId(), projectAlmSettingDto.getAlmRepo(), almSettingDto.getClientId(), almSettingDto.getClientSecret()), createObjectMapper());
} else {
return new BitbucketServerClient(bitbucketConfiguration, createObjectMapper());
return new BitbucketServerClient(new BitbucketServerConfiguration(projectAlmSettingDto.getAlmRepo(), projectAlmSettingDto.getAlmSlug(), almSettingDto.getUrl(), almSettingDto.getPersonalAccessToken()), createObjectMapper());
}
}

Expand Down
Loading

0 comments on commit 9970d5c

Please sign in to comment.