]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14091 handle indexation tasks bound to an orphan branch
authorPierre Guillot <50145663+pierre-guillot-sonarsource@users.noreply.github.com>
Mon, 30 Nov 2020 10:50:10 +0000 (11:50 +0100)
committersonartech <sonartech@sonarsource.com>
Mon, 30 Nov 2020 20:07:06 +0000 (20:07 +0000)
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IgnoreOrphanBranchStep.java [new file with mode: 0644]
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IndexIssuesStep.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IssueSyncTaskModule.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IssueSyncTaskProcessor.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/taskprocessor/IgnoreOrphanBranchStepTest.java [new file with mode: 0644]
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/taskprocessor/IssueSyncTaskProcessorTest.java
server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeQueueMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeQueueDaoTest.java

diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IgnoreOrphanBranchStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/taskprocessor/IgnoreOrphanBranchStep.java
new file mode 100644 (file)
index 0000000..1e809a0
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.ce.task.projectanalysis.taskprocessor;
+
+import java.util.Optional;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.ce.task.CeTask;
+import org.sonar.ce.task.step.ComputationStep;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+
+public final class IgnoreOrphanBranchStep implements ComputationStep {
+  private static final Logger LOG = Loggers.get(IgnoreOrphanBranchStep.class);
+  private final CeTask ceTask;
+  private final DbClient dbClient;
+
+  public IgnoreOrphanBranchStep(CeTask ceTask, DbClient dbClient) {
+    this.ceTask = ceTask;
+    this.dbClient = dbClient;
+  }
+
+  @Override
+  public void execute(Context context) {
+    String mainComponentUuid = ceTask.getMainComponent().orElseThrow(() -> new UnsupportedOperationException("main component not found in task")).getUuid();
+    String componentUuid = ceTask.getComponent().orElseThrow(() -> new UnsupportedOperationException("component not found in task")).getUuid();
+
+    try (DbSession dbSession = dbClient.openSession(false)) {
+      Optional<ComponentDto> componentDto = dbClient.componentDao().selectByUuid(dbSession, mainComponentUuid);
+      if(!componentDto.isPresent()){
+        LOG.info("reindexation task has been trigger on an orphan branch. removing any exclude_from_purge flag, and skip the indexation");
+        dbClient.branchDao().updateExcludeFromPurge(dbSession, componentUuid, false);
+        dbClient.branchDao().updateNeedIssueSync(dbSession, componentUuid, false);
+        dbSession.commit();
+      }
+    }
+  }
+
+  @Override
+  public String getDescription() {
+    return "Ignore orphan component";
+  }
+}
index a291b7006ea24ef74bdc46bc2ae1899bc4683acb..38fcc30536fd2fd0cf053f09807d485209f25055 100644 (file)
@@ -57,7 +57,6 @@ public final class IndexIssuesStep implements ComputationStep {
             LOG.debug("issues of branch {} are already in sync", branchUuid);
           }
         });
-
     }
   }
 
index 23eb54fdf1e62fe2ccea9b6b7107f5f9f4220c1d..b40e333009ca92ae0e37062d00d8623ef9c83358 100644 (file)
@@ -26,6 +26,7 @@ public class IssueSyncTaskModule extends Module {
   @Override
   protected void configureModule() {
     add(
+      IgnoreOrphanBranchStep.class,
       IssueSyncTaskProcessor.class);
   }
 }
index 53f1826975bf6a661ed5da09db1c87a95a919669..ba2d179871b573b04b6037943c5ce9371dcfba01 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.ce.task.projectanalysis.taskprocessor;
 
 import com.google.common.collect.ImmutableSet;
