From: Michal Duda Date: Mon, 1 Mar 2021 16:48:43 +0000 (+0100) Subject: SONAR-14525 include CI usage information in telemetry X-Git-Tag: 8.8.0.42792~62 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4c007c151c20a92ed5d76ce5ac04bae53919586e;p=sonarqube.git SONAR-14525 include CI usage information in telemetry --- diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistAnalysisPropertiesStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistAnalysisPropertiesStep.java index ec1055ff4b5..633f2ff9e01 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistAnalysisPropertiesStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistAnalysisPropertiesStep.java @@ -19,8 +19,10 @@ */ package org.sonar.ce.task.projectanalysis.step; +import com.google.common.collect.ImmutableSet; import java.util.ArrayList; import java.util.List; +import java.util.Set; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.ce.task.projectanalysis.batch.BatchReportReader; import org.sonar.ce.task.step.ComputationStep; @@ -32,6 +34,7 @@ import org.sonar.db.component.AnalysisPropertyDto; import org.sonar.scanner.protocol.output.ScannerReport; import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS; +import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDCI; import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDSCM; /** @@ -40,6 +43,7 @@ import static org.sonar.core.config.CorePropertyDefinitions.SONAR_ANALYSIS_DETEC public class PersistAnalysisPropertiesStep implements ComputationStep { private static final String SONAR_PULL_REQUEST = "sonar.pullrequest."; + private static final Set ANALYSIS_PROPERTIES_TO_PERSIST = ImmutableSet.of(SONAR_ANALYSIS_DETECTEDSCM, SONAR_ANALYSIS_DETECTEDCI); private final DbClient dbClient; private final AnalysisMetadataHolder analysisMetadataHolder; @@ -61,7 +65,8 @@ public class PersistAnalysisPropertiesStep implements ComputationStep { it.forEachRemaining( contextProperty -> { String propertyKey = contextProperty.getKey(); - if (propertyKey.startsWith(SONAR_ANALYSIS) || propertyKey.startsWith(SONAR_PULL_REQUEST) || SONAR_ANALYSIS_DETECTEDSCM.equals(propertyKey)) { + if (propertyKey.startsWith(SONAR_ANALYSIS) || propertyKey.startsWith(SONAR_PULL_REQUEST) || + ANALYSIS_PROPERTIES_TO_PERSIST.contains(propertyKey)) { analysisPropertyDtos.add(new AnalysisPropertyDto() .setUuid(uuidFactory.create()) .setKey(propertyKey) diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java b/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java index a6d51d11204..6859da51a36 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java @@ -44,6 +44,7 @@ public class TelemetryData { private final Map nclocByLanguage; private final List externalAuthenticationProviders; private final Map projectCountByScm; + private final Map projectCountByCi; private final EditionProvider.Edition edition; private final String licenseType; private final Long installationDate; @@ -77,6 +78,7 @@ public class TelemetryData { customSecurityConfigs = builder.customSecurityConfigs == null ? emptyList() : builder.customSecurityConfigs; externalAuthenticationProviders = builder.externalAuthenticationProviders; projectCountByScm = builder.projectCountByScm; + projectCountByCi = builder.projectCountByCi; } public String getServerId() { @@ -167,6 +169,10 @@ public class TelemetryData { return projectCountByScm; } + public Map getProjectCountByCi() { + return projectCountByCi; + } + static Builder builder() { return new Builder(); } @@ -192,7 +198,7 @@ public class TelemetryData { private List customSecurityConfigs; private List externalAuthenticationProviders; private Map projectCountByScm; - + private Map projectCountByCi; private Builder() { // enforce static factory method @@ -213,6 +219,11 @@ public class TelemetryData { return this; } + Builder setProjectCountByCi(Map projectCountByCi) { + this.projectCountByCi = projectCountByCi; + return this; + } + Builder setServerId(String serverId) { this.serverId = serverId; return this; @@ -309,6 +320,7 @@ public class TelemetryData { requireNonNull(usingBranches); requireNonNull(externalAuthenticationProviders); requireNonNull(projectCountByScm); + requireNonNull(projectCountByCi); return new TelemetryData(this); } diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java b/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java index f427f0c5e28..94d6f78c751 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java @@ -95,17 +95,11 @@ public class TelemetryDataJsonWriter { statistics.getExternalAuthenticationProviders().forEach(json::value); json.endArray(); - json.name("projectCountByScm"); - json.beginArray(); - statistics.getProjectCountByScm().forEach((scm, count) -> { - json.beginObject(); - json.prop("scm", scm); - json.prop(COUNT, count); - json.endObject(); - }); - json.endArray(); + addScmInfo(json, statistics); + addCiInfo(json, statistics); json.prop("sonarlintWeeklyUsers", statistics.sonarlintWeeklyUsers()); + if (statistics.getInstallationDate() != null) { json.prop("installationDate", statistics.getInstallationDate()); } @@ -115,4 +109,28 @@ public class TelemetryDataJsonWriter { json.prop("docker", statistics.isInDocker()); json.endObject(); } + + private static void addScmInfo(JsonWriter json, TelemetryData statistics) { + json.name("projectCountByScm"); + json.beginArray(); + statistics.getProjectCountByScm().forEach((scm, count) -> { + json.beginObject(); + json.prop("scm", scm); + json.prop(COUNT, count); + json.endObject(); + }); + json.endArray(); + } + + private static void addCiInfo(JsonWriter json, TelemetryData statistics) { + json.name("projectCountByCI"); + json.beginArray(); + statistics.getProjectCountByCi().forEach((ci, count) -> { + json.beginObject(); + json.prop("ci", ci); + json.prop(COUNT, count); + json.endObject(); + }); + json.endArray(); + } } diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java index 2b0c918d9c5..f1d55c74abf 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java @@ -60,6 +60,7 @@ public class TelemetryDataJsonWriterTest { .setExternalAuthenticationProviders(asList("github", "gitlab")) .setProjectCountByScm(Collections.emptyMap()) .setSonarlintWeeklyUsers(10) + .setProjectCountByCi(Collections.emptyMap()) .setDatabase(new TelemetryData.Database("H2", "11")) .setUsingBranches(true); @@ -244,6 +245,23 @@ public class TelemetryDataJsonWriterTest { + "]}"); } + @Test + public void write_project_count_by_ci() { + TelemetryData data = SOME_TELEMETRY_DATA + .setProjectCountByCi(ImmutableMap.of("Bitbucket Pipelines", 5L, "Github Actions", 4L, "Jenkins", 3L, "undetected", 2L)) + .build(); + + String json = writeTelemetryData(data); + + assertJson(json).isSimilarTo("{" + + " \"projectCountByCI\": [" + + "{ \"ci\":\"Bitbucket Pipelines\", \"count\":5}," + + "{ \"ci\":\"Github Actions\", \"count\":4}," + + "{ \"ci\":\"Jenkins\", \"count\":3}," + + "{ \"ci\":\"undetected\", \"count\":2}," + + "]}"); + } + @Test public void write_project_stats_by_language() { int projectCount = random.nextInt(8909); diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java index 16354f7b359..8d26cb3300c 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/TelemetryDataLoaderImpl.java @@ -139,12 +139,9 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { data.setAlmIntegrationCountByAlm(countAlmUsage(dbSession)); data.setExternalAuthenticationProviders(dbClient.userDao().selectExternalIdentityProviders(dbSession)); - Map projectCountPerScmDetected = dbClient.analysisPropertiesDao() - .selectProjectCountPerAnalysisPropertyValueInLastAnalysis(dbSession, CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDSCM) - .stream() - .collect(Collectors.toMap(ProjectCountPerAnalysisPropertyValue::getPropertyValue, ProjectCountPerAnalysisPropertyValue::getCount)); - data.setProjectCountByScm(projectCountPerScmDetected); data.setSonarlintWeeklyUsers(dbClient.userDao().countSonarlintWeeklyUsers(dbSession)); + addScmInformationToTelemetry(dbSession, data); + addCiInformationToTelemetry(dbSession, data); } setSecurityCustomConfigIfPresent(data); @@ -174,6 +171,22 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader { }); } + private void addScmInformationToTelemetry(DbSession dbSession, TelemetryData.Builder data) { + Map projectCountPerScmDetected = dbClient.analysisPropertiesDao() + .selectProjectCountPerAnalysisPropertyValueInLastAnalysis(dbSession, CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDSCM) + .stream() + .collect(Collectors.toMap(ProjectCountPerAnalysisPropertyValue::getPropertyValue, ProjectCountPerAnalysisPropertyValue::getCount)); + data.setProjectCountByScm(projectCountPerScmDetected); + } + + private void addCiInformationToTelemetry(DbSession dbSession, TelemetryData.Builder data) { + Map projectCountPerCiDetected = dbClient.analysisPropertiesDao() + .selectProjectCountPerAnalysisPropertyValueInLastAnalysis(dbSession, CorePropertyDefinitions.SONAR_ANALYSIS_DETECTEDCI) + .stream() + .collect(Collectors.toMap(ProjectCountPerAnalysisPropertyValue::getPropertyValue, ProjectCountPerAnalysisPropertyValue::getCount)); + data.setProjectCountByCi(projectCountPerCiDetected); + } + private Map countAlmUsage(DbSession dbSession) { return dbClient.almSettingDao().selectAll(dbSession).stream() .collect(Collectors.groupingBy(almSettingDto -> { diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/ClusterSystemInfoWriterTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/ClusterSystemInfoWriterTest.java index e22bbe0cd20..f90cb0dba9d 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/ClusterSystemInfoWriterTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/ClusterSystemInfoWriterTest.java @@ -74,8 +74,8 @@ public class ClusterSystemInfoWriterTest { + "\"Search Nodes\":[{\"Name\":\"searchNodes\",\"\":{\"name\":\"searchNodes\"}}]," + "\"Statistics\":{\"id\":\"\",\"version\":\"\",\"database\":{\"name\":\"\",\"version\":\"\"},\"plugins\":[]," + "\"userCount\":0,\"projectCount\":0,\"usingBranches\":false,\"ncloc\":0,\"projectCountByLanguage\":[]," - + "\"nclocByLanguage\":[],\"almIntegrationCount\":[],\"externalAuthProviders\":[],\"projectCountByScm\":[],\"sonarlintWeeklyUsers\":0,\"installationDate\":0," - + "\"installationVersion\":\"\",\"docker\":false}}"); + + "\"nclocByLanguage\":[],\"almIntegrationCount\":[],\"externalAuthProviders\":[],\"projectCountByScm\":[],\"projectCountByCI\":[],\"sonarlintWeeklyUsers\":0," + + "\"installationDate\":0,\"installationVersion\":\"\",\"docker\":false}}"); } private static NodeInfo createNodeInfo(String name) { diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/StandaloneSystemInfoWriterTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/StandaloneSystemInfoWriterTest.java index d9e68091ae1..bd893c90327 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/StandaloneSystemInfoWriterTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/platform/StandaloneSystemInfoWriterTest.java @@ -81,7 +81,7 @@ public class StandaloneSystemInfoWriterTest { assertThat(writer).hasToString("{\"Health\":\"GREEN\",\"Health Causes\":[],\"Section One\":{\"foo\":\"bar\"},\"Section Two\":{\"one\":1,\"two\":2}," + "\"Statistics\":{\"id\":\"\",\"version\":\"\",\"database\":{\"name\":\"\",\"version\":\"\"},\"plugins\":[],\"userCount\":0,\"projectCount\":0,\"usingBranches\":false," + "\"ncloc\":0,\"projectCountByLanguage\":[],\"nclocByLanguage\":[],\"almIntegrationCount\":[],\"externalAuthProviders\":[],\"projectCountByScm\":[]," - + "\"sonarlintWeeklyUsers\":0,\"installationDate\":0,\"installationVersion\":\"\",\"docker\":false}}"); + + "\"projectCountByCI\":[],\"sonarlintWeeklyUsers\":0,\"installationDate\":0,\"installationVersion\":\"\",\"docker\":false}}"); } private void logInAsSystemAdministrator() { diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java index ccf32d67327..4d643f91ac8 100644 --- a/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java +++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDaemonTest.java @@ -68,6 +68,7 @@ public class TelemetryDaemonTest { .setAlmIntegrationCountByAlm(Collections.emptyMap()) .setExternalAuthenticationProviders(singletonList("github")) .setProjectCountByScm(Collections.emptyMap()) + .setProjectCountByCi(Collections.emptyMap()) .setProjectMeasuresStatistics(ProjectMeasuresStatistics.builder() .setProjectCount(12) .setProjectCountByLanguage(Collections.emptyMap()) diff --git a/sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java b/sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java index 58162ad28b6..7e75d695708 100644 --- a/sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java +++ b/sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java @@ -35,6 +35,7 @@ public class CorePropertyDefinitions { public static final String SONAR_ANALYSIS = "sonar.analysis."; public static final String SONAR_ANALYSIS_DETECTEDSCM = "sonar.analysis.detectedscm"; + public static final String SONAR_ANALYSIS_DETECTEDCI = "sonar.analysis.detectedci"; private static final String CATEGORY_ORGANIZATIONS = "organizations"; 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 @@ -28,6 +28,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 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 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 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 - * + *

* 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/ - * + *

* 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 - * + *

* 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 - * + *

* 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/ - * + *

* 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 - * + *

* 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 - * + *

* 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 - * + *

* 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 fromCache = Stream.concat(cache.getAll().entrySet().stream(), Stream.of(constructScmInfo())).map(transformer); - + List> 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 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 constructScmInfo() { @@ -71,12 +80,7 @@ public class ContextPropertiesPublisher implements ReportPublisherStep { } } - private static final class MapEntryToContextPropertyFunction implements Function, ScannerReport.ContextProperty> { - private final ScannerReport.ContextProperty.Builder builder = ScannerReport.ContextProperty.newBuilder(); - - @Override - public ScannerReport.ContextProperty apply(@Nonnull Map.Entry input) { - return builder.clear().setKey(input.getKey()).setValue(input.getValue()).build(); - } + private Map.Entry 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 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 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 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); }