]> source.dussan.org Git - sonarqube.git/commitdiff
add ability to dump batch report enabled by sonar.batch.dumpReportDir
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 2 Jul 2015 10:13:04 +0000 (12:13 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 2 Jul 2015 14:14:34 +0000 (16:14 +0200)
batch report dump are saved in the directory specified by the property sonar.batch.dumpReportDir and the batch is NOT pushed to the server

scripts/generate_batch_reports.sh [new file with mode: 0755]
scripts/replay_batch.sh [new file with mode: 0755]
sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java

diff --git a/scripts/generate_batch_reports.sh b/scripts/generate_batch_reports.sh
new file mode 100755 (executable)
index 0000000..227d734
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+##############################
+#
+# Generates batch reports dumps of a specific project into a given dump repository
+# from the Git history of that project.
+#
+# This script runs the analysis of the project in the current directory of the N
+# last commits of the current project. N can be configured.
+#
+# Batch report dumps can be processed with the replay_batch.sh script
+#
+#
+##############################
+
+
+set -euo pipefail
+
+DUMP_DIR="/tmp/batch_dumps"
+HISTORY_LENGTH=30
+SONAR_HOST="http://localhost:9000"
+SONAR_USER="admin"
+SONAR_PASSWORD="admin"
+SONAR_JDBC_URL="jdbc:postgresql://localhost:5432/sonar"
+SONAR_JDBC_USERNAME="sonar"
+SONAR_JDBC_PASSWORD="sonar"
+
+function clean() {
+  git co $branch_name
+  git branch -D working_branch
+}
+
+trap "clean" EXIT
+
+# retrieve ${HISTORY_LENGTH} commits for the current directory
+git log -${HISTORY_LENGTH} --pretty=%h -- . | tac > /tmp/sha1s.txt
+
+branch_name=$(git symbolic-ref -q HEAD)
+branch_name=${branch_name##refs/heads/}
+branch_name=${branch_name:-HEAD}
+
+git co -b working_branch 
+while read sha1; do
+  echo $sha1
+  git reset --hard $sha1
+  date=`git show -s --format=%ci | sed 's/ /T/' | sed 's/ //'`
+
+  echo ""
+  echo "======================== analyzing at $date ($sha1) ======================================="
+  $M2_HOME/bin/mvn sonar:sonar -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_USER -Dsonar.password=$SONAR_PASSWORD -Dsonar.analysis.mode=analysis -Dsonar.issuesReport.html.enable= -Dsonar.issuesReport.console.enable= -Dsonar.jdbc.url=$SONAR_JDBC_URL -Dsonar.jdbc.username=$SONAR_JDBC_USERNAME -Dsonar.jdbc.password=$SONAR_JDBC_PASSWORD -Dsonar.batch.dumpReportDir=$DUMP_DIR -Dsonar.projectDate=$date
+  
+done < /tmp/sha1s.txt
+
diff --git a/scripts/replay_batch.sh b/scripts/replay_batch.sh
new file mode 100755 (executable)
index 0000000..c1bd982
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set -euo pipefail
+
+DUMP_DIR="/tmp/batch_dumps"
+SQ_ROOT_URL="http://localhost:9000"
+
+cd $DUMP_DIR
+for file in *.zip; do
+  base=${file%.zip}
+  url=$(cat ${base}.txt)
+  echo "base=$base, url=$url"
+
+  curl -u admin:admin -F report=@$DUMP_DIR/${base}.zip ${SQ_ROOT_URL}${url}
+done
index 5660e8fc23f9772ae087d92e56d0479ca95f343c..0f60fe4f876d0517f8a30ee284a2a53cee99f8cb 100644 (file)
@@ -22,9 +22,12 @@ package org.sonar.batch.report;
 import com.github.kevinsawicki.http.HttpRequest;
 import com.google.common.annotations.VisibleForTesting;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.net.URISyntaxException;
 import java.net.URL;
+import java.util.Date;
 import org.apache.commons.io.FileUtils;
 import org.picocontainer.Startable;
 import org.slf4j.Logger;
@@ -41,11 +44,14 @@ import org.sonar.batch.bootstrap.ServerClient;
 import org.sonar.batch.protocol.output.BatchReportWriter;
 import org.sonar.batch.scan.ImmutableProjectReactor;
 
+import static java.lang.String.format;
+
 @BatchSide
 public class ReportPublisher implements Startable {
 
   private static final Logger LOG = LoggerFactory.getLogger(ReportPublisher.class);
   public static final String KEEP_REPORT_PROP_KEY = "sonar.batch.keepReport";
+  public static final String DUMP_REPORT_PROP_KEY = "sonar.batch.dumpReportDir";
 
   private final ServerClient serverClient;
   private final Server server;
@@ -98,7 +104,7 @@ public class ReportPublisher implements Startable {
     if (!analysisMode.isPreview()) {
       File report = prepareReport();
       if (!analysisMode.isMediumTest()) {
-        uploadMultiPartReport(report);
+        sendOrDumpReport(report);
       }
     }
     logSuccess(LoggerFactory.getLogger(getClass()));
@@ -125,38 +131,72 @@ public class ReportPublisher implements Startable {
   }
 
   @VisibleForTesting
-  void uploadMultiPartReport(File report) {
+  void sendOrDumpReport(File report) {
+    ProjectDefinition projectDefinition = projectReactor.getRoot();
+    String effectiveKey = projectDefinition.getKeyWithBranch();
+    String relativeUrl = "/api/computation/submit_report?projectKey=" + effectiveKey + "&projectName=" + ServerClient.encodeForUrl(projectDefinition.getName());
+
+    String dumpDirLocation = settings.getString(DUMP_REPORT_PROP_KEY);
+    if (dumpDirLocation == null) {
+      uploadMultiPartReport(report, relativeUrl);
+    } else {
+      dumpReport(dumpDirLocation, effectiveKey, relativeUrl, report);
+    }
+  }
+
+  private void uploadMultiPartReport(File report, String relativeUrl) {
     LOG.debug("Publish results");
     long startTime = System.currentTimeMillis();
     URL url;
     try {
-      ProjectDefinition projectDefinition = projectReactor.getRoot();
-      String effectiveKey = projectDefinition.getKeyWithBranch();
-      url = new URL(serverClient.getURL() + "/api/computation/submit_report?projectKey=" + effectiveKey + "&projectName=" + ServerClient.encodeForUrl(projectDefinition.getName()));
+      url = new URL(serverClient.getURL() + relativeUrl);
     } catch (MalformedURLException e) {
       throw new IllegalArgumentException("Invalid URL", e);
     }
     HttpRequest request = HttpRequest.post(url);
     request.trustAllCerts();
     request.trustAllHosts();
-    request.header("User-Agent", String.format("SonarQube %s", server.getVersion()));
+    request.header("User-Agent", format("SonarQube %s", server.getVersion()));
     request.basic(serverClient.getLogin(), serverClient.getPassword());
     request.part("report", null, "application/octet-stream", report);
     if (!request.ok()) {
       int responseCode = request.code();
       if (responseCode == 401) {
-        throw new IllegalStateException(String.format(serverClient.getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD));
+        throw new IllegalStateException(format(serverClient.getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD));
       }
       if (responseCode == 403) {
         // SONAR-4397 Details are in response content
         throw new IllegalStateException(request.body());
       }
-      throw new IllegalStateException(String.format("Fail to execute request [code=%s, url=%s]: %s", responseCode, url, request.body()));
+      throw new IllegalStateException(format("Fail to execute request [code=%s, url=%s]: %s", responseCode, url, request.body()));
     }
     long stopTime = System.currentTimeMillis();
     LOG.info("Analysis reports sent to server in " + (stopTime - startTime) + "ms");
   }
 
+  private void dumpReport(String dumpDirLocation, String projectKey, String relativeUrl, File report) {
+    LOG.debug("Dump report to file");
+    try {
+      dumpReportImpl(dumpDirLocation, projectKey, relativeUrl, report);
+    } catch (IOException | URISyntaxException e) {
+      LOG.error("Failed to dump report to directory " + dumpDirLocation, e);
+    }
+  }
+
+  private void dumpReportImpl(String dumpDirLocation, String projectKey, String relativeUrl, File report) throws IOException, URISyntaxException {
+    File dumpDir = new File(dumpDirLocation);
+    if (!dumpDir.exists() || !dumpDir.isDirectory()) {
+      LOG.warn("Report dump directory '{}' does not exist or is not a directory", dumpDirLocation);
+      return;
+    }
+    long dateTime = new Date().getTime();
+    File dumpedZip = new File(dumpDir, format("batch-report_%s_%s.zip", projectKey, dateTime));
+    FileUtils.copyFile(report, new FileOutputStream(dumpedZip));
+    File dumpedMetadata = new File(dumpDir, format("batch-report_%s_%s.txt", projectKey, dateTime));
+    FileUtils.write(dumpedMetadata, relativeUrl);
+    LOG.info("Batch report dumped to {}", dumpedZip.getAbsolutePath());
+  }
+
   @VisibleForTesting
   void logSuccess(Logger logger) {
     if (analysisMode.isPreview() || analysisMode.isMediumTest()) {