aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2022-03-18 14:34:51 -0500
committersonartech <sonartech@sonarsource.com>2022-03-23 20:02:45 +0000
commita9f41cbcedaed97174740ebb5dbcf110b2d4617b (patch)
tree76c4936b811ce21932b93c4b02ab8ab90cbaafbe
parentb9fb568ae65b2bff724452a756ce93040dfd40db (diff)
downloadsonarqube-a9f41cbcedaed97174740ebb5dbcf110b2d4617b.tar.gz
sonarqube-a9f41cbcedaed97174740ebb5dbcf110b2d4617b.zip
SONAR-16162 Enable New Code based on "reference branch" with a scanner parameter
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java10
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ReferenceBranchSupplier.java38
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java20
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java59
-rw-r--r--sonar-scanner-protocol/src/main/protobuf/scanner_report.proto2
5 files changed, 110 insertions, 19 deletions
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
index 12e402f2edd..f0b8c0713a3 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
@@ -37,6 +37,7 @@ import org.sonar.scanner.fs.InputModuleHierarchy;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Metadata.BranchType;
import org.sonar.scanner.protocol.output.ScannerReportWriter;
+import org.sonar.scanner.repository.ReferenceBranchSupplier;
import org.sonar.scanner.rule.QProfile;
import org.sonar.scanner.rule.QualityProfiles;
import org.sonar.scanner.scan.branch.BranchConfiguration;
@@ -57,10 +58,11 @@ public class MetadataPublisher implements ReportPublisherStep {
private final ScmRevision scmRevision;
private final InputComponentStore componentStore;
private final ScmConfiguration scmConfiguration;
+ private final ReferenceBranchSupplier referenceBranchSupplier;
public MetadataPublisher(ProjectInfo projectInfo, InputModuleHierarchy moduleHierarchy, QualityProfiles qProfiles,
CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration,
- ScmRevision scmRevision, InputComponentStore componentStore, ScmConfiguration scmConfiguration) {
+ ScmRevision scmRevision, InputComponentStore componentStore, ScmConfiguration scmConfiguration, ReferenceBranchSupplier referenceBranchSupplier) {
this.projectInfo = projectInfo;
this.moduleHierarchy = moduleHierarchy;
this.qProfiles = qProfiles;
@@ -70,6 +72,7 @@ public class MetadataPublisher implements ReportPublisherStep {
this.scmRevision = scmRevision;
this.componentStore = componentStore;
this.scmConfiguration = scmConfiguration;
+ this.referenceBranchSupplier = referenceBranchSupplier;
}
@Override
@@ -88,6 +91,11 @@ public class MetadataPublisher implements ReportPublisherStep {
addBranchInformation(builder);
}
+ String newCodeReferenceBranch = referenceBranchSupplier.getFromProperties();
+ if (newCodeReferenceBranch != null) {
+ builder.setNewCodeReferenceBranch(newCodeReferenceBranch);
+ }
+
addScmInformation(builder);
addNotAnalyzedFileCountsByLanguage(builder);
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ReferenceBranchSupplier.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ReferenceBranchSupplier.java
index f5ca8b165c2..b700fa59ada 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ReferenceBranchSupplier.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/repository/ReferenceBranchSupplier.java
@@ -19,8 +19,10 @@
*/
package org.sonar.scanner.repository;
+import java.util.Optional;
import javax.annotation.CheckForNull;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.config.Configuration;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
@@ -28,16 +30,22 @@ import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.branch.ProjectBranches;
import org.sonarqube.ws.NewCodePeriods;
+import static java.lang.String.format;
+
public class ReferenceBranchSupplier {
private static final Logger LOG = Loggers.get(ReferenceBranchSupplier.class);
private static final String LOG_MSG_WS = "Load New Code definition";
+ private static final String NEW_CODE_PARAM_KEY = "sonar.newCode.referenceBranch";
+ private final Configuration configuration;
private final NewCodePeriodLoader newCodePeriodLoader;
private final BranchConfiguration branchConfiguration;
private final DefaultInputProject project;
private final ProjectBranches branches;
- public ReferenceBranchSupplier(NewCodePeriodLoader newCodePeriodLoader, BranchConfiguration branchConfiguration, DefaultInputProject project, ProjectBranches branches) {
+ public ReferenceBranchSupplier(Configuration configuration, NewCodePeriodLoader newCodePeriodLoader, BranchConfiguration branchConfiguration, DefaultInputProject project,
+ ProjectBranches branches) {
+ this.configuration = configuration;
this.newCodePeriodLoader = newCodePeriodLoader;
this.branchConfiguration = branchConfiguration;
this.project = project;
@@ -51,8 +59,12 @@ public class ReferenceBranchSupplier {
return null;
}
+ return Optional.ofNullable(getFromProperties()).orElseGet(this::loadWs);
+ }
+
+ private String loadWs() {
+ String branchName = getBranchName();
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG_WS);
- String branchName = branchConfiguration.branchName() != null ? branchConfiguration.branchName() : branches.defaultBranchName();
NewCodePeriods.ShowWSResponse newCode = newCodePeriodLoader.load(project.key(), branchName);
profiler.stopInfo();
if (newCode.getType() != NewCodePeriods.NewCodePeriodType.REFERENCE_BRANCH) {
@@ -67,4 +79,26 @@ public class ReferenceBranchSupplier {
return referenceBranchName;
}
+
+ @CheckForNull
+ public String getFromProperties() {
+ // branches will be empty in CE
+ if (branchConfiguration.isPullRequest() || branches.isEmpty()) {
+ return null;
+ }
+
+ Optional<String> value = configuration.get(NEW_CODE_PARAM_KEY);
+ if (value.isPresent()) {
+ String referenceBranchName = value.get();
+ if (getBranchName().equals(referenceBranchName)) {
+ throw new IllegalStateException(format("Reference branch set with '%s' points to the current branch '%s'", NEW_CODE_PARAM_KEY, referenceBranchName));
+ }
+ return referenceBranchName;
+ }
+ return null;
+ }
+
+ private String getBranchName() {
+ return branchConfiguration.branchName() != null ? branchConfiguration.branchName() : branches.defaultBranchName();
+ }
}
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
index 5d8e1967ede..f10faf46a4b 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
@@ -28,7 +28,6 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.time.Instant;
import java.util.Collections;
import java.util.Date;
import java.util.Optional;
@@ -116,7 +115,7 @@ public class MetadataPublisherTest {
scmConfiguration = mock(ScmConfiguration.class);
when(scmConfiguration.provider()).thenReturn(scmProvider);
underTest = new MetadataPublisher(projectInfo, inputModuleHierarchy, qProfiles, cpdSettings,
- pluginRepository, branches, scmRevision, componentStore, scmConfiguration);
+ pluginRepository, branches, scmRevision, componentStore, scmConfiguration, referenceBranchSupplier);
}
@Test
@@ -128,12 +127,13 @@ public class MetadataPublisherTest {
"php", new ScannerPlugin("php", 45678L, null)));
File outputDir = temp.newFolder();
ScannerReportWriter writer = new ScannerReportWriter(outputDir);
-
+ when(referenceBranchSupplier.getFromProperties()).thenReturn("newCodeReference");
underTest.publish(writer);
ScannerReportReader reader = new ScannerReportReader(outputDir);
ScannerReport.Metadata metadata = reader.readMetadata();
assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L);
+ assertThat(metadata.getNewCodeReferenceBranch()).isEqualTo("newCodeReference");
assertThat(metadata.getProjectKey()).isEqualTo("root");
assertThat(metadata.getModulesProjectRelativePathByKeyMap()).containsOnly(entry("module", "modulePath"), entry("root", ""));
assertThat(metadata.getProjectVersion()).isEmpty();
@@ -241,6 +241,20 @@ public class MetadataPublisherTest {
}
@Test
+ public void dont_write_new_code_reference_if_not_specified_in_properties() throws IOException {
+ when(referenceBranchSupplier.get()).thenReturn("ref");
+ when(referenceBranchSupplier.getFromProperties()).thenReturn(null);
+
+ File outputDir = temp.newFolder();
+ underTest.publish(new ScannerReportWriter(outputDir));
+
+ ScannerReportReader reader = new ScannerReportReader(outputDir);
+ ScannerReport.Metadata metadata = reader.readMetadata();
+
+ assertThat(metadata.getNewCodeReferenceBranch()).isEmpty();
+ }
+
+ @Test
public void write_project_basedir() throws Exception {
String path = "some/dir";
Path relativePathFromScmRoot = Paths.get(path);
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java
index ac79dd82557..3b51bd63d61 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/repository/ReferenceBranchSupplierTest.java
@@ -21,20 +21,18 @@ package org.sonar.scanner.repository;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.time.Instant;
+import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.fs.internal.DefaultInputProject;
-import org.sonar.api.batch.scm.ScmProvider;
-import org.sonar.api.notifications.AnalysisWarnings;
+import org.sonar.api.config.Configuration;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scan.branch.BranchType;
import org.sonar.scanner.scan.branch.ProjectBranches;
-import org.sonar.scanner.scm.ScmConfiguration;
import org.sonarqube.ws.NewCodePeriods;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.anyString;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -49,19 +47,21 @@ public class ReferenceBranchSupplierTest {
private final NewCodePeriodLoader newCodePeriodLoader = mock(NewCodePeriodLoader.class);
private final BranchConfiguration branchConfiguration = mock(BranchConfiguration.class);
+ private final Configuration configuration = mock(Configuration.class);
private final DefaultInputProject project = mock(DefaultInputProject.class);
private final ProjectBranches projectBranches = mock(ProjectBranches.class);
- private final ReferenceBranchSupplier referenceBranchSupplier = new ReferenceBranchSupplier(newCodePeriodLoader, branchConfiguration, project, projectBranches);
+ private final ReferenceBranchSupplier referenceBranchSupplier = new ReferenceBranchSupplier(configuration, newCodePeriodLoader, branchConfiguration, project, projectBranches);
@Before
public void setUp() {
when(projectBranches.isEmpty()).thenReturn(false);
when(project.key()).thenReturn(PROJECT_KEY);
when(project.getBaseDir()).thenReturn(BASE_DIR);
+ when(configuration.get("sonar.newCode.referenceBranch")).thenReturn(Optional.empty());
}
@Test
- public void returns_reference_branch_when_set() {
+ public void get_returns_reference_branch_when_set() {
when(branchConfiguration.branchType()).thenReturn(BranchType.BRANCH);
when(branchConfiguration.branchName()).thenReturn(BRANCH_KEY);
when(newCodePeriodLoader.load(PROJECT_KEY, BRANCH_KEY)).thenReturn(createResponse(NewCodePeriods.NewCodePeriodType.REFERENCE_BRANCH, "master"));
@@ -70,7 +70,40 @@ public class ReferenceBranchSupplierTest {
}
@Test
- public void uses_default_branch_if_no_branch_specified() {
+ public void get_uses_scanner_property_with_higher_priority() {
+ when(branchConfiguration.branchType()).thenReturn(BranchType.BRANCH);
+ when(branchConfiguration.branchName()).thenReturn(BRANCH_KEY);
+ when(newCodePeriodLoader.load(PROJECT_KEY, BRANCH_KEY)).thenReturn(createResponse(NewCodePeriods.NewCodePeriodType.REFERENCE_BRANCH, "master"));
+
+ when(configuration.get("sonar.newCode.referenceBranch")).thenReturn(Optional.of("master2"));
+
+ assertThat(referenceBranchSupplier.get()).isEqualTo("master2");
+ }
+
+ @Test
+ public void getFromProperties_uses_scanner_property() {
+ when(branchConfiguration.branchType()).thenReturn(BranchType.BRANCH);
+ when(branchConfiguration.branchName()).thenReturn(BRANCH_KEY);
+ when(configuration.get("sonar.newCode.referenceBranch")).thenReturn(Optional.of("master2"));
+ assertThat(referenceBranchSupplier.getFromProperties()).isEqualTo("master2");
+ }
+
+ @Test
+ public void getFromProperties_returns_null_if_no_property() {
+ assertThat(referenceBranchSupplier.getFromProperties()).isNull();
+ }
+
+ @Test
+ public void getFromProperties_throws_ISE_if_reference_is_the_same_as_branch() {
+ when(branchConfiguration.branchType()).thenReturn(BranchType.BRANCH);
+ when(branchConfiguration.branchName()).thenReturn(BRANCH_KEY);
+
+ when(configuration.get("sonar.newCode.referenceBranch")).thenReturn(Optional.of(BRANCH_KEY));
+ assertThatThrownBy(referenceBranchSupplier::getFromProperties).isInstanceOf(IllegalStateException.class);
+ }
+
+ @Test
+ public void get_uses_default_branch_if_no_branch_specified() {
when(branchConfiguration.branchType()).thenReturn(BranchType.BRANCH);
when(branchConfiguration.branchName()).thenReturn(null);
when(projectBranches.defaultBranchName()).thenReturn("default");
@@ -80,7 +113,7 @@ public class ReferenceBranchSupplierTest {
}
@Test
- public void returns_null_if_no_branches() {
+ public void get_returns_null_if_no_branches() {
when(projectBranches.isEmpty()).thenReturn(true);
assertThat(referenceBranchSupplier.get()).isNull();
@@ -92,7 +125,7 @@ public class ReferenceBranchSupplierTest {
}
@Test
- public void returns_null_if_reference_branch_is_the_branch_being_analyzed() {
+ public void get_returns_null_if_reference_branch_is_the_branch_being_analyzed() {
when(branchConfiguration.branchType()).thenReturn(BranchType.BRANCH);
when(branchConfiguration.branchName()).thenReturn(BRANCH_KEY);
when(newCodePeriodLoader.load(PROJECT_KEY, BRANCH_KEY)).thenReturn(createResponse(NewCodePeriods.NewCodePeriodType.REFERENCE_BRANCH, BRANCH_KEY));
@@ -100,14 +133,14 @@ public class ReferenceBranchSupplierTest {
assertThat(referenceBranchSupplier.get()).isNull();
verify(branchConfiguration, times(2)).branchName();
- verify(branchConfiguration).isPullRequest();
+ verify(branchConfiguration, times(2)).isPullRequest();
verify(newCodePeriodLoader).load(PROJECT_KEY, BRANCH_KEY);
verifyNoMoreInteractions(branchConfiguration);
}
@Test
- public void returns_null_if_pull_request() {
+ public void get_returns_null_if_pull_request() {
when(branchConfiguration.isPullRequest()).thenReturn(true);
assertThat(referenceBranchSupplier.get()).isNull();
@@ -118,7 +151,7 @@ public class ReferenceBranchSupplierTest {
}
@Test
- public void returns_null_if_new_code_period_is_not_ref() {
+ public void get_returns_null_if_new_code_period_is_not_ref() {
when(branchConfiguration.isPullRequest()).thenReturn(true);
when(branchConfiguration.branchName()).thenReturn(BRANCH_KEY);
when(newCodePeriodLoader.load(PROJECT_KEY, BRANCH_KEY)).thenReturn(createResponse(NewCodePeriods.NewCodePeriodType.NUMBER_OF_DAYS, "2"));
diff --git a/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto b/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto
index a6fc6398869..dda0893f219 100644
--- a/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto
+++ b/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto
@@ -60,6 +60,8 @@ message Metadata {
map<string, int32> not_analyzed_files_by_language = 20;
+ string new_code_reference_branch = 21;
+
message QProfile {
string key = 1;
string name = 2;