diff options
author | Michal Duda <michal.duda@sonarsource.com> | 2021-03-01 17:48:43 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-03-04 20:12:49 +0000 |
commit | 4c007c151c20a92ed5d76ce5ac04bae53919586e (patch) | |
tree | 46ebcf58d5bc7949c513d54b9ebb1feae5df8f1c /sonar-scanner-engine | |
parent | 4558e5786f367160a219fd8bbc1f9872e51ea661 (diff) | |
download | sonarqube-4c007c151c20a92ed5d76ce5ac04bae53919586e.tar.gz sonarqube-4c007c151c20a92ed5d76ce5ac04bae53919586e.zip |
SONAR-14525 include CI usage information in telemetry
Diffstat (limited to 'sonar-scanner-engine')
26 files changed, 455 insertions, 63 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 index 8b8ee783a7d..5b57c38015f 100644 --- 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 @@ -29,6 +29,11 @@ import java.util.Optional; public interface CiConfiguration { /** + * Name of the CI environment + */ + String getCiName(); + + /** * 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 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 index f7baa5741f5..9ac6bd86573 100644 --- 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 @@ -25,16 +25,23 @@ import javax.annotation.Nullable; import static org.apache.commons.lang.StringUtils.defaultIfBlank; public class CiConfigurationImpl implements CiConfiguration { + private final String ciName; @Nullable private final String scmRevision; - public CiConfigurationImpl(@Nullable String scmRevision) { + public CiConfigurationImpl(@Nullable String scmRevision, String ciName) { this.scmRevision = defaultIfBlank(scmRevision, null); + this.ciName = ciName; } @Override public Optional<String> getScmRevision() { return Optional.ofNullable(scmRevision); } + + @Override + public String getCiName() { + return ciName; + } } 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 index be8f5c1f84d..ea84fbcb918 100644 --- 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 @@ -57,10 +57,15 @@ public class CiConfigurationProvider extends ProviderAdapter { return new EmptyCiConfiguration(); } - private static class EmptyCiConfiguration implements CiConfiguration { + static class EmptyCiConfiguration implements CiConfiguration { @Override public Optional<String> getScmRevision() { return Optional.empty(); } + + @Override + public String getCiName() { + return "undetected"; + } } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AppVeyor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AppVeyor.java index 2444e4475fa..863221c7b6e 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AppVeyor.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AppVeyor.java @@ -26,7 +26,7 @@ import org.sonar.scanner.ci.CiVendor; /** * Support of https://www.appveyor.com - * + * <p> * Environment variables: https://www.appveyor.com/docs/environment-variables/ */ public class AppVeyor implements CiVendor { @@ -50,6 +50,6 @@ public class AppVeyor implements CiVendor { @Override public CiConfiguration loadConfiguration() { String revision = system.envVariable("APPVEYOR_REPO_COMMIT"); - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AwsCodeBuild.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AwsCodeBuild.java new file mode 100644 index 00000000000..5f57825ddc4 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AwsCodeBuild.java @@ -0,0 +1,54 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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; + +public class AwsCodeBuild implements CiVendor { + private final System2 system; + + public AwsCodeBuild(System2 system) { + this.system = system; + } + + @Override + public String getName() { + return "AwsCodeBuild"; + } + + + @Override + public boolean isDetected() { + return environmentVariableIsPresent("CODEBUILD_BUILD_ID") && + environmentVariableIsPresent("CODEBUILD_START_TIME"); + } + + @Override + public CiConfiguration loadConfiguration() { + return new CiConfigurationImpl(null, getName()); + } + + private boolean environmentVariableIsPresent(String key) { + return system.envVariable(key) != null; + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AzureDevops.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AzureDevops.java index 3610691fbdb..0e2d2b09697 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AzureDevops.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/AzureDevops.java @@ -28,7 +28,7 @@ import static org.apache.commons.lang.StringUtils.isBlank; /** * Support of https://azure.microsoft.com/en-us/services/devops/ - * + * <p> * Environment variables: https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables */ public class AzureDevops implements CiVendor { @@ -55,6 +55,6 @@ public class AzureDevops implements CiVendor { if (isBlank(revision)) { revision = system.envVariable("BUILD_SOURCEVERSION"); } - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Bamboo.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Bamboo.java new file mode 100644 index 00000000000..98e856d2858 --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Bamboo.java @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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; + +public class Bamboo implements CiVendor { + private final System2 system; + + public Bamboo(System2 system) { + this.system = system; + } + + @Override + public String getName() { + return "Bamboo"; + } + + + @Override + public boolean isDetected() { + return system.envVariable("bamboo_buildNumber") != null; + } + + @Override + public CiConfiguration loadConfiguration() { + String revision = system.envVariable("bamboo_planRepository_revision"); + return new CiConfigurationImpl(revision, getName()); + } +} 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 index c4f96476ce7..798166a8102 100644 --- 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 @@ -49,6 +49,6 @@ public class BitbucketPipelines implements CiVendor { @Override public CiConfiguration loadConfiguration() { String revision = system.envVariable("BITBUCKET_COMMIT"); - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Bitrise.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Bitrise.java new file mode 100644 index 00000000000..9fec71f4efc --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Bitrise.java @@ -0,0 +1,57 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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 java.util.Optional; +import org.sonar.api.utils.System2; +import org.sonar.scanner.ci.CiConfiguration; +import org.sonar.scanner.ci.CiConfigurationImpl; +import org.sonar.scanner.ci.CiVendor; + +public class Bitrise implements CiVendor { + + private final System2 system2; + + public Bitrise(System2 system2) { + this.system2 = system2; + } + + @Override + public String getName() { + return "Bitrise"; + } + + @Override + public boolean isDetected() { + return environmentVariableIsTrue("CI") && environmentVariableIsTrue("BITRISE_IO"); + } + + @Override + public CiConfiguration loadConfiguration() { + String revision = system2.envVariable("BITRISE_GIT_COMMIT"); + return new CiConfigurationImpl(revision, getName()); + } + + private boolean environmentVariableIsTrue(String key) { + return Optional.ofNullable(system2.envVariable(key)) + .map(Boolean::parseBoolean) + .orElse(false); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Buildkite.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Buildkite.java index c230293ec19..4f6105e1e19 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Buildkite.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Buildkite.java @@ -26,7 +26,7 @@ import org.sonar.scanner.ci.CiVendor; /** * Support of https://buildkite.com - * + * <p> * Environment variables: https://buildkite.com/docs/pipelines/environment-variables */ public class Buildkite implements CiVendor { @@ -50,6 +50,6 @@ public class Buildkite implements CiVendor { @Override public CiConfiguration loadConfiguration() { String revision = system.envVariable("BUILDKITE_COMMIT"); - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/CircleCi.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/CircleCi.java index c67807851ad..0070768b6f6 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/CircleCi.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/CircleCi.java @@ -26,7 +26,7 @@ import org.sonar.scanner.ci.CiVendor; /** * Support of https://circleci.com - * + * <p> * Environment variables: https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables */ public class CircleCi implements CiVendor { @@ -50,6 +50,6 @@ public class CircleCi implements CiVendor { @Override public CiConfiguration loadConfiguration() { String revision = system.envVariable("CIRCLE_SHA1"); - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } 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 index 1b252d0581c..e794a2eb102 100644 --- 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 @@ -29,7 +29,7 @@ import static org.apache.commons.lang.StringUtils.isEmpty; /** * Support https://cirrus-ci.org/ - * + * <p> * Environment variables are documented at https://cirrus-ci.org/guide/writing-tasks/#environment-variables */ public class CirrusCi implements CiVendor { @@ -57,6 +57,6 @@ public class CirrusCi implements CiVendor { if (isEmpty(revision)) { Loggers.get(getClass()).warn("Missing environment variable " + PROPERTY_COMMIT); } - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/DroneCi.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/DroneCi.java index a4ccc6e31df..53b84bff6ab 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/DroneCi.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/DroneCi.java @@ -26,7 +26,7 @@ import org.sonar.scanner.ci.CiVendor; /** * Support https://drone.io - * + * <p> * Environment variables are documented at https://docs.drone.io/reference/environ/ */ public class DroneCi implements CiVendor { @@ -49,6 +49,6 @@ public class DroneCi implements CiVendor { @Override public CiConfiguration loadConfiguration() { String revision = system.envVariable("DRONE_COMMIT_SHA"); - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/GithubActions.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/GithubActions.java index de9d81460b5..e0c5940abaa 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/GithubActions.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/GithubActions.java @@ -30,7 +30,7 @@ import static org.apache.commons.lang.StringUtils.isEmpty; /** * Support of https://github.com/features/actions - * + * <p> * Environment variables: https://developer.github.com/actions/creating-github-actions/accessing-the-runtime-environment/#environment-variables */ public class GithubActions implements CiVendor { @@ -59,6 +59,6 @@ public class GithubActions implements CiVendor { if (isEmpty(revision)) { Loggers.get(getClass()).warn("Missing environment variable " + PROPERTY_COMMIT); } - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/GitlabCi.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/GitlabCi.java index 68b860cd717..995af3afba8 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/GitlabCi.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/GitlabCi.java @@ -47,6 +47,6 @@ public class GitlabCi implements CiVendor { @Override public CiConfiguration loadConfiguration() { String revision = system.envVariable("CI_COMMIT_SHA"); - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Jenkins.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Jenkins.java index db3d61727dd..2581809f79e 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Jenkins.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/Jenkins.java @@ -62,7 +62,7 @@ public class Jenkins implements CiVendor { // https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project String revision = system.envVariable("ghprbActualCommit"); if (StringUtils.isNotBlank(revision)) { - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } revision = system.envVariable("GIT_COMMIT"); @@ -71,14 +71,14 @@ public class Jenkins implements CiVendor { if (StringUtils.isNotBlank(system.envVariable("CHANGE_ID"))) { String jenkinsGitPrSha1 = getJenkinsGitPrSha1(); if (StringUtils.isNotBlank(jenkinsGitPrSha1)) { - return new CiConfigurationImpl(jenkinsGitPrSha1); + return new CiConfigurationImpl(jenkinsGitPrSha1, getName()); } } - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } revision = system.envVariable("SVN_COMMIT"); - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } private String getJenkinsGitPrSha1() { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/SemaphoreCi.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/SemaphoreCi.java index 94b178ec626..d9428997036 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/SemaphoreCi.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/SemaphoreCi.java @@ -49,6 +49,6 @@ public class SemaphoreCi implements CiVendor { @Override public CiConfiguration loadConfiguration() { String revision = system.envVariable("SEMAPHORE_GIT_SHA"); - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/TravisCi.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/TravisCi.java index 63027665b61..8b24d0d33b5 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/TravisCi.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/ci/vendors/TravisCi.java @@ -28,7 +28,7 @@ import static org.apache.commons.lang.StringUtils.isBlank; /** * Support of https://travis-ci.com - * + * <p> * Environment variables: https://docs.travis-ci.com/user/environment-variables/ */ public class TravisCi implements CiVendor { @@ -58,6 +58,6 @@ public class TravisCi implements CiVendor { revision = system.envVariable("TRAVIS_PULL_REQUEST_SHA"); } - return new CiConfigurationImpl(revision); + return new CiConfigurationImpl(revision, getName()); } } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java index 0c8e49da4d7..525d3c6d8f8 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ContextPropertiesPublisher.java @@ -20,46 +20,55 @@ package org.sonar.scanner.report; import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; -import javax.annotation.Nonnull; import org.sonar.api.batch.scm.ScmProvider; import org.sonar.core.config.CorePropertyDefinitions; +import org.sonar.scanner.ci.CiConfiguration; import org.sonar.scanner.config.DefaultConfiguration; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReportWriter; import org.sonar.scanner.repository.ContextPropertiesCache; import org.sonar.scanner.scm.ScmConfiguration; +import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDCI; import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDSCM; public class ContextPropertiesPublisher implements ReportPublisherStep { private final ContextPropertiesCache cache; private final DefaultConfiguration config; private final ScmConfiguration scmConfiguration; + private final CiConfiguration ciConfiguration; - public ContextPropertiesPublisher(ContextPropertiesCache cache, DefaultConfiguration config, ScmConfiguration scmConfiguration) { + public ContextPropertiesPublisher(ContextPropertiesCache cache, DefaultConfiguration config, ScmConfiguration scmConfiguration, + CiConfiguration ciConfiguration) { this.cache = cache; this.config = config; this.scmConfiguration = scmConfiguration; + this.ciConfiguration = ciConfiguration; } @Override public void publish(ScannerReportWriter writer) { - MapEntryToContextPropertyFunction transformer = new MapEntryToContextPropertyFunction(); - - // properties defined programmatically by plugins - Stream<ScannerReport.ContextProperty> fromCache = Stream.concat(cache.getAll().entrySet().stream(), Stream.of(constructScmInfo())).map(transformer); - + List<Map.Entry<String, String>> properties = new ArrayList<>(cache.getAll().entrySet()); + properties.add(constructScmInfo()); + properties.add(constructCiInfo()); // properties that are automatically included to report so that // they can be included to webhook payloads - Stream<ScannerReport.ContextProperty> fromSettings = config.getProperties().entrySet().stream() + properties.addAll(config.getProperties().entrySet() + .stream() .filter(e -> e.getKey().startsWith(CorePropertyDefinitions.SONAR_ANALYSIS)) - .map(transformer); + .collect(Collectors.toList())); - writer.writeContextProperties(Stream.concat(fromCache, fromSettings).collect(Collectors.toList())); + writer.writeContextProperties(properties + .stream() + .map(e -> ScannerReport.ContextProperty.newBuilder() + .setKey(e.getKey()) + .setValue(e.getValue()) + .build()) + .collect(Collectors.toList())); } private Map.Entry<String, String> constructScmInfo() { @@ -71,12 +80,7 @@ public class ContextPropertiesPublisher implements ReportPublisherStep { } } - private static final class MapEntryToContextPropertyFunction implements Function<Map.Entry<String, String>, ScannerReport.ContextProperty> { - private final ScannerReport.ContextProperty.Builder builder = ScannerReport.ContextProperty.newBuilder(); - - @Override - public ScannerReport.ContextProperty apply(@Nonnull Map.Entry<String, String> input) { - return builder.clear().setKey(input.getKey()).setValue(input.getValue()).build(); - } + private Map.Entry<String, String> constructCiInfo() { + return new AbstractMap.SimpleEntry<>(SONAR_ANALYSIS_DETECTEDCI, ciConfiguration.getCiName()); } } 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 8ee1267d4d0..300d15568d9 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,8 +46,11 @@ import org.sonar.scanner.bootstrap.MetricProvider; import org.sonar.scanner.bootstrap.PostJobExtensionDictionnary; import org.sonar.scanner.ci.CiConfigurationProvider; import org.sonar.scanner.ci.vendors.AppVeyor; +import org.sonar.scanner.ci.vendors.AwsCodeBuild; import org.sonar.scanner.ci.vendors.AzureDevops; +import org.sonar.scanner.ci.vendors.Bamboo; import org.sonar.scanner.ci.vendors.BitbucketPipelines; +import org.sonar.scanner.ci.vendors.Bitrise; import org.sonar.scanner.ci.vendors.Buildkite; import org.sonar.scanner.ci.vendors.CircleCi; import org.sonar.scanner.ci.vendors.CirrusCi; @@ -286,8 +289,11 @@ public class ProjectScanContainer extends ComponentContainer { // CI new CiConfigurationProvider(), AppVeyor.class, + AwsCodeBuild.class, AzureDevops.class, + Bamboo.class, BitbucketPipelines.class, + Bitrise.class, Buildkite.class, CircleCi.class, CirrusCi.class, diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationImplTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationImplTest.java index 2dec5954336..4eb8a6e13a9 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationImplTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationImplTest.java @@ -27,9 +27,19 @@ public class CiConfigurationImplTest { @Test public void getScmRevision() { - assertThat(new CiConfigurationImpl(null).getScmRevision()).isEmpty(); - assertThat(new CiConfigurationImpl("").getScmRevision()).isEmpty(); - assertThat(new CiConfigurationImpl(" ").getScmRevision()).isEmpty(); - assertThat(new CiConfigurationImpl("a7bdf2d").getScmRevision()).hasValue("a7bdf2d"); + assertThat(new CiConfigurationImpl(null, "test").getScmRevision()).isEmpty(); + assertThat(new CiConfigurationImpl("", "test").getScmRevision()).isEmpty(); + assertThat(new CiConfigurationImpl(" ", "test").getScmRevision()).isEmpty(); + assertThat(new CiConfigurationImpl("a7bdf2d", "test").getScmRevision()).hasValue("a7bdf2d"); + } + + @Test + public void getNam_for_undetected_ci() { + assertThat(new CiConfigurationProvider.EmptyCiConfiguration().getCiName()).isEqualTo("undetected"); + } + + @Test + public void getName_for_detected_ci() { + assertThat(new CiConfigurationImpl(null, "test").getCiName()).isEqualTo("test"); } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java index b99ff837499..e980d53de97 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/CiConfigurationProviderTest.java @@ -28,8 +28,8 @@ import static org.assertj.core.api.Assertions.catchThrowable; public class CiConfigurationProviderTest { - private MapSettings cli = new MapSettings(); - private CiConfigurationProvider underTest = new CiConfigurationProvider(); + private final MapSettings cli = new MapSettings(); + private final CiConfigurationProvider underTest = new CiConfigurationProvider(); @Test public void empty_configuration_if_no_ci_vendors() { @@ -40,21 +40,21 @@ public class CiConfigurationProviderTest { @Test public void empty_configuration_if_no_ci_detected() { - CiConfiguration ciConfiguration = underTest.provide(cli.asConfig(), new CiVendor[] {new DisabledCiVendor("vendor1"), new DisabledCiVendor("vendor2")}); + CiConfiguration ciConfiguration = underTest.provide(cli.asConfig(), new CiVendor[]{new DisabledCiVendor("vendor1"), new DisabledCiVendor("vendor2")}); assertThat(ciConfiguration.getScmRevision()).isEmpty(); } @Test public void configuration_defined_by_ci_vendor() { - CiConfiguration ciConfiguration = underTest.provide(cli.asConfig(), new CiVendor[] {new DisabledCiVendor("vendor1"), new EnabledCiVendor("vendor2")}); + CiConfiguration ciConfiguration = underTest.provide(cli.asConfig(), new CiVendor[]{new DisabledCiVendor("vendor1"), new EnabledCiVendor("vendor2")}); assertThat(ciConfiguration.getScmRevision()).hasValue(EnabledCiVendor.SHA); } @Test public void fail_if_multiple_ci_vendor_are_detected() { - Throwable thrown = catchThrowable(() -> underTest.provide(cli.asConfig(), new CiVendor[] {new EnabledCiVendor("vendor1"), new EnabledCiVendor("vendor2")})); + Throwable thrown = catchThrowable(() -> underTest.provide(cli.asConfig(), new CiVendor[]{new EnabledCiVendor("vendor1"), new EnabledCiVendor("vendor2")})); assertThat(thrown) .isInstanceOf(MessageException.class) @@ -64,7 +64,7 @@ public class CiConfigurationProviderTest { @Test public void empty_configuration_if_auto_configuration_is_disabled() { cli.setProperty("sonar.ci.autoconfig.disabled", true); - CiConfiguration ciConfiguration = underTest.provide(cli.asConfig(), new CiVendor[] {new EnabledCiVendor("vendor1")}); + CiConfiguration ciConfiguration = underTest.provide(cli.asConfig(), new CiVendor[]{new EnabledCiVendor("vendor1")}); assertThat(ciConfiguration.getScmRevision()).isEmpty(); } @@ -112,7 +112,7 @@ public class CiConfigurationProviderTest { @Override public CiConfiguration loadConfiguration() { - return new CiConfigurationImpl(SHA); + return new CiConfigurationImpl(SHA, name); } } } diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AwsCodeBuildTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AwsCodeBuildTest.java new file mode 100644 index 00000000000..f9094a34bd2 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/AwsCodeBuildTest.java @@ -0,0 +1,64 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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 javax.annotation.Nullable; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.scanner.ci.CiVendor; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class AwsCodeBuildTest { + + private final System2 system = mock(System2.class); + private final CiVendor underTest = new AwsCodeBuild(system); + + @Test + public void getName() { + assertThat(underTest.getName()).isEqualTo("AwsCodeBuild"); + } + + @Test + public void isDetected() { + assertThat(underTest.isDetected()).isFalse(); + + setEnvVariable("CODEBUILD_BUILD_ID", "51"); + assertThat(underTest.isDetected()).isFalse(); + + setEnvVariable("CODEBUILD_BUILD_ID", "52"); + setEnvVariable("CODEBUILD_START_TIME", "some-time"); + assertThat(underTest.isDetected()).isTrue(); + } + + @Test + public void loadConfiguration() { + setEnvVariable("CODEBUILD_BUILD_ID", "51"); + setEnvVariable("CODEBUILD_START_TIME", "some-time"); + + assertThat(underTest.loadConfiguration().getScmRevision()).isEmpty(); + } + + private void setEnvVariable(String key, @Nullable String value) { + when(system.envVariable(key)).thenReturn(value); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BambooTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BambooTest.java new file mode 100644 index 00000000000..330b538d718 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BambooTest.java @@ -0,0 +1,60 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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 javax.annotation.Nullable; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.scanner.ci.CiVendor; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class BambooTest { + + private final System2 system = mock(System2.class); + private final CiVendor underTest = new Bamboo(system); + + @Test + public void getName() { + assertThat(underTest.getName()).isEqualTo("Bamboo"); + } + + @Test + public void isDetected() { + assertThat(underTest.isDetected()).isFalse(); + + setEnvVariable("bamboo_buildNumber", "41"); + assertThat(underTest.isDetected()).isTrue(); + } + + @Test + public void loadConfiguration() { + setEnvVariable("bamboo_buildNumber", "41"); + setEnvVariable("bamboo_planRepository_revision", "42109719-93c9-4d47-9d7c-b3b0b87b6985"); + + assertThat(underTest.loadConfiguration().getScmRevision()).hasValue("42109719-93c9-4d47-9d7c-b3b0b87b6985"); + } + + private void setEnvVariable(String key, @Nullable String value) { + when(system.envVariable(key)).thenReturn(value); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitriseTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitriseTest.java new file mode 100644 index 00000000000..b80440866b6 --- /dev/null +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/ci/vendors/BitriseTest.java @@ -0,0 +1,70 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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 javax.annotation.Nullable; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.scanner.ci.CiVendor; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class BitriseTest { + + private final System2 system = mock(System2.class); + private final CiVendor underTest = new Bitrise(system); + + @Test + public void getName() { + assertThat(underTest.getName()).isEqualTo("Bitrise"); + } + + @Test + public void isDetected() { + + assertThat(underTest.isDetected()).isFalse(); + + setEnvVariable("CI", "true"); + assertThat(underTest.isDetected()).isFalse(); + + setEnvVariable("CI", "true"); + setEnvVariable("BITRISE_IO", "false"); + assertThat(underTest.isDetected()).isFalse(); + + setEnvVariable("CI", "true"); + setEnvVariable("BITRISE_IO", "true"); + assertThat(underTest.isDetected()).isTrue(); + } + + @Test + public void loadConfiguration() { + setEnvVariable("CI", "true"); + setEnvVariable("BITRISE_IO", "true"); + setEnvVariable("BITRISE_GIT_COMMIT", "abd12fc"); + + assertThat(underTest.loadConfiguration().getScmRevision()).hasValue("abd12fc"); + } + + private void setEnvVariable(String key, @Nullable String value) { + when(system.envVariable(key)).thenReturn(value); + } +} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java index db450a00657..0dd340f5b3f 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ContextPropertiesPublisherTest.java @@ -25,9 +25,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.sonar.scanner.ci.CiConfiguration; import org.sonar.scanner.config.DefaultConfiguration; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReportWriter; @@ -40,19 +39,18 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class ContextPropertiesPublisherTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - private final ScannerReportWriter writer = mock(ScannerReportWriter.class); private final ContextPropertiesCache cache = new ContextPropertiesCache(); private final DefaultConfiguration config = mock(DefaultConfiguration.class); private final Map<String, String> props = new HashMap<>(); private final ScmConfiguration scmConfiguration = mock(ScmConfiguration.class); - private final ContextPropertiesPublisher underTest = new ContextPropertiesPublisher(cache, config, scmConfiguration); + private final CiConfiguration ciConfiguration = mock(CiConfiguration.class); + private final ContextPropertiesPublisher underTest = new ContextPropertiesPublisher(cache, config, scmConfiguration, ciConfiguration); @Before public void prepareMock() { when(config.getProperties()).thenReturn(props); + when(ciConfiguration.getCiName()).thenReturn("undetected"); } @Test @@ -65,7 +63,8 @@ public class ContextPropertiesPublisherTest { List<ScannerReport.ContextProperty> expected = Arrays.asList( newContextProperty("foo1", "bar1"), newContextProperty("foo2", "bar2"), - newContextProperty("sonar.analysis.detectedscm", "undetected")); + newContextProperty("sonar.analysis.detectedscm", "undetected"), + newContextProperty("sonar.analysis.detectedci", "undetected")); expectWritten(expected); } @@ -80,7 +79,8 @@ public class ContextPropertiesPublisherTest { List<ScannerReport.ContextProperty> expected = Arrays.asList( newContextProperty("sonar.analysis.revision", "ab45b3"), newContextProperty("sonar.analysis.build.number", "B123"), - newContextProperty("sonar.analysis.detectedscm", "undetected")); + newContextProperty("sonar.analysis.detectedscm", "undetected"), + newContextProperty("sonar.analysis.detectedci", "undetected")); expectWritten(expected); } |