aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorMatteo Mara <matteo.mara@sonarsource.com>2023-09-12 11:30:54 +0200
committersonartech <sonartech@sonarsource.com>2023-09-27 20:02:58 +0000
commit360a4b93d39f94b9fc8aea2aff7dfd37203b5a1b (patch)
tree97677ee6120b8d31b1694e5e63e467956c59f6d4 /server
parent319abd794487e6e17eb2b08ca9ac266cbb16c66a (diff)
downloadsonarqube-360a4b93d39f94b9fc8aea2aff7dfd37203b5a1b.tar.gz
sonarqube-360a4b93d39f94b9fc8aea2aff7dfd37203b5a1b.zip
SONAR-20442 Add new extension point before measure calculation
Diffstat (limited to 'server')
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationCheck.java50
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationChecksStep.java69
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/ReportComputationSteps.java4
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationChecksStepTest.java119
4 files changed, 242 insertions, 0 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationCheck.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationCheck.java
new file mode 100644
index 00000000000..909514b9d3f
--- /dev/null
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationCheck.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.measure;
+
+import org.sonar.api.ExtensionPoint;
+import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.ce.task.projectanalysis.analysis.Branch;
+
+/**
+ * Extension point that is called during processing of a task
+ * by {@link PreMeasuresComputationChecksStep}.
+ *
+ * It is stateless, the same instance is reused for all tasks.
+ * As a consequence Compute Engine task components can't be injected
+ * as dependencies.
+ */
+@ComputeEngineSide
+@ExtensionPoint
+public interface PreMeasuresComputationCheck {
+
+ /**
+ * This method can make the task fail by throwing a {@link RuntimeException}
+ */
+ void onCheck(Context context);
+
+ interface Context {
+
+ String getProjectUuid();
+
+ Branch getBranch();
+
+ }
+}
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationChecksStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationChecksStep.java
new file mode 100644
index 00000000000..79257403306
--- /dev/null
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationChecksStep.java
@@ -0,0 +1,69 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.measure;
+
+import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
+import org.sonar.ce.task.projectanalysis.analysis.Branch;
+import org.sonar.ce.task.step.ComputationStep;
+
+/**
+ * Execute {@link PreMeasuresComputationCheck} instances in no specific order.
+ * If an extension fails (throws an exception), consecutive extensions
+ * won't be called.
+ */
+@ComputeEngineSide
+public class PreMeasuresComputationChecksStep implements ComputationStep {
+
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+ private final PreMeasuresComputationCheck[] extensions;
+
+ public PreMeasuresComputationChecksStep(AnalysisMetadataHolder analysisMetadataHolder, PreMeasuresComputationCheck... extensions) {
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ this.extensions = extensions;
+ }
+
+ @Override
+ public void execute(Context context) {
+ PreMeasuresComputationCheck.Context extensionContext = new ContextImpl();
+ for (PreMeasuresComputationCheck extension : extensions) {
+ extension.onCheck(extensionContext);
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Checks executed before computation of measures";
+ }
+
+ private class ContextImpl implements PreMeasuresComputationCheck.Context {
+
+ @Override
+ public String getProjectUuid() {
+ return analysisMetadataHolder.getProject().getUuid();
+ }
+
+ @Override
+ public Branch getBranch() {
+ return analysisMetadataHolder.getBranch();
+ }
+
+ }
+}
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 6432f2a3aef..731935a5425 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
@@ -26,6 +26,7 @@ import org.sonar.ce.task.projectanalysis.filemove.FileMoveDetectionStep;
import org.sonar.ce.task.projectanalysis.filemove.PullRequestFileMoveDetectionStep;
import org.sonar.ce.task.projectanalysis.language.HandleUnanalyzedLanguagesStep;
import org.sonar.ce.task.projectanalysis.measure.PostMeasuresComputationChecksStep;
+import org.sonar.ce.task.projectanalysis.measure.PreMeasuresComputationChecksStep;
import org.sonar.ce.task.projectanalysis.purge.PurgeDatastoresStep;
import org.sonar.ce.task.projectanalysis.qualityprofile.RegisterQualityProfileStatusStep;
import org.sonar.ce.task.projectanalysis.source.PersistFileSourcesStep;
@@ -50,6 +51,9 @@ public class ReportComputationSteps extends AbstractComputationSteps {
ValidateProjectStep.class,
LoadQualityProfilesStep.class,
+ // Pre analysis operations
+ PreMeasuresComputationChecksStep.class,
+
// load project related stuffs
LoadFileHashesAndStatusStep.class,
LoadQualityGateStep.class,
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationChecksStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationChecksStepTest.java
new file mode 100644
index 00000000000..5f2481025f0
--- /dev/null
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/measure/PreMeasuresComputationChecksStepTest.java
@@ -0,0 +1,119 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.measure;
+
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.ce.task.projectanalysis.analysis.Branch;
+import org.sonar.ce.task.projectanalysis.measure.PreMeasuresComputationCheck.Context;
+import org.sonar.ce.task.step.TestComputationStepContext;
+import org.sonar.db.component.BranchType;
+import org.sonar.server.project.Project;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
+
+public class PreMeasuresComputationChecksStepTest {
+
+ public AnalysisMetadataHolderRule analysisMetadataHolder = mock(AnalysisMetadataHolderRule.class);
+
+ @Test
+ public void execute_extensions() {
+ PreMeasuresComputationCheck check1 = mock(PreMeasuresComputationCheck.class);
+ PreMeasuresComputationCheck check2 = mock(PreMeasuresComputationCheck.class);
+
+ newStep(check1, check2).execute(new TestComputationStepContext());
+
+ InOrder inOrder = inOrder(check1, check2);
+ inOrder.verify(check1).onCheck(any(Context.class));
+ inOrder.verify(check2).onCheck(any(Context.class));
+ }
+
+ @Test
+ public void context_contains_project_uuid_from_analysis_metadata_holder() {
+ Project project = Project.from(newPrivateProjectDto());
+ when(analysisMetadataHolder.getProject()).thenReturn(project);
+ PreMeasuresComputationCheck check = mock(PreMeasuresComputationCheck.class);
+
+ newStep(check).execute(new TestComputationStepContext());
+
+ ArgumentCaptor<Context> contextArgumentCaptor = ArgumentCaptor.forClass(Context.class);
+ verify(check).onCheck(contextArgumentCaptor.capture());
+ assertThat(contextArgumentCaptor.getValue().getProjectUuid()).isEqualTo(project.getUuid());
+ }
+
+ @Test
+ public void context_contains_pullRequest_key_from_analysis_metadata_holder() {
+ mockPr("pr1");
+ PreMeasuresComputationCheck check = mock(PreMeasuresComputationCheck.class);
+
+ newStep(check).execute(new TestComputationStepContext());
+
+ ArgumentCaptor<Context> contextArgumentCaptor = ArgumentCaptor.forClass(Context.class);
+ verify(check).onCheck(contextArgumentCaptor.capture());
+ assertThat(contextArgumentCaptor.getValue().getBranch().getPullRequestKey()).isEqualTo("pr1");
+ }
+
+ @Test
+ public void context_contains_branch_from_analysis_metadata_holder() {
+ mockBranch("branchName");
+ PreMeasuresComputationCheck check = mock(PreMeasuresComputationCheck.class);
+
+ newStep(check).execute(new TestComputationStepContext());
+
+ ArgumentCaptor<Context> contextArgumentCaptor = ArgumentCaptor.forClass(Context.class);
+ verify(check).onCheck(contextArgumentCaptor.capture());
+ assertThat(contextArgumentCaptor.getValue().getBranch().getName()).isEqualTo("branchName");
+ }
+
+ @Test
+ public void test_getDescription() {
+ assertThat(newStep().getDescription()).isNotEmpty();
+ }
+
+ private PreMeasuresComputationChecksStep newStep(PreMeasuresComputationCheck... preMeasuresComputationChecks) {
+ if (preMeasuresComputationChecks.length == 0) {
+ return new PreMeasuresComputationChecksStep(analysisMetadataHolder);
+ }
+ return new PreMeasuresComputationChecksStep(analysisMetadataHolder, preMeasuresComputationChecks);
+ }
+
+ private void mockBranch(String branchName) {
+ Branch branch = mock(Branch.class);
+ when(branch.getName()).thenReturn(branchName);
+ when(branch.getType()).thenReturn(BranchType.BRANCH);
+ when(analysisMetadataHolder.getBranch()).thenReturn(branch);
+ }
+
+ private void mockPr(String pullRequestKey) {
+ Branch branch = mock(Branch.class);
+ when(branch.getType()).thenReturn(BranchType.PULL_REQUEST);
+ when(branch.getPullRequestKey()).thenReturn(pullRequestKey);
+ when(analysisMetadataHolder.getBranch()).thenReturn(branch);
+ }
+
+}