in scanner reporttags/7.7
@@ -70,6 +70,8 @@ public class ComponentTreeBuilder { | |||
private final Branch branch; | |||
@Nullable | |||
private final SnapshotDto baseAnalysis; | |||
@Nullable | |||
private final String projectVersion; | |||
private final IssueRelocationToRoot issueRelocationToRoot; | |||
private ScannerReport.Component rootComponent; | |||
@@ -81,7 +83,9 @@ public class ComponentTreeBuilder { | |||
Function<String, String> uuidSupplier, | |||
Function<Integer, ScannerReport.Component> scannerComponentSupplier, | |||
Project project, | |||
Branch branch, @Nullable SnapshotDto baseAnalysis, IssueRelocationToRoot issueRelocationToRoot) { | |||
Branch branch, @Nullable SnapshotDto baseAnalysis, | |||
@Nullable String projectVersion, | |||
IssueRelocationToRoot issueRelocationToRoot) { | |||
this.keyGenerator = keyGenerator; | |||
this.publicKeyGenerator = publicKeyGenerator; | |||
@@ -90,6 +94,7 @@ public class ComponentTreeBuilder { | |||
this.project = project; | |||
this.branch = branch; | |||
this.baseAnalysis = baseAnalysis; | |||
this.projectVersion = projectVersion; | |||
this.issueRelocationToRoot = issueRelocationToRoot; | |||
} | |||
@@ -193,7 +198,7 @@ public class ComponentTreeBuilder { | |||
.setDbKey(projectKey) | |||
.setKey(projectPublicKey) | |||
.setStatus(convertStatus(rootComponent.getStatus())) | |||
.setProjectAttributes(new ProjectAttributes(createProjectVersion(rootComponent))) | |||
.setProjectAttributes(new ProjectAttributes(createProjectVersion())) | |||
.setReportAttributes(createAttributesBuilder(rootComponent.getRef(), rootComponent.getProjectRelativePath(), scmBasePath).build()) | |||
.addChildren(children); | |||
setNameAndDescription(rootComponent, builder); | |||
@@ -334,16 +339,12 @@ public class ComponentTreeBuilder { | |||
return project.getName(); | |||
} | |||
private static String nameOfOthers(ScannerReport.Component reportComponent, String defaultName) { | |||
String name = trimToNull(reportComponent.getName()); | |||
return name == null ? defaultName : name; | |||
} | |||
private String createProjectVersion(ScannerReport.Component component) { | |||
String version = trimToNull(component.getVersion()); | |||
if (version != null) { | |||
return version; | |||
private String createProjectVersion() { | |||
String cleanedProjectVersion = trimToNull(this.projectVersion); | |||
if (cleanedProjectVersion != null) { | |||
return cleanedProjectVersion; | |||
} | |||
// FIXME SONAR-11631 code below applies to the analysisVersion, not the project version, fix it | |||
if (baseAnalysis != null) { | |||
return firstNonNull(baseAnalysis.getVersion(), DEFAULT_PROJECT_VERSION); | |||
} |
@@ -90,7 +90,9 @@ public class BuildComponentTreeStep implements ComputationStep { | |||
reportReader::readComponent, | |||
analysisMetadataHolder.getProject(), | |||
analysisMetadataHolder.getBranch(), | |||
baseAnalysis, issueRelocationToRoot); | |||
baseAnalysis, | |||
metadata.getProjectVersion(), | |||
issueRelocationToRoot); | |||
String relativePathFromScmRoot = metadata.getRelativePathFromScmRoot(); | |||
Component reportTreeRoot = builder.buildProject(reportProject, relativePathFromScmRoot); |
@@ -25,6 +25,7 @@ import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.Random; | |||
import java.util.function.Function; | |||
import javax.annotation.Nullable; | |||
import org.junit.Rule; | |||
@@ -65,6 +66,8 @@ public class ComponentTreeBuilderTest { | |||
private static final Function<String, String> UUID_SUPPLIER = (componentKey) -> componentKey + "_uuid"; | |||
private static final EnumSet<ScannerReport.Component.ComponentType> REPORT_TYPES = EnumSet.of(PROJECT, MODULE, DIRECTORY, FILE); | |||
private static final String NO_SCM_BASE_PATH = ""; | |||
// both no project as "" or null should be supported | |||
private static final String NO_PROJECT_VERSION = new Random().nextBoolean() ? "" : null; | |||
private IssueRelocationToRoot issueRelocationToRoot = mock(IssueRelocationToRoot.class); | |||
@Rule | |||
@@ -95,7 +98,7 @@ public class ComponentTreeBuilderTest { | |||
.setProjectRelativePath("src") | |||
.setLines(1)); | |||
try { | |||
call(project); | |||
call(project, NO_SCM_BASE_PATH, null); | |||
fail("Should have thrown a IllegalArgumentException"); | |||
} catch (IllegalArgumentException e) { | |||
assertThat(e).hasMessage("Unsupported component type '" + type + "'"); | |||
@@ -130,8 +133,7 @@ public class ComponentTreeBuilderTest { | |||
.setRef(42) | |||
.setName(nameInReport) | |||
.setDescription(descriptionInReport) | |||
.setVersion("6.5") | |||
.build()); | |||
.build(), NO_SCM_BASE_PATH, "6.5"); | |||
assertThat(root.getUuid()).isEqualTo("generated_K1_uuid"); | |||
assertThat(root.getDbKey()).isEqualTo("generated_K1"); | |||
@@ -149,7 +151,7 @@ public class ComponentTreeBuilderTest { | |||
public void project_name_is_loaded_from_db_if_absent_from_report() { | |||
Component root = call(newBuilder() | |||
.setType(PROJECT) | |||
.build()); | |||
.build(), NO_SCM_BASE_PATH, NO_PROJECT_VERSION); | |||
assertThat(root.getName()).isEqualTo(projectInDb.getName()); | |||
} | |||
@@ -162,7 +164,7 @@ public class ComponentTreeBuilderTest { | |||
.setName(reportName) | |||
.build(); | |||
Component root = newUnderTest(null, true).buildProject(reportProject, NO_SCM_BASE_PATH); | |||
Component root = newUnderTest(null, true, NO_PROJECT_VERSION).buildProject(reportProject, NO_SCM_BASE_PATH); | |||
assertThat(root.getName()).isEqualTo(reportName); | |||
} | |||
@@ -175,7 +177,8 @@ public class ComponentTreeBuilderTest { | |||
.setName(reportName) | |||
.build(); | |||
Component root = newUnderTest(null, false).buildProject(reportProject, NO_SCM_BASE_PATH); | |||
Component root = newUnderTest(null, false, null) | |||
.buildProject(reportProject, NO_SCM_BASE_PATH); | |||
assertThat(root.getName()).isEqualTo(projectInDb.getName()); | |||
} | |||
@@ -185,7 +188,7 @@ public class ComponentTreeBuilderTest { | |||
SnapshotDto baseAnalysis = new SnapshotDto().setVersion("6.5"); | |||
Component root = call(newBuilder() | |||
.setType(PROJECT) | |||
.build(), baseAnalysis); | |||
.build(), baseAnalysis, NO_SCM_BASE_PATH, NO_PROJECT_VERSION); | |||
assertThat(root.getProjectAttributes().getVersion()).isEqualTo("6.5"); | |||
} | |||
@@ -195,8 +198,7 @@ public class ComponentTreeBuilderTest { | |||
SnapshotDto baseAnalysis = new SnapshotDto().setVersion("6.5"); | |||
Component root = call(newBuilder() | |||
.setType(PROJECT) | |||
.setVersion("") | |||
.build(), baseAnalysis); | |||
.build(), baseAnalysis, NO_SCM_BASE_PATH, NO_PROJECT_VERSION); | |||
assertThat(root.getProjectAttributes().getVersion()).isEqualTo("6.5"); | |||
} | |||
@@ -205,7 +207,7 @@ public class ComponentTreeBuilderTest { | |||
public void project_version_is_hardcoded_if_absent_from_report_and_db() { | |||
Component root = call(newBuilder() | |||
.setType(PROJECT) | |||
.build()); | |||
.build(), NO_SCM_BASE_PATH, NO_PROJECT_VERSION); | |||
assertThat(root.getProjectAttributes().getVersion()).isEqualTo("not provided"); | |||
} | |||
@@ -214,7 +216,7 @@ public class ComponentTreeBuilderTest { | |||
public void project_description_is_loaded_from_db_if_absent_from_report() { | |||
Component root = call(newBuilder() | |||
.setType(PROJECT) | |||
.build()); | |||
.build(), NO_SCM_BASE_PATH, NO_PROJECT_VERSION); | |||
assertThat(root.getDescription()).isEqualTo(projectInDb.getDescription()); | |||
} | |||
@@ -227,7 +229,7 @@ public class ComponentTreeBuilderTest { | |||
.setDescription(reportDescription) | |||
.build(); | |||
Component root = newUnderTest(null, true).buildProject(reportProject, NO_SCM_BASE_PATH); | |||
Component root = newUnderTest(null, true, null).buildProject(reportProject, NO_SCM_BASE_PATH); | |||
assertThat(root.getDescription()).isEqualTo(reportDescription); | |||
} | |||
@@ -240,7 +242,7 @@ public class ComponentTreeBuilderTest { | |||
.setDescription(reportDescription) | |||
.build(); | |||
Component root = newUnderTest(null, false).buildProject(reportProject, NO_SCM_BASE_PATH); | |||
Component root = newUnderTest(null, false, null).buildProject(reportProject, NO_SCM_BASE_PATH); | |||
assertThat(root.getDescription()).isEqualTo(projectInDb.getDescription()); | |||
} | |||
@@ -249,7 +251,7 @@ public class ComponentTreeBuilderTest { | |||
public void project_scmPath_is_empty_if_scmBasePath_is_empty() { | |||
Component root = call(newBuilder() | |||
.setType(PROJECT) | |||
.build(), NO_SCM_BASE_PATH); | |||
.build(), NO_SCM_BASE_PATH, NO_PROJECT_VERSION); | |||
assertThat(root.getReportAttributes().getScmPath()).isEmpty(); | |||
} | |||
@@ -269,7 +271,7 @@ public class ComponentTreeBuilderTest { | |||
.setProjectRelativePath("src/js/Foo.js") | |||
.setLines(1)); | |||
Component root = call(project, NO_SCM_BASE_PATH); | |||
Component root = call(project, NO_SCM_BASE_PATH, NO_PROJECT_VERSION); | |||
assertThat(root.getReportAttributes().getScmPath()) | |||
.contains("root"); | |||
@@ -286,7 +288,7 @@ public class ComponentTreeBuilderTest { | |||
ScannerReport.Component project = createProject(); | |||
String scmBasePath = randomAlphabetic(10); | |||
Component root = call(project, scmBasePath); | |||
Component root = call(project, scmBasePath, NO_PROJECT_VERSION); | |||
assertThat(root.getReportAttributes().getScmPath()) | |||
.contains(scmBasePath); | |||
Component directory = root.getChildren().iterator().next(); | |||
@@ -901,25 +903,22 @@ public class ComponentTreeBuilderTest { | |||
} | |||
private Component call(ScannerReport.Component project) { | |||
return call(project, NO_SCM_BASE_PATH); | |||
return call(project, NO_SCM_BASE_PATH, NO_PROJECT_VERSION); | |||
} | |||
private Component call(ScannerReport.Component project, String scmBasePath) { | |||
return newUnderTest(null, true).buildProject(project, scmBasePath); | |||
private Component call(ScannerReport.Component project, String scmBasePath, @Nullable String projectVersion) { | |||
return call(project, null, scmBasePath, projectVersion); | |||
} | |||
private Component call(ScannerReport.Component project, @Nullable SnapshotDto baseAnalysis) { | |||
return call(project, baseAnalysis, NO_SCM_BASE_PATH); | |||
private Component call(ScannerReport.Component project, @Nullable SnapshotDto baseAnalysis, String scmBasePath, @Nullable String projectVersion) { | |||
return newUnderTest(baseAnalysis, true, projectVersion).buildProject(project, scmBasePath); | |||
} | |||
private Component call(ScannerReport.Component project, @Nullable SnapshotDto baseAnalysis, String scmBasePath) { | |||
return newUnderTest(baseAnalysis, true).buildProject(project, scmBasePath); | |||
} | |||
private ComponentTreeBuilder newUnderTest(@Nullable SnapshotDto baseAnalysis, boolean mainBranch) { | |||
private ComponentTreeBuilder newUnderTest(@Nullable SnapshotDto baseAnalysis, boolean mainBranch, @Nullable String projectVersion) { | |||
Branch branch = mock(Branch.class); | |||
when(branch.isMain()).thenReturn(mainBranch); | |||
return new ComponentTreeBuilder(KEY_GENERATOR, PUBLIC_KEY_GENERATOR, UUID_SUPPLIER, scannerComponentProvider, projectInDb, branch, baseAnalysis, | |||
return new ComponentTreeBuilder(KEY_GENERATOR, PUBLIC_KEY_GENERATOR, UUID_SUPPLIER, scannerComponentProvider, | |||
projectInDb, branch, baseAnalysis, projectVersion, | |||
issueRelocationToRoot); | |||
} | |||
@@ -48,8 +48,6 @@ public class ProjectDefinition { | |||
public static final String TESTS_PROPERTY = "sonar.tests"; | |||
public static final String BUILD_DIR_PROPERTY = "sonar.buildDir"; | |||
private static final char SEPARATOR = ','; | |||
private File baseDir; | |||
@@ -149,7 +147,7 @@ public class ProjectDefinition { | |||
return this; | |||
} | |||
public ProjectDefinition setVersion(String s) { | |||
public ProjectDefinition setProjectVersion(String s) { | |||
properties.put(CoreProperties.PROJECT_VERSION_PROPERTY, StringUtils.defaultString(s)); | |||
return this; | |||
} | |||
@@ -191,12 +189,29 @@ public class ProjectDefinition { | |||
return null; | |||
} | |||
/** | |||
* @deprecated since 7.7, use {@link #getOriginalProjectVersion()} instead | |||
*/ | |||
@Deprecated | |||
@CheckForNull | |||
public String getOriginalVersion() { | |||
return properties.get(CoreProperties.PROJECT_VERSION_PROPERTY); | |||
return getOriginalProjectVersion(); | |||
} | |||
/** | |||
* @deprecated since 7.7, use {@link #getProjectVersion()} instead | |||
*/ | |||
@Deprecated | |||
public String getVersion() { | |||
return getProjectVersion(); | |||
} | |||
@CheckForNull | |||
public String getOriginalProjectVersion() { | |||
return properties.get(CoreProperties.PROJECT_VERSION_PROPERTY); | |||
} | |||
public String getProjectVersion() { | |||
String version = properties.get(CoreProperties.PROJECT_VERSION_PROPERTY); | |||
if (StringUtils.isBlank(version)) { | |||
version = "not provided"; |
@@ -43,9 +43,7 @@ public abstract class AbstractProjectOrModule extends DefaultInputComponent { | |||
private final Path baseDir; | |||
private final Path workDir; | |||
private final String name; | |||
private final String version; | |||
private final String originalName; | |||
private final String originalVersion; | |||
private final String description; | |||
private final String keyWithBranch; | |||
private final String branch; | |||
@@ -61,8 +59,6 @@ public abstract class AbstractProjectOrModule extends DefaultInputComponent { | |||
this.workDir = initWorkingDir(definition); | |||
this.name = definition.getName(); | |||
this.originalName = definition.getOriginalName(); | |||
this.version = definition.getVersion(); | |||
this.originalVersion = definition.getOriginalVersion(); | |||
this.description = definition.getDescription(); | |||
this.keyWithBranch = definition.getKeyWithBranch(); | |||
this.branch = definition.getBranch(); | |||
@@ -145,15 +141,6 @@ public abstract class AbstractProjectOrModule extends DefaultInputComponent { | |||
return properties; | |||
} | |||
@CheckForNull | |||
public String getOriginalVersion() { | |||
return originalVersion; | |||
} | |||
public String getVersion() { | |||
return version; | |||
} | |||
@CheckForNull | |||
public String getOriginalName() { | |||
return originalName; |
@@ -66,7 +66,7 @@ public class ProjectBuilderTest { | |||
subProject.setBaseDir(baseDir); | |||
subProject.setWorkDir(new File(baseDir, "target/.sonar")); | |||
subProject.setKey("groupId:parentProjectId"); | |||
subProject.setVersion(root.getOriginalVersion()); | |||
subProject.setProjectVersion(root.getOriginalVersion()); | |||
subProject.setName("Sub Project"); | |||
subProject.setSources("src"); | |||
root.addSubProject(subProject); |
@@ -37,14 +37,14 @@ public class ProjectDefinitionTest { | |||
@Test | |||
public void shouldSetVersion() { | |||
ProjectDefinition def = ProjectDefinition.create(); | |||
def.setVersion("2.0-SNAPSHOT"); | |||
def.setProjectVersion("2.0-SNAPSHOT"); | |||
assertThat(def.getVersion()).isEqualTo("2.0-SNAPSHOT"); | |||
} | |||
@Test | |||
public void shouldSupportNoVersion() { | |||
ProjectDefinition def = ProjectDefinition.create(); | |||
def.setVersion(null); | |||
def.setProjectVersion(null); | |||
assertThat(def.getVersion()).isEqualTo("not provided"); | |||
assertThat(def.getOriginalVersion()).isEqualTo(""); | |||
} |
@@ -42,7 +42,6 @@ public class DefaultInputProjectTest { | |||
def.setName("projectName"); | |||
File baseDir = temp.newFolder(); | |||
def.setBaseDir(baseDir); | |||
def.setVersion("version"); | |||
def.setDescription("desc"); | |||
File workDir = temp.newFolder(); | |||
def.setWorkDir(workDir); | |||
@@ -57,13 +56,11 @@ public class DefaultInputProjectTest { | |||
assertThat(project.getBranch()).isNull(); | |||
assertThat(project.getBaseDir()).isEqualTo(baseDir.toPath()); | |||
assertThat(project.getKeyWithBranch()).isEqualTo("projectKey"); | |||
assertThat(project.getVersion()).isEqualTo("version"); | |||
assertThat(project.getOriginalVersion()).isEqualTo("version"); | |||
assertThat(project.getDescription()).isEqualTo("desc"); | |||
assertThat(project.getWorkDir()).isEqualTo(workDir.toPath()); | |||
assertThat(project.getEncoding()).isEqualTo(Charset.defaultCharset()); | |||
assertThat(project.properties()).hasSize(6); | |||
assertThat(project.properties()).hasSize(5); | |||
assertThat(project.isFile()).isFalse(); | |||
} | |||
@@ -75,7 +72,7 @@ public class DefaultInputProjectTest { | |||
def.setName("projectName"); | |||
File baseDir = temp.newFolder(); | |||
def.setBaseDir(baseDir); | |||
def.setVersion("version"); | |||
def.setProjectVersion("version"); | |||
def.setDescription("desc"); | |||
File workDir = temp.newFolder(); | |||
def.setWorkDir(workDir); |
@@ -22,24 +22,28 @@ package org.sonar.scanner; | |||
import java.time.Clock; | |||
import java.util.Date; | |||
import java.util.Optional; | |||
import javax.annotation.CheckForNull; | |||
import org.picocontainer.Startable; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.config.Configuration; | |||
import org.sonar.api.utils.DateUtils; | |||
import org.sonar.api.utils.MessageException; | |||
import static java.lang.String.format; | |||
/** | |||
* @since 6.3 | |||
* | |||
* | |||
* Immutable after {@link #start()} | |||
*/ | |||
public class ProjectAnalysisInfo implements Startable { | |||
public class ProjectInfo implements Startable { | |||
private final Clock clock; | |||
private Configuration settings; | |||
private Date analysisDate; | |||
private String analysisVersion; | |||
private String projectVersion; | |||
public ProjectAnalysisInfo(Configuration settings, Clock clock) { | |||
public ProjectInfo(Configuration settings, Clock clock) { | |||
this.settings = settings; | |||
this.clock = clock; | |||
} | |||
@@ -48,8 +52,9 @@ public class ProjectAnalysisInfo implements Startable { | |||
return analysisDate; | |||
} | |||
public String analysisVersion() { | |||
return analysisVersion; | |||
@CheckForNull | |||
public String projectVersion() { | |||
return projectVersion; | |||
} | |||
private Date loadAnalysisDate() { | |||
@@ -71,14 +76,23 @@ public class ProjectAnalysisInfo implements Startable { | |||
} | |||
} | |||
private String loadAnalysisVersion() { | |||
return settings.get(CoreProperties.PROJECT_VERSION_PROPERTY).orElse(null); | |||
@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.analysisVersion = loadAnalysisVersion(); | |||
this.projectVersion = loadProjectVersion(); | |||
} | |||
@Override |
@@ -30,19 +30,19 @@ import org.sonar.api.batch.fs.internal.DefaultTextPointer; | |||
import org.sonar.api.batch.fs.internal.DefaultTextRange; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.scan.issue.filter.FilterableIssue; | |||
import org.sonar.scanner.ProjectAnalysisInfo; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Issue; | |||
@ThreadSafe | |||
public class DefaultFilterableIssue implements FilterableIssue { | |||
private final Issue rawIssue; | |||
private final InputComponent component; | |||
private final ProjectAnalysisInfo projectAnalysisInfo; | |||
private final ProjectInfo projectInfo; | |||
private DefaultInputProject project; | |||
public DefaultFilterableIssue(DefaultInputProject project, ProjectAnalysisInfo projectAnalysisInfo, Issue rawIssue, InputComponent component) { | |||
public DefaultFilterableIssue(DefaultInputProject project, ProjectInfo projectInfo, Issue rawIssue, InputComponent component) { | |||
this.project = project; | |||
this.projectAnalysisInfo = projectAnalysisInfo; | |||
this.projectInfo = projectInfo; | |||
this.rawIssue = rawIssue; | |||
this.component = component; | |||
} | |||
@@ -91,7 +91,7 @@ public class DefaultFilterableIssue implements FilterableIssue { | |||
@Override | |||
public Date creationDate() { | |||
return projectAnalysisInfo.analysisDate(); | |||
return projectInfo.analysisDate(); | |||
} | |||
@Override |
@@ -24,7 +24,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputProject; | |||
import org.sonar.api.scan.issue.filter.FilterableIssue; | |||
import org.sonar.api.scan.issue.filter.IssueFilter; | |||
import org.sonar.api.scan.issue.filter.IssueFilterChain; | |||
import org.sonar.scanner.ProjectAnalysisInfo; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.protocol.output.ScannerReport; | |||
/** | |||
@@ -34,20 +34,20 @@ import org.sonar.scanner.protocol.output.ScannerReport; | |||
public class IssueFilters { | |||
private final IssueFilterChain filterChain; | |||
private final DefaultInputProject project; | |||
private final ProjectAnalysisInfo projectAnalysisInfo; | |||
private final ProjectInfo projectInfo; | |||
public IssueFilters(DefaultInputProject project, ProjectAnalysisInfo projectAnalysisInfo, IssueFilter[] exclusionFilters) { | |||
public IssueFilters(DefaultInputProject project, ProjectInfo projectInfo, IssueFilter[] exclusionFilters) { | |||
this.project = project; | |||
this.filterChain = new DefaultIssueFilterChain(exclusionFilters); | |||
this.projectAnalysisInfo = projectAnalysisInfo; | |||
this.projectInfo = projectInfo; | |||
} | |||
public IssueFilters(DefaultInputProject project, ProjectAnalysisInfo projectAnalysisInfo) { | |||
this(project, projectAnalysisInfo, new IssueFilter[0]); | |||
public IssueFilters(DefaultInputProject project, ProjectInfo projectInfo) { | |||
this(project, projectInfo, new IssueFilter[0]); | |||
} | |||
public boolean accept(InputComponent component, ScannerReport.Issue rawIssue) { | |||
FilterableIssue fIssue = new DefaultFilterableIssue(project, projectAnalysisInfo, rawIssue, component); | |||
FilterableIssue fIssue = new DefaultFilterableIssue(project, projectInfo, rawIssue, component); | |||
return filterChain.accept(fIssue); | |||
} | |||
@@ -28,7 +28,7 @@ import javax.annotation.Nullable; | |||
import org.sonar.api.batch.fs.InputComponent; | |||
import org.sonar.api.batch.fs.internal.DefaultInputComponent; | |||
import org.sonar.core.util.CloseableIterator; | |||
import org.sonar.scanner.ProjectAnalysisInfo; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.issue.IssueCache; | |||
import org.sonar.scanner.issue.IssueTransformer; | |||
import org.sonar.scanner.protocol.output.ScannerReport; | |||
@@ -45,17 +45,17 @@ public class IssueTransition { | |||
@Nullable | |||
private final LocalIssueTracking localIssueTracking; | |||
public IssueTransition(InputComponentStore inputComponentCache, ProjectAnalysisInfo projectAnalysisInfo, IssueCache issueCache, ReportPublisher reportPublisher, | |||
@Nullable LocalIssueTracking localIssueTracking) { | |||
public IssueTransition(InputComponentStore inputComponentCache, ProjectInfo projectInfo, IssueCache issueCache, ReportPublisher reportPublisher, | |||
@Nullable LocalIssueTracking localIssueTracking) { | |||
this.inputComponentStore = inputComponentCache; | |||
this.issueCache = issueCache; | |||
this.reportPublisher = reportPublisher; | |||
this.localIssueTracking = localIssueTracking; | |||
this.analysisDate = projectAnalysisInfo.analysisDate(); | |||
this.analysisDate = projectInfo.analysisDate(); | |||
} | |||
public IssueTransition(InputComponentStore inputComponentCache, ProjectAnalysisInfo projectAnalysisInfo, IssueCache issueCache, ReportPublisher reportPublisher) { | |||
this(inputComponentCache, projectAnalysisInfo, issueCache, reportPublisher, null); | |||
public IssueTransition(InputComponentStore inputComponentCache, ProjectInfo projectInfo, IssueCache issueCache, ReportPublisher reportPublisher) { | |||
this(inputComponentCache, projectInfo, issueCache, reportPublisher, null); | |||
} | |||
public void execute() { |
@@ -96,11 +96,6 @@ public class ComponentsPublisher implements ReportPublisherStep { | |||
projectBuilder.setDescription(description); | |||
} | |||
String version = project.getOriginalVersion(); | |||
if (version != null) { | |||
projectBuilder.setVersion(version); | |||
} | |||
writeLinks(project, projectBuilder); | |||
return projectBuilder; | |||
} |
@@ -23,7 +23,6 @@ import java.io.File; | |||
import java.nio.file.Path; | |||
import java.util.LinkedList; | |||
import java.util.Map.Entry; | |||
import java.util.Optional; | |||
import java.util.regex.Pattern; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.batch.fs.internal.AbstractProjectOrModule; | |||
@@ -32,7 +31,7 @@ import org.sonar.api.batch.fs.internal.InputModuleHierarchy; | |||
import org.sonar.api.batch.scm.ScmProvider; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.scanner.ProjectAnalysisInfo; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.bootstrap.ScannerPlugin; | |||
import org.sonar.scanner.bootstrap.ScannerPluginRepository; | |||
import org.sonar.scanner.cpd.CpdSettings; | |||
@@ -45,13 +44,16 @@ import org.sonar.scanner.scan.ScanProperties; | |||
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 { | |||
private static final Logger LOG = Loggers.get(MetadataPublisher.class); | |||
private final ScanProperties properties; | |||
private final QualityProfiles qProfiles; | |||
private final ProjectAnalysisInfo projectAnalysisInfo; | |||
private final ProjectInfo projectInfo; | |||
private final InputModuleHierarchy moduleHierarchy; | |||
private final CpdSettings cpdSettings; | |||
private final ScannerPluginRepository pluginRepository; | |||
@@ -60,10 +62,10 @@ public class MetadataPublisher implements ReportPublisherStep { | |||
@Nullable | |||
private final ScmConfiguration scmConfiguration; | |||
public MetadataPublisher(ProjectAnalysisInfo projectAnalysisInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties, | |||
public MetadataPublisher(ProjectInfo projectInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties, | |||
QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration, | |||
@Nullable ScmConfiguration scmConfiguration) { | |||
this.projectAnalysisInfo = projectAnalysisInfo; | |||
this.projectInfo = projectInfo; | |||
this.moduleHierarchy = moduleHierarchy; | |||
this.properties = properties; | |||
this.qProfiles = qProfiles; | |||
@@ -73,20 +75,21 @@ public class MetadataPublisher implements ReportPublisherStep { | |||
this.scmConfiguration = scmConfiguration; | |||
} | |||
public MetadataPublisher(ProjectAnalysisInfo projectAnalysisInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties, | |||
public MetadataPublisher(ProjectInfo projectInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties, | |||
QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration) { | |||
this(projectAnalysisInfo, moduleHierarchy, properties, qProfiles, cpdSettings, pluginRepository, branchConfiguration, null); | |||
this(projectInfo, moduleHierarchy, properties, qProfiles, cpdSettings, pluginRepository, branchConfiguration, null); | |||
} | |||
@Override | |||
public void publish(ScannerReportWriter writer) { | |||
AbstractProjectOrModule rootProject = moduleHierarchy.root(); | |||
ScannerReport.Metadata.Builder builder = ScannerReport.Metadata.newBuilder() | |||
.setAnalysisDate(projectAnalysisInfo.analysisDate().getTime()) | |||
.setAnalysisDate(projectInfo.analysisDate().getTime()) | |||
// Here we want key without branch | |||
.setProjectKey(rootProject.key()) | |||
.setCrossProjectDuplicationActivated(cpdSettings.isCrossProjectDuplicationEnabled()) | |||
.setRootComponentRef(rootProject.scannerId()); | |||
ofNullable(trimToNull(projectInfo.projectVersion())).ifPresent(builder::setProjectVersion); | |||
properties.organizationKey().ifPresent(builder::setOrganizationKey); | |||
@@ -94,7 +97,7 @@ public class MetadataPublisher implements ReportPublisherStep { | |||
addBranchInformation(builder); | |||
} | |||
Optional.ofNullable(rootProject.getBranch()).ifPresent(builder::setDeprecatedBranch); | |||
ofNullable(rootProject.getBranch()).ifPresent(builder::setDeprecatedBranch); | |||
if (scmConfiguration != null) { | |||
addScmInformation(builder); |
@@ -35,7 +35,7 @@ public class InputProjectProvider extends ProviderAdapter { | |||
private DefaultInputProject project = null; | |||
public DefaultInputProject provide(ProjectBuildersExecutor projectBuildersExecutor, ProjectReactorValidator validator, | |||
ProjectReactor projectReactor, ScannerComponentIdGenerator scannerComponentIdGenerator) { | |||
ProjectReactor projectReactor, ScannerComponentIdGenerator scannerComponentIdGenerator) { | |||
if (project == null) { | |||
// 1 Apply project builders | |||
projectBuildersExecutor.execute(projectReactor); |
@@ -120,11 +120,6 @@ public class ProjectReactorValidator { | |||
validationMessages.add(format("\"%s\" is not a valid project or module key. " | |||
+ "Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", moduleDef.getKey())); | |||
} | |||
String originalVersion = moduleDef.getOriginalVersion(); | |||
if (originalVersion != null && originalVersion.length() > 100) { | |||
validationMessages.add(format("\"%s\" is not a valid version name for module \"%s\". " + | |||
"The maximum length for version numbers is 100 characters.", originalVersion, moduleDef.getKey())); | |||
} | |||
} | |||
private static void validateBranch(List<String> validationMessages, @Nullable String branch) { |
@@ -37,7 +37,7 @@ import org.sonar.core.extension.CoreExtensionsInstaller; | |||
import org.sonar.core.metric.ScannerMetrics; | |||
import org.sonar.core.platform.ComponentContainer; | |||
import org.sonar.scanner.DefaultFileLinesContextFactory; | |||
import org.sonar.scanner.ProjectAnalysisInfo; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.analysis.AnalysisTempFolderProvider; | |||
import org.sonar.scanner.analysis.DefaultAnalysisMode; | |||
import org.sonar.scanner.bootstrap.ExtensionInstaller; | |||
@@ -167,7 +167,7 @@ public class ProjectScanContainer extends ComponentContainer { | |||
ResourceTypes.class, | |||
ProjectReactorValidator.class, | |||
MetricProvider.class, | |||
ProjectAnalysisInfo.class, | |||
ProjectInfo.class, | |||
Storages.class, | |||
new RulesProvider(), | |||
new BranchConfigurationProvider(), |
@@ -30,51 +30,64 @@ import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.config.internal.MapSettings; | |||
import org.sonar.api.utils.MessageException; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
public class ProjectAnalysisInfoTest { | |||
public class ProjectInfoTest { | |||
@Rule | |||
public ExpectedException thrown = ExpectedException.none(); | |||
private MapSettings settings = new MapSettings(); | |||
private Clock clock = mock(Clock.class); | |||
private ProjectInfo underTest = new ProjectInfo(settings.asConfig(), clock); | |||
@Test | |||
public void testSimpleDateTime() { | |||
MapSettings settings = new MapSettings(); | |||
OffsetDateTime date = OffsetDateTime.of(2017, 1, 1, 12, 13, 14, 0, ZoneOffset.ofHours(2)); | |||
settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01T12:13:14+0200"); | |||
settings.appendProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "version"); | |||
Clock clock = mock(Clock.class); | |||
ProjectAnalysisInfo info = new ProjectAnalysisInfo(settings.asConfig(), clock); | |||
info.start(); | |||
OffsetDateTime date = OffsetDateTime.of(2017, 1, 1, 12, 13, 14, 0, ZoneOffset.ofHours(2)); | |||
assertThat(info.analysisDate()).isEqualTo(Date.from(date.toInstant())); | |||
assertThat(info.analysisVersion()).isEqualTo("version"); | |||
underTest.start(); | |||
assertThat(underTest.analysisDate()).isEqualTo(Date.from(date.toInstant())); | |||
assertThat(underTest.projectVersion()).isEqualTo("version"); | |||
} | |||
@Test | |||
public void testSimpleDate() { | |||
MapSettings settings = new MapSettings(); | |||
settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01"); | |||
Clock clock = mock(Clock.class); | |||
ProjectAnalysisInfo info = new ProjectAnalysisInfo(settings.asConfig(), clock); | |||
info.start(); | |||
LocalDate date = LocalDate.of(2017, 1, 1); | |||
settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, "2017-01-01"); | |||
underTest.start(); | |||
assertThat(info.analysisDate()).isEqualTo(Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())); | |||
assertThat(underTest.analysisDate()) | |||
.isEqualTo(Date.from(date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant())); | |||
} | |||
@Test | |||
public void emptyDate() { | |||
MapSettings settings = new MapSettings(); | |||
settings.appendProperty(CoreProperties.PROJECT_DATE_PROPERTY, ""); | |||
settings.appendProperty(CoreProperties.PROJECT_VERSION_PROPERTY, "version"); | |||
Clock clock = mock(Clock.class); | |||
ProjectAnalysisInfo info = new ProjectAnalysisInfo(settings.asConfig(), clock); | |||
thrown.expect(RuntimeException.class); | |||
info.start(); | |||
underTest.start(); | |||
} | |||
@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); | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("\"" + version +"\" is not a valid project version. " + | |||
"The maximum length for version numbers is 100 characters."); | |||
underTest.start(); | |||
} | |||
} |
@@ -24,7 +24,7 @@ import org.junit.Before; | |||
import org.junit.Test; | |||
import org.sonar.api.batch.fs.InputComponent; | |||
import org.sonar.api.batch.fs.internal.DefaultInputProject; | |||
import org.sonar.scanner.ProjectAnalysisInfo; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.protocol.Constants.Severity; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Issue; | |||
import org.sonar.scanner.protocol.output.ScannerReport.TextRange; | |||
@@ -36,14 +36,14 @@ import static org.mockito.Mockito.when; | |||
public class DefaultFilterableIssueTest { | |||
private DefaultFilterableIssue issue; | |||
private DefaultInputProject mockedProject; | |||
private ProjectAnalysisInfo projectAnalysisInfo; | |||
private ProjectInfo projectInfo; | |||
private InputComponent component; | |||
private Issue rawIssue; | |||
@Before | |||
public void setUp() { | |||
mockedProject = mock(DefaultInputProject.class); | |||
projectAnalysisInfo = mock(ProjectAnalysisInfo.class); | |||
projectInfo = mock(ProjectInfo.class); | |||
component = mock(InputComponent.class); | |||
when(component.key()).thenReturn("foo"); | |||
} | |||
@@ -70,9 +70,9 @@ public class DefaultFilterableIssueTest { | |||
@Test | |||
public void testRoundTrip() { | |||
rawIssue = createIssue(); | |||
issue = new DefaultFilterableIssue(mockedProject, projectAnalysisInfo, rawIssue, component); | |||
issue = new DefaultFilterableIssue(mockedProject, projectInfo, rawIssue, component); | |||
when(projectAnalysisInfo.analysisDate()).thenReturn(new Date(10_000)); | |||
when(projectInfo.analysisDate()).thenReturn(new Date(10_000)); | |||
when(mockedProject.key()).thenReturn("projectKey"); | |||
assertThat(issue.componentKey()).isEqualTo(component.key()); | |||
@@ -90,7 +90,7 @@ public class DefaultFilterableIssueTest { | |||
@Test | |||
public void nullValues() { | |||
rawIssue = createIssueWithoutFields(); | |||
issue = new DefaultFilterableIssue(mockedProject, projectAnalysisInfo, rawIssue, component); | |||
issue = new DefaultFilterableIssue(mockedProject, projectInfo, rawIssue, component); | |||
assertThat(issue.line()).isNull(); | |||
assertThat(issue.gap()).isNull(); |
@@ -35,7 +35,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputProject; | |||
import org.sonar.api.batch.fs.internal.TestInputFileBuilder; | |||
import org.sonar.api.utils.DateUtils; | |||
import org.sonar.scanner.ProjectAnalysisInfo; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.protocol.output.FileStructure; | |||
import org.sonar.scanner.protocol.output.ScannerReport; | |||
import org.sonar.scanner.protocol.output.ScannerReport.Component; | |||
@@ -73,8 +73,8 @@ public class ComponentsPublisherTest { | |||
@Test | |||
public void add_components_to_report() throws Exception { | |||
ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); | |||
when(projectAnalysisInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectInfo projectInfo = mock(ProjectInfo.class); | |||
when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectDefinition rootDef = ProjectDefinition.create() | |||
.setKey("foo") | |||
@@ -128,7 +128,6 @@ public class ComponentsPublisherTest { | |||
Component rootProtobuf = reader.readComponent(1); | |||
assertThat(rootProtobuf.getKey()).isEqualTo("foo"); | |||
assertThat(rootProtobuf.getDescription()).isEqualTo("Root description"); | |||
assertThat(rootProtobuf.getVersion()).isEqualTo("1.0"); | |||
assertThat(rootProtobuf.getLinkCount()).isEqualTo(0); | |||
assertThat(reader.readComponent(4).getStatus()).isEqualTo(FileStatus.SAME); | |||
@@ -138,8 +137,8 @@ public class ComponentsPublisherTest { | |||
@Test | |||
public void should_set_modified_name_with_branch() throws IOException { | |||
ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); | |||
when(projectAnalysisInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectInfo projectInfo = mock(ProjectInfo.class); | |||
when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectDefinition rootDef = ProjectDefinition.create() | |||
.setKey("foo") | |||
@@ -162,8 +161,8 @@ public class ComponentsPublisherTest { | |||
@Test | |||
public void publish_unchanged_components_even_in_short_branches() throws IOException { | |||
when(branchConfiguration.isShortOrPullRequest()).thenReturn(true); | |||
ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); | |||
when(projectAnalysisInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectInfo projectInfo = mock(ProjectInfo.class); | |||
when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
Path baseDir = temp.newFolder().toPath(); | |||
ProjectDefinition rootDef = ProjectDefinition.create() | |||
@@ -202,8 +201,8 @@ public class ComponentsPublisherTest { | |||
@Test | |||
public void publish_project_without_version_and_name() throws IOException { | |||
ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); | |||
when(projectAnalysisInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectInfo projectInfo = mock(ProjectInfo.class); | |||
when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectDefinition rootDef = ProjectDefinition.create() | |||
.setKey("foo") | |||
@@ -223,14 +222,13 @@ public class ComponentsPublisherTest { | |||
assertThat(rootProtobuf.getKey()).isEqualTo("foo"); | |||
assertThat(rootProtobuf.getName()).isEqualTo(""); | |||
assertThat(rootProtobuf.getDescription()).isEqualTo("Root description"); | |||
assertThat(rootProtobuf.getVersion()).isEqualTo(""); | |||
assertThat(rootProtobuf.getLinkCount()).isEqualTo(0); | |||
} | |||
@Test | |||
public void publish_project_with_links_and_branch() throws Exception { | |||
ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); | |||
when(projectAnalysisInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectInfo projectInfo = mock(ProjectInfo.class); | |||
when(projectInfo.analysisDate()).thenReturn(DateUtils.parseDate("2012-12-12")); | |||
ProjectDefinition rootDef = ProjectDefinition.create() | |||
.setKey("foo") | |||
@@ -250,7 +248,6 @@ public class ComponentsPublisherTest { | |||
ScannerReportReader reader = new ScannerReportReader(outputDir); | |||
Component rootProtobuf = reader.readComponent(1); | |||
assertThat(rootProtobuf.getVersion()).isEqualTo("1.0"); | |||
assertThat(rootProtobuf.getLinkCount()).isEqualTo(2); | |||
assertThat(rootProtobuf.getLink(0).getType()).isEqualTo(ComponentLinkType.HOME); | |||
assertThat(rootProtobuf.getLink(0).getHref()).isEqualTo("http://home"); |
@@ -20,6 +20,9 @@ | |||
package org.sonar.scanner.report; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.tngtech.java.junit.dataprovider.DataProvider; | |||
import com.tngtech.java.junit.dataprovider.DataProviderRunner; | |||
import com.tngtech.java.junit.dataprovider.UseDataProvider; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.file.Files; | |||
@@ -28,17 +31,19 @@ import java.nio.file.Paths; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import java.util.Optional; | |||
import javax.annotation.Nullable; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.junit.runner.RunWith; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.batch.bootstrap.ProjectDefinition; | |||
import org.sonar.api.batch.fs.internal.DefaultInputModule; | |||
import org.sonar.api.batch.fs.internal.InputModuleHierarchy; | |||
import org.sonar.api.batch.fs.internal.TestInputFileBuilder; | |||
import org.sonar.api.batch.scm.ScmProvider; | |||
import org.sonar.scanner.ProjectAnalysisInfo; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.bootstrap.ScannerPlugin; | |||
import org.sonar.scanner.bootstrap.ScannerPluginRepository; | |||
import org.sonar.scanner.cpd.CpdSettings; | |||
@@ -60,6 +65,7 @@ import static org.mockito.ArgumentMatchers.any; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
@RunWith(DataProviderRunner.class) | |||
public class MetadataPublisherTest { | |||
@Rule | |||
@@ -69,7 +75,7 @@ public class MetadataPublisherTest { | |||
private MetadataPublisher underTest; | |||
private ScanProperties properties = mock(ScanProperties.class); | |||
private QualityProfiles qProfiles = mock(QualityProfiles.class); | |||
private ProjectAnalysisInfo projectAnalysisInfo = mock(ProjectAnalysisInfo.class); | |||
private ProjectInfo projectInfo = mock(ProjectInfo.class); | |||
private CpdSettings cpdSettings = mock(CpdSettings.class); | |||
private InputModuleHierarchy inputModuleHierarchy; | |||
private ScannerPluginRepository pluginRepository = mock(ScannerPluginRepository.class); | |||
@@ -79,7 +85,7 @@ public class MetadataPublisherTest { | |||
@Before | |||
public void prepare() throws IOException { | |||
when(projectAnalysisInfo.analysisDate()).thenReturn(new Date(1234567L)); | |||
when(projectInfo.analysisDate()).thenReturn(new Date(1234567L)); | |||
when(scmProvider.relativePathFromScmRoot(any(Path.class))).thenReturn(Paths.get("dummy/path")); | |||
when(scmProvider.revisionId(any(Path.class))).thenReturn("dummy-sha1"); | |||
@@ -107,7 +113,7 @@ public class MetadataPublisherTest { | |||
branches = mock(BranchConfiguration.class); | |||
scmConfiguration = mock(ScmConfiguration.class); | |||
when(scmConfiguration.provider()).thenReturn(scmProvider); | |||
underTest = new MetadataPublisher(projectAnalysisInfo, inputModuleHierarchy, properties, qProfiles, cpdSettings, | |||
underTest = new MetadataPublisher(projectInfo, inputModuleHierarchy, properties, qProfiles, cpdSettings, | |||
pluginRepository, branches, scmConfiguration); | |||
} | |||
@@ -180,6 +186,31 @@ public class MetadataPublisherTest { | |||
assertThat(metadata.getOrganizationKey()).isEqualTo("SonarSource"); | |||
} | |||
@Test | |||
@UseDataProvider("projectVersions") | |||
public void write_project_version(@Nullable String projectVersion, String expected) throws Exception { | |||
when(projectInfo.projectVersion()).thenReturn(projectVersion); | |||
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.getProjectVersion()).isEqualTo(expected); | |||
} | |||
@DataProvider | |||
public static Object[][] projectVersions() { | |||
return new Object[][] { | |||
{null, ""}, | |||
{"", ""}, | |||
{"5.6.3", "5.6.3"} | |||
}; | |||
} | |||
@Test | |||
public void write_long_lived_branch_info() throws Exception { | |||
String branchName = "long-lived"; |
@@ -19,96 +19,83 @@ | |||
*/ | |||
package org.sonar.scanner.scan; | |||
import com.tngtech.java.junit.dataprovider.DataProvider; | |||
import com.tngtech.java.junit.dataprovider.DataProviderRunner; | |||
import com.tngtech.java.junit.dataprovider.UseDataProvider; | |||
import java.util.Arrays; | |||
import java.util.function.Consumer; | |||
import java.util.Optional; | |||
import java.util.function.Consumer; | |||
import org.junit.Before; | |||
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.batch.AnalysisMode; | |||
import org.sonar.api.batch.bootstrap.ProjectDefinition; | |||
import org.sonar.api.batch.bootstrap.ProjectReactor; | |||
import org.sonar.api.utils.MessageException; | |||
import org.sonar.core.config.ScannerProperties; | |||
import org.sonar.scanner.ProjectInfo; | |||
import org.sonar.scanner.bootstrap.GlobalConfiguration; | |||
import static org.apache.commons.lang.StringUtils.repeat; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAscii; | |||
import static org.mockito.ArgumentMatchers.anyString; | |||
import static org.mockito.ArgumentMatchers.eq; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
@RunWith(DataProviderRunner.class) | |||
public class ProjectReactorValidatorTest { | |||
@Rule | |||
public ExpectedException thrown = ExpectedException.none(); | |||
private AnalysisMode mode; | |||
private ProjectReactorValidator validator; | |||
private GlobalConfiguration settings; | |||
private AnalysisMode mode = mock(AnalysisMode.class); | |||
private GlobalConfiguration settings = mock(GlobalConfiguration.class); | |||
private ProjectInfo projectInfo = mock(ProjectInfo.class); | |||
private ProjectReactorValidator underTest = new ProjectReactorValidator(mode, settings); | |||
@Before | |||
public void prepare() { | |||
mode = mock(AnalysisMode.class); | |||
settings = mock(GlobalConfiguration.class); | |||
when(settings.get(anyString())).thenReturn(Optional.empty()); | |||
validator = new ProjectReactorValidator(mode, settings); | |||
} | |||
@Test | |||
public void not_fail_with_valid_key() { | |||
validator.validate(createProjectReactor("foo")); | |||
validator.validate(createProjectReactor("123foo")); | |||
validator.validate(createProjectReactor("foo123")); | |||
validator.validate(createProjectReactor("1Z3")); | |||
validator.validate(createProjectReactor("a123")); | |||
validator.validate(createProjectReactor("123a")); | |||
validator.validate(createProjectReactor("1:2")); | |||
validator.validate(createProjectReactor("3-3")); | |||
validator.validate(createProjectReactor("-:")); | |||
@UseDataProvider("validKeys") | |||
public void not_fail_with_valid_key(String validKey) { | |||
underTest.validate(createProjectReactor(validKey)); | |||
} | |||
@DataProvider | |||
public static Object[][] validKeys() { | |||
return new Object[][] { | |||
{"foo"}, | |||
{"123foo"}, | |||
{"foo123"}, | |||
{"1Z3"}, | |||
{"a123"}, | |||
{"123a"}, | |||
{"1:2"}, | |||
{"3-3"}, | |||
{"-:"}, | |||
{"Foobar2"}, | |||
{"foo.bar"}, | |||
{"foo-bar"}, | |||
{"foo:bar"}, | |||
{"foo_bar"} | |||
}; | |||
} | |||
@Test | |||
public void allow_slash_issues_mode() { | |||
when(mode.isIssues()).thenReturn(true); | |||
validator.validate(createProjectReactor("project/key")); | |||
underTest.validate(createProjectReactor("project/key")); | |||
when(mode.isIssues()).thenReturn(false); | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("is not a valid project or module key"); | |||
validator.validate(createProjectReactor("project/key")); | |||
} | |||
@Test | |||
public void not_fail_with_alphanumeric_key() { | |||
ProjectReactor reactor = createProjectReactor("Foobar2"); | |||
validator.validate(reactor); | |||
} | |||
@Test | |||
public void should_not_fail_with_dot_key() { | |||
ProjectReactor reactor = createProjectReactor("foo.bar"); | |||
validator.validate(reactor); | |||
} | |||
@Test | |||
public void not_fail_with_dash_key() { | |||
ProjectReactor reactor = createProjectReactor("foo-bar"); | |||
validator.validate(reactor); | |||
} | |||
@Test | |||
public void not_fail_with_colon_key() { | |||
ProjectReactor reactor = createProjectReactor("foo:bar"); | |||
validator.validate(reactor); | |||
} | |||
@Test | |||
public void not_fail_with_underscore_key() { | |||
ProjectReactor reactor = createProjectReactor("foo_bar"); | |||
validator.validate(reactor); | |||
underTest.validate(createProjectReactor("project/key")); | |||
} | |||
@Test | |||
@@ -117,7 +104,7 @@ public class ProjectReactorValidatorTest { | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("\"foo$bar\" is not a valid project or module key"); | |||
validator.validate(reactor); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
@@ -126,33 +113,46 @@ public class ProjectReactorValidatorTest { | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("\"foo\\bar\" is not a valid project or module key"); | |||
validator.validate(reactor); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
public void not_fail_with_valid_branch() { | |||
validator.validate(createProjectReactor("foo", "branch")); | |||
validator.validate(createProjectReactor("foo", "Branch2")); | |||
validator.validate(createProjectReactor("foo", "bra.nch")); | |||
validator.validate(createProjectReactor("foo", "bra-nch")); | |||
validator.validate(createProjectReactor("foo", "1")); | |||
validator.validate(createProjectReactor("foo", "bra_nch")); | |||
@UseDataProvider("validBranches") | |||
public void not_fail_with_valid_branch(String validBranch) { | |||
ProjectReactor reactor = createProjectReactor("foo", validBranch); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
public void fail_with_invalid_branch() { | |||
ProjectReactor reactor = createProjectReactor("foo", "bran#ch"); | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("\"bran#ch\" is not a valid branch name"); | |||
validator.validate(reactor); | |||
@DataProvider | |||
public static Object[][] validBranches() { | |||
return new Object[][] { | |||
{"branch"}, | |||
{"Branch2"}, | |||
{"bra.nch"}, | |||
{"bra-nch"}, | |||
{"1"}, | |||
{"bra_nch"} | |||
}; | |||
} | |||
@Test | |||
public void fail_with_colon_in_branch() { | |||
ProjectReactor reactor = createProjectReactor("foo", "bran:ch"); | |||
@UseDataProvider("invalidBranches") | |||
public void fail_with_invalid_branch(String invalidBranch) { | |||
ProjectReactor reactor = createProjectReactor("foo", invalidBranch); | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("\"bran:ch\" is not a valid branch name"); | |||
validator.validate(reactor); | |||
thrown.expectMessage("\"" + invalidBranch + "\" is not a valid branch name"); | |||
underTest.validate(reactor); | |||
} | |||
@DataProvider | |||
public static Object[][] invalidBranches() { | |||
return new Object[][] { | |||
{"bran#ch"}, | |||
{"bran:ch"} | |||
}; | |||
} | |||
@Test | |||
@@ -161,7 +161,8 @@ public class ProjectReactorValidatorTest { | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("\"12345\" is not a valid project or module key"); | |||
validator.validate(reactor); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
@@ -174,7 +175,7 @@ public class ProjectReactorValidatorTest { | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("the branch plugin is required but not installed"); | |||
validator.validate(reactor); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
@@ -187,7 +188,7 @@ public class ProjectReactorValidatorTest { | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("the branch plugin is required but not installed"); | |||
validator.validate(reactor); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
@@ -200,7 +201,7 @@ public class ProjectReactorValidatorTest { | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("the branch plugin is required but not installed"); | |||
validator.validate(reactor); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
@@ -213,7 +214,7 @@ public class ProjectReactorValidatorTest { | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("the branch plugin is required but not installed"); | |||
validator.validate(reactor); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
@@ -226,25 +227,24 @@ public class ProjectReactorValidatorTest { | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("the branch plugin is required but not installed"); | |||
validator.validate(reactor); | |||
} | |||
@Test | |||
public void not_fail_with_valid_version() { | |||
validator.validate(createProjectReactor("foo", def -> def.setVersion("1.0"))); | |||
validator.validate(createProjectReactor("foo", def -> def.setVersion("2017-10-16"))); | |||
validator.validate(createProjectReactor("foo", def -> def.setVersion(repeat("a", 100)))); | |||
underTest.validate(reactor); | |||
} | |||
@Test | |||
public void fail_with_too_long_version() { | |||
ProjectReactor reactor = createProjectReactor("foo", def -> def.setVersion(repeat("a", 101))); | |||
@UseDataProvider("validVersions") | |||
public void not_fail_with_valid_version(String validVersion) { | |||
when(projectInfo.projectVersion()).thenReturn(validVersion); | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\" is not a valid version name for module \"foo\". " + | |||
"The maximum length for version numbers is 100 characters."); | |||
underTest.validate(createProjectReactor("foo")); | |||
} | |||
validator.validate(reactor); | |||
@DataProvider | |||
public static Object[][] validVersions() { | |||
return new Object[][] { | |||
{"1.0"}, | |||
{"2017-10-16"}, | |||
{randomAscii(100)} | |||
}; | |||
} | |||
private ProjectReactor createProjectReactor(String projectKey, String branch) { |
@@ -49,6 +49,8 @@ message Metadata { | |||
string pull_request_key = 14; | |||
map<string, string> modules_project_relative_path_by_key = 15; | |||
string projectVersion = 16; | |||
message QProfile { | |||
string key = 1; | |||
string name = 2; | |||
@@ -108,7 +110,7 @@ message Component { | |||
string language = 6; | |||
repeated int32 child_ref = 7 [packed = true]; | |||
repeated ComponentLink link = 8; | |||
// Only available on PROJECT and MODULE types | |||
// FIXME SONAR-11631 delete this property after deployment on SC of metadata.projectVersion | |||
string version = 9; | |||
// Only available on PROJECT and MODULE types | |||
// TODO rename this property -> moduleKey ? | |||
@@ -121,7 +123,7 @@ message Component { | |||
// Path relative to project base directory | |||
string project_relative_path = 14; | |||
enum ComponentType { | |||
UNSET = 0; | |||
PROJECT = 1; |