From a8d2df8b6546115dd219a28c913f035f63cdcfd0 Mon Sep 17 00:00:00 2001 From: Eric Giffon Date: Tue, 19 Dec 2023 12:54:29 +0100 Subject: [PATCH] SONAR-21259 Compute metric pull_request_fixed_issues --- gradle.properties | 2 +- .../PullRequestFixedIssuesMeasureStep.java | 67 +++++++++++++ .../step/ReportComputationSteps.java | 3 + ...PullRequestFixedIssuesMeasureStepTest.java | 99 +++++++++++++++++++ 4 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PullRequestFixedIssuesMeasureStep.java create mode 100644 server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PullRequestFixedIssuesMeasureStepTest.java diff --git a/gradle.properties b/gradle.properties index b06a20fc635..923e9b7bda1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ group=org.sonarsource.sonarqube version=10.4 -pluginApiVersion=10.3.0.1951 +pluginApiVersion=10.4.0.2040 description=Open source platform for continuous inspection of code quality projectTitle=SonarQube org.gradle.jvmargs=-Xmx2048m diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PullRequestFixedIssuesMeasureStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PullRequestFixedIssuesMeasureStep.java new file mode 100644 index 00000000000..f4a79065c10 --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PullRequestFixedIssuesMeasureStep.java @@ -0,0 +1,67 @@ +/* + * 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.step; + +import org.sonar.api.measures.CoreMetrics; +import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; +import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; +import org.sonar.ce.task.projectanalysis.issue.fixedissues.PullRequestFixedIssueRepository; +import org.sonar.ce.task.projectanalysis.measure.Measure; +import org.sonar.ce.task.projectanalysis.measure.MeasureRepository; +import org.sonar.ce.task.projectanalysis.metric.MetricRepository; +import org.sonar.ce.task.step.ComputationStep; + +/** + * Compute the measure for the metric {@link CoreMetrics#PULL_REQUEST_FIXED_ISSUES_KEY} that contains the number of issues that would be + * fixed by the pull request on the target branch. + */ +public class PullRequestFixedIssuesMeasureStep implements ComputationStep { + + private final TreeRootHolder treeRootHolder; + private final MetricRepository metricRepository; + private final MeasureRepository measureRepository; + private final PullRequestFixedIssueRepository pullRequestFixedIssueRepository; + private final AnalysisMetadataHolder analysisMetadataHolder; + + public PullRequestFixedIssuesMeasureStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, + MeasureRepository measureRepository, + PullRequestFixedIssueRepository pullRequestFixedIssueRepository, + AnalysisMetadataHolder analysisMetadataHolder) { + this.treeRootHolder = treeRootHolder; + this.metricRepository = metricRepository; + this.measureRepository = measureRepository; + this.pullRequestFixedIssueRepository = pullRequestFixedIssueRepository; + this.analysisMetadataHolder = analysisMetadataHolder; + } + + @Override + public void execute(Context context) { + if (analysisMetadataHolder.isPullRequest()) { + int fixedIssuesCount = pullRequestFixedIssueRepository.getFixedIssues().size(); + measureRepository.add(treeRootHolder.getRoot(), metricRepository.getByKey(CoreMetrics.PULL_REQUEST_FIXED_ISSUES_KEY), + Measure.newMeasureBuilder().create(fixedIssuesCount)); + } + } + + @Override + public String getDescription() { + return "Compute pull request fixed issues measure"; + } +} 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 2d11a9fa301..725247a3e8b 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 @@ -83,6 +83,9 @@ public class ReportComputationSteps extends AbstractComputationSteps { PostMeasuresComputationChecksStep.class, + // Must be executed after visitors execution + PullRequestFixedIssuesMeasureStep.class, + QualityGateMeasuresStep.class, // Must be executed after computation of language distribution ComputeQProfileMeasureStep.class, diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PullRequestFixedIssuesMeasureStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PullRequestFixedIssuesMeasureStepTest.java new file mode 100644 index 00000000000..dc3b856211e --- /dev/null +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PullRequestFixedIssuesMeasureStepTest.java @@ -0,0 +1,99 @@ +/* + * 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.step; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; +import org.sonar.ce.task.projectanalysis.component.Component; +import org.sonar.ce.task.projectanalysis.component.ReportComponent; +import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; +import org.sonar.ce.task.projectanalysis.issue.fixedissues.PullRequestFixedIssueRepository; +import org.sonar.ce.task.projectanalysis.measure.Measure; +import org.sonar.ce.task.projectanalysis.measure.MeasureAssert; +import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule; +import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule; +import org.sonar.ce.task.step.TestComputationStepContext; +import org.sonar.core.issue.DefaultIssue; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PullRequestFixedIssuesMeasureStepTest { + + private static final int ROOT_REF = 1; + + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); + @Rule + public MetricRepositoryRule metricRepository = new MetricRepositoryRule(); + @Rule + public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); + private final PullRequestFixedIssueRepository pullRequestFixedIssueRepository = mock(PullRequestFixedIssueRepository.class); + private final AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class); + + private final PullRequestFixedIssuesMeasureStep underTest = new PullRequestFixedIssuesMeasureStep(treeRootHolder, metricRepository, + measureRepository, pullRequestFixedIssueRepository, analysisMetadataHolder); + + @Before + public void setUp() throws Exception { + treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, ROOT_REF).build()); + metricRepository.add(CoreMetrics.PULL_REQUEST_FIXED_ISSUES); + } + + @Test + public void execute_whenComponentIsPullRequest_shouldCreateMeasure() { + when(analysisMetadataHolder.isPullRequest()).thenReturn(true); + when(pullRequestFixedIssueRepository.getFixedIssues()).thenReturn(List.of(new DefaultIssue(), new DefaultIssue())); + + underTest.execute(new TestComputationStepContext()); + + assertThat(measureRepository.getAddedRawMeasures(ROOT_REF)).hasSize(1); + Optional addedRawMeasure = measureRepository.getAddedRawMeasure(ROOT_REF, CoreMetrics.PULL_REQUEST_FIXED_ISSUES_KEY); + MeasureAssert.assertThat(addedRawMeasure).hasValue(2); + } + + @Test + public void execute_whenComponentIsNotPullRequest_shouldNotCreateMeasure() { + when(analysisMetadataHolder.isPullRequest()).thenReturn(false); + + underTest.execute(new TestComputationStepContext()); + + assertThat(measureRepository.getAddedRawMeasures(ROOT_REF)).isEmpty(); + } + + @Test + public void execute_whenNoFixedIssues_shouldCreateMeasureWithValueZero() { + when(analysisMetadataHolder.isPullRequest()).thenReturn(true); + when(pullRequestFixedIssueRepository.getFixedIssues()).thenReturn(Collections.emptyList()); + + underTest.execute(new TestComputationStepContext()); + + assertThat(measureRepository.getAddedRawMeasures(ROOT_REF)).hasSize(1); + Optional addedRawMeasure = measureRepository.getAddedRawMeasure(ROOT_REF, CoreMetrics.PULL_REQUEST_FIXED_ISSUES_KEY); + MeasureAssert.assertThat(addedRawMeasure).hasValue(0); + } +} -- 2.39.5