aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-ce-task-projectanalysis
diff options
context:
space:
mode:
authorPierre <pierre.guillot@sonarsource.com>2021-02-11 16:11:37 +0100
committersonartech <sonartech@sonarsource.com>2021-02-19 20:07:20 +0000
commit4843d35c9376b4c96d5fbef7c89d49a7058dd409 (patch)
tree02bf7ef1a1ce5d4ea7dd79e76a3df9b5fcb443b1 /server/sonar-ce-task-projectanalysis
parent7be50957eac88890a4341888986b5d750d3767f4 (diff)
downloadsonarqube-4843d35c9376b4c96d5fbef7c89d49a7058dd409.tar.gz
sonarqube-4843d35c9376b4c96d5fbef7c89d49a7058dd409.zip
SONAR-14461 save the default main branch when needed
Diffstat (limited to 'server/sonar-ce-task-projectanalysis')
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java1
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/UpdateMainBranchStep.java79
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/UpdateMainBranchStepTest.java136
3 files changed, 216 insertions, 0 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java
index bfca57e6c57..f04fe03a2a9 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java
@@ -107,6 +107,7 @@ public class ReportComputationSteps extends AbstractComputationSteps {
PurgeDatastoresStep.class,
IndexAnalysisStep.class,
UpdateNeedIssueSyncStep.class,
+ UpdateMainBranchStep.class,
// notifications are sent at the end, so that webapp displays up-to-date information
SendIssueNotificationsStep.class,
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/UpdateMainBranchStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/UpdateMainBranchStep.java
new file mode 100644
index 00000000000..1d70c9b7389
--- /dev/null
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/UpdateMainBranchStep.java
@@ -0,0 +1,79 @@
+/*
+ * 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.ce.task.projectanalysis.step;
+
+import java.util.Optional;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
+import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
+import org.sonar.ce.task.step.ComputationStep;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.project.ProjectDto;
+
+public class UpdateMainBranchStep implements ComputationStep {
+
+ private static final Logger LOGGER = Loggers.get(UpdateMainBranchStep.class);
+
+ private final BatchReportReader batchReportReader;
+ private final DbClient dbClient;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+
+ public UpdateMainBranchStep(BatchReportReader batchReportReader, DbClient dbClient, AnalysisMetadataHolder analysisMetadataHolder) {
+ this.batchReportReader = batchReportReader;
+ this.dbClient = dbClient;
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ }
+
+ @Override
+ public void execute(Context context) {
+
+ if (!analysisMetadataHolder.isFirstAnalysis()) {
+ return;
+ }
+
+ String gitDefaultMainBranch = batchReportReader.readMetadata().getGitDefaultMainBranch();
+ if (gitDefaultMainBranch.isEmpty()) {
+ LOGGER.debug("GIT default main branch detected is empty");
+ return;
+ }
+ LOGGER.debug(String.format("GIT default main branch detected is [%s]", gitDefaultMainBranch));
+ updateProjectDefaultMainBranch(gitDefaultMainBranch);
+ }
+
+ private void updateProjectDefaultMainBranch(String gitDefaultMainBranch) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ String projectKey = analysisMetadataHolder.getProject().getKey();
+ Optional<ProjectDto> projectDto = dbClient.projectDao().selectProjectByKey(dbSession, projectKey);
+ if (!projectDto.isPresent()) {
+ throw new IllegalStateException(String.format("root component key [%s] is not a project", projectKey));
+ }
+ LOGGER.info(String.format("updating project [%s] default main branch to [%s]", projectKey, gitDefaultMainBranch));
+ dbClient.branchDao().updateMainBranchName(dbSession, projectDto.get().getUuid(), gitDefaultMainBranch);
+ dbSession.commit();
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Update the project main branch name, based on GIT information. Only for the first project's analysis.";
+ }
+}
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/UpdateMainBranchStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/UpdateMainBranchStepTest.java
new file mode 100644
index 00000000000..ff18ae50338
--- /dev/null
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/UpdateMainBranchStepTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.ce.task.projectanalysis.step;
+
+import java.util.Collection;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
+import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
+import org.sonar.ce.task.step.ComputationStep;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.server.project.Project;
+
+import static java.util.Collections.emptyList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.utils.log.LoggerLevel.TRACE;
+
+public class UpdateMainBranchStepTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public LogTester logTester = new LogTester().setLevel(TRACE);
+
+ private final AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class);
+ BatchReportReader batchReportReader = mock(BatchReportReader.class);
+
+ private final UpdateMainBranchStep underTest = new UpdateMainBranchStep(batchReportReader, dbTester.getDbClient(), analysisMetadataHolder);
+ private ComputationStep.Context context = mock(ComputationStep.Context.class);
+
+ @Test
+ public void update_main_branch_on_first_analysis() {
+ ScannerReport.Metadata metadata = ScannerReport.Metadata.newBuilder().setGitDefaultMainBranch("new_name").buildPartial();
+ when(batchReportReader.readMetadata()).thenReturn(metadata);
+ when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(true);
+ ComponentDto privateProject = dbTester.components().insertPrivateProject();
+ when(analysisMetadataHolder.getProject())
+ .thenReturn(new Project(privateProject.uuid(), privateProject.getKey(), privateProject.name(), privateProject.description(), emptyList()));
+
+ assertMainBranchName(privateProject, "master");
+
+ underTest.execute(context);
+
+ assertMainBranchName(privateProject, "new_name");
+ assertThat(logTester.logs()).contains("GIT default main branch detected is [new_name]");
+ assertThat(logTester.logs()).contains(String.format("updating project [%s] default main branch to [new_name]", privateProject.getKey()));
+ }
+
+ @Test
+ public void do_not_update_main_branch_on_second_analysis() {
+ ScannerReport.Metadata metadata = ScannerReport.Metadata.newBuilder().setGitDefaultMainBranch("new_name").buildPartial();
+ when(batchReportReader.readMetadata()).thenReturn(metadata);
+ when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false);
+ ComponentDto privateProject = dbTester.components().insertPrivateProject();
+ when(analysisMetadataHolder.getProject())
+ .thenReturn(new Project(privateProject.uuid(), privateProject.getKey(), privateProject.name(), privateProject.description(), emptyList()));
+
+ assertMainBranchName(privateProject, "master");
+
+ underTest.execute(context);
+
+ assertMainBranchName(privateProject, "master");
+ assertThat(logTester.logs()).isEmpty();
+ }
+
+ @Test
+ public void do_not_update_main_branch_if_no_git_info_found() {
+ String emptyGitMainBranchInfo = "";
+ ScannerReport.Metadata metadata = ScannerReport.Metadata.newBuilder().setGitDefaultMainBranch(emptyGitMainBranchInfo).buildPartial();
+ when(batchReportReader.readMetadata()).thenReturn(metadata);
+ when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(true);
+ ComponentDto privateProject = dbTester.components().insertPrivateProject();
+ when(analysisMetadataHolder.getProject())
+ .thenReturn(new Project(privateProject.uuid(), privateProject.getKey(), privateProject.name(), privateProject.description(), emptyList()));
+
+ assertMainBranchName(privateProject, "master");
+
+ underTest.execute(context);
+
+ assertMainBranchName(privateProject, "master");
+ assertThat(logTester.logs()).contains("GIT default main branch detected is empty");
+ }
+
+ @Test
+ public void fail_on_invalid_project_key() {
+ ScannerReport.Metadata metadata = ScannerReport.Metadata.newBuilder().setGitDefaultMainBranch("new_name").buildPartial();
+ when(batchReportReader.readMetadata()).thenReturn(metadata);
+ when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(true);
+ ComponentDto privateProject = dbTester.components().insertPrivateProject();
+ when(analysisMetadataHolder.getProject())
+ .thenReturn(new Project(privateProject.uuid(), "invalid project key", privateProject.name(), privateProject.description(), emptyList()));
+
+ assertThatThrownBy(() -> underTest.execute(context))
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessage("root component key [invalid project key] is not a project");
+ assertThat(logTester.logs()).contains("GIT default main branch detected is [new_name]");
+ }
+
+ @Test
+ public void getDescription() {
+ assertThat(underTest.getDescription()).isNotEmpty();
+ }
+
+ private void assertMainBranchName(ComponentDto privateProject, String expectedBranchName) {
+ Collection<BranchDto> branches = dbTester.getDbClient().branchDao().selectByComponent(dbTester.getSession(), privateProject);
+ assertThat(branches).isNotEmpty();
+ assertThat(branches).hasSize(1);
+ assertThat(branches.iterator().next().getKey()).isEqualTo(expectedBranchName);
+ }
+}