-import java.util.Collections;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 import javax.annotation.CheckForNull;
@@ -64,6 +64,7 @@ public class IssueSyncTaskProcessor implements CeTaskProcessor {
   static ContainerPopulator<TaskContainer> newContainerPopulator(CeTask task) {
     return taskContainer -> {
       taskContainer.add(task);
+      taskContainer.add(IgnoreOrphanBranchStep.class);
       taskContainer.add(IndexIssuesStep.class);
       taskContainer.add(new SyncComputationSteps(taskContainer));
       taskContainer.add(ComputationStepExecutor.class);
@@ -78,7 +79,7 @@ public class IssueSyncTaskProcessor implements CeTaskProcessor {
 
     @Override
     public List<Class<? extends ComputationStep>> orderedStepClasses() {
-      return Collections.singletonList(IndexIssuesStep.class);
+      return Arrays.asList(IgnoreOrphanBranchStep.class, IndexIssuesStep.class);
     }
 
   }
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/taskprocessor/IgnoreOrphanBranchStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/taskprocessor/IgnoreOrphanBranchStepTest.java
new file mode 100644 (file)
index 0000000..91ed08e
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.ce.task.projectanalysis.taskprocessor;
+
+import java.util.Optional;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.ce.task.CeTask;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchDto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.sonar.db.component.BranchType.BRANCH;
+
+public class IgnoreOrphanBranchStepTest {
+
+  private String BRANCH_UUID = "branch_uuid";
+
+  @Rule
+  public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+  private CeTask.Component component = new CeTask.Component(BRANCH_UUID, "component key", "component name");
+  private CeTask ceTask = new CeTask.Builder()
+    .setOrganizationUuid("organizationUuid")
+    .setType("type")
+    .setUuid("uuid")
+    .setComponent(component)
+    .setMainComponent(component)
+    .build();
+
+  private DbClient dbClient = dbTester.getDbClient();
+  private IgnoreOrphanBranchStep underTest = new IgnoreOrphanBranchStep(ceTask, dbClient);
+
+  @Test
+  public void execute() {
+    BranchDto branchDto = new BranchDto()
+      .setBranchType(BRANCH)
+      .setKey("branchName")
+      .setUuid(BRANCH_UUID)
+      .setProjectUuid("project_uuid")
+      .setNeedIssueSync(true);
+    dbClient.branchDao().insert(dbTester.getSession(), branchDto);
+    dbTester.commit();
+
+    underTest.execute(() -> null);
+
+    Optional<BranchDto> branch = dbClient.branchDao().selectByUuid(dbTester.getSession(), BRANCH_UUID);
+    assertThat(branch.get().isNeedIssueSync()).isFalse();
+    assertThat(branch.get().isExcludeFromPurge()).isFalse();
+  }
+
+  @Test
+  public void execute_on_already_indexed_branch() {
+    BranchDto branchDto = new BranchDto()
+      .setBranchType(BRANCH)
+      .setKey("branchName")
+      .setUuid(BRANCH_UUID)
+      .setProjectUuid("project_uuid")
+      .setNeedIssueSync(false);
+    dbClient.branchDao().insert(dbTester.getSession(), branchDto);
+    dbTester.commit();
+
+    underTest.execute(() -> null);
+
+    Optional<BranchDto> branch = dbClient.branchDao().selectByUuid(dbTester.getSession(), BRANCH_UUID);
+    assertThat(branch.get().isNeedIssueSync()).isFalse();
+    assertThat(branch.get().isExcludeFromPurge()).isFalse();
+  }
+
+  @Test
+  public void fail_if_missing_main_component_in_task() {
+    CeTask ceTask = new CeTask.Builder()
+      .setOrganizationUuid("organizationUuid")
+      .setType("type")
+      .setUuid("uuid")
+      .setComponent(null)
+      .setMainComponent(null)
+      .build();
+    IgnoreOrphanBranchStep underTest = new IgnoreOrphanBranchStep(ceTask, dbClient);
+
+    assertThatThrownBy(() -> underTest.execute(() -> null))
+      .isInstanceOf(UnsupportedOperationException.class)
+      .hasMessage("main component not found in task");
+  }
+
+  @Test
+  public void verify_step_description() {
+    assertThat(underTest.getDescription()).isEqualTo("Ignore orphan component");
+  }
+
+}
index cbc4bfb530ef35a554972fc9fce152bf2310270b..3dd49083c26dfbd7efb5e33bfe1df3f31563fe17 100644 (file)
@@ -53,7 +53,7 @@ public class IssueSyncTaskProcessorTest {
       .build();
 
     IssueSyncTaskProcessor.newContainerPopulator(task).populateContainer(container);
-    Mockito.verify(container, Mockito.times(4)).add(any());
+    Mockito.verify(container, Mockito.times(5)).add(any());
   }
 
   @Test
@@ -62,7 +62,7 @@ public class IssueSyncTaskProcessorTest {
 
     List<Class<? extends ComputationStep>> steps = syncComputationSteps.orderedStepClasses();
 
-    Assertions.assertThat(steps).containsExactly(IndexIssuesStep.class);
+    Assertions.assertThat(steps).containsExactly(IgnoreOrphanBranchStep.class, IndexIssuesStep.class);
   }
 
 }
index 92003dda714b9f9ed7b9238c83f8da6a4e147e71..8f39246a6240206a50943cb08fd9ad0cdf176511 100644 (file)
     from
       ce_queue cq
     <if test="excludeViewRefresh">
-        inner join components c on c.uuid = cq.main_component_uuid and c.qualifier &lt;&gt; 'VW'
+        left join components c on c.uuid = cq.main_component_uuid and c.qualifier &lt;&gt; 'VW'
     </if>
     where
       cq.status='PENDING'
index 21b8b38be47af8dff724fe68409da5a855d71103..3af142c4223484b284a1ee3d177ed916d5c8dafc 100644 (file)
@@ -659,6 +659,20 @@ public class CeQueueDaoTest {
     assertThat(peek2.get().getUuid()).isEqualTo(TASK_UUID_2);
   }
 
+  @Test
+  public void excluding_view_pick_up_orphan_branches() {
+    insertPending(newCeQueueDto(TASK_UUID_1)
+      .setComponentUuid(MAIN_COMPONENT_UUID_1)
+      .setMainComponentUuid("non-existing-uuid")
+      .setStatus(PENDING)
+      .setTaskType(CeTaskTypes.BRANCH_ISSUE_SYNC)
+      .setCreatedAt(100_000L));
+
+    Optional<CeQueueDto> peek = underTest.peek(db.getSession(), WORKER_UUID_1, false, true);
+    assertThat(peek).isPresent();
+    assertThat(peek.get().getUuid()).isEqualTo(TASK_UUID_1);
+  }
+
   @Test
   public void hasAnyIssueSyncTaskPendingOrInProgress_PENDING() {
     assertThat(underTest.hasAnyIssueSyncTaskPendingOrInProgress(db.getSession())).isFalse();