]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-23064 Add is_ai_code_assured flag to telemetry payload
authorAlain Kermis <alain.kermis@sonarsource.com>
Thu, 19 Sep 2024 14:06:50 +0000 (16:06 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 25 Sep 2024 20:02:53 +0000 (20:02 +0000)
server/sonar-telemetry/src/it/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImplIT.java
server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/TelemetryData.java
server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/TelemetryDataJsonWriter.java
server/sonar-telemetry/src/main/java/org/sonar/telemetry/legacy/TelemetryDataLoaderImpl.java
server/sonar-telemetry/src/test/java/org/sonar/telemetry/legacy/TelemetryDataJsonWriterTest.java

index 18a19365cf62a1a0fc08165f5493f16d7e244470..42af73dcce8da269c01be372a23c3495f0b19aea 100644 (file)
  */
 package org.sonar.telemetry.legacy;
 
-import com.tngtech.java.junit.dataprovider.DataProvider;
-import com.tngtech.java.junit.dataprovider.DataProviderRunner;
-import com.tngtech.java.junit.dataprovider.UseDataProvider;
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
-import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.IntStream;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.sonar.api.config.Configuration;
 import org.sonar.api.impl.utils.TestSystem2;
 import org.sonar.core.platform.PlatformEditionProvider;
@@ -47,12 +45,14 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.alm.setting.AlmSettingDto;
 import org.sonar.db.component.AnalysisPropertyDto;
+import org.sonar.db.component.ComponentDbTester;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ProjectData;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.db.newcodeperiod.NewCodePeriodType;
 import org.sonar.db.project.CreationMethod;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.db.property.PropertyDto;
 import org.sonar.db.qualitygate.QualityGateConditionDto;
 import org.sonar.db.qualitygate.QualityGateDto;
@@ -60,6 +60,7 @@ import org.sonar.db.qualityprofile.QProfileDto;
 import org.sonar.db.user.UserDbTester;
 import org.sonar.db.user.UserDto;
 import org.sonar.db.user.UserTelemetryDto;
+import org.sonar.server.ai.code.assurance.AiCodeAssuranceVerifier;
 import org.sonar.server.management.ManagedInstanceService;
 import org.sonar.server.platform.ContainerSupport;
 import org.sonar.server.property.InternalProperties;
@@ -105,14 +106,13 @@ import static org.sonar.server.metric.UnanalyzedLanguageMetrics.UNANALYZED_C_KEY
 import static org.sonar.server.qualitygate.QualityGateCaycStatus.NON_COMPLIANT;
 import static org.sonar.telemetry.legacy.TelemetryDataLoaderImpl.EXTERNAL_SECURITY_REPORT_EXPORTED_AT;
 
-@RunWith(DataProviderRunner.class)
-public class TelemetryDataLoaderImplIT {
-  private final static Long NOW = 100_000_000L;
+class TelemetryDataLoaderImplIT {
+  private static final Long NOW = 100_000_000L;
   public static final String SERVER_ID = "AU-TpxcB-iU5OvuD2FL7";
   private final TestSystem2 system2 = new TestSystem2().setNow(NOW);
 
-  @Rule
-  public DbTester db = DbTester.create(system2);
+  @RegisterExtension
+  private final DbTester db = DbTester.create(system2);
 
   private final FakeServer server = new FakeServer();
   private final PluginRepository pluginRepository = mock(PluginRepository.class);
@@ -126,11 +126,12 @@ public class TelemetryDataLoaderImplIT {
   private final InternalProperties internalProperties = spy(new MapInternalProperties());
   private final ManagedInstanceService managedInstanceService = mock(ManagedInstanceService.class);
   private final CloudUsageDataProvider cloudUsageDataProvider = mock(CloudUsageDataProvider.class);
+  private final AiCodeAssuranceVerifier aiCodeAssuranceVerifier = mock(AiCodeAssuranceVerifier.class);
 
   private final TelemetryDataLoader communityUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, editionProvider,
-    internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider, qualityProfileDataProvider);
+    internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider, qualityProfileDataProvider, aiCodeAssuranceVerifier);
   private final TelemetryDataLoader commercialUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, editionProvider,
-    internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider, qualityProfileDataProvider);
+    internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider, qualityProfileDataProvider, aiCodeAssuranceVerifier);
 
   private QualityGateDto builtInDefaultQualityGate;
   private MetricDto bugsDto;
