aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-scanner-engine/src/main
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2019-05-12 15:12:42 +0200
committerSonarTech <sonartech@sonarsource.com>2019-05-22 20:21:18 +0200
commitf24fd0a266ca0dc30b99ab32defba039eb145df4 (patch)
tree0db916b74ae164994478ee41aca64ae8017f8765 /sonar-scanner-engine/src/main
parent09d6f7a1a956f9648916469be482a0fe5b5e33cb (diff)
downloadsonarqube-f24fd0a266ca0dc30b99ab32defba039eb145df4.tar.gz
sonarqube-f24fd0a266ca0dc30b99ab32defba039eb145df4.zip
SONAR-11950 autoconfig of SCM revision on Cirrus and Bitbucket
Diffstat (limited to 'sonar-scanner-engine/src/main')
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfiguration.java39
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationImpl.java40
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java66
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiVendor.java43
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/package-info.java23
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/BitbucketPipelines.java54
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/CirrusCi.java62
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/package-info.java23
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java49
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java10
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java4
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmRevision.java37
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmRevisionImpl.java77
13 files changed, 495 insertions, 32 deletions
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfiguration.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfiguration.java
new file mode 100644
index 00000000000..fc1d3c62677
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfiguration.java
@@ -0,0 +1,39 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.scanner.ci;
+
+import java.util.Optional;
+
+/**
+ * Configuration provided by CI environments like TravisCI or Jenkins.
+ *
+ * @see CiVendor
+ */
+public interface CiConfiguration {
+
+ /**
+ * The revision that triggered the analysis. It should
+ * be the revision as seen by end-user, but not the necessarily
+ * the effective revision of the clone on disk (merge commit with
+ * base branch for instance).
+ */
+ Optional<String> getScmRevision();
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationImpl.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationImpl.java
new file mode 100644
index 00000000000..aabd92bc30a
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationImpl.java
@@ -0,0 +1,40 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.scanner.ci;
+
+import java.util.Optional;
+import javax.annotation.Nullable;
+
+import static org.apache.commons.lang.StringUtils.defaultIfBlank;
+
+public class CiConfigurationImpl implements CiConfiguration {
+
+ @Nullable
+ private final String scmRevision;
+
+ public CiConfigurationImpl(@Nullable String scmRevision) {
+ this.scmRevision = defaultIfBlank(scmRevision, null);
+ }
+
+ @Override
+ public Optional<String> getScmRevision() {
+ return Optional.ofNullable(scmRevision);
+ }
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java
new file mode 100644
index 00000000000..38032976b05
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiConfigurationProvider.java
@@ -0,0 +1,66 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.scanner.ci;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.picocontainer.injectors.ProviderAdapter;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+public class CiConfigurationProvider extends ProviderAdapter {
+
+ private static final Logger LOG = Loggers.get(CiConfigurationProvider.class);
+ private static final String PROP_DISABLED = "sonar.ci.autoconfig.disabled";
+
+ public CiConfiguration provide(Configuration configuration, CiVendor[] ciVendors) {
+ boolean disabled = configuration.getBoolean(PROP_DISABLED).orElse(false);
+ if (disabled) {
+ return new EmptyCiConfiguration();
+ }
+
+ List<CiVendor> detectedVendors = Arrays.stream(ciVendors)
+ .filter(CiVendor::isDetected)
+ .collect(Collectors.toList());
+
+ if (detectedVendors.size() > 1) {
+ List<String> names = detectedVendors.stream().map(CiVendor::getName).collect(Collectors.toList());
+ throw MessageException.of("Multiple CI environments are detected: " + names + ". Please check environment variables or set property " + PROP_DISABLED + " to true.");
+ }
+
+ if (detectedVendors.size() == 1) {
+ CiVendor vendor = detectedVendors.get(0);
+ LOG.info("Detected {}", vendor.getName());
+ return vendor.loadConfiguration();
+ }
+ return new EmptyCiConfiguration();
+ }
+
+ private static class EmptyCiConfiguration implements CiConfiguration {
+ @Override
+ public Optional<String> getScmRevision() {
+ return Optional.empty();
+ }
+ }
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiVendor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiVendor.java
new file mode 100644
index 00000000000..30aefcd90a0
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/CiVendor.java
@@ -0,0 +1,43 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.scanner.ci;
+
+import org.sonar.api.scanner.ScannerSide;
+
+@ScannerSide
+public interface CiVendor {
+
+ /**
+ * The display name, for example "Jenkins"
+ */
+ String getName();
+
+ /**
+ * Whether the analyser runs in the CI vendor or not.
+ */
+ boolean isDetected();
+
+ /**
+ * The configuration guessed by CI vendor. Called only
+ * if {@link #isDetected()} is true.
+ */
+ CiConfiguration loadConfiguration();
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/package-info.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/package-info.java
new file mode 100644
index 00000000000..d7a896d0b70
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.scanner.ci;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/BitbucketPipelines.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/BitbucketPipelines.java
new file mode 100644
index 00000000000..7e86de90b91
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/BitbucketPipelines.java
@@ -0,0 +1,54 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.scanner.ci.vendors;
+
+import org.sonar.api.utils.System2;
+import org.sonar.scanner.ci.CiConfiguration;
+import org.sonar.scanner.ci.CiConfigurationImpl;
+import org.sonar.scanner.ci.CiVendor;
+
+import static org.apache.commons.lang.StringUtils.isNotEmpty;
+
+public class BitbucketPipelines implements CiVendor {
+
+ private final System2 system;
+
+ public BitbucketPipelines(System2 system) {
+ this.system = system;
+ }
+
+ @Override
+ public String getName() {
+ return "Bitbucket Pipelines";
+ }
+
+ @Override
+ public boolean isDetected() {
+ String ci = system.envVariable("CI");
+ String revision = system.envVariable("BITBUCKET_COMMIT");
+ return "true".equals(ci) && isNotEmpty(revision);
+ }
+
+ @Override
+ public CiConfiguration loadConfiguration() {
+ String revision = system.envVariable("BITBUCKET_COMMIT");
+ return new CiConfigurationImpl(revision);
+ }
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/CirrusCi.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/CirrusCi.java
new file mode 100644
index 00000000000..9e2bc921b13
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/CirrusCi.java
@@ -0,0 +1,62 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.scanner.ci.vendors;
+
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.scanner.ci.CiConfiguration;
+import org.sonar.scanner.ci.CiConfigurationImpl;
+import org.sonar.scanner.ci.CiVendor;
+
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
+/**
+ * Support https://cirrus-ci.org/
+ *
+ * Environment variables are documented at https://cirrus-ci.org/guide/writing-tasks/#environment-variables
+ */
+public class CirrusCi implements CiVendor {
+
+ private static final String PROPERTY_COMMIT = "CIRRUS_CHANGE_IN_REPO";
+ private final System2 system;
+
+ public CirrusCi(System2 system) {
+ this.system = system;
+ }
+
+ @Override
+ public String getName() {
+ return "CirrusCI";
+ }
+
+ @Override
+ public boolean isDetected() {
+ return "true".equals(system.envVariable("CIRRUS_CI"));
+ }
+
+ @Override
+ public CiConfiguration loadConfiguration() {
+ String revision = system.envVariable(PROPERTY_COMMIT);
+ if (isEmpty(revision)) {
+ Loggers.get(getClass()).warn("Missing environment variable " + PROPERTY_COMMIT);
+ }
+ return new CiConfigurationImpl(revision);
+ }
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/package-info.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/package-info.java
new file mode 100644
index 00000000000..daae39d4d1b
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.scanner.ci.vendors;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
index dc79f7262f4..06f20e70e95 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/MetadataPublisher.java
@@ -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;
@@ -44,6 +43,7 @@ import org.sonar.scanner.rule.QualityProfiles;
import org.sonar.scanner.scan.ScanProperties;
import org.sonar.scanner.scan.branch.BranchConfiguration;
import org.sonar.scanner.scm.ScmConfiguration;
+import org.sonar.scanner.scm.ScmRevision;
import static java.util.Optional.ofNullable;
@@ -58,13 +58,14 @@ public class MetadataPublisher implements ReportPublisherStep {
private final CpdSettings cpdSettings;
private final ScannerPluginRepository pluginRepository;
private final BranchConfiguration branchConfiguration;
+ private final ScmRevision scmRevision;
@Nullable
private final ScmConfiguration scmConfiguration;
public MetadataPublisher(ProjectInfo projectInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties,
QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration,
- @Nullable ScmConfiguration scmConfiguration) {
+ ScmRevision scmRevision, @Nullable ScmConfiguration scmConfiguration) {
this.projectInfo = projectInfo;
this.moduleHierarchy = moduleHierarchy;
this.properties = properties;
@@ -72,12 +73,13 @@ public class MetadataPublisher implements ReportPublisherStep {
this.cpdSettings = cpdSettings;
this.pluginRepository = pluginRepository;
this.branchConfiguration = branchConfiguration;
+ this.scmRevision = scmRevision;
this.scmConfiguration = scmConfiguration;
}
public MetadataPublisher(ProjectInfo projectInfo, InputModuleHierarchy moduleHierarchy, ScanProperties properties,
- QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration) {
- this(projectInfo, moduleHierarchy, properties, qProfiles, cpdSettings, pluginRepository, branchConfiguration, null);
+ QualityProfiles qProfiles, CpdSettings cpdSettings, ScannerPluginRepository pluginRepository, BranchConfiguration branchConfiguration, ScmRevision scmRevision) {
+ this(projectInfo, moduleHierarchy, properties, qProfiles, cpdSettings, pluginRepository, branchConfiguration, scmRevision, null);
}
@Override
@@ -100,9 +102,7 @@ public class MetadataPublisher implements ReportPublisherStep {
ofNullable(rootProject.getBranch()).ifPresent(builder::setDeprecatedBranch);
- if (scmConfiguration != null) {
- addScmInformation(builder);
- }
+ addScmInformation(builder);
for (QProfile qp : qProfiles.findAll()) {
builder.putQprofilesPerLanguage(qp.getLanguage(), ScannerReport.Metadata.QProfile.newBuilder()
@@ -134,33 +134,26 @@ public class MetadataPublisher implements ReportPublisherStep {
builder.putModulesProjectRelativePathByKey(module.key(), relativePath);
}
}
- }
- private void addScmInformation(ScannerReport.Metadata.Builder builder) {
- ScmProvider scmProvider = scmConfiguration.provider();
- if (scmProvider != null) {
- Path projectBasedir = moduleHierarchy.root().getBaseDir();
- try {
- builder.setRelativePathFromScmRoot(toSonarQubePath(scmProvider.relativePathFromScmRoot(projectBasedir)));
- } catch (UnsupportedOperationException e) {
- LOG.debug(e.getMessage());
- }
- try {
- computeScmRevision().ifPresent(builder::setScmRevisionId);
- } catch (UnsupportedOperationException e) {
- LOG.debug(e.getMessage());
+ if (scmConfiguration != null) {
+ ScmProvider scmProvider = scmConfiguration.provider();
+ if (scmProvider != null) {
+ Path projectBasedir = moduleHierarchy.root().getBaseDir();
+ try {
+ builder.setRelativePathFromScmRoot(toSonarQubePath(scmProvider.relativePathFromScmRoot(projectBasedir)));
+ } catch (UnsupportedOperationException e) {
+ LOG.debug(e.getMessage());
+ }
}
}
}
- private Optional<String> computeScmRevision() {
- Optional<String> scmRevision = properties.getScmRevision();
- ScmProvider scmProvider = scmConfiguration.provider();
- if (!scmRevision.isPresent() && scmProvider != null) {
- scmRevision = Optional.ofNullable(scmProvider.revisionId(moduleHierarchy.root().getBaseDir()));
+ private void addScmInformation(ScannerReport.Metadata.Builder builder) {
+ try {
+ scmRevision.get().ifPresent(builder::setScmRevisionId);
+ } catch (UnsupportedOperationException e) {
+ LOG.debug(e.getMessage());
}
-
- return scmRevision;
}
private void addBranchInformation(ScannerReport.Metadata.Builder builder) {
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
index d31dfe56c1b..edb43371cd2 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java
@@ -46,6 +46,9 @@ import org.sonar.scanner.bootstrap.GlobalAnalysisMode;
import org.sonar.scanner.bootstrap.MetricProvider;
import org.sonar.scanner.bootstrap.PostJobExtensionDictionnary;
import org.sonar.scanner.bootstrap.ProcessedScannerProperties;
+import org.sonar.scanner.ci.CiConfigurationProvider;
+import org.sonar.scanner.ci.vendors.BitbucketPipelines;
+import org.sonar.scanner.ci.vendors.CirrusCi;
import org.sonar.scanner.cpd.CpdExecutor;
import org.sonar.scanner.cpd.CpdSettings;
import org.sonar.scanner.cpd.index.SonarCpdBlockIndex;
@@ -109,6 +112,7 @@ import org.sonar.scanner.scan.measure.DefaultMetricFinder;
import org.sonar.scanner.scm.ScmChangedFilesProvider;
import org.sonar.scanner.scm.ScmConfiguration;
import org.sonar.scanner.scm.ScmPublisher;
+import org.sonar.scanner.scm.ScmRevisionImpl;
import org.sonar.scanner.sensor.DefaultSensorStorage;
import org.sonar.scanner.sensor.ProjectSensorContext;
import org.sonar.scanner.sensor.ProjectSensorExtensionDictionnary;
@@ -248,6 +252,7 @@ public class ProjectScanContainer extends ComponentContainer {
// SCM
ScmConfiguration.class,
ScmPublisher.class,
+ ScmRevisionImpl.class,
// Sensors
DefaultSensorStorage.class,
@@ -260,6 +265,11 @@ public class ProjectScanContainer extends ComponentContainer {
// Filesystem
DefaultProjectFileSystem.class,
+ // CI
+ new CiConfigurationProvider(),
+ BitbucketPipelines.class,
+ CirrusCi.class,
+
AnalysisObservers.class);
addIfMissing(DefaultProjectSettingsLoader.class, ProjectSettingsLoader.class);
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java
index 36fd9b5d41e..1033292a4b8 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ScanProperties.java
@@ -79,10 +79,6 @@ public class ScanProperties {
}
}
- public Optional<String> getScmRevision() {
- return configuration.get(SCM_REVISION);
- }
-
/**
* This should be called in the beginning of the analysis to fail fast
*/
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmRevision.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmRevision.java
new file mode 100644
index 00000000000..28af0127b6f
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmRevision.java
@@ -0,0 +1,37 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.scanner.scm;
+
+import java.util.Optional;
+import org.sonar.api.scanner.ScannerSide;
+
+/**
+ * The SCM revision that triggered the analysis. It may be different than
+ * the effective revision checked-out on disk, as provided by {@link org.sonar.api.batch.scm.ScmProvider}.
+ *
+ * For instance on pull requests it's not the merge-commit that some CI services check out. It is
+ * the commit that was pushed by user to the branch.
+ */
+@ScannerSide
+public interface ScmRevision {
+
+ Optional<String> get();
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmRevisionImpl.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmRevisionImpl.java
new file mode 100644
index 00000000000..6eb15be6e81
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scm/ScmRevisionImpl.java
@@ -0,0 +1,77 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.scanner.scm;
+
+import java.util.Optional;
+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.bootstrap.RawScannerProperties;
+import org.sonar.scanner.ci.CiConfiguration;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+import static org.sonar.scanner.scan.ScanProperties.SCM_REVISION;
+
+public class ScmRevisionImpl implements ScmRevision {
+
+ private static final Logger LOG = Loggers.get(ScmRevisionImpl.class);
+
+ private final CiConfiguration ciConfiguration;
+ private final RawScannerProperties scannerConfiguration;
+ private final ScmConfiguration scmConfiguration;
+ private final InputModuleHierarchy moduleHierarchy;
+
+ public ScmRevisionImpl(CiConfiguration ciConfiguration, RawScannerProperties scannerConfiguration, ScmConfiguration scmConfiguration, InputModuleHierarchy moduleHierarchy) {
+ this.ciConfiguration = ciConfiguration;
+ this.scannerConfiguration = scannerConfiguration;
+ this.scmConfiguration = scmConfiguration;
+ this.moduleHierarchy = moduleHierarchy;
+ }
+
+ @Override
+ public Optional<String> get() {
+ Optional<String> revision = Optional.ofNullable(scannerConfiguration.property(SCM_REVISION));
+ if (isSet(revision)) {
+ return revision;
+ }
+ revision = ciConfiguration.getScmRevision();
+ if (isSet(revision)) {
+ return revision;
+ }
+ ScmProvider scmProvider = scmConfiguration.provider();
+ if (scmProvider != null) {
+ try {
+ revision = Optional.ofNullable(scmProvider.revisionId(moduleHierarchy.root().getBaseDir()));
+ } catch (UnsupportedOperationException e) {
+ LOG.debug(e.getMessage());
+ revision = Optional.empty();
+ }
+ }
+ if (isSet(revision)) {
+ return revision;
+ }
+ return Optional.empty();
+ }
+
+ private static boolean isSet(Optional<String> opt) {
+ return opt.isPresent() && !isBlank(opt.get());
+ }
+}