Browse Source

SONAR-11631 add sonar.codePeriodVersion scanner property

and pass it in scanner report as Metadata.codePeriodVersion property
tags/7.7
Sébastien Lesaint 5 years ago
parent
commit
c61b59435f

+ 1
- 0
sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java View File

@@ -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

+ 30
- 19
sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java View File

@@ -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

+ 1
- 1
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultFilterableIssue.java View File

@@ -91,7 +91,7 @@ public class DefaultFilterableIssue implements FilterableIssue {

@Override
public Date creationDate() {
return projectInfo.analysisDate();
return projectInfo.getAnalysisDate();
}

@Override

+ 2
- 2
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/IssueTransition.java View File

@@ -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) {

+ 3
- 3
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java View File

@@ -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);


+ 71
- 12
sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java View File

@@ -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)}
};
}
}

+ 1
- 1
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java View File

@@ -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());

+ 5
- 5
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java View File

@@ -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")

+ 34
- 3
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java View File

@@ -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}
};
}


+ 2
- 1
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java View File

@@ -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)}

+ 1
- 0
sonar-scanner-protocol/src/main/protobuf/scanner_report.proto View File

@@ -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;

Loading…
Cancel
Save