Skip to content

Commit

Permalink
Add support for Sonarqube 8.1.0
Browse files Browse the repository at this point in the history
Sonarqube 8.1 removed the concept of short and long lived branches, instead simplifying the setup to either `BRANCH` or `PULL_REQUEST`. This release of Sonarqube also moved the management of Pull Request decoration into a standard User Interface calling a set of 'ALM' services that provide the management of decorators, and the binding of each project to these decorators. However the implementation of these services is not included in the Community Edition of Sonarqube, although the UI is made visible based on the presence of the branch management components provided by this plugin.

This change therefore introduces the services required to support UI components for the management of Pull Request decoration, as well as updating the handling of the configuration and loading of branches to support the removal of the SHORT/LONG branch constructs. As these changes require the reference of classes that were not present in older version of Sonarqube (namely `AlmSettingsDao` and `ProjectAlmSettingsDao`), the compatibility interfaces for these versions have been removed, as well as any methods and classes that existed purely to allow these versions to be supported by this plugin, meaning this version of the plugin is not backwards compatible with previous Sonarqube versions.

Given the standard UI provides a restricted set of fields for creating and binding each Pull Request decorator, some of the patterns that were previously used by this plugin for configuring the decoration of Pull Requests do not fit into this UI, and were awkward to find/manage when moved to another screen in the UI. This results in the configuration for disabling the addition and removing of comments on Merge Requests being removed from the plugin, with the Gitlab decorator removing the deleting of old comments since this was leading to discussion boxes being shown in Gitlab with no content, and the BitBucket decorator removing since it can't work out which user posted comments based purely on the configuration provided by Sonarqube.

To ensure the UI works for all configuration options, the services for configuring and binding Azure DevOps configuration have been included in this change-set, although no decorator currently exists for this ALM, so any project attempting to use this configuration will get a warning appear in the CE logs when attempting to use this decorator. Similarly, as the UI does not provide any options for configuring the URL for the Gitlab API, or the Slug/name of the project on the binding, a `Sensor` has been added into the scanner to detect these properties from injection by the Gitlab CI Runner, as well as injection directly from scanner arguments of `com.github.mc1arke.sonarqube.plugin.branch.pullrequest.gitlab.url` and `com.github.mc1arke.sonarqube.plugin.branch.pullrequest.gitlab.repositorySlug` for the repository URL and repository-name configuration entries.
  • Loading branch information
mc1arke committed Jun 7, 2020
1 parent c3a686f commit 4227d88
Show file tree
Hide file tree
Showing 97 changed files with 4,283 additions and 2,536 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) 2019 Michael Clarke
* Copyright (C) 2020 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 = '7.8'
def sonarqubeVersion = '8.1.0.31237'
def sonarqubeLibDir = "${projectDir}/sonarqube-lib"
def sonarLibraries = "${sonarqubeLibDir}/sonarqube-${sonarqubeVersion}/lib"

Expand Down

Large diffs are not rendered by default.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Michael Clarke
* Copyright (C) 2020 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 @@ -18,7 +18,7 @@
*/
package com.github.mc1arke.sonarqube.plugin.ce;

