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

Implemented PullRequest decoration to AzureDevOps server (issue/102 8 1support) #123

Closed
wants to merge 29 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fdb382a
Add support for Sonarqube 8.1.0
mc1arke Feb 2, 2020
a228fc0
[GITLAB] URL needs to point to the GitLab API
tisoft Feb 11, 2020
3dfad7d
[Gitlab] reenable deletion of comments
tisoft Feb 11, 2020
5776c97
[GITLAB] allow overrding of autodetected gitlab ci values
tisoft Feb 12, 2020
edb6e12
[GITLAB] auto config branch/MR
tisoft Feb 12, 2020
4090510
[GITLAB] use same property names as sonar developer edition
tisoft Feb 12, 2020
2d85835
Fix adding discussions for gitlab
uwej711 Jan 14, 2020
9e9c59c
[GITLAB] don't fail, if no new coverage condition is provided
tisoft Feb 12, 2020
cae9131
[GITLAB] support multiple pipelines on a single commit
tisoft Feb 12, 2020
87fc1b5
#90: Use correct field to retrieve Github repository name
ndeitch Feb 20, 2020
5d4b432
[email protected]
Mar 1, 2020
a93110a
[email protected]
Mar 3, 2020
5f327b0
[email protected]
Mar 3, 2020
e04f486
[email protected]
Iloer Mar 6, 2020
3e7d57c
[email protected]
Iloer Mar 8, 2020
b42d8e6
[email protected]
Iloer Mar 10, 2020
174483a
[email protected]
Iloer Mar 10, 2020
05a5224
[email protected]
Iloer Mar 11, 2020
885e1b3
[email protected]
Iloer Mar 11, 2020
e197ff8
[email protected]
Iloer Mar 12, 2020
db4f93e
[email protected]
Iloer Mar 12, 2020
dc9a1cc
[email protected]
Iloer Mar 12, 2020
8670a7f
[email protected]
Iloer Mar 15, 2020
7c6d8a1
[email protected]
Mar 1, 2020
6903c45
Merge branch 'issue/102-8_1support' of https://github.com/Iloer/sonar…
Iloer Mar 16, 2020
fd58369
#102 Add support AzureDevOps PullRequest decoration on SonarQube 8.1 …
Iloer Mar 16, 2020
0289c4f
Merge branch 'issue/102-8_1support' of https://github.com/Iloer/sonar…
Iloer Mar 16, 2020
7401aa3
[email protected]
Iloer Mar 16, 2020
935afff
[email protected]
Iloer Mar 30, 2020
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
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.

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 @@ -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 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, targetBranchName);
} else {
throw new IllegalStateException(String.format("Invalid branch type '%s'", branchType.name()));
}
Expand All @@ -100,7 +100,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) {
String targetBranchName) {
String targetUuid;
if (null == targetBranch) {
targetUuid = projectUuid;
Expand All @@ -113,8 +113,7 @@ 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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.PostAnalysisIssueVisitor;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.PullRequestPostAnalysisTask;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.azuredevops.AzureDevOpsServerPullRequestDecorator;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.github.GithubPullRequestDecorator;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.github.v3.RestApplicationAuthenticationProvider;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.github.v4.GraphqlCheckRunProvider;
Expand All @@ -40,7 +41,8 @@ public List<Object> getComponents() {
return Arrays.asList(CommunityBranchLoaderDelegate.class, PullRequestPostAnalysisTask.class,
PostAnalysisIssueVisitor.class, GithubPullRequestDecorator.class,
GraphqlCheckRunProvider.class, RestApplicationAuthenticationProvider.class,
BitbucketServerPullRequestDecorator.class, GitlabServerPullRequestDecorator.class);
BitbucketServerPullRequestDecorator.class, GitlabServerPullRequestDecorator.class,
AzureDevOpsServerPullRequestDecorator.class);
}

}
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 @@ -19,8 +19,6 @@
package com.github.mc1arke.sonarqube.plugin.ce.pullrequest;


