diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2019-01-17 13:21:44 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2019-02-11 09:11:47 +0100 |
commit | c61b59435f65f5ed67b4de6f22210fe568c7316d (patch) | |
tree | f6cc72c54d4d67e0f4832a757eaa7e467aff173c | |
parent | c0594dbcdf5d269ffe97da68faed6fec9e2e072e (diff) | |
download | sonarqube-c61b59435f65f5ed67b4de6f22210fe568c7316d.tar.gz sonarqube-c61b59435f65f5ed67b4de6f22210fe568c7316d.zip |
SONAR-11631 add sonar.codePeriodVersion scanner property
and pass it in scanner report as Metadata.codePeriodVersion property
11 files changed, 151 insertions, 47 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java index 09f0c0e991e..f5968db34b0 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java @@ -146,6 +146,7 @@ public interface CoreProperties { @Deprecated String PROJECT_BRANCH_PROPERTY = "sonar.branch"; String PROJECT_VERSION_PROPERTY = "sonar.projectVersion"; + String CODE_PERIOD_VERSION_PROPERTY = "sonar.codePeriodVersion"; /** * @since 2.6 diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java index 71c0e77b692..3ae78266298 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java @@ -22,7 +22,8 @@ package org.sonar.scanner; import java.time.Clock; import java.util.Date; import java.util.Optional; -import javax.annotation.CheckForNull; +import java.util.function.Predicate; +import org.apache.commons.lang.StringUtils; import org.picocontainer.Startable; import org.sonar.api.CoreProperties; import org.sonar.api.config.Configuration; @@ -30,6 +31,8 @@ import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.MessageException; import static java.lang.String.format; +import static org.sonar.api.CoreProperties.CODE_PERIOD_VERSION_PROPERTY; +import static org.sonar.api.CoreProperties.PROJECT_VERSION_PROPERTY; /** * @since 6.3 @@ -42,19 +45,23 @@ public class ProjectInfo implements Startable { private Date analysisDate; private String projectVersion; + private String codePeriodVersion; public ProjectInfo(Configuration settings, Clock clock) { this.settings = settings; this.clock = clock; } - public Date analysisDate() { + public Date getAnalysisDate() { return analysisDate; } - @CheckForNull - public String projectVersion() { - return projectVersion; + public Optional<String> getProjectVersion() { + return Optional.ofNullable(projectVersion); + } + + public Optional<String> getCodePeriodVersion() { + return Optional.ofNullable(codePeriodVersion); } private Date loadAnalysisDate() { @@ -76,23 +83,27 @@ public class ProjectInfo implements Startable { } } - @CheckForNull - private String loadProjectVersion() { - return settings.get(CoreProperties.PROJECT_VERSION_PROPERTY) - .filter(version -> { - if (version.length() > 100) { - throw MessageException.of(format("\"%s\" is not a valid project version. " + - "The maximum length for version numbers is 100 characters.", version)); - } - return true; - }) - .orElse(null); - } - @Override public void start() { this.analysisDate = loadAnalysisDate(); - this.projectVersion = loadProjectVersion(); + this.projectVersion = settings.get(PROJECT_VERSION_PROPERTY) + .map(StringUtils::trimToNull) + .filter(validateVersion("project")) + .orElse(null); + this.codePeriodVersion = settings.get(CODE_PERIOD_VERSION_PROPERTY) + .map(StringUtils::trimToNull) + .filter(validateVersion("codePeriod")) + .orElse(projectVersion); + } + + private static Predicate<String> validateVersion(String versionLabel) { + return version -> { + if (version.length() > 100) { + throw MessageException.of(format("\"%s\" is not a valid %s version. " + + "The maximum length is 100 characters.", version, versionLabel)); + } + return true; + }; } @Override diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultFilterableIssue.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultFilterableIssue.java index d6c925c6f50..8dd8829d9b3 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultFilterableIssue.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultFilterableIssue.java @@ -91,7 +91,7 @@ public class DefaultFilterableIssue implements FilterableIssue { @Override public Date creationDate() { - return projectInfo.analysisDate(); + return projectInfo.getAnalysisDate(); } @Override diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/IssueTransition.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/IssueTransition.java index fb90c7f5a0e..a111c51f503 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/IssueTransition.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/IssueTransition.java @@ -46,12 +46,12 @@ public class IssueTransition { private final LocalIssueTracking localIssueTracking; public IssueTransition(InputComponentStore inputComponentCache, ProjectInfo projectInfo, IssueCache issueCache, ReportPublisher reportPublisher, - @Nullable LocalIssueTracking localIssueTracking) { + @Nullable LocalIssueTracking localIssueTracking) { this.inputComponentStore = inputComponentCache; this.issueCache = issueCache; this.reportPublisher = reportPublisher; this.localIssueTracking = localIssueTracking; - this.analysisDate = projectInfo.analysisDate(); + this.analysisDate = projectInfo.getAnalysisDate(); } public IssueTransition(InputComponentStore inputComponentCache, ProjectInfo projectInfo, IssueCache issueCache, ReportPublisher reportPublisher) { 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 2c83efeeb90..c5fabaed1c9 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 @@ -45,7 +45,6 @@ import org.sonar.scanner.scan.branch.BranchConfiguration; import org.sonar.scanner.scm.ScmConfiguration; import static java.util.Optional.ofNullable; -import static org.apache.commons.lang.StringUtils.trimToNull; public class MetadataPublisher implements ReportPublisherStep { @@ -84,12 +83,13 @@ public class MetadataPublisher implements ReportPublisherStep { public void publish(ScannerReportWriter writer) { AbstractProjectOrModule rootProject = moduleHierarchy.root(); ScannerReport.Metadata.Builder builder = ScannerReport.Metadata.newBuilder() - .setAnalysisDate(projectInfo.analysisDate().getTime()) + .setAnalysisDate(projectInfo.getAnalysisDate().getTime()) // Here we want key without branch .setProjectKey(rootProject.key()) .setCrossProjectDuplicationActivated(cpdSettings.isCrossProjectDuplicationEnabled()) .setRootComponentRef(rootProject.scannerId()); - ofNullable(trimToNull(projectInfo.projectVersion())).ifPresent(builder::setProjectVersion); + projectInfo.getProjectVersion().ifPresent(builder::setProjectVersion); + projectInfo.getCodePeriodVersion().ifPresent(builder::setCodePeriodVersion); properties.organizationKey().ifPresent(builder::setOrganizationKey); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java index 8c00cd4597b..7bdc75c20b7 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java @@ -19,15 +19,21 @@ */ package org.sonar.scanner; +import com.tngtech.java.junit.dataprovider.DataProvider; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.time.Clock; import java.time.LocalDate; import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.util.Date; +import javax.annotation.Nullable; +import org.apache.commons.lang.RandomStringUtils; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; import org.sonar.api.CoreProperties; import org.sonar.api.config.internal.MapSettings; import org.sonar.api.utils.MessageException; @@ -36,10 +42,11 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +@RunWith(DataProviderRunner.class) public class ProjectInfoTest { @Rule - public ExpectedException thrown = ExpectedException.none(); + public ExpectedException expectedException = ExpectedException.none(); private MapSettings settings = new MapSettings(); private Clock clock = mock(Clock.class); @@ -53,8 +60,8 @@ public class ProjectInfoTest { underTest.start(); - assertThat(underTest.analysisDate()).isEqualTo(Date.from(date.toInstant())); - assertThat(underTest.projectVersion()).isEqualTo("version"); + assertThat(underTest.getAnalysisDate()).isEqualTo(Date.from(date.toInstant())); + assertThat(underTest.getProjectVersion()).contains("version"); } @Test @@ -64,16 +71,16 @@ public class ProjectInfoTest { underTest.start(); - assertThat(underTest.analysisDate()) + assertThat(underTest.getAnalysisDate()) .isEqualTo(Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())); } @Test public void emptyDate() { - settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, ""); - settings.appendProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "version"); + settings.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, ""); + settings.setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "version"); - thrown.expect(RuntimeException.class); + expectedException.expect(RuntimeException.class); underTest.start(); } @@ -81,13 +88,65 @@ public class ProjectInfoTest { @Test public void fail_with_too_long_version() { String version = randomAlphabetic(101); - settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01"); - settings.appendProperty(CoreProperties.PROJECT_VERSION_PROPERTY, version); + settings.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01"); + settings.setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, version); + + expectedException.expect(MessageException.class); + expectedException.expectMessage("\"" + version + "\" is not a valid project version. " + + "The maximum length is 100 characters."); + + underTest.start(); + } + + @Test + @UseDataProvider("projectVersions") + public void getCodePeriodVersion_has_value_of_projectVersion_if_property_is_unset(@Nullable String projectVersion) { + settings.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01"); + settings.setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, projectVersion); + + underTest.start(); + + if (projectVersion == null) { + assertThat(underTest.getCodePeriodVersion()).isEmpty(); + } else { + assertThat(underTest.getCodePeriodVersion()).contains(projectVersion); + } + } - thrown.expect(MessageException.class); - thrown.expectMessage("\"" + version +"\" is not a valid project version. " + - "The maximum length for version numbers is 100 characters."); + @Test + @UseDataProvider("projectVersions") + public void getCodePeriodVersion_is_empty_if_property_is_empty(@Nullable String projectVersion) { + settings.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01"); + settings.setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, projectVersion); + settings.setProperty(CoreProperties.CODE_PERIOD_VERSION_PROPERTY, ""); underTest.start(); + + if (projectVersion == null) { + assertThat(underTest.getCodePeriodVersion()).isEmpty(); + } else { + assertThat(underTest.getCodePeriodVersion()).contains(projectVersion); + } + } + + @Test + @UseDataProvider("projectVersions") + public void getCodePeriodVersion_contains_value_of_property(@Nullable String projectVersion) { + String version = RandomStringUtils.randomAlphabetic(10); + settings.setProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01"); + settings.setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, projectVersion); + settings.setProperty(CoreProperties.CODE_PERIOD_VERSION_PROPERTY, version); + + underTest.start(); + + assertThat(underTest.getCodePeriodVersion()).contains(version); + } + + @DataProvider + public static Object[][] projectVersions() { + return new Object[][] { + {null}, + {randomAlphabetic(12)} + }; } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java index 3b8a6ee26d9..b506b78f074 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java @@ -72,7 +72,7 @@ public class DefaultFilterableIssueTest { rawIssue = createIssue(); issue = new DefaultFilterableIssue(mockedProject, projectInfo, rawIssue, component); - when(projectInfo.analysisDate()).thenReturn(new Date(10_000)); + when(projectInfo.getAnalysisDate()).thenReturn(new Date(10_000)); when(mockedProject.key()).thenReturn("projectKey"); assertThat(issue.componentKey()).isEqualTo(component.key()); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java index b0d47a56931..41a5c2eeb78 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java @@ -74,7 +74,7 @@ public class ComponentsPublisherTest { @Test public void add_components_to_report() throws Exception { ProjectInfo projectInfo = mock(ProjectInfo.class); - when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); + when(projectInfo.getAnalysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); ProjectDefinition rootDef = ProjectDefinition.create() .setKey("foo") @@ -138,7 +138,7 @@ public class ComponentsPublisherTest { @Test public void should_set_modified_name_with_branch() throws IOException { ProjectInfo projectInfo = mock(ProjectInfo.class); - when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); + when(projectInfo.getAnalysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); ProjectDefinition rootDef = ProjectDefinition.create() .setKey("foo") @@ -162,7 +162,7 @@ public class ComponentsPublisherTest { public void publish_unchanged_components_even_in_short_branches() throws IOException { when(branchConfiguration.isShortOrPullRequest()).thenReturn(true); ProjectInfo projectInfo = mock(ProjectInfo.class); - when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); + when(projectInfo.getAnalysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); Path baseDir = temp.newFolder().toPath(); ProjectDefinition rootDef = ProjectDefinition.create() @@ -202,7 +202,7 @@ public class ComponentsPublisherTest { @Test public void publish_project_without_version_and_name() throws IOException { ProjectInfo projectInfo = mock(ProjectInfo.class); - when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); + when(projectInfo.getAnalysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); ProjectDefinition rootDef = ProjectDefinition.create() .setKey("foo") @@ -228,7 +228,7 @@ public class ComponentsPublisherTest { @Test public void publish_project_with_links_and_branch() throws Exception { ProjectInfo projectInfo = mock(ProjectInfo.class); - when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); + when(projectInfo.getAnalysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); ProjectDefinition rootDef = ProjectDefinition.create() .setKey("foo") 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 534051a35b2..cf46878a7dd 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 @@ -59,6 +59,7 @@ import org.sonar.scanner.scm.ScmConfiguration; import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; +import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; import static org.mockito.ArgumentMatchers.any; @@ -85,7 +86,7 @@ public class MetadataPublisherTest { @Before public void prepare() throws IOException { - when(projectInfo.analysisDate()).thenReturn(new Date(1234567L)); + when(projectInfo.getAnalysisDate()).thenReturn(new Date(1234567L)); when(scmProvider.relativePathFromScmRoot(any(Path.class))).thenReturn(Paths.get("dummy/path")); when(scmProvider.revisionId(any(Path.class))).thenReturn("dummy-sha1"); @@ -134,6 +135,7 @@ public class MetadataPublisherTest { assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L); assertThat(metadata.getProjectKey()).isEqualTo("root"); assertThat(metadata.getModulesProjectRelativePathByKeyMap()).containsOnly(entry("module", "modulePath"), entry("root", "")); + assertThat(metadata.getProjectVersion()).isEmpty(); assertThat(metadata.getQprofilesPerLanguageMap()).containsOnly(entry("java", org.sonar.scanner.protocol.output.ScannerReport.Metadata.QProfile.newBuilder() .setKey("q1") .setName("Q1") @@ -189,7 +191,7 @@ public class MetadataPublisherTest { @Test @UseDataProvider("projectVersions") public void write_project_version(@Nullable String projectVersion, String expected) throws Exception { - when(projectInfo.projectVersion()).thenReturn(projectVersion); + when(projectInfo.getProjectVersion()).thenReturn(Optional.ofNullable(projectVersion)); when(properties.organizationKey()).thenReturn(Optional.of("SonarSource")); File outputDir = temp.newFolder(); @@ -204,10 +206,39 @@ public class MetadataPublisherTest { @DataProvider public static Object[][] projectVersions() { + String version = randomAlphabetic(15); return new Object[][] { {null, ""}, {"", ""}, - {"5.6.3", "5.6.3"} + {"5.6.3", "5.6.3"}, + {version, version} + }; + } + + @Test + @UseDataProvider("codePeriodVersions") + public void write_codePeriod_version(@Nullable String codePeriodVersion, String expected) throws Exception { + when(projectInfo.getCodePeriodVersion()).thenReturn(Optional.ofNullable(codePeriodVersion)); + when(properties.organizationKey()).thenReturn(Optional.of("SonarSource")); + + File outputDir = temp.newFolder(); + ScannerReportWriter writer = new ScannerReportWriter(outputDir); + + underTest.publish(writer); + + ScannerReportReader reader = new ScannerReportReader(outputDir); + ScannerReport.Metadata metadata = reader.readMetadata(); + assertThat(metadata.getCodePeriodVersion()).isEqualTo(expected); + } + + @DataProvider + public static Object[][] codePeriodVersions() { + String randomVersion = randomAlphabetic(15); + return new Object[][] { + {null, ""}, + {"", ""}, + {"5.6.3", "5.6.3"}, + {randomVersion, randomVersion} }; } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java index f105ce86517..e91ddfa31fb 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java @@ -233,7 +233,7 @@ public class ProjectReactorValidatorTest { @Test @UseDataProvider("validVersions") public void not_fail_with_valid_version(String validVersion) { - when(projectInfo.projectVersion()).thenReturn(validVersion); + when(projectInfo.getProjectVersion()).thenReturn(Optional.ofNullable(validVersion)); underTest.validate(createProjectReactor("foo")); } @@ -241,6 +241,7 @@ public class ProjectReactorValidatorTest { @DataProvider public static Object[][] validVersions() { return new Object[][] { + {null}, {"1.0"}, {"2017-10-16"}, {randomAscii(100)} diff --git a/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto b/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto index 9c7812eea02..19181f1faf7 100644 --- a/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto +++ b/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto @@ -50,6 +50,7 @@ message Metadata { map<string, string> modules_project_relative_path_by_key = 15; string projectVersion = 16; + string codePeriodVersion = 17; message QProfile { string key = 1; |