]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11631 add sonar.codePeriodVersion scanner property
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 17 Jan 2019 12:21:44 +0000 (13:21 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 11 Feb 2019 08:11:47 +0000 (09:11 +0100)
and pass it in scanner report as Metadata.codePeriodVersion property

sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/ProjectInfo.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/DefaultFilterableIssue.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/tracking/IssueTransition.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/ProjectInfoTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/DefaultFilterableIssueTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ComponentsPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/report/MetadataPublisherTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java
sonar-scanner-protocol/src/main/protobuf/scanner_report.proto

index 09f0c0e991eb7d91a0ec7e16d2a8ffe7ec5da997..f5968db34b099eede1f011149647cb8706486247 100644 (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
index 71c0e77b6923298cf77aade6595741bb85520319..3ae7826629899d34864dd6709264fcf2fa576d7a 100644 (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
index d6c925c6f5068b6d9067cb36345d6cdc3101aef4..8dd8829d9b311a1f5f219053803ab7a9525fe7ff 100644 (file)
@@ -91,7 +91,7 @@ public class DefaultFilterableIssue implements FilterableIssue {
 
   @Override
   public Date creationDate() {
-    return projectInfo.analysisDate();
+    return projectInfo.getAnalysisDate();
   }
 
   @Override
index fb90c7f5a0e8ae0ddf5bcc93ee18c77dde7cb7f4..a111c51f5037420dc99fb78442c8887e350aa7a5 100644 (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) {
index 2c83efeeb9092f6005e28731066342151144b72a..c5fabaed1c943a060754803cc3ed7d66605a0251 100644 (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);
 
index 8c00cd4597b74c251b27cca9c21551249c3c33b4..7bdc75c20b75e83e2c42010c3e06a49b73a7b6bf 100644 (file)
  */
 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)}
+    };
   }
 }
index 3b8a6ee26d9dd37779e59ade872be0af8709ece3..b506b78f0749f44be3a83933c1cf4b39746fbce8 100644 (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());
index b0d47a569314ef53e12323498de40aab5e3a21eb..41a5c2eeb784628d8450b31fbacb6a5bd47e9cc5 100644 (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")
index 534051a35b259f872d044c87084bd08ba5d14894..cf46878a7dd42c92c06634344e02ebe4babe7568 100644 (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}
     };
   }
 
index f105ce86517c28f3d5dfa42f63f218ec86c40d81..e91ddfa31fb6f0517ba05db4d9dbf893612f8b72 100644 (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)}
index 9c7812eea0246d6f0ad586f38fbbafdfdb358c16..19181f1faf7df7389af997f47fafa459ef76e62d 100644 (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;