From 0bf00b256a437a356b2544b4929dda13dd6d8a62 Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 7 Nov 2019 10:40:04 +0100 Subject: [PATCH] SONAR-12630 Improve Quality Gate Check logging messages --- .../analysis/AnalysisResultReporter.java | 54 ------------ .../scanner/qualitygate/QualityGateCheck.java | 14 ++-- .../sonar/scanner/report/ReportPublisher.java | 12 +++ .../scanner/scan/ProjectScanContainer.java | 8 +- .../analysis/AnalysisResultReporterTest.java | 83 ------------------- .../qualitygate/QualityGateCheckTest.java | 43 ++++------ .../scanner/report/ReportPublisherTest.java | 14 +++- 7 files changed, 49 insertions(+), 179 deletions(-) delete mode 100644 sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisResultReporter.java delete mode 100644 sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisResultReporterTest.java diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisResultReporter.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisResultReporter.java deleted file mode 100644 index a4831961aa3..00000000000 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/analysis/AnalysisResultReporter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 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.scanner.analysis; - -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.scanner.bootstrap.GlobalAnalysisMode; -import org.sonar.scanner.report.CeTaskReportDataHolder; -import org.sonar.scanner.scan.ScanProperties; - -public class AnalysisResultReporter { - - private static final Logger LOG = Loggers.get(AnalysisResultReporter.class); - - private final CeTaskReportDataHolder ceTaskReportDataHolder; - private final GlobalAnalysisMode analysisMode; - private final ScanProperties scanProperties; - - public AnalysisResultReporter(GlobalAnalysisMode analysisMode, CeTaskReportDataHolder ceTaskReportDataHolder, - ScanProperties scanProperties) { - this.analysisMode = analysisMode; - this.ceTaskReportDataHolder = ceTaskReportDataHolder; - this.scanProperties = scanProperties; - } - - public void report() { - if (analysisMode.isMediumTest()) { - LOG.info("ANALYSIS SUCCESSFUL"); - } else { - LOG.info("ANALYSIS SUCCESSFUL, you can browse {}", ceTaskReportDataHolder.getDashboardUrl()); - if (!scanProperties.shouldWaitForQualityGate()) { - LOG.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report"); - LOG.info("More about the report processing at {}", ceTaskReportDataHolder.getCeTaskUrl()); - } - } - } -} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java index 52c52bd2cb1..49b32dabbfb 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/qualitygate/QualityGateCheck.java @@ -83,20 +83,22 @@ public class QualityGateCheck implements Startable { throw new IllegalStateException("Quality Gate check not available in medium test mode"); } + LOG.info("Waiting for the analysis report to be processed (max {}s)", properties.qualityGateWaitTimeout()); String taskId = ceTaskReportDataHolder.getCeTaskId(); Ce.Task task = waitForCeTaskToFinish(taskId); if (!TaskStatus.SUCCESS.equals(task.getStatus())) { - throw MessageException.of(String.format("CE Task finished abnormally with status: %s", task.getStatus().name())); + throw MessageException.of(String.format("CE Task finished abnormally with status: %s, you can check details here: %s", + task.getStatus().name(), ceTaskReportDataHolder.getCeTaskUrl())); } Status qualityGateStatus = getQualityGateStatus(task.getAnalysisId()); if (Status.OK.equals(qualityGateStatus)) { - LOG.info("Quality Gate - OK"); + LOG.info("QUALITY GATE STATUS: PASSED - View details on " + ceTaskReportDataHolder.getDashboardUrl()); } else { - throw MessageException.of("Quality Gate - FAILED, you can browse " + ceTaskReportDataHolder.getDashboardUrl()); + throw MessageException.of("QUALITY GATE STATUS: FAILED - View details on " + ceTaskReportDataHolder.getDashboardUrl()); } } @@ -113,8 +115,6 @@ public class QualityGateCheck implements Startable { if (TASK_TERMINAL_STATUSES.contains(task.getStatus())) { return task; } - LOG.debug("Received CE task with status {} ", task.getStatus()); - LOG.info("Waiting {} ms for task to finish...", POLLING_INTERVAL_IN_MS); Thread.sleep(POLLING_INTERVAL_IN_MS); currentTime += POLLING_INTERVAL_IN_MS; @@ -122,10 +122,10 @@ public class QualityGateCheck implements Startable { throw MessageException.of(String.format("Failed to get CE Task status - %s", DefaultScannerWsClient.createErrorMessage(e))); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw MessageException.of("Quality Gate check has been interrupted", e); + throw new IllegalStateException("Quality Gate check has been interrupted", e); } } - throw MessageException.of("Quality Gate check timeout exceeded"); + throw MessageException.of("Quality Gate check timeout exceeded - View details on " + ceTaskReportDataHolder.getDashboardUrl()); } private static Ce.Task parseCeTaskResponse(WsResponse response) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java index 1c6ce3987b1..157772c1057 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/ReportPublisher.java @@ -143,6 +143,18 @@ public class ReportPublisher implements Startable { String taskId = upload(report); prepareAndDumpMetadata(taskId); } + + logSuccess(); + } + + private void logSuccess() { + if (analysisMode.isMediumTest()) { + LOG.info("ANALYSIS SUCCESSFUL"); + } else if (!properties.shouldWaitForQualityGate()) { + LOG.info("ANALYSIS SUCCESSFUL, you can browse {}", ceTaskReportDataHolder.getDashboardUrl()); + LOG.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report"); + LOG.info("More about the report processing at {}", ceTaskReportDataHolder.getCeTaskUrl()); + } } private File generateReportFile() { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java index 6092d065016..eadf6859a4e 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectScanContainer.java @@ -37,7 +37,6 @@ import org.sonar.core.metric.ScannerMetrics; import org.sonar.core.platform.ComponentContainer; import org.sonar.scanner.DefaultFileLinesContextFactory; import org.sonar.scanner.ProjectInfo; -import org.sonar.scanner.analysis.AnalysisResultReporter; import org.sonar.scanner.analysis.AnalysisTempFolderProvider; import org.sonar.scanner.analysis.DefaultAnalysisMode; import org.sonar.scanner.bootstrap.ExtensionInstaller; @@ -250,11 +249,10 @@ public class ProjectScanContainer extends ComponentContainer { TestExecutionPublisher.class, SourcePublisher.class, ChangedLinesPublisher.class, - AnalysisResultReporter.class, CeTaskReportDataHolder.class, - //QualityGate check + // QualityGate check QualityGateCheck.class, // Cpd @@ -361,12 +359,10 @@ public class ProjectScanContainer extends ComponentContainer { getComponentByType(ReportPublisher.class).execute(); if (properties.shouldWaitForQualityGate()) { - LOG.info("------------- Quality Gate wait enabled"); + LOG.info("------------- Check Quality Gate status"); getComponentByType(QualityGateCheck.class).await(); } - getComponentByType(AnalysisResultReporter.class).report(); - getComponentByType(PostJobsExecutor.class).execute(); if (analysisMode.isMediumTest()) { diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisResultReporterTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisResultReporterTest.java deleted file mode 100644 index 97aa3208906..00000000000 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/analysis/AnalysisResultReporterTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2019 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.scanner.analysis; - -import org.junit.Rule; -import org.junit.Test; -import org.sonar.api.utils.log.LogTester; -import org.sonar.api.utils.log.LoggerLevel; -import org.sonar.scanner.bootstrap.GlobalAnalysisMode; -import org.sonar.scanner.report.CeTaskReportDataHolder; -import org.sonar.scanner.scan.ScanProperties; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class AnalysisResultReporterTest { - @Rule - public LogTester logTester = new LogTester(); - - private CeTaskReportDataHolder ceTaskReportDataHolder = mock(CeTaskReportDataHolder.class); - private GlobalAnalysisMode analysisMode = mock(GlobalAnalysisMode.class); - private ScanProperties scanProperties = mock(ScanProperties.class); - - private AnalysisResultReporter underTest = new AnalysisResultReporter(analysisMode, ceTaskReportDataHolder, scanProperties); - - @Test - public void should_log_simple_success_message() { - when(analysisMode.isMediumTest()).thenReturn(true); - underTest.report(); - - assertThat(logTester.logs(LoggerLevel.INFO)) - .containsOnly("ANALYSIS SUCCESSFUL"); - } - - @Test - public void should_log_success_message_with_urls() { - String ceTaskUrl = "http://sonarqube/taskurl"; - String dashboardUrl = "http://sonarqube/dashboardurl"; - when(ceTaskReportDataHolder.getCeTaskUrl()).thenReturn(ceTaskUrl); - when(ceTaskReportDataHolder.getDashboardUrl()).thenReturn(dashboardUrl); - - underTest.report(); - - assertThat(logTester.logs(LoggerLevel.INFO)) - .containsExactly( - "ANALYSIS SUCCESSFUL, you can browse " + dashboardUrl, - "Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report", - "More about the report processing at " + ceTaskUrl); - } - - @Test - public void should_log_short_success_message_with_urls_if_quality_gate_wait_enabled() { - String ceTaskUrl = "http://sonarqube/taskurl"; - String dashboardUrl = "http://sonarqube/dashboardurl"; - when(ceTaskReportDataHolder.getCeTaskUrl()).thenReturn(ceTaskUrl); - when(ceTaskReportDataHolder.getDashboardUrl()).thenReturn(dashboardUrl); - - when(scanProperties.shouldWaitForQualityGate()).thenReturn(true); - - underTest.report(); - - assertThat(logTester.logs(LoggerLevel.INFO)) - .containsExactly("ANALYSIS SUCCESSFUL, you can browse " + dashboardUrl); - } -} diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/qualitygate/QualityGateCheckTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/qualitygate/QualityGateCheckTest.java index 49165a44ea3..f347fb0585e 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/qualitygate/QualityGateCheckTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/qualitygate/QualityGateCheckTest.java @@ -22,6 +22,7 @@ package org.sonar.scanner.qualitygate; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -64,13 +65,17 @@ public class QualityGateCheckTest { QualityGateCheck underTest = new QualityGateCheck(wsClient, analysisMode, reportMetadataHolder, properties); + @Before + public void before() { + when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); + when(reportMetadataHolder.getDashboardUrl()).thenReturn("http://dashboard-url.com"); + } + @Test public void should_pass_if_quality_gate_ok() { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(5); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse ceTaskWsResponse = getCeTaskWsResponse(TaskStatus.SUCCESS); doReturn(ceTaskWsResponse).when(wsClient).call(newGetCeTaskRequest()); @@ -84,7 +89,9 @@ public class QualityGateCheckTest { underTest.stop(); assertThat(logTester.logs()) - .containsOnly("Quality Gate - OK"); + .containsOnly( + "Waiting for the analysis report to be processed (max 5s)", + "QUALITY GATE STATUS: PASSED - View details on http://dashboard-url.com"); } @Test @@ -92,8 +99,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(10); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse pendingTask = getCeTaskWsResponse(TaskStatus.PENDING); MockWsResponse successTask = getCeTaskWsResponse(TaskStatus.SUCCESS); doReturn(pendingTask, successTask).when(wsClient).call(newGetCeTaskRequest()); @@ -106,7 +111,7 @@ public class QualityGateCheckTest { underTest.await(); assertThat(logTester.logs()) - .contains("Quality Gate - OK"); + .contains("QUALITY GATE STATUS: PASSED - View details on http://dashboard-url.com"); } @Test @@ -114,8 +119,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(5); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse ceTaskWsResponse = getCeTaskWsResponse(TaskStatus.SUCCESS); doReturn(ceTaskWsResponse).when(wsClient).call(newGetCeTaskRequest()); @@ -125,7 +128,7 @@ public class QualityGateCheckTest { underTest.start(); exception.expect(MessageException.class); - exception.expectMessage("Quality Gate - FAILED"); + exception.expectMessage("QUALITY GATE STATUS: FAILED - View details on http://dashboard-url.com"); underTest.await(); } @@ -134,8 +137,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(5); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse ceTaskWsResponse = getCeTaskWsResponse(TaskStatus.SUCCESS); doReturn(ceTaskWsResponse).when(wsClient).call(newGetCeTaskRequest()); @@ -145,7 +146,7 @@ public class QualityGateCheckTest { underTest.start(); exception.expect(MessageException.class); - exception.expectMessage("Quality Gate - FAILED"); + exception.expectMessage("QUALITY GATE STATUS: FAILED - View details on http://dashboard-url.com"); underTest.await(); } @@ -154,8 +155,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(10); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse pendingTask = getCeTaskWsResponse(TaskStatus.PENDING); MockWsResponse successTask = getCeTaskWsResponse(TaskStatus.SUCCESS); doReturn(pendingTask, successTask).when(wsClient).call(newGetCeTaskRequest()); @@ -166,7 +165,7 @@ public class QualityGateCheckTest { underTest.start(); exception.expect(MessageException.class); - exception.expectMessage("Quality Gate - FAILED"); + exception.expectMessage("QUALITY GATE STATUS: FAILED - View details on http://dashboard-url.com"); underTest.await(); } @@ -176,15 +175,13 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(1); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse ceTaskWsResponse = getCeTaskWsResponse(TaskStatus.PENDING); doReturn(ceTaskWsResponse).when(wsClient).call(newGetCeTaskRequest()); underTest.start(); exception.expect(MessageException.class); - exception.expectMessage("Quality Gate check timeout exceeded"); + exception.expectMessage("Quality Gate check timeout exceeded - View details on http://dashboard-url.com"); underTest.await(); } @@ -193,8 +190,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(5); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse ceTaskWsResponse = getCeTaskWsResponse(TaskStatus.SUCCESS); doReturn(ceTaskWsResponse).when(wsClient).call(newGetCeTaskRequest()); @@ -212,8 +207,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(5); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse ceTaskWsResponse = getCeTaskWsResponse(TaskStatus.SUCCESS); doReturn(ceTaskWsResponse).when(wsClient).call(newGetCeTaskRequest()); @@ -234,8 +227,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(5); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - when(wsClient.call(newGetCeTaskRequest())).thenThrow(new HttpException("task-url", 400, "content")); underTest.start(); @@ -250,8 +241,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(5); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse getCeTaskRequest = new MockWsResponse(); getCeTaskRequest.setRequestUrl("ce-task-url"); getCeTaskRequest.setContent("blabla"); @@ -271,8 +260,6 @@ public class QualityGateCheckTest { when(properties.shouldWaitForQualityGate()).thenReturn(true); when(properties.qualityGateWaitTimeout()).thenReturn(5); - when(reportMetadataHolder.getCeTaskId()).thenReturn("task-1234"); - MockWsResponse ceTaskWsResponse = getCeTaskWsResponse(taskStatus); when(wsClient.call(newGetCeTaskRequest())).thenReturn(ceTaskWsResponse); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java index 3fc00a31110..dee94ded490 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/report/ReportPublisherTest.java @@ -211,11 +211,19 @@ public class ReportPublisherTest { when(mode.isMediumTest()).thenReturn(true); underTest.start(); underTest.execute(); + + assertThat(logTester.logs(LoggerLevel.INFO)) + .contains("ANALYSIS SUCCESSFUL") + .doesNotContain("dashboard/index"); + assertThat(properties.metadataFilePath()).doesNotExist(); } @Test public void should_upload_and_dump_information() { + when(reportMetadataHolder.getDashboardUrl()).thenReturn("https://publicserver/sonarqube/dashboard?id=org.sonarsource.sonarqube%3Asonarqube"); + when(reportMetadataHolder.getCeTaskUrl()).thenReturn("https://publicserver/sonarqube/api/ce/task?id=TASK-123"); + MockWsResponse submitMockResponse = new MockWsResponse(); submitMockResponse.setContent(Ce.SubmitResponse.newBuilder().setTaskId("task-1234").build().toByteArray()); when(wsClient.call(any())).thenReturn(submitMockResponse); @@ -223,7 +231,11 @@ public class ReportPublisherTest { underTest.execute(); assertThat(properties.metadataFilePath()).exists(); - assertThat(logTester.logs(LoggerLevel.DEBUG)).contains("Report metadata written to " + properties.metadataFilePath()); + assertThat(logTester.logs(LoggerLevel.DEBUG)) + .contains("Report metadata written to " + properties.metadataFilePath()); + assertThat(logTester.logs(LoggerLevel.INFO)) + .contains("ANALYSIS SUCCESSFUL, you can browse https://publicserver/sonarqube/dashboard?id=org.sonarsource.sonarqube%3Asonarqube") + .contains("More about the report processing at https://publicserver/sonarqube/api/ce/task?id=TASK-123"); } @Test -- 2.39.5