@@ -236,7 +236,7 @@ subprojects { | |||
dependency 'org.postgresql:postgresql:42.2.5' | |||
dependency 'org.reflections:reflections:0.9.9' | |||
dependency 'org.simpleframework:simple:4.1.21' | |||
dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.24.0.1993' | |||
dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.25.0.2071' | |||
dependency 'org.sonarsource.update-center:sonar-update-center-common:1.18.0.487' | |||
dependency 'org.subethamail:subethasmtp:3.1.7' | |||
dependency 'xml-apis:xml-apis:1.4.01' |
@@ -99,7 +99,6 @@ Key | Description | Default | |||
| ![](/images/cross.svg) These parameters are listed for completeness, but are deprecated and should not be used in new analyses. | |||
Key | Description | |||
---|----|--- | |||
`sonar.branch` **![](/images/cross.svg)Deprecated since SQ 6.7** | _The Developer Edition provides fuller-featured branch functionality._ Manage SCM branches. Two branches of the same project are considered to be different projects in SonarQube. As a consequence issues found in a project A in a branch B1 are not linked to issues found for this project A in a branch B2. There is no way to automatically resolve issues from B2 when they are resolved in B1 as again A-B1 & A-B2 are considered separated projects. | |||
---|----|--- | |||
`sonar.links.scm_dev` **![](/images/cross.svg)Deprecated since SQ 7.1** | Developer connection. | `<scm><developerConnection>` for Maven projects | |||
<!-- /sonarqube --> |
@@ -21,10 +21,6 @@ No, you don't need to be connected to a SCM. But if you use Git or SVN we can be | |||
## What if I mark an Issue "Won't Fix" or "False-Positive" in a branch? | |||
It be replicated as such when merging my short-lived branch into the Master. Each time there is an analysis of a long-lived branch, we look at the issues on the short-lived branches and try to synchronize them with the newly raised issues on the long-lived branch. In case you made some changes on the issues (false-positive, won't fix), these changes will be reported on the long-lived branch. | |||
## Can I still use 'sonar.branch'? | |||
`sonar.branch` is deprecated. You can still use it but it will behave the same way it always has: a separate project will be created. We encourage you to smoothly migrate your users to the new parameter `sonar.branch.name`. | |||
Please note you cannot use `sonar.branch` together with `sonar.branch.name`. | |||
## Can I manually delete a branch? | |||
This can be achieved by going into the Administration menu at Project's level, then Branches. | |||
@@ -93,6 +93,7 @@ public class CreateAction implements ProjectsWsAction { | |||
.setExampleValue("SonarQube"); | |||
action.createParam(PARAM_BRANCH) | |||
.setDeprecatedSince("7.8") | |||
.setDescription("SCM Branch of the project. The key of the project will become key:branch, for instance 'SonarQube:branch-5.0'") | |||
.setExampleValue("branch-5.0"); | |||
@@ -392,6 +392,9 @@ public class CreateActionTest { | |||
WebService.Param name = definition.param(PARAM_NAME); | |||
assertThat(name.isRequired()).isTrue(); | |||
assertThat(name.description()).isEqualTo("Name of the project. If name is longer than 500, it is abbreviated."); | |||
WebService.Param branch = definition.param(PARAM_BRANCH); | |||
assertThat(branch.deprecatedSince()).isNotNull(); | |||
} | |||
private CreateWsResponse call(CreateRequest request) { |
@@ -28,6 +28,7 @@ import org.sonar.api.Plugin; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.SonarQubeSide; | |||
import org.sonar.api.SonarQubeVersion; | |||
import org.sonar.api.SonarRuntime; | |||
import org.sonar.api.internal.MetadataLoader; | |||
import org.sonar.api.internal.SonarRuntimeImpl; | |||
import org.sonar.api.utils.MessageException; | |||
@@ -100,9 +101,7 @@ public class GlobalContainer extends ComponentContainer { | |||
PluginClassloaderFactory.class, | |||
ScannerPluginJarExploder.class, | |||
ExtensionInstaller.class, | |||
new SonarQubeVersion(apiVersion), | |||
SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SCANNER, edition), | |||
new GlobalServerSettingsProvider(), | |||
new GlobalConfigurationProvider(), | |||
new ScannerWsClientProvider(), | |||
@@ -115,6 +114,7 @@ public class GlobalContainer extends ComponentContainer { | |||
Clock.systemDefaultZone(), | |||
new MetricsRepositoryProvider(), | |||
UuidFactoryImpl.INSTANCE); | |||
addIfMissing(SonarRuntimeImpl.forSonarQube(apiVersion, SonarQubeSide.SCANNER, edition), SonarRuntime.class); | |||
addIfMissing(ScannerPluginInstaller.class, PluginInstaller.class); | |||
add(CoreExtensionRepositoryImpl.class, CoreExtensionsLoader.class, ScannerCoreExtensionsInstaller.class); | |||
addIfMissing(DefaultGlobalSettingsLoader.class, GlobalSettingsLoader.class); | |||
@@ -138,7 +138,6 @@ public class GlobalContainer extends ComponentContainer { | |||
if (!analysisMode.equals("publish")) { | |||
throw MessageException.of("The preview mode, along with the 'sonar.analysis.mode' parameter, is no more supported. You should stop using this parameter."); | |||
} | |||
new ProjectScanContainer(this).execute(); | |||
LOG.info("Analysis total time: {}", formatTime(System.currentTimeMillis() - startTime)); |
@@ -21,6 +21,8 @@ package org.sonar.scanner.scan; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.SonarRuntime; | |||
import org.sonar.api.batch.fs.internal.DefaultInputModule; | |||
import org.sonar.api.batch.fs.internal.FileMetadata; | |||
import org.sonar.api.batch.fs.internal.InputModuleHierarchy; | |||
@@ -30,6 +32,7 @@ import org.sonar.api.issue.NoSonarFilter; | |||
import org.sonar.api.resources.Languages; | |||
import org.sonar.api.resources.ResourceTypes; | |||
import org.sonar.api.scan.filesystem.PathResolver; | |||
import org.sonar.api.utils.MessageException; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.core.config.ScannerProperties; | |||
@@ -321,15 +324,22 @@ public class ProjectScanContainer extends ComponentContainer { | |||
GlobalAnalysisMode analysisMode = getComponentByType(GlobalAnalysisMode.class); | |||
InputModuleHierarchy tree = getComponentByType(InputModuleHierarchy.class); | |||
ScanProperties properties = getComponentByType(ScanProperties.class); | |||
SonarRuntime sonarRuntime = getComponentByType(SonarRuntime.class); | |||
properties.validate(); | |||
properties.organizationKey().ifPresent(k -> LOG.info("Organization key: {}", k)); | |||
String branch = tree.root().definition().getBranch(); | |||
if (branch != null) { | |||
LOG.info("Branch key: {}", branch); | |||
LOG.warn("The use of \"sonar.branch\" is deprecated and replaced by \"{}\". See {}.", | |||
ScannerProperties.BRANCH_NAME, ScannerProperties.BRANCHES_DOC_LINK); | |||
if (sonarRuntime.getEdition() == SonarEdition.SONARCLOUD) { | |||
String branch = tree.root().definition().getBranch(); | |||
if (branch != null) { | |||
LOG.info("Branch key: {}", branch); | |||
LOG.warn("The use of \"sonar.branch\" is deprecated and replaced by \"{}\". See {}.", | |||
ScannerProperties.BRANCH_NAME, ScannerProperties.BRANCHES_DOC_LINK); | |||
} | |||
} else { | |||
properties.get("sonar.branch").ifPresent(deprecatedBranch -> { | |||
throw MessageException.of("The 'sonar.branch' parameter is no longer supported. You should stop using it. " + | |||
"Branch analysis is available in Developer Edition and above. See https://redirect.sonarsource.com/editions/developer.html for more information."); | |||
}); | |||
} | |||
BranchConfiguration branchConfig = getComponentByType(BranchConfiguration.class); |
@@ -66,6 +66,10 @@ public class ScanProperties { | |||
return configuration.get(BRANCH_NAME); | |||
} | |||
public Optional<String> get(String propertyKey) { | |||
return configuration.get(propertyKey); | |||
} | |||
public Path metadataFilePath() { | |||
Optional<String> metadataFilePath = configuration.get(METADATA_FILE_PATH_KEY); | |||
if (metadataFilePath.isPresent()) { |
@@ -41,12 +41,17 @@ import javax.annotation.Nullable; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.rules.ExternalResource; | |||
import org.sonar.api.Plugin; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.SonarProduct; | |||
import org.sonar.api.SonarQubeSide; | |||
import org.sonar.api.SonarRuntime; | |||
import org.sonar.api.measures.CoreMetrics; | |||
import org.sonar.api.measures.Metric; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.server.rule.RulesDefinition; | |||
import org.sonar.api.server.rule.RulesDefinition.Repository; | |||
import org.sonar.api.utils.DateUtils; | |||
import org.sonar.api.utils.Version; | |||
import org.sonar.batch.bootstrapper.Batch; | |||
import org.sonar.batch.bootstrapper.EnvironmentInformation; | |||
import org.sonar.batch.bootstrapper.LogOutput; | |||
@@ -89,6 +94,7 @@ public class ScannerMediumTester extends ExternalResource { | |||
private final FakeRulesLoader rulesLoader = new FakeRulesLoader(); | |||
private final FakeQualityProfileLoader qualityProfiles = new FakeQualityProfileLoader(); | |||
private final FakeActiveRulesLoader activeRules = new FakeActiveRulesLoader(); | |||
private final FakeSonarRuntime sonarRuntime = new FakeSonarRuntime(); | |||
private LogOutput logOutput = null; | |||
private static void createWorkingDirs() throws IOException { | |||
@@ -220,7 +226,7 @@ public class ScannerMediumTester extends ExternalResource { | |||
} | |||
@Override | |||
protected void before() throws Throwable { | |||
protected void before() { | |||
try { | |||
createWorkingDirs(); | |||
} catch (IOException e) { | |||
@@ -287,6 +293,7 @@ public class ScannerMediumTester extends ExternalResource { | |||
tester.activeRules, | |||
tester.globalSettingsLoader, | |||
tester.projectSettingsLoader, | |||
tester.sonarRuntime, | |||
result) | |||
.setLogOutput(tester.logOutput) | |||
.build().execute(); | |||
@@ -404,6 +411,39 @@ public class ScannerMediumTester extends ExternalResource { | |||
} | |||
} | |||
private static class FakeSonarRuntime implements SonarRuntime { | |||
private SonarEdition edition; | |||
FakeSonarRuntime() { | |||
this.edition = SonarEdition.COMMUNITY; | |||
} | |||
@Override | |||
public Version getApiVersion() { | |||
return Version.create(7, 8); | |||
} | |||
@Override | |||
public SonarProduct getProduct() { | |||
return SonarProduct.SONARQUBE; | |||
} | |||
@Override | |||
public SonarQubeSide getSonarQubeSide() { | |||
return SonarQubeSide.SCANNER; | |||
} | |||
@Override | |||
public SonarEdition getEdition() { | |||
return edition; | |||
} | |||
public void setEdition(SonarEdition edition) { | |||
this.edition = edition; | |||
} | |||
} | |||
public ScannerMediumTester setBranchType(BranchType branchType) { | |||
branchConfiguration.branchType = branchType; | |||
return this; | |||
@@ -424,6 +464,11 @@ public class ScannerMediumTester extends ExternalResource { | |||
return this; | |||
} | |||
public ScannerMediumTester setEdition(SonarEdition edition) { | |||
this.sonarRuntime.setEdition(edition); | |||
return this; | |||
} | |||
private class FakeBranchConfigurationLoader implements BranchConfigurationLoader { | |||
@Override | |||
public BranchConfiguration load(Map<String, String> localSettings, Supplier<Map<String, String>> settingsSupplier, ProjectBranches branches, ProjectPullRequests pullRequests) { |
@@ -31,9 +31,11 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester; | |||
import org.sonar.api.utils.MessageException; | |||
import org.sonar.scanner.mediumtest.AnalysisResult; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester; | |||
import org.sonar.xoo.XooPlugin; | |||
import org.sonar.xoo.rule.XooRulesDefinition; | |||
@@ -55,6 +57,15 @@ public class DeprecatedBranchMediumTest { | |||
.addActiveRule("xoo", "xoo:OneIssuePerFile", null, "One Issue Per File", null, null, null) | |||
.addDefaultQProfile("xoo", "Sonar Way"); | |||
@Rule | |||
public ScannerMediumTester testerSC = new ScannerMediumTester() | |||
.setEdition(SonarEdition.SONARCLOUD) | |||
.registerPlugin("xoo", new XooPlugin()) | |||
.addRules(new XooRulesDefinition()) | |||
// active a rule just to be sure that xoo files are published | |||
.addActiveRule("xoo", "xoo:OneIssuePerFile", null, "One Issue Per File", null, null, null) | |||
.addDefaultQProfile("xoo", "Sonar Way"); | |||
private File baseDir; | |||
private Map<String, String> commonProps; | |||
@@ -75,14 +86,34 @@ public class DeprecatedBranchMediumTest { | |||
} | |||
@Test | |||
public void scanProjectWithBranch() throws IOException { | |||
public void scanProjectWithBranchOnSonarQube() throws IOException { | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
File xooFile = new File(srcDir, "sample.xoo"); | |||
FileUtils.write(xooFile, "Sample xoo\ncontent"); | |||
thrown.expect(MessageException.class); | |||
thrown.expectMessage("The 'sonar.branch' parameter is no longer supported. You should stop using it. " + | |||
"Branch analysis is available in Developer Edition and above. See https://redirect.sonarsource.com/editions/developer.html for more information."); | |||
tester.newAnalysis() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.putAll(commonProps) | |||
.put("sonar.branch", "branch") | |||
.build()) | |||
.execute(); | |||
} | |||
@Test | |||
public void scanProjectWithBranchOnSonarCloud() throws IOException { | |||
File srcDir = new File(baseDir, "src"); | |||
srcDir.mkdir(); | |||
File xooFile = new File(srcDir, "sample.xoo"); | |||
FileUtils.write(xooFile, "Sample xoo\ncontent"); | |||
AnalysisResult result = tester.newAnalysis() | |||
AnalysisResult result = testerSC.newAnalysis() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.putAll(commonProps) | |||
.put("sonar.branch", "branch") | |||
@@ -97,7 +128,7 @@ public class DeprecatedBranchMediumTest { | |||
assertThat(result.getReportReader().readMetadata().getDeprecatedBranch()).isEqualTo("branch"); | |||
result = tester.newAnalysis() | |||
result = testerSC.newAnalysis() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.putAll(commonProps) | |||
.put("sonar.branch", "") | |||
@@ -109,14 +140,14 @@ public class DeprecatedBranchMediumTest { | |||
} | |||
@Test | |||
public void scanMultiModuleWithBranch() throws IOException { | |||
public void scanMultiModuleWithBranchOnSonarCloud() throws IOException { | |||
Path srcDir = baseDir.toPath().resolve("moduleA").resolve("src"); | |||
Files.createDirectories(srcDir); | |||
File xooFile = new File(srcDir.toFile(), "sample.xoo"); | |||
FileUtils.write(xooFile, "Sample xoo\ncontent"); | |||
AnalysisResult result = tester.newAnalysis() | |||
AnalysisResult result = testerSC.newAnalysis() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.putAll(commonProps) | |||
.put("sonar.branch", "branch") | |||
@@ -133,7 +164,7 @@ public class DeprecatedBranchMediumTest { | |||
assertThat(result.getReportReader().readMetadata().getDeprecatedBranch()).isEqualTo("branch"); | |||
result = tester.newAnalysis() | |||
result = testerSC.newAnalysis() | |||
.properties(ImmutableMap.<String, String>builder() | |||
.putAll(commonProps) | |||
.put("sonar.branch", "") |
@@ -34,6 +34,7 @@ import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.utils.MessageException; | |||
@@ -65,6 +66,7 @@ public class FileSystemMediumTest { | |||
@Rule | |||
public ScannerMediumTester tester = new ScannerMediumTester() | |||
.setEdition(SonarEdition.SONARCLOUD) | |||
.registerPlugin("xoo", new XooPlugin()) | |||
.addDefaultQProfile("xoo", "Sonar Way") | |||
.addDefaultQProfile("xoo2", "Sonar Way"); | |||
@@ -152,7 +154,7 @@ public class FileSystemMediumTest { | |||
} | |||
@Test | |||
public void logBranchNameAndType() throws IOException { | |||
public void logBranchNameAndType() { | |||
builder.put("sonar.branch.name", "my-branch"); | |||
File srcDir = new File(baseDir, "src"); | |||
assertThat(srcDir.mkdir()).isTrue(); | |||
@@ -1065,7 +1067,8 @@ public class FileSystemMediumTest { | |||
.execute(); | |||
assertThat(result.inputFiles()).hasSize(1); | |||
assertThat(logTester.logs(LoggerLevel.WARN)).contains("File '" + xooFile2.getAbsolutePath() + "' is ignored. It is not located in module basedir '" + new File(baseDir, "moduleA") + "'."); | |||
assertThat(logTester.logs(LoggerLevel.WARN)) | |||
.contains("File '" + xooFile2.getAbsolutePath() + "' is ignored. It is not located in module basedir '" + new File(baseDir, "moduleA") + "'."); | |||
} | |||
@Test |
@@ -30,6 +30,7 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.batch.bootstrap.ProjectBuilder; | |||
import org.sonar.api.utils.MessageException; | |||
import org.sonar.scanner.mediumtest.AnalysisResult; | |||
@@ -56,6 +57,7 @@ public class ProjectBuilderMediumTest { | |||
@Rule | |||
public ScannerMediumTester tester = new ScannerMediumTester() | |||
.setEdition(SonarEdition.SONARCLOUD) | |||
.registerPlugin("xoo", new XooPluginWithBuilder(projectBuilder)) | |||
.addRules(new XooRulesDefinition()) | |||
.addDefaultQProfile("xoo", "Sonar Way") |
@@ -31,6 +31,7 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.utils.log.LogTester; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester; | |||
import org.sonar.scanner.mediumtest.ScannerMediumTester.AnalysisBuilder; | |||
@@ -64,6 +65,7 @@ public class ScmMediumTest { | |||
@Rule | |||
public ScannerMediumTester tester = new ScannerMediumTester() | |||
.setEdition(SonarEdition.SONARCLOUD) | |||
.registerPlugin("xoo", new XooPlugin()) | |||
.addDefaultQProfile("xoo", "Sonar Way") | |||
.addRules(new XooRulesDefinition()) |