@@ -139,8 +140,8 @@ public class TelemetryDataLoaderImplIT {
   private MetricDto technicalDebtDto;
   private MetricDto developmentCostDto;
 
-  @Before
-  public void setUpBuiltInQualityGate() {
+  @BeforeEach
+  void setUpBuiltInQualityGate() {
     String builtInQgName = "Sonar way";
     builtInDefaultQualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName(builtInQgName).setBuiltIn(true));
     when(qualityGateCaycChecker.checkCaycCompliant(any(), any())).thenReturn(NON_COMPLIANT);
@@ -154,7 +155,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void send_telemetry_data() {
+  void send_telemetry_data() {
     String version = "7.5.4";
     Long analysisDate = 1L;
     Long lastConnectionDate = 5L;
@@ -177,7 +178,9 @@ public class TelemetryDataLoaderImplIT {
     MetricDto coverage = db.measures().insertMetric(m -> m.setKey(COVERAGE_KEY));
     MetricDto nclocDistrib = db.measures().insertMetric(m -> m.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY));
 
-    ProjectData projectData1 = db.components().insertPrivateProject();
+    ProjectData projectData1 = db.components().insertPrivateProject(ComponentDbTester.defaults(), projectDto -> projectDto.setAiCodeAssurance(true));
+    when(aiCodeAssuranceVerifier.isAiCodeAssured(projectData1.getProjectDto().getAiCodeAssurance())).thenReturn(true);
+
     ComponentDto mainBranch1 = projectData1.getMainBranchComponent();
     var branch1 = db.components().insertProjectBranch(mainBranch1, branchDto -> branchDto.setKey("reference"));
     var branch2 = db.components().insertProjectBranch(mainBranch1, branchDto -> branchDto.setKey("custom"));
@@ -194,7 +197,9 @@ public class TelemetryDataLoaderImplIT {
     db.measures().insertLiveMeasure(branch1, technicalDebtDto, m -> m.setValue(6d).setData((String) null));
     db.measures().insertLiveMeasure(branch2, technicalDebtDto, m -> m.setValue(7d).setData((String) null));
 
-    ProjectData projectData2 = db.components().insertPrivateProject();
+    ProjectData projectData2 = db.components().insertPrivateProject(ComponentDbTester.defaults(), projectDto -> projectDto.setAiCodeAssurance(false));
+    when(aiCodeAssuranceVerifier.isAiCodeAssured(projectData2.getProjectDto().getAiCodeAssurance())).thenReturn(false);
+
     ComponentDto mainBranch2 = projectData2.getMainBranchComponent();
     db.measures().insertLiveMeasure(mainBranch2, lines, m -> m.setValue(200d));
     db.measures().insertLiveMeasure(mainBranch2, ncloc, m -> m.setValue(200d));
@@ -289,12 +294,13 @@ public class TelemetryDataLoaderImplIT {
         ProjectStatistics::getDevelopmentCost,
         ProjectStatistics::getTechnicalDebt,
         ProjectStatistics::getNcdId,
-        ProjectStatistics::isMonorepo)
+        ProjectStatistics::isMonorepo,
+        ProjectStatistics::isAiCodeAssured)
       .containsExactlyInAnyOrder(
         tuple(3L, 0L, qualityGate1.getUuid(), "scm-1", "ci-1", "azure_devops_cloud", Optional.of(1L), Optional.of(1L), Optional.of(1L), Optional.of(50L), Optional.of(5L),
-          projectNcdId, false),
+          projectNcdId, false, true),
         tuple(1L, 0L, builtInDefaultQualityGate.getUuid(), "scm-2", "ci-2", "github_cloud", Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(),
-          Optional.empty(), instanceNcdId, true));
+          Optional.empty(), instanceNcdId, true, false));
 
     assertThat(data.getBranches())
       .extracting(Branch::branchUuid, Branch::ncdId)
@@ -333,7 +339,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void send_branch_measures_data() {
+  void send_branch_measures_data() {
     Long analysisDate = ZonedDateTime.now(ZoneId.systemDefault()).toInstant().toEpochMilli();
 
     MetricDto qg = db.measures().insertMetric(m -> m.setKey(ALERT_STATUS_KEY));
@@ -395,7 +401,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void take_largest_branch_snapshot_project_data() {
+  void take_largest_branch_snapshot_project_data() {
     server.setId(SERVER_ID).setVersion("7.5.4");
 
     MetricDto lines = db.measures().insertMetric(m -> m.setKey(LINES_KEY));
@@ -442,7 +448,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void load_shouldProvideQualityProfileInProjectSection() {
+  void load_shouldProvideQualityProfileInProjectSection() {
     server.setId(SERVER_ID).setVersion("7.5.4");
     MetricDto ncloc = db.measures().insertMetric(m -> m.setKey(NCLOC_KEY));
     MetricDto nclocDistrib = db.measures().insertMetric(m -> m.setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY));
@@ -480,7 +486,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void load_shouldProvideCreationMethodInProjectStatisticsSection() {
+  void load_shouldProvideCreationMethodInProjectStatisticsSection() {
     server.setId(SERVER_ID).setVersion("7.5.4");
 
     ProjectData projectData1 = db.components().insertPrivateProjectWithCreationMethod(CreationMethod.LOCAL_API);
@@ -503,7 +509,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void test_ncd_on_community_edition() {
+  void test_ncd_on_community_edition() {
     server.setId(SERVER_ID).setVersion("7.5.4");
     when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY));
 
@@ -526,8 +532,23 @@ public class TelemetryDataLoaderImplIT {
       .contains(tuple(branch.uuid(), projectNcdId));
   }
 
+  @ParameterizedTest
+  @MethodSource("values")
+  void load_shouldContainCorrectAiCodeAssuranceField(boolean expected) {
+    ProjectDto project1 = db.components().insertPublicProject(componentDto -> {},
+      projectDto -> projectDto.setAiCodeAssurance(expected)).getProjectDto();
+
+    when(aiCodeAssuranceVerifier.isAiCodeAssured(project1.getAiCodeAssurance())).thenReturn(expected);
+
+    TelemetryData data = communityUnderTest.load();
+
+    assertThat(data.getProjectStatistics())
+      .extracting(ProjectStatistics::isAiCodeAssured)
+      .containsExactly(expected);
+  }
+
   @Test
-  public void data_contains_weekly_count_sonarlint_users() {
+  void data_contains_weekly_count_sonarlint_users() {
     db.users().insertUser(c -> c.setLastSonarlintConnectionDate(NOW - 100_000L));
     db.users().insertUser(c -> c.setLastSonarlintConnectionDate(NOW));
     // these don't count
@@ -540,7 +561,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void send_server_id_and_version() {
+  void send_server_id_and_version() {
     String id = randomAlphanumeric(40);
     String version = randomAlphanumeric(10);
     server.setId(id);
@@ -556,7 +577,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void send_server_installation_date_and_installation_version() {
+  void send_server_installation_date_and_installation_version() {
     String installationVersion = "7.9.BEST.LTS.EVER";
     Long installationDate = 1546300800000L; // 2019/01/01
     internalProperties.write(InternalProperties.INSTALLATION_DATE, String.valueOf(installationDate));
@@ -569,14 +590,14 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void send_correct_sequence_number() {
+  void send_correct_sequence_number() {
     internalProperties.write(TelemetryDaemon.I_PROP_MESSAGE_SEQUENCE, "10");
     TelemetryData data = communityUnderTest.load();
     assertThat(data.getMessageSequenceNumber()).isEqualTo(11L);
   }
 
   @Test
-  public void do_not_send_server_installation_details_if_missing_property() {
+  void do_not_send_server_installation_details_if_missing_property() {
     TelemetryData data = communityUnderTest.load();
     assertThat(data.getInstallationDate()).isNull();
     assertThat(data.getInstallationVersion()).isNull();
@@ -587,7 +608,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void send_unanalyzed_languages_flags_when_edition_is_community() {
+  void send_unanalyzed_languages_flags_when_edition_is_community() {
     when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY));
     MetricDto unanalyzedC = db.measures().insertMetric(m -> m.setKey(UNANALYZED_C_KEY));
     MetricDto unanalyzedCpp = db.measures().insertMetric(m -> m.setKey(UNANALYZED_CPP_KEY));
@@ -604,7 +625,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void do_not_send_unanalyzed_languages_flags_when_edition_is_not_community() {
+  void do_not_send_unanalyzed_languages_flags_when_edition_is_not_community() {
     when(editionProvider.get()).thenReturn(Optional.of(DEVELOPER));
     MetricDto unanalyzedC = db.measures().insertMetric(m -> m.setKey(UNANALYZED_C_KEY));
     MetricDto unanalyzedCpp = db.measures().insertMetric(m -> m.setKey(UNANALYZED_CPP_KEY));
@@ -620,7 +641,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void unanalyzed_languages_flags_are_set_to_false_when_no_unanalyzed_languages_and_edition_is_community() {
+  void unanalyzed_languages_flags_are_set_to_false_when_no_unanalyzed_languages_and_edition_is_community() {
     when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY));
 
     TelemetryData data = communityUnderTest.load();
@@ -630,7 +651,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void populate_security_custom_config_for_languages_on_enterprise() {
+  void populate_security_custom_config_for_languages_on_enterprise() {
     when(editionProvider.get()).thenReturn(Optional.of(ENTERPRISE));
 
     when(configuration.get("sonar.security.config.javasecurity")).thenReturn(Optional.of("{}"));
@@ -645,7 +666,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void skip_security_custom_config_on_community() {
+  void skip_security_custom_config_on_community() {
     when(editionProvider.get()).thenReturn(Optional.of(COMMUNITY));
 
     TelemetryData data = communityUnderTest.load();
@@ -654,7 +675,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void undetected_alm_ci_slm_data() {
+  void undetected_alm_ci_slm_data() {
     server.setId(SERVER_ID).setVersion("7.5.4");
     db.components().insertPublicProject().getMainBranchComponent();
     TelemetryData data = communityUnderTest.load();
@@ -664,7 +685,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void givenExistingExternalSecurityReport_whenTelemetryIsGenerated_payloadShouldContainLastUsageDate() {
+  void givenExistingExternalSecurityReport_whenTelemetryIsGenerated_payloadShouldContainLastUsageDate() {
     server.setId(SERVER_ID).setVersion("7.5.4");
     ProjectData projectData = db.components().insertPublicProject();
     db.getDbClient().propertiesDao().saveProperty(new PropertyDto().setKey(EXTERNAL_SECURITY_REPORT_EXPORTED_AT).setEntityUuid(projectData.projectUuid()).setValue("1"));
@@ -676,9 +697,9 @@ public class TelemetryDataLoaderImplIT {
       .get().isEqualTo(1L);
   }
 
-  @Test
-  @UseDataProvider("getManagedInstanceData")
-  public void managedInstanceData_containsCorrectInformation(boolean isManaged, String provider) {
+  @ParameterizedTest
+  @MethodSource("managedInstanceData")
+  void managedInstanceData_containsCorrectInformation(boolean isManaged, String provider) {
     when(managedInstanceService.isInstanceExternallyManaged()).thenReturn(isManaged);
     when(managedInstanceService.getProviderName()).thenReturn(provider);
 
@@ -690,7 +711,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void load_shouldContainCloudUsage() {
+  void load_shouldContainCloudUsage() {
     CloudUsage cloudUsage = new CloudUsage(true, "1.27", "linux/amd64", "5.4.181-99.354.amzn2.x86_64", "10.1.0", false, false, "docker", false);
     when(cloudUsageDataProvider.getCloudUsage()).thenReturn(cloudUsage);
 
@@ -699,7 +720,7 @@ public class TelemetryDataLoaderImplIT {
   }
 
   @Test
-  public void default_quality_gate_sent_with_project() {
+  void default_quality_gate_sent_with_project() {
     db.components().insertPublicProject();
     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(qg -> qg.setName("anything").setBuiltIn(true));
     db.qualityGates().setDefaultQualityGate(qualityGate);
@@ -723,22 +744,19 @@ public class TelemetryDataLoaderImplIT {
       .setCreatedAt(1L));
   }
 
-  @DataProvider
-  public static Set<String> getScimFeatureStatues() {
-    HashSet<String> result = new HashSet<>();
-    result.add("true");
-    result.add("false");
-    result.add(null);
-    return result;
+  private static Stream<Arguments> managedInstanceData() {
+    return Stream.of(
+      Arguments.of(true, "scim"),
+      Arguments.of(true, "github"),
+      Arguments.of(true, "gitlab"),
+      Arguments.of(false, null)
+    );
   }
 
-  @DataProvider
-  public static Object[][] getManagedInstanceData() {
-    return new Object[][] {
-      {true, "scim"},
-      {true, "github"},
-      {true, "gitlab"},
-      {false, null},
-    };
+  private static Stream<Arguments> values() {
+    return Stream.of(
+      Arguments.of(false),
+      Arguments.of(true)
+    );
   }
 }
index 649a34710dc5756842e217c31855da087e5fa386..9278d81162dfe08700b7ff41ab15ab4812844d25 100644 (file)
@@ -406,6 +406,7 @@ public class TelemetryData {
     private final Long externalSecurityReportExportedAt;
     private final CreationMethod creationMethod;
     private final Boolean monorepo;
+    private final Boolean isAiCodeAssured;
 
     ProjectStatistics(Builder builder) {
       this.projectUuid = builder.projectUuid;
@@ -424,6 +425,7 @@ public class TelemetryData {
       this.externalSecurityReportExportedAt = builder.externalSecurityReportExportedAt;
       this.creationMethod = builder.creationMethod;
       this.monorepo = builder.monorepo;
+      this.isAiCodeAssured = builder.isAiCodeAssured;
     }
 
     public int getNcdId() {
@@ -490,6 +492,10 @@ public class TelemetryData {
       return monorepo;
     }
 
+    public Boolean isAiCodeAssured() {
+      return isAiCodeAssured;
+    }
+
     static class Builder {
       private String projectUuid;
       private Long branchCount;
@@ -507,6 +513,7 @@ public class TelemetryData {
       private Long externalSecurityReportExportedAt;
       private CreationMethod creationMethod;
       private Boolean monorepo;
+      private Boolean isAiCodeAssured;
 
       public Builder setProjectUuid(String projectUuid) {
         this.projectUuid = projectUuid;
@@ -588,6 +595,11 @@ public class TelemetryData {
         return this;
       }
 
+      public Builder setIsAiCodeAssured(Boolean isAiCodeAssured) {
+        this.isAiCodeAssured = isAiCodeAssured;
+        return this;
+      }
+
       public ProjectStatistics build() {
         return new ProjectStatistics(this);
       }
index 486a47e1d65d522031395654533d9e7b84fdf06a..b186e15f05983014d485d0eec5a227b0bd5b5d7e 100644 (file)
@@ -204,6 +204,7 @@ public class TelemetryDataJsonWriter {
         json.prop(NCD_ID, project.getNcdId());
         json.prop("project_creation_method", project.getCreationMethod().name());
         json.prop("monorepo", project.isMonorepo());
+        json.prop("is_ai_code_assured", project.isAiCodeAssured());
         project.getBugs().ifPresent(bugs -> json.prop("bugs", bugs));
         project.getVulnerabilities().ifPresent(vulnerabilities -> json.prop("vulnerabilities", vulnerabilities));
         project.getSecurityHotspots().ifPresent(securityHotspots -> json.prop("securityHotspots", securityHotspots));
index 112ea8a4c13c3cf67e1e773c9988570fabe32ec4..b1eac7b4e527aa3e519924faf59d4dd5b553adc7 100644 (file)
@@ -59,6 +59,7 @@ import org.sonar.db.property.PropertyQuery;
 import org.sonar.db.qualitygate.ProjectQgateAssociationDto;
 import org.sonar.db.qualitygate.QualityGateConditionDto;
 import org.sonar.db.qualitygate.QualityGateDto;
+import org.sonar.server.ai.code.assurance.AiCodeAssuranceVerifier;
 import org.sonar.server.management.ManagedInstanceService;
 import org.sonar.server.platform.ContainerSupport;
 import org.sonar.server.property.InternalProperties;
@@ -114,6 +115,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader {
   private final ManagedInstanceService managedInstanceService;
   private final CloudUsageDataProvider cloudUsageDataProvider;
   private final QualityProfileDataProvider qualityProfileDataProvider;
+  private final AiCodeAssuranceVerifier aiCodeAssuranceVerifier;
   private final Set<NewCodeDefinition> newCodeDefinitions = new HashSet<>();
   private final Map<String, NewCodeDefinition> ncdByProject = new HashMap<>();
   private final Map<String, NewCodeDefinition> ncdByBranch = new HashMap<>();
@@ -125,7 +127,8 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader {
   public TelemetryDataLoaderImpl(Server server, DbClient dbClient, PluginRepository pluginRepository,
     PlatformEditionProvider editionProvider, InternalProperties internalProperties, Configuration configuration,
     ContainerSupport containerSupport, QualityGateCaycChecker qualityGateCaycChecker, QualityGateFinder qualityGateFinder,
-    ManagedInstanceService managedInstanceService, CloudUsageDataProvider cloudUsageDataProvider, QualityProfileDataProvider qualityProfileDataProvider) {
+    ManagedInstanceService managedInstanceService, CloudUsageDataProvider cloudUsageDataProvider, QualityProfileDataProvider qualityProfileDataProvider,
+    AiCodeAssuranceVerifier aiCodeAssuranceVerifier) {
     this.server = server;
     this.dbClient = dbClient;
     this.pluginRepository = pluginRepository;
@@ -138,6 +141,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader {
     this.managedInstanceService = managedInstanceService;
     this.cloudUsageDataProvider = cloudUsageDataProvider;
     this.qualityProfileDataProvider = qualityProfileDataProvider;
+    this.aiCodeAssuranceVerifier = aiCodeAssuranceVerifier;
   }
 
   private static Database loadDatabaseMetadata(DbSession dbSession) {
@@ -323,6 +327,7 @@ public class TelemetryDataLoaderImpl implements TelemetryDataLoader {
         .setExternalSecurityReportExportedAt(securityReportExportedAtByProjectUuid.get(projectUuid))
         .setCreationMethod(project.getCreationMethod())
         .setMonorepo(resolveMonorepo(almAndUrlAndMonorepoByProject, projectUuid))
+        .setIsAiCodeAssured(aiCodeAssuranceVerifier.isAiCodeAssured(project.getAiCodeAssurance()))
         .build();
       projectStatistics.add(stats);
     }
index 80f72fd2c2b333b02b8b63b93cbc5c9b29115398..a4cdbb2559d6a9bb28393043594de768b2f41f8b 100644 (file)
@@ -30,9 +30,11 @@ import java.util.Random;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
+import java.util.stream.Stream;
 import org.jetbrains.annotations.NotNull;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.text.JsonWriter;
@@ -462,7 +464,8 @@ class TelemetryDataJsonWriterTest {
             "ncdId": 12345,
             "externalSecurityReportExportedAt": 1500000,
             "project_creation_method": "LOCAL_API",
-            "monorepo": true
+            "monorepo": true,
+            "is_ai_code_assured": false
           },
           {
             "projectUuid": "uuid-1",
@@ -480,7 +483,8 @@ class TelemetryDataJsonWriterTest {
             "ncdId": 12345,
             "externalSecurityReportExportedAt": 1500001,
             "project_creation_method": "LOCAL_API",
-            "monorepo": false
+            "monorepo": false,
+            "is_ai_code_assured": true
           },
           {
             "projectUuid": "uuid-2",
@@ -498,7 +502,8 @@ class TelemetryDataJsonWriterTest {
             "ncdId": 12345,
             "externalSecurityReportExportedAt": 1500002,
             "project_creation_method": "LOCAL_API",
-            "monorepo": true
+            "monorepo": true,
+            "is_ai_code_assured": false
           }
         ]
       }
@@ -732,7 +737,8 @@ class TelemetryDataJsonWriterTest {
       .setDevops("devops-" + i)
       .setNcdId(NCD_ID)
       .setCreationMethod(CreationMethod.LOCAL_API)
-      .setMonorepo(false);
+      .setMonorepo(false)
+      .setIsAiCodeAssured(true);
   }
 
   private static TelemetryData.ProjectStatistics.Builder getProjectStatisticsWithMetricBuilder(int i) {
@@ -744,6 +750,7 @@ class TelemetryDataJsonWriterTest {
       .setTechnicalDebt((i + 1L) * 60d)
       .setExternalSecurityReportExportedAt(1_500_000L + i)
       .setCreationMethod(CreationMethod.LOCAL_API)
+      .setIsAiCodeAssured(i % 2 != 0)
       .setMonorepo(i % 2 == 0);
   }
 
@@ -768,11 +775,8 @@ class TelemetryDataJsonWriterTest {
     return List.of(NCD_INSTANCE, NCD_PROJECT);
   }
 
-  @DataProvider
-  public static Object[][] allEditions() {
-    return Arrays.stream(EditionProvider.Edition.values())
-      .map(t -> new Object[] {t})
-      .toArray(Object[][]::new);
+  private static Stream<Arguments> allEditions() {
+    return Arrays.stream(EditionProvider.Edition.values()).map(Arguments::of);
   }
 
   private String writeTelemetryData(TelemetryData data) {