diff options
author | Pierre <pierre.guillot@sonarsource.com> | 2021-02-11 16:11:37 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-02-19 20:07:20 +0000 |
commit | 4843d35c9376b4c96d5fbef7c89d49a7058dd409 (patch) | |
tree | 02bf7ef1a1ce5d4ea7dd79e76a3df9b5fcb443b1 /server/sonar-ce-task-projectanalysis | |
parent | 7be50957eac88890a4341888986b5d750d3767f4 (diff) | |
download | sonarqube-4843d35c9376b4c96d5fbef7c89d49a7058dd409.tar.gz sonarqube-4843d35c9376b4c96d5fbef7c89d49a7058dd409.zip |
SONAR-14461 save the default main branch when needed
Diffstat (limited to 'server/sonar-ce-task-projectanalysis')
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); + } +} |