import org.apache.logging.log4j.util.Strings;
import org.apache.commons.lang.StringUtils;
import org.sonar.ce.task.projectanalysis.analysis.Branch;
import org.sonar.core.component.ComponentKeys;
import org.sonar.db.component.BranchType;
Expand All @@ -27,22 +27,22 @@
/**
* @author Michael Clarke
*/
public class CommunityBranch implements Branch, BranchCompatibility.BranchCompatibilityMajor7.BranchCompatibilityMinor9 {
public class CommunityBranch implements Branch {

private final String name;
private final BranchType branchType;
private final boolean main;
private final String mergeBranchUuid;
private final String referenceBranchUuid;
private final String pullRequestKey;
private final String targetBranchName;

public CommunityBranch(String name, BranchType branchType, boolean main, String mergeBranchUuid,
public CommunityBranch(String name, BranchType branchType, boolean main, String referenceBranchUuid,
String pullRequestKey, String targetBranchName) {
super();
this.name = name;
this.branchType = branchType;
this.main = main;
this.mergeBranchUuid = mergeBranchUuid;
this.referenceBranchUuid = referenceBranchUuid;
this.pullRequestKey = pullRequestKey;
this.targetBranchName = targetBranchName;
}
Expand All @@ -63,13 +63,8 @@ public boolean isMain() {
}

@Override
public boolean isLegacyFeature() {
return false;
}

@Override
public String getMergeBranchUuid() {
return mergeBranchUuid;
public String getReferenceBranchUuid() {
return referenceBranchUuid;
}

@Override
Expand All @@ -91,7 +86,7 @@ public String generateKey(String projectKey, String fileOrDirPath) {
if (null == fileOrDirPath) {
effectiveKey = projectKey;
} else {
effectiveKey = ComponentKeys.createEffectiveKey(projectKey, Strings.trimToNull(fileOrDirPath));
effectiveKey = ComponentKeys.createEffectiveKey(projectKey, StringUtils.trimToNull(fileOrDirPath));
}

if (main) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Michael Clarke
* Copyright (C) 2020 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 @@ -29,6 +29,7 @@
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.server.project.Project;

import javax.annotation.Nonnull;
import java.util.Optional;

/**
Expand All @@ -45,7 +46,7 @@ public CommunityBranchLoaderDelegate(DbClient dbClient, MutableAnalysisMetadataH
}

@Override
public void load(ScannerReport.Metadata metadata) {
public void load(@Nonnull ScannerReport.Metadata metadata) {
Branch branch = load(metadata, metadataHolder.getProject(), dbClient);

metadataHolder.setBranch(branch);
Expand All @@ -67,17 +68,16 @@ private static Branch load(ScannerReport.Metadata metadata, Project project, DbC
throw new IllegalStateException("Could not find main branch");
}
} else {
String targetBranch = StringUtils.trimToNull(metadata.getMergeBranchName());
String targetBranch = StringUtils.trimToNull(metadata.getReferenceBranchName());
ScannerReport.Metadata.BranchType branchType = metadata.getBranchType();
if (null == targetBranchName) {
targetBranchName = targetBranch;
}

if (ScannerReport.Metadata.BranchType.PULL_REQUEST == branchType) {
return createPullRequest(metadata, dbClient, branchName, projectUuid, targetBranch, targetBranchName);
} else if (ScannerReport.Metadata.BranchType.LONG == branchType ||
ScannerReport.Metadata.BranchType.SHORT == branchType) {
return createBranch(dbClient, branchName, projectUuid, targetBranch, branchType, targetBranchName);
} else if (ScannerReport.Metadata.BranchType.BRANCH == branchType) {
return createBranch(dbClient, branchName, projectUuid, targetBranch);
} else {
throw new IllegalStateException(String.format("Invalid branch type '%s'", branchType.name()));
}
Expand All @@ -99,8 +99,7 @@ private static Branch createPullRequest(ScannerReport.Metadata metadata, DbClien
}
}

private static Branch createBranch(DbClient dbClient, String branchName, String projectUuid, String targetBranch,
ScannerReport.Metadata.BranchType branchType, String targetBranchName) {
private static Branch createBranch(DbClient dbClient, String branchName, String projectUuid, String targetBranch) {
String targetUuid;
if (null == targetBranch) {
targetUuid = projectUuid;
Expand All @@ -113,10 +112,9 @@ private static Branch createBranch(DbClient dbClient, String branchName, String
String.format("Could not find target branch '%s' in project", targetBranch));
}
}
return new CommunityBranch(branchName, ScannerReport.Metadata.BranchType.LONG == branchType ? BranchType.LONG :
BranchType.SHORT,
return new CommunityBranch(branchName, BranchType.BRANCH,
findBranchByKey(projectUuid, branchName, dbClient).map(BranchDto::isMain)
.orElse(false), targetUuid, null, targetBranchName);
.orElse(false), targetUuid, null, null);
}

private static Optional<BranchDto> findBranchByUuid(String projectUuid, DbClient dbClient) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 Michael Clarke
* Copyright (C) 2020 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 @@ -20,7 +20,6 @@


import com.github.mc1arke.sonarqube.plugin.CommunityBranchPlugin;
import com.github.mc1arke.sonarqube.plugin.SonarqubeCompatibility;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Document;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.FormatterFactory;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Heading;
Expand All @@ -35,6 +34,7 @@
import org.sonar.api.ce.posttask.Project;
import org.sonar.api.ce.posttask.QualityGate;
import org.sonar.api.ce.posttask.QualityGate.EvaluationStatus;
import org.sonar.api.ce.posttask.ScannerContext;
import org.sonar.api.config.Configuration;
import org.sonar.api.issue.Issue;
import org.sonar.api.measures.CoreMetrics;
Expand Down Expand Up @@ -83,11 +83,12 @@ public class AnalysisDetails {
private final QualityGate qualityGate;
private final Analysis analysis;
private final Project project;
private final ScannerContext scannerContext;
private final Configuration configuration;

AnalysisDetails(BranchDetails branchDetails, PostAnalysisIssueVisitor postAnalysisIssueVisitor,
QualityGate qualityGate, MeasuresHolder measuresHolder, Analysis analysis, Project project,
Configuration configuration, String publicRootURL) {
Configuration configuration, String publicRootURL, ScannerContext scannerContext) {
super();
this.publicRootURL = publicRootURL;
this.branchDetails = branchDetails;
Expand All @@ -96,6 +97,7 @@ public class AnalysisDetails {
this.qualityGate = qualityGate;
this.analysis = analysis;
this.project = project;
this.scannerContext = scannerContext;
this.configuration = configuration;
}

Expand All @@ -119,12 +121,16 @@ public QualityGate.Status getQualityGateStatus() {
return qualityGate.getStatus();
}

public Optional<String> getScannerProperty(String propertyName) {
return Optional.ofNullable(scannerContext.getProperties().get(propertyName));
}

public String createAnalysisSummary(FormatterFactory formatterFactory) {

BigDecimal newCoverage = getNewCoverage().orElse(null);


double coverage = findMeasure(CoreMetrics.COVERAGE_KEY).map(MeasureWrapper::getDoubleValue).orElse(0D);
double coverage = findMeasure(CoreMetrics.COVERAGE_KEY).map(Measure::getDoubleValue).orElse(0D);

BigDecimal newDuplications = findQualityGateCondition(CoreMetrics.NEW_DUPLICATED_LINES_DENSITY_KEY)
.filter(condition -> condition.getStatus() != EvaluationStatus.NO_VALUE)
Expand All @@ -133,7 +139,7 @@ public String createAnalysisSummary(FormatterFactory formatterFactory) {
.orElse(null);

double duplications =
findMeasure(CoreMetrics.DUPLICATED_LINES_DENSITY_KEY).map(MeasureWrapper::getDoubleValue).orElse(0D);
findMeasure(CoreMetrics.DUPLICATED_LINES_DENSITY_KEY).map(Measure::getDoubleValue).orElse(0D);

NumberFormat decimalFormat = new DecimalFormat("#0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH));

Expand Down Expand Up @@ -292,11 +298,10 @@ public List<QualityGate.Condition> findFailedConditions() {
.collect(Collectors.toList());
}

public Optional<MeasureWrapper> findMeasure(String metricKey) {
public Optional<Measure> findMeasure(String metricKey) {
return measuresHolder.getMeasureRepository().getRawMeasure(measuresHolder.getTreeRootHolder().getRoot(),
measuresHolder.getMetricRepository()
.getByKey(metricKey))
.map(MeasureWrapper::new);
.getByKey(metricKey));
}

public Optional<QualityGate.Condition> findQualityGateCondition(String metricKey) {
Expand Down Expand Up @@ -411,23 +416,4 @@ private String getImageName() {
}
}

private static class MeasureWrapper implements SonarqubeCompatibility.Major7.Minor9 {

private final Measure measure;

MeasureWrapper(Measure measure) {
super();
this.measure = measure;
}

Double getDoubleValue() {
try {
return (Double) Measure.class.getDeclaredMethod("getDoubleValue").invoke(measure);
} catch (ReflectiveOperationException ex) {
throw new IllegalStateException("Could not invoke getDoubleValue", ex);
}
}

}

}
Loading

0 comments on commit 4227d88

Please sign in to comment.