import com.github.mc1arke.sonarqube.plugin.SonarqubeCompatibility;
import org.apache.commons.lang.StringUtils;
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 @@ -30,10 +28,12 @@
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Node;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Paragraph;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.markup.Text;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.ce.posttask.Analysis;
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 All @@ -47,8 +47,11 @@
import org.sonar.core.issue.DefaultIssue;
import org.sonar.server.measure.Rating;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
Expand Down Expand Up @@ -83,10 +86,11 @@ public class AnalysisDetails {
private final Analysis analysis;
private final Project project;
private final Configuration configuration;
private final ScannerContext scannerContext;

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 +100,7 @@ public class AnalysisDetails {
this.analysis = analysis;
this.project = project;
this.configuration = configuration;
this.scannerContext = scannerContext;
}

public String getBranchName() {
Expand All @@ -110,6 +115,10 @@ 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 =
Expand All @@ -119,7 +128,7 @@ public String createAnalysisSummary(FormatterFactory formatterFactory) {
.map(BigDecimal::new)
.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 @@ -128,7 +137,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 @@ -184,8 +193,9 @@ public String createAnalysisSummary(FormatterFactory formatterFactory) {
.map(i -> i + "% Duplicated Code")
.orElse("No duplication information") + " (" +
decimalFormat.format(duplications) +
"% Estimated after merge)"))),
new Link(publicRootURL + "/dashboard?id=" + URLEncoder.encode(project.getKey()) + "&pullRequest=" + branchDetails.getBranchName(), new Text("View in SonarQube")));
"% Estimated after merge)"))), new Link(
publicRootURL + "/dashboard?id=" + encode(project.getKey(), StandardCharsets.UTF_8) + "&pullRequest=" +
branchDetails.getBranchName(), new Text("View in SonarQube")));

return formatterFactory.documentFormatter().format(document, formatterFactory);
}
Expand All @@ -206,9 +216,10 @@ public String createAnalysisIssueSummary(PostAnalysisIssueVisitor.ComponentIssue
new Paragraph(new Text(String.format("**Type:** %s ", issue.type().name())), new Image(issue.type().name(), String.format("%s/checks/IssueType/%s.svg?sanitize=true", baseImageUrl, issue.type().name().toLowerCase()))),
new Paragraph(new Text(String.format("**Severity:** %s ", issue.severity())), new Image(issue.severity(), String.format("%s/checks/Severity/%s.svg?sanitize=true", baseImageUrl, issue.severity().toLowerCase()))),
new Paragraph(new Text(String.format("**Message:** %s", issue.getMessage()))),
effortNode,
resolutionNode,
new Link(publicRootURL + "/project/issues?id=" + URLEncoder.encode(project.getKey()) + "&pullRequest=" + branchDetails.getBranchName() + "&issues=" + issue.key() + "&open=" + issue.key(), new Text("View in SonarQube"))
effortNode, resolutionNode, new Link(
publicRootURL + "/project/issues?id=" + encode(project.getKey(), StandardCharsets.UTF_8) +
"&pullRequest=" + branchDetails.getBranchName() + "&issues=" + issue.key() + "&open=" + issue.key(),
new Text("View in SonarQube"))
);
return formatterFactory.documentFormatter().format(document, formatterFactory);
}
Expand Down Expand Up @@ -276,11 +287,10 @@ private List<QualityGate.Condition> findFailedConditions() {
.collect(Collectors.toList());
}

private Optional<MeasureWrapper> findMeasure(String metricKey) {
private 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 @@ -322,6 +332,14 @@ private static String format(QualityGate.Condition condition) {
}
}

private static String encode(String original, Charset charset) {
try {
return URLEncoder.encode(original, charset.name());
} catch (UnsupportedEncodingException ex) {
throw new IllegalStateException("Could not encode input", ex);
}
}

public static class BranchDetails {

private final String branchName;
Expand Down Expand Up @@ -388,23 +406,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