]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10597 Update CE_ACTIVITY#SUBMITTER_LOGIN to SUBMITTER_UUID
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 9 May 2018 15:30:25 +0000 (17:30 +0200)
committerSonarTech <sonartech@sonarsource.com>
Wed, 23 May 2018 18:20:48 +0000 (20:20 +0200)
12 files changed:
server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeActivityDto.java
server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/DbVersion72Test.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest/ce_activity.sql [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java
server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java
tests/src/test/java/org/sonarqube/tests/user/SonarCloudUpdateLoginDuringAuthenticationTest.java

index 99ad46f3a05c478bc91bc9660aafe2b7f4efcd7d..1718c97533d18caad18eaf9a60e19d7db99cd857 100644 (file)
@@ -655,7 +655,7 @@ CREATE TABLE "CE_ACTIVITY" (
   "STATUS" VARCHAR(15) NOT NULL,
   "IS_LAST" BOOLEAN NOT NULL,
   "IS_LAST_KEY" VARCHAR(55) NOT NULL,
-  "SUBMITTER_LOGIN" VARCHAR(255) NULL,
+  "SUBMITTER_UUID" VARCHAR(255) NULL,
   "WORKER_UUID" VARCHAR(40) NULL,
   "EXECUTION_COUNT" INTEGER NOT NULL,
   "SUBMITTED_AT" BIGINT NOT NULL,
index 1be750ac32355a7a79743d90cec4db90da7fed23..df5d9aa8b008edcb5aae54c1357bacfeb2c509c5 100644 (file)
@@ -42,7 +42,7 @@ public class CeActivityDto {
   private String taskType;
   private boolean isLast;
   private String isLastKey;
-  private String submitterLogin;
+  private String submitterUuid;
   private String workerUuid;
   private long submittedAt;
   private Long startedAt;
@@ -92,8 +92,7 @@ public class CeActivityDto {
     this.taskType = queueDto.getTaskType();
     this.componentUuid = queueDto.getComponentUuid();
     this.isLastKey = format("%s%s", taskType, Strings.nullToEmpty(componentUuid));
-    // FIXME
-    this.submitterLogin = queueDto.getSubmitterUuid();
+    this.submitterUuid = queueDto.getSubmitterUuid();
     this.workerUuid = queueDto.getWorkerUuid();
     this.submittedAt = queueDto.getCreatedAt();
     this.startedAt = queueDto.getStartedAt();
@@ -152,8 +151,8 @@ public class CeActivityDto {
   }
 
   @CheckForNull
-  public String getSubmitterLogin() {
-    return submitterLogin;
+  public String getSubmitterUuid() {
+    return submitterUuid;
   }
 
   public long getSubmittedAt() {
@@ -294,7 +293,7 @@ public class CeActivityDto {
       ", taskType='" + taskType + '\'' +
       ", isLast=" + isLast +
       ", isLastKey='" + isLastKey + '\'' +
-      ", submitterLogin='" + submitterLogin + '\'' +
+      ", submitterUuid='" + submitterUuid + '\'' +
       ", workerUuid='" + workerUuid + '\'' +
       ", submittedAt=" + submittedAt +
       ", startedAt=" + startedAt +
index 127b1e2098c131f50b55179ae5879f5f5d2303c0..6c4779f6e93190f632afee58826dcb3324a5d83f 100644 (file)
@@ -22,7 +22,7 @@
     ca.component_uuid as componentUuid,
     ca.analysis_uuid as analysisUuid,
     ca.status as status,
-    ca.submitter_login as submitterLogin,
+    ca.submitter_uuid as submitterUuid,
     ca.submitted_at as submittedAt,
     ca.worker_uuid as workerUuid,
     ca.started_at as startedAt,
       task_type,
       is_last,
       is_last_key,
-      submitter_login,
+      submitter_uuid,
       submitted_at,
       worker_uuid,
       execution_count,
       #{taskType,jdbcType=VARCHAR},
       #{isLast,jdbcType=BOOLEAN},
       #{isLastKey,jdbcType=VARCHAR},
-      #{submitterLogin,jdbcType=VARCHAR},
+      #{submitterUuid,jdbcType=VARCHAR},
       #{submittedAt,jdbcType=BIGINT},
       #{workerUuid,jdbcType=VARCHAR},
       0,
index b8ed217c8ed11597fae713108602464b49dc7396..f03acf465479b029c488968275ed9b0350f57141 100644 (file)
@@ -63,7 +63,7 @@ public class CeActivityDaoTest {
     assertThat(dto.getUuid()).isEqualTo("TASK_1");
     assertThat(dto.getComponentUuid()).isEqualTo("PROJECT_1");
     assertThat(dto.getStatus()).isEqualTo(CeActivityDto.Status.SUCCESS);
-    assertThat(dto.getSubmitterLogin()).isEqualTo("submitter uuid");
+    assertThat(dto.getSubmitterUuid()).isEqualTo("submitter uuid");
     assertThat(dto.getSubmittedAt()).isEqualTo(1_300_000_000_000L);
     assertThat(dto.getWorkerUuid()).isEqualTo("worker uuid");
     assertThat(dto.getIsLast()).isTrue();
index 598349bb8211c1aafdeb3f35288a089b4b0cc9c7..d072d97038643b9370fe154da043dd81c323a327 100644 (file)
@@ -50,6 +50,7 @@ public class DbVersion72 implements DbVersion {
       .add(2120, "Rename USER_LOGIN TO USER_UUID on table MANUAL_MEASURES", RenameUserLoginToUserUuidOnTableManualMeasures.class)
       .add(2121, "Rename NOTE_USER_LOGIN TO NOTE_USER_UUID on table RULES_METADATA", RenameNoteUserLoginToNoteUserUuidOnTableRulesMetadata.class)
       .add(2122, "Rename SUBMITTER_LOGIN TO SUBMITTER_UUID on table CE_QUEUE", RenameSubmitterLoginToSubmitterUuidOnTableCeQueue.class)
+      .add(2123, "Rename SUBMITTER_LOGIN TO SUBMITTER_UUID on table CE_ACTIVITY", RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.class)
     ;
   }
 }
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivity.java
new file mode 100644 (file)
index 0000000..b57f575
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.server.platform.db.migration.version.v72;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.RenameColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class RenameSubmitterLoginToSubmitterUuidOnTableCeActivity extends DdlChange {
+
+  public RenameSubmitterLoginToSubmitterUuidOnTableCeActivity(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new RenameColumnsBuilder(getDialect(), "ce_activity")
+      .renameColumn("submitter_login",
+        newVarcharColumnDefBuilder()
+          .setColumnName("submitter_uuid")
+          .setLimit(255)
+          .setIsNullable(true)
+          .build())
+      .build());
+  }
+}
index 899207322d4d7e5f14d93a7b87401d77c8983602..3109b8f8735a33a610d925528955b75f0c86071a 100644 (file)
@@ -34,7 +34,7 @@ public class DbVersion72Test {
 
   @Test
   public void verify_migration_count() {
-    verifyMigrationCount(underTest, 23);
+    verifyMigrationCount(underTest, 24);
   }
 
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.java
new file mode 100644 (file)
index 0000000..988b2be
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.server.platform.db.migration.version.v72;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static java.sql.Types.VARCHAR;
+
+public class RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest {
+
+  @Rule
+  public final CoreDbTester db = CoreDbTester.createForSchema(RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest.class, "ce_activity.sql");
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private RenameSubmitterLoginToSubmitterUuidOnTableCeActivity underTest = new RenameSubmitterLoginToSubmitterUuidOnTableCeActivity(db.database());
+
+  @Test
+  public void rename_column() throws SQLException {
+    underTest.execute();
+
+    db.assertColumnDefinition("ce_activity", "submitter_uuid", VARCHAR, 255, true);
+    db.assertColumnDoesNotExist("ce_activity", "submitter_login");
+  }
+
+  public void migration_is_not_reentrant() throws SQLException {
+    underTest.execute();
+
+    expectedException.expect(IllegalStateException.class);
+
+    underTest.execute();
+  }
+
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest/ce_activity.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v72/RenameSubmitterLoginToSubmitterUuidOnTableCeActivityTest/ce_activity.sql
new file mode 100644 (file)
index 0000000..fe5d1ba
--- /dev/null
@@ -0,0 +1,27 @@
+CREATE TABLE "CE_ACTIVITY" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(40) NOT NULL,
+  "TASK_TYPE" VARCHAR(15) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(40) NULL,
+  "ANALYSIS_UUID" VARCHAR(50) NULL,
+  "STATUS" VARCHAR(15) NOT NULL,
+  "IS_LAST" BOOLEAN NOT NULL,
+  "IS_LAST_KEY" VARCHAR(55) NOT NULL,
+  "SUBMITTER_LOGIN" VARCHAR(255) NULL,
+  "WORKER_UUID" VARCHAR(40) NULL,
+  "EXECUTION_COUNT" INTEGER NOT NULL,
+  "SUBMITTED_AT" BIGINT NOT NULL,
+  "STARTED_AT" BIGINT NULL,
+  "EXECUTED_AT" BIGINT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+  "EXECUTION_TIME_MS" BIGINT NULL,
+  "ERROR_MESSAGE" VARCHAR(1000),
+  "ERROR_STACKTRACE" CLOB,
+  "ERROR_TYPE" VARCHAR(20)
+);
+
+CREATE UNIQUE INDEX "CE_ACTIVITY_UUID" ON "CE_ACTIVITY" ("UUID");
+CREATE INDEX "CE_ACTIVITY_COMPONENT_UUID" ON "CE_ACTIVITY" ("COMPONENT_UUID");
+CREATE INDEX "CE_ACTIVITY_ISLASTKEY" ON "CE_ACTIVITY" ("IS_LAST_KEY");
+CREATE INDEX "CE_ACTIVITY_ISLAST_STATUS" ON "CE_ACTIVITY" ("IS_LAST", "STATUS");
\ No newline at end of file
index 9b20e1f340081da1ac79c9091e67911ce9375944..54e48e3c160c06d14c4cec6bde50c339f700ded6 100644 (file)
@@ -68,36 +68,30 @@ public class TaskFormatter {
 
   public List<Ce.Task> formatQueue(DbSession dbSession, List<CeQueueDto> dtos) {
     DtoCache cache = DtoCache.forQueueDtos(dbClient, dbSession, dtos);
-    Map<String, UserDto> usersByUuid = getUsersByUuid(dbSession, dtos);
-    return dtos.stream().map(input -> formatQueue(input, cache, usersByUuid)).collect(MoreCollectors.toList(dtos.size()));
+    return dtos.stream().map(input -> formatQueue(input, cache)).collect(MoreCollectors.toList(dtos.size()));
   }
 
   public Ce.Task formatQueue(DbSession dbSession, CeQueueDto queue) {
-    return formatQueue(queue, DtoCache.forQueueDtos(dbClient, dbSession, singletonList(queue)), getUsersByUuid(dbSession, singletonList(queue)));
+    return formatQueue(queue, DtoCache.forQueueDtos(dbClient, dbSession, singletonList(queue)));
   }
 
-  private Map<String, UserDto> getUsersByUuid(DbSession dbSession, Collection<CeQueueDto> dtos) {
-    Set<String> submitterUuids = dtos.stream().map(CeQueueDto::getSubmitterUuid).filter(Objects::nonNull).collect(toSet());
-    return dbClient.userDao().selectByUuids(dbSession, submitterUuids).stream().collect(uniqueIndex(UserDto::getUuid));
-  }
-
-  private Ce.Task formatQueue(CeQueueDto dto, DtoCache componentDtoCache, Map<String, UserDto> usersByUuid) {
+  private Ce.Task formatQueue(CeQueueDto dto, DtoCache cache) {
     Ce.Task.Builder builder = Ce.Task.newBuilder();
-    String organizationKey = componentDtoCache.getOrganizationKey(dto.getComponentUuid());
+    String organizationKey = cache.getOrganizationKey(dto.getComponentUuid());
     setNullable(organizationKey, builder::setOrganization);
     if (dto.getComponentUuid() != null) {
       builder.setComponentId(dto.getComponentUuid());
-      setComponent(builder, dto.getComponentUuid(), componentDtoCache);
+      setComponent(builder, dto.getComponentUuid(), cache);
     }
     builder.setId(dto.getUuid());
     builder.setStatus(Ce.TaskStatus.valueOf(dto.getStatus().name()));
     builder.setType(dto.getTaskType());
     builder.setLogs(false);
-    setNullable(dto.getSubmitterUuid(), s -> builder.setSubmitterLogin(usersByUuid.get(s).getLogin()));
+    cache.getUser(dto.getSubmitterUuid()).ifPresent(user -> builder.setSubmitterLogin(user.getLogin()));
     builder.setSubmittedAt(formatDateTime(new Date(dto.getCreatedAt())));
     setNullable(dto.getStartedAt(), builder::setStartedAt, DateUtils::formatDateTime);
     setNullable(computeExecutionTimeMs(dto), builder::setExecutionTimeMs);
-    setBranchOrPullRequest(builder, dto.getUuid(), componentDtoCache);
+    setBranchOrPullRequest(builder, dto.getUuid(), cache);
     return builder.build();
   }
 
@@ -112,20 +106,20 @@ public class TaskFormatter {
       .collect(MoreCollectors.toList(dtos.size()));
   }
 
-  private static Ce.Task formatActivity(CeActivityDto dto, DtoCache componentDtoCache, @Nullable String scannerContext) {
+  private static Ce.Task formatActivity(CeActivityDto dto, DtoCache cache, @Nullable String scannerContext) {
     Ce.Task.Builder builder = Ce.Task.newBuilder();
-    String organizationKey = componentDtoCache.getOrganizationKey(dto.getComponentUuid());
+    String organizationKey = cache.getOrganizationKey(dto.getComponentUuid());
     setNullable(organizationKey, builder::setOrganization);
     builder.setId(dto.getUuid());
     builder.setStatus(Ce.TaskStatus.valueOf(dto.getStatus().name()));
     builder.setType(dto.getTaskType());
     builder.setLogs(false);
-    setNullable(dto.getComponentUuid(), uuid -> setComponent(builder, uuid, componentDtoCache).setComponentId(uuid));
+    setNullable(dto.getComponentUuid(), uuid -> setComponent(builder, uuid, cache).setComponentId(uuid));
     String analysisUuid = dto.getAnalysisUuid();
     setNullable(analysisUuid, builder::setAnalysisId);
-    setBranchOrPullRequest(builder, dto.getUuid(), componentDtoCache);
+    setBranchOrPullRequest(builder, dto.getUuid(), cache);
     setNullable(analysisUuid, builder::setAnalysisId);
-    setNullable(dto.getSubmitterLogin(), builder::setSubmitterLogin);
+    cache.getUser(dto.getSubmitterUuid()).ifPresent(user -> builder.setSubmitterLogin(user.getLogin()));
     builder.setSubmittedAt(formatDateTime(new Date(dto.getSubmittedAt())));
     setNullable(dto.getStartedAt(), builder::setStartedAt, DateUtils::formatDateTime);
     setNullable(dto.getExecutedAt(), builder::setExecutedAt, DateUtils::formatDateTime);
@@ -172,12 +166,14 @@ public class TaskFormatter {
     private final Map<String, ComponentDto> componentsByUuid;
     private final Map<String, OrganizationDto> organizationsByUuid;
     private final Multimap<String, CeTaskCharacteristicDto> characteristicsByTaskUuid;
+    private final Map<String, UserDto> usersByUuid;
 
     private DtoCache(Map<String, ComponentDto> componentsByUuid, Map<String, OrganizationDto> organizationsByUuid,
-      Multimap<String, CeTaskCharacteristicDto> characteristicsByTaskUuid) {
+      Multimap<String, CeTaskCharacteristicDto> characteristicsByTaskUuid, Map<String, UserDto> usersByUuid) {
       this.componentsByUuid = componentsByUuid;
       this.organizationsByUuid = organizationsByUuid;
       this.characteristicsByTaskUuid = characteristicsByTaskUuid;
+      this.usersByUuid = usersByUuid;
     }
 
     static DtoCache forQueueDtos(DbClient dbClient, DbSession dbSession, Collection<CeQueueDto> ceQueueDtos) {
@@ -187,7 +183,9 @@ public class TaskFormatter {
       Multimap<String, CeTaskCharacteristicDto> characteristicsByTaskUuid = dbClient.ceTaskCharacteristicsDao()
         .selectByTaskUuids(dbSession, ceQueueDtos.stream().map(CeQueueDto::getUuid).collect(Collectors.toList()))
         .stream().collect(MoreCollectors.index(CeTaskCharacteristicDto::getTaskUuid));
-      return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), characteristicsByTaskUuid);
+      Set<String> submitterUuids = ceQueueDtos.stream().map(CeQueueDto::getSubmitterUuid).filter(Objects::nonNull).collect(toSet());
+      Map<String, UserDto> usersByUuid = dbClient.userDao().selectByUuids(dbSession, submitterUuids).stream().collect(uniqueIndex(UserDto::getUuid));
+      return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), characteristicsByTaskUuid, usersByUuid);
     }
 
     private static Set<String> componentUuidsOfCeQueues(Collection<CeQueueDto> ceQueueDtos) {
@@ -207,7 +205,9 @@ public class TaskFormatter {
       Multimap<String, CeTaskCharacteristicDto> characteristicsByTaskUuid = dbClient.ceTaskCharacteristicsDao()
         .selectByTaskUuids(dbSession, ceActivityDtos.stream().map(CeActivityDto::getUuid).collect(Collectors.toList()))
         .stream().collect(MoreCollectors.index(CeTaskCharacteristicDto::getTaskUuid));
-      return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), characteristicsByTaskUuid);
+      Set<String> submitterUuids = ceActivityDtos.stream().map(CeActivityDto::getSubmitterUuid).filter(Objects::nonNull).collect(toSet());
+      Map<String, UserDto> usersByUuid = dbClient.userDao().selectByUuids(dbSession, submitterUuids).stream().collect(uniqueIndex(UserDto::getUuid));
+      return new DtoCache(componentsByUuid, buildOrganizationsByUuid(dbClient, dbSession, componentsByUuid), characteristicsByTaskUuid, usersByUuid);
     }
 
     private static Set<String> getComponentUuidsOfCeActivities(Collection<CeActivityDto> ceActivityDtos) {
@@ -271,6 +271,13 @@ public class TaskFormatter {
         .map(CeTaskCharacteristicDto::getValue)
         .findAny();
     }
+
+    Optional<UserDto> getUser(@Nullable String userUuid) {
+      if (userUuid == null) {
+        return Optional.empty();
+      }
+      return Optional.ofNullable(usersByUuid.get(userUuid));
+    }
   }
 
   /**
index 6e51cee0dd4cab36e3a6c161ddb5677672a04875..42a81c4a6d5fcb8c86b932ea8c7debeeb00bf4e9 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.ce.ws;
 
 import java.util.Collections;
 import java.util.Date;
+import javax.annotation.Nullable;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.DateUtils;
@@ -35,6 +36,7 @@ import org.sonarqube.ws.Ce;
 
 import static java.util.Arrays.asList;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -158,7 +160,8 @@ public class TaskFormatterTest {
 
   @Test
   public void formatActivity() {
-    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED);
+    UserDto user = db.users().insertUser();
+    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, user);
 
     Ce.Task wsTask = underTest.formatActivity(db.getSession(), dto, null);
 
@@ -166,6 +169,7 @@ public class TaskFormatterTest {
     assertThat(wsTask.getId()).isEqualTo("UUID");
     assertThat(wsTask.getStatus()).isEqualTo(Ce.TaskStatus.FAILED);
     assertThat(wsTask.getSubmittedAt()).isEqualTo(DateUtils.formatDateTime(new Date(1_450_000_000_000L)));
+    assertThat(wsTask.getSubmitterLogin()).isEqualTo(user.getLogin());
     assertThat(wsTask.getExecutionTimeMs()).isEqualTo(500L);
     assertThat(wsTask.getAnalysisId()).isEqualTo("U1");
     assertThat(wsTask.getLogs()).isFalse();
@@ -174,7 +178,7 @@ public class TaskFormatterTest {
 
   @Test
   public void formatActivity_set_scanner_context_if_argument_is_non_null() {
-    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED);
+    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null);
 
     String expected = "scanner context baby!";
     Ce.Task wsTask = underTest.formatActivity(db.getSession(), dto, expected);
@@ -185,17 +189,23 @@ public class TaskFormatterTest {
 
   @Test
   public void formatActivities() {
-    CeActivityDto dto1 = newActivity("UUID1", "COMPONENT_UUID", CeActivityDto.Status.FAILED);
-    CeActivityDto dto2 = newActivity("UUID2", "COMPONENT_UUID", CeActivityDto.Status.SUCCESS);
+    UserDto user1 = db.users().insertUser();
+    UserDto user2 = db.users().insertUser();
+    CeActivityDto dto1 = newActivity("UUID1", "COMPONENT_UUID", CeActivityDto.Status.FAILED, user1);
+    CeActivityDto dto2 = newActivity("UUID2", "COMPONENT_UUID", CeActivityDto.Status.SUCCESS, user2);
 
     Iterable<Ce.Task> wsTasks = underTest.formatActivity(db.getSession(), asList(dto1, dto2));
 
-    assertThat(wsTasks).extracting("id").containsExactly("UUID1", "UUID2");
+    assertThat(wsTasks)
+      .extracting(Ce.Task::getId, Ce.Task::getSubmitterLogin)
+      .containsExactlyInAnyOrder(
+        tuple("UUID1", user1.getLogin()),
+        tuple("UUID2", user2.getLogin()));
   }
 
   @Test
   public void formatActivity_with_both_error_message_and_stacktrace() {
-    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED)
+    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null)
       .setErrorMessage("error msg")
       .setErrorStacktrace("error stacktrace")
       .setErrorType("anErrorType");
@@ -209,7 +219,7 @@ public class TaskFormatterTest {
 
   @Test
   public void formatActivity_with_both_error_message_only() {
-    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED)
+    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null)
       .setErrorMessage("error msg");
 
     Ce.Task task = underTest.formatActivity(db.getSession(), Collections.singletonList(dto)).iterator().next();
@@ -220,7 +230,7 @@ public class TaskFormatterTest {
 
   @Test
   public void formatActivity_with_both_error_message_and_only_stacktrace_flag() {
-    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED)
+    CeActivityDto dto = newActivity("UUID", "COMPONENT_UUID", CeActivityDto.Status.FAILED, null)
       .setErrorMessage("error msg");
 
     Ce.Task task = underTest.formatActivity(db.getSession(), Collections.singletonList(dto)).iterator().next();
@@ -229,16 +239,16 @@ public class TaskFormatterTest {
     assertThat(task.hasErrorStacktrace()).isFalse();
   }
 
-  private CeActivityDto newActivity(String taskUuid, String componentUuid, CeActivityDto.Status status) {
-    CeQueueDto queueDto = new CeQueueDto();
-    queueDto.setCreatedAt(1_450_000_000_000L);
-    queueDto.setTaskType(CeTaskTypes.REPORT);
-    queueDto.setComponentUuid(componentUuid);
-    queueDto.setUuid(taskUuid);
-    CeActivityDto activityDto = new CeActivityDto(queueDto);
-    activityDto.setStatus(status);
-    activityDto.setExecutionTimeMs(500L);
-    activityDto.setAnalysisUuid("U1");
-    return activityDto;
+  private CeActivityDto newActivity(String taskUuid, String componentUuid, CeActivityDto.Status status, @Nullable UserDto user) {
+    CeQueueDto queueDto = new CeQueueDto()
+      .setCreatedAt(1_450_000_000_000L)
+      .setTaskType(CeTaskTypes.REPORT)
+      .setComponentUuid(componentUuid)
+      .setSubmitterUuid(user == null ? null : user.getUuid())
+      .setUuid(taskUuid);
+    return new CeActivityDto(queueDto)
+      .setStatus(status)
+      .setExecutionTimeMs(500L)
+      .setAnalysisUuid("U1");
   }
 }
index b7ec0965057ec1e5ccd4a58afb030896e65e5438..9240e14e0a5e66ce7085065a3b01d29ba941bfdf 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonarqube.tests.user;
 
 import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.build.BuildResult;
 import com.sonar.orchestrator.build.SonarScanner;
 import java.util.List;
 import org.json.JSONException;
@@ -30,6 +31,7 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.sonarqube.qa.util.Tester;
 import org.sonarqube.qa.util.TesterSession;
+import org.sonarqube.ws.Ce;
 import org.sonarqube.ws.Issues;
 import org.sonarqube.ws.Issues.Issue;
 import org.sonarqube.ws.Organizations.Organization;
@@ -42,6 +44,8 @@ import org.sonarqube.ws.UserTokens;
 import org.sonarqube.ws.Users;
 import org.sonarqube.ws.client.GetRequest;
 import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.ce.ActivityRequest;
+import org.sonarqube.ws.client.ce.TaskRequest;
 import org.sonarqube.ws.client.custommeasures.CreateRequest;
 import org.sonarqube.ws.client.issues.AssignRequest;
 import org.sonarqube.ws.client.organizations.AddMemberRequest;
@@ -58,6 +62,7 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.skyscreamer.jsonassert.JSONAssert.assertEquals;
+import static util.ItUtils.extractCeTaskId;
 import static util.ItUtils.projectDir;
 
 public class SonarCloudUpdateLoginDuringAuthenticationTest {
@@ -361,6 +366,37 @@ public class SonarCloudUpdateLoginDuringAuthenticationTest {
         .containsExactlyInAnyOrder(tuple("xoo:OneIssuePerLine", newLogin, "A user note"));
   }
 
+  @Test
+  public void ce_task_and_activity_after_login_update() {
+    String providerId = tester.users().generateProviderId();
+    String oldLogin = tester.users().generateLogin();
+
+    // Create user using authentication
+    authenticate(oldLogin, providerId);
+    String userToken = tester.wsClient().userTokens().generate(new GenerateRequest().setLogin(oldLogin).setName("token")).getToken();
+
+    // Execute an analysis using user token
+    Organization organization = tester.organizations().generate();
+    Project project = tester.projects().provision(organization);
+    tester.organizations().service().addMember(new AddMemberRequest().setOrganization(organization.getKey()).setLogin(oldLogin));
+    tester.wsClient().permissions().addUser(new AddUserRequest().setLogin(oldLogin).setOrganization(organization.getKey()).setPermission("scan"));
+    String analysisTaskId = executeAnalysisOnSampleProject(organization, project, userToken);
+
+    // Check login in ce task and activity
+    assertThat(tester.wsClient().ce().task(new TaskRequest().setId(analysisTaskId)).getTask().getSubmitterLogin()).isEqualTo(oldLogin);
+    assertThat(tester.wsClient().ce().activity(new ActivityRequest().setQ(analysisTaskId)).getTasksList())
+      .extracting(Ce.Task::getComponentKey, Ce.Task::getSubmitterLogin)
+      .containsExactlyInAnyOrder(tuple(project.getKey(), oldLogin));
+
+    // Update login during authentication, check ce task and activity contains new login
+    String newLogin = tester.users().generateLogin();
+    authenticate(newLogin, providerId);
+    assertThat(tester.wsClient().ce().task(new TaskRequest().setId(analysisTaskId)).getTask().getSubmitterLogin()).isEqualTo(newLogin);
+    assertThat(tester.wsClient().ce().activity(new ActivityRequest().setQ(analysisTaskId)).getTasksList())
+      .extracting(Ce.Task::getComponentKey, Ce.Task::getSubmitterLogin)
+      .containsExactlyInAnyOrder(tuple(project.getKey(), newLogin));
+  }
+
   private void authenticate(String login, String providerId) {
     tester.settings().setGlobalSettings("sonar.auth.fake-base-id-provider.user", login + "," + providerId + ",fake-" + login + ",John,john@email.com");
     tester.wsClient().wsConnector().call(
@@ -368,6 +404,14 @@ public class SonarCloudUpdateLoginDuringAuthenticationTest {
       .failIfNotSuccessful();
   }
 
+  private static String executeAnalysisOnSampleProject(Organization organization, Project project, String userToken) {
+    BuildResult buildResult = orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-sample"),
+      "sonar.organization", organization.getKey(),
+      "sonar.projectKey", project.getKey(),
+      "sonar.login", userToken));
+    return extractCeTaskId(buildResult);
+  }
+
   private Issue getIssue(Organization organization, String issueKey) {
     List<Issue> issues = tester.wsClient().issues().search(new org.sonarqube.ws.client.issues.SearchRequest()
       .setIssues(singletonList(issueKey))