]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10713 Badges can only be used on projects, long living branches and applications
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 23 May 2018 17:19:51 +0000 (19:19 +0200)
committerSonarTech <sonartech@sonarsource.com>
Mon, 28 May 2018 18:20:45 +0000 (20:20 +0200)
26 files changed:
server/sonar-server/src/main/java/org/sonar/server/badge/ws/MeasureAction.java
server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsModule.java
server/sonar-server/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java
server/sonar-server/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/error.svg
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/badge.svg
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_failed.svg
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_passed.svg
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_warn.svg
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/badge.svg
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_failed.svg
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_passed.svg
server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_warn.svg
server/sonar-server/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java
server/sonar-server/src/test/java/org/sonar/server/badge/ws/ProjectBadgesWsModuleTest.java
server/sonar-server/src/test/java/org/sonar/server/badge/ws/QualityGateActionTest.java
sonar-ws-generator/src/main/java/org/sonarqube/wsgenerator/ApiDefinitionDownloader.java
sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java
sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java
sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/MeasureRequest.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/ProjectBadgesService.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/QualityGateRequest.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/package-info.java [new file with mode: 0644]
tests/src/test/java/org/sonarqube/tests/project/ProjectBadgesTest.java
tests/src/test/java/org/sonarqube/tests/project/SonarCloudProjectBadgesTest.java

index 083e858ed3f9b967419aeb3d7b785fe6e953eef5..5a2f9406a6bb26e9d73b2de1a70d686890aa11ed 100644 (file)
@@ -34,11 +34,9 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.measure.LiveMeasureDto;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.server.badge.ws.SvgGenerator.Color;
-import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.computation.task.projectanalysis.qualitymodel.Rating;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.user.UserSession;
 
 import static com.google.common.base.Preconditions.checkState;
 import static java.lang.String.format;
@@ -60,7 +58,6 @@ import static org.sonar.api.measures.Metric.ValueType;
 import static org.sonar.api.measures.Metric.Level.ERROR;
 import static org.sonar.api.measures.Metric.Level.OK;
 import static org.sonar.api.measures.Metric.Level.WARN;
-import static org.sonar.api.web.UserRole.USER;
 import static org.sonar.server.badge.ws.SvgFormatter.formatDuration;
 import static org.sonar.server.badge.ws.SvgFormatter.formatNumeric;
 import static org.sonar.server.badge.ws.SvgFormatter.formatPercent;
@@ -70,16 +67,10 @@ import static org.sonar.server.computation.task.projectanalysis.qualitymodel.Rat
 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.Rating.D;
 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.Rating.E;
 import static org.sonar.server.computation.task.projectanalysis.qualitymodel.Rating.valueOf;
-import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001;
 import static org.sonarqube.ws.MediaTypes.SVG;
 
 public class MeasureAction implements ProjectBadgesWsAction {
 
-  private static final String PARAM_PROJECT = "project";
-  private static final String PARAM_BRANCH = "branch";
-  private static final String PARAM_PULL_REQUEST = "pullRequest";
   private static final String PARAM_METRIC = "metric";
 
   private static final Map<String, String> METRIC_NAME_BY_KEY = ImmutableMap.<String, String>builder()
@@ -113,15 +104,13 @@ public class MeasureAction implements ProjectBadgesWsAction {
     D, Color.RATING_D,
     E, Color.RATING_E));
 
-  private final UserSession userSession;
   private final DbClient dbClient;
-  private final ComponentFinder componentFinder;
+  private final ProjectBadgesSupport support;
   private final SvgGenerator svgGenerator;
 
-  public MeasureAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder, SvgGenerator svgGenerator) {
-    this.userSession = userSession;
+  public MeasureAction(DbClient dbClient, ProjectBadgesSupport support, SvgGenerator svgGenerator) {
     this.dbClient = dbClient;
-    this.componentFinder = componentFinder;
+    this.support = support;
     this.svgGenerator = svgGenerator;
   }
 
@@ -133,18 +122,7 @@ public class MeasureAction implements ProjectBadgesWsAction {
         "Requires 'Browse' permission on the specified project.")
       .setSince("7.1")
       .setResponseExample(Resources.getResource(getClass(), "measure-example.svg"));
-    action.createParam(PARAM_PROJECT)
-      .setDescription("Project key")
-      .setRequired(true)
-      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
-    action
-      .createParam(PARAM_BRANCH)
-      .setDescription("Branch key")
-      .setExampleValue(KEY_BRANCH_EXAMPLE_001);
-    action
-      .createParam(PARAM_PULL_REQUEST)
-      .setDescription("Pull request id")
-      .setExampleValue(KEY_PULL_REQUEST_EXAMPLE_001);
+    support.addProjectAndBranchParams(action);
     action.createParam(PARAM_METRIC)
       .setDescription("Metric key")
       .setRequired(true)
@@ -156,7 +134,7 @@ public class MeasureAction implements ProjectBadgesWsAction {
     response.stream().setMediaType(SVG);
     String metricKey = request.mandatoryParam(PARAM_METRIC);
     try (DbSession dbSession = dbClient.openSession(false)) {
-      ComponentDto project = getProject(dbSession, request);
+      ComponentDto project = support.getComponent(dbSession, request);
       MetricDto metric = dbClient.metricDao().selectByKey(dbSession, metricKey);
       checkState(metric != null && metric.isEnabled(), "Metric '%s' hasn't been found", metricKey);
       LiveMeasureDto measure = getMeasure(dbSession, project, metricKey);
@@ -166,19 +144,6 @@ public class MeasureAction implements ProjectBadgesWsAction {
     }
   }
 
-  private ComponentDto getProject(DbSession dbSession, Request request) {
-    try {
-      String projectKey = request.mandatoryParam(PARAM_PROJECT);
-      String branch = request.param(PARAM_BRANCH);
-      String pullRequest = request.param(PARAM_PULL_REQUEST);
-      ComponentDto project = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, projectKey, branch, pullRequest);
-      userSession.checkComponentPermission(USER, project);
-      return project;
-    } catch (NotFoundException e) {
-      throw new NotFoundException("Component not found");
-    }
-  }
-
   private LiveMeasureDto getMeasure(DbSession dbSession, ComponentDto project, String metricKey) {
     return dbClient.liveMeasureDao().selectMeasure(dbSession, project.uuid(), metricKey)
       .orElseThrow(() -> new ProjectBadgesException("Measure has not been found"));
@@ -218,7 +183,7 @@ public class MeasureAction implements ProjectBadgesWsAction {
 
   private static <PARAM> PARAM getNonNullValue(LiveMeasureDto measure, Function<LiveMeasureDto, PARAM> function) {
     PARAM value = function.apply(measure);
-    checkState(value != null, "Measure not found");
+    checkState(value != null, "Measure has not been found");
     return value;
   }
 
diff --git a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java
new file mode 100644 (file)
index 0000000..a80bcb4
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.server.badge.ws;
+
+import java.util.Optional;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.BranchDto;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.user.UserSession;
+
+import static org.sonar.api.resources.Qualifiers.APP;
+import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.db.component.BranchType.LONG;
+import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+
+public class ProjectBadgesSupport {
+
+  private static final String PARAM_PROJECT = "project";
+  private static final String PARAM_BRANCH = "branch";
+
+  private final UserSession userSession;
+  private final DbClient dbClient;
+  private final ComponentFinder componentFinder;
+
+  public ProjectBadgesSupport(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder) {
+    this.userSession = userSession;
+    this.dbClient = dbClient;
+    this.componentFinder = componentFinder;
+  }
+
+  void addProjectAndBranchParams(WebService.NewAction action) {
+    action.createParam(PARAM_PROJECT)
+      .setDescription("Project or application key")
+      .setRequired(true)
+      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
+    action
+      .createParam(PARAM_BRANCH)
+      .setDescription("Long living branch key")
+      .setExampleValue(KEY_BRANCH_EXAMPLE_001);
+  }
+
+  ComponentDto getComponent(DbSession dbSession, Request request) {
+    try {
+      String projectKey = request.mandatoryParam(PARAM_PROJECT);
+      String branchName = request.param(PARAM_BRANCH);
+      ComponentDto project = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, projectKey, branchName, null);
+      checkComponentType(dbSession, project);
+      userSession.checkComponentPermission(USER, project);
+      return project;
+    } catch (NotFoundException e) {
+      throw new NotFoundException("Project has not been found");
+    }
+  }
+
+  private void checkComponentType(DbSession dbSession, ComponentDto project) {
+    Optional<BranchDto> branch = dbClient.branchDao().selectByUuid(dbSession, project.uuid());
+    if (project.isPrivate()) {
+      throw generateInvalidProjectExcpetion();
+    }
+    if (branch.isPresent() && !branch.get().getBranchType().equals(LONG)) {
+      throw generateInvalidProjectExcpetion();
+    }
+    if (!project.qualifier().equals(PROJECT) && !project.qualifier().equals(APP)) {
+      throw generateInvalidProjectExcpetion();
+    }
+  }
+
+  private static ProjectBadgesException generateInvalidProjectExcpetion() {
+    return new ProjectBadgesException("Project is invalid");
+  }
+}
index 0a351bf21646c59e1a221d35edd221a32ed39899..1fead5916771e222c23182d199584552670d75bc 100644 (file)
@@ -29,6 +29,7 @@ public class ProjectBadgesWsModule extends Module {
       ProjectBadgesWs.class,
       QualityGateAction.class,
       MeasureAction.class,
-      SvgGenerator.class);
+      SvgGenerator.class,
+      ProjectBadgesSupport.class);
   }
 }
index 066940e2c1f10775f30605de92662f41e715d0db..dad88fd643f759782284f9a61522d96c3038c3bc 100644 (file)
@@ -20,7 +20,6 @@
 package org.sonar.server.badge.ws;
 
 import com.google.common.io.Resources;
-import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric.Level;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
@@ -30,35 +29,23 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.measure.LiveMeasureDto;
-import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
-import org.sonar.server.user.UserSession;
 
-import static java.lang.String.format;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.commons.io.IOUtils.write;
-import static org.sonar.api.web.UserRole.USER;
-import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
-import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
-import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001;
+import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
 import static org.sonarqube.ws.MediaTypes.SVG;
 
 public class QualityGateAction implements ProjectBadgesWsAction {
 
-  private static final String PARAM_PROJECT = "project";
-  private static final String PARAM_BRANCH = "branch";
-  private static final String PARAM_PULL_REQUEST = "pullRequest";
-
-  private final UserSession userSession;
   private final DbClient dbClient;
-  private final ComponentFinder componentFinder;
+  private final ProjectBadgesSupport support;
   private final SvgGenerator svgGenerator;
 
-  public QualityGateAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder, SvgGenerator svgGenerator) {
-    this.userSession = userSession;
+  public QualityGateAction(DbClient dbClient, ProjectBadgesSupport support, SvgGenerator svgGenerator) {
     this.dbClient = dbClient;
-    this.componentFinder = componentFinder;
+    this.support = support;
     this.svgGenerator = svgGenerator;
   }
 
@@ -70,26 +57,14 @@ public class QualityGateAction implements ProjectBadgesWsAction {
       .setDescription("Generate badge for project's quality gate as an SVG.<br/>" +
         "Requires 'Browse' permission on the specified project.")
       .setResponseExample(Resources.getResource(getClass(), "quality_gate-example.svg"));
-    action.createParam(PARAM_PROJECT)
-      .setDescription("Project key")
-      .setRequired(true)
-      .setExampleValue(KEY_PROJECT_EXAMPLE_001);
-    action
-      .createParam(PARAM_BRANCH)
-      .setDescription("Branch key")
-      .setExampleValue(KEY_BRANCH_EXAMPLE_001);
-    action
-      .createParam(PARAM_PULL_REQUEST)
-      .setDescription("Pull request id")
-      .setExampleValue(KEY_PULL_REQUEST_EXAMPLE_001);
+    support.addProjectAndBranchParams(action);
   }
 
   @Override
   public void handle(Request request, Response response) throws Exception {
     response.stream().setMediaType(SVG);
     try (DbSession dbSession = dbClient.openSession(false)) {
-      ComponentDto project = getProject(dbSession, request);
-      userSession.checkComponentPermission(USER, project);
+      ComponentDto project = support.getComponent(dbSession, request);
       Level qualityGateStatus = getQualityGate(dbSession, project);
       write(svgGenerator.generateQualityGate(qualityGateStatus), response.stream().output(), UTF_8);
     } catch (ProjectBadgesException | ForbiddenException | NotFoundException e) {
@@ -97,23 +72,10 @@ public class QualityGateAction implements ProjectBadgesWsAction {
     }
   }
 
-  private ComponentDto getProject(DbSession dbSession, Request request) {
-    try {
-      String projectKey = request.mandatoryParam(PARAM_PROJECT);
-      String branch = request.param(PARAM_BRANCH);
-      String pullRequest = request.param(PARAM_PULL_REQUEST);
-      ComponentDto project = componentFinder.getByKeyAndOptionalBranchOrPullRequest(dbSession, projectKey, branch, pullRequest);
-      userSession.checkComponentPermission(USER, project);
-      return project;
-    } catch (NotFoundException e) {
-      throw new NotFoundException("Component not found");
-    }
-  }
-
   private Level getQualityGate(DbSession dbSession, ComponentDto project) {
-    return Level.valueOf(dbClient.liveMeasureDao().selectMeasure(dbSession, project.uuid(), CoreMetrics.ALERT_STATUS_KEY)
+    return Level.valueOf(dbClient.liveMeasureDao().selectMeasure(dbSession, project.uuid(), ALERT_STATUS_KEY)
       .map(LiveMeasureDto::getTextValue)
-      .orElseThrow(() -> new ProjectBadgesException(format("Quality gate has not been found for project '%s' and branch '%s'", project.getKey(), project.getBranch()))));
+      .orElseThrow(() -> new ProjectBadgesException("Quality gate has not been found")));
   }
 
 }
index b486dab9298e8b0c41655f489683e50a997bc8b2..5d7176f84c2f62aa82837cadaeceaf0b56bb7d87 100644 (file)
@@ -175,7 +175,7 @@ public class SvgGenerator {
 
   private static int computeWidth(String text) {
     return text.chars()
-      .mapToObj(i -> (char)i)
+      .mapToObj(i -> (char) i)
       .mapToInt(c -> {
         Integer length = CHAR_LENGTH.get(c);
         checkState(length != null, "Invalid character '%s'", c);
index c9a7d35010d604b8b018fc6567d84ae7c7890cbf..f088f6fc5a646e96b8f987ca99e6adc6f42c6417 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" height="20" width="${totalWidth}">
+    <!-- ERROR -->
     <linearGradient id="b" x2="0" y2="100%">
         <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
         <stop offset="1" stop-opacity=".1"/>
index b13050ef230766b4bd82ccc5fbf2f4792d03e73f..68877b16b1a1c00f38f99cd5341f7ce2046201da 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" height="20" width="${totalWidth}">
+    <!-- SONARCLOUD MEASURE -->
     <linearGradient id="b" x2="0" y2="100%">
         <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
         <stop offset="1" stop-opacity=".1"/>
index a83f9c79d622e21b39223721bd270eab48be1543..629d3b34baf83946cb5ff23171b6d147f051772f 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 262.5" width="128px" height="96px">
+       <!-- SONARCLOUD QUALITY GATE FAIL -->
        <path fill="#fff" d="M328.4 259.5H21.3c-10.6 0-19.5-8.7-19.5-19.5V22c0-10.6 8.7-19.5 19.5-19.5h307.1c10.6 0 19.5 8.7 19.5 19.5v218c0 10.8-8.9 19.5-19.5 19.5z"/>
        <path fill="#cfd3d7" d="M328.4 260.4H21.3C10.1 260.4.9 251.2.9 240V22c0-11.2 9.2-20.4 20.4-20.4h307.1c11.2 0 20.4 9.2 20.4 20.4v218c0 11.2-9.3 20.4-20.4 20.4zM21.3 3.4C11 3.4 2.7 11.7 2.7 22v218c0 10.3 8.3 18.6 18.6 18.6h307.1c10.3 0 18.6-8.3 18.6-18.6V22c0-10.3-8.3-18.6-18.6-18.6H21.3z"/>
        <path fill="#434447" d="M94.9 54.3c0 2.7-.4 5-1.3 7-.9 1.9-2.1 3.5-3.6 4.6l5 3.9-2.5 2.2-5.9-4.7c-.9.2-1.9.3-2.9.3-2.2 0-4.1-.5-5.8-1.6-1.7-1.1-3-2.6-3.9-4.6-.9-2-1.4-4.3-1.4-6.9v-2c0-2.7.5-5 1.4-7.1.9-2.1 2.2-3.6 3.9-4.7s3.6-1.6 5.8-1.6c2.2 0 4.2.5 5.9 1.6 1.7 1.1 3 2.6 3.9 4.7.9 2 1.4 4.4 1.4 7.1v1.8zm-3.6-1.8c0-3.3-.7-5.8-2-7.6-1.3-1.8-3.2-2.7-5.6-2.7-2.3 0-4.1.9-5.5 2.6-1.3 1.8-2 4.2-2.1 7.4v2c0 3.2.7 5.7 2 7.5 1.3 1.8 3.2 2.8 5.6 2.8 2.4 0 4.2-.9 5.5-2.6 1.3-1.7 2-4.2 2-7.4v-2zM112.8 65.3c-1.4 1.6-3.4 2.4-6.1 2.4-2.2 0-3.9-.6-5-1.9-1.2-1.3-1.7-3.2-1.7-5.7V46.6h3.5V60c0 3.1 1.3 4.7 3.8 4.7 2.7 0 4.5-1 5.4-3v-15h3.5v20.7h-3.4v-2.1zM134.4 67.3c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7-1.3-1.2-2-2.6-2-4.4 0-2.2.8-3.8 2.5-5 1.6-1.2 3.9-1.8 6.9-1.8h3.4v-1.6c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3 1.3-.6 2.6-.8 4.1-.8 2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9 1-.6 1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zM146.8 67.3h-3.5V37.9h3.5v29.4zM152.5 41.1c0-.6.2-1.1.5-1.5s.9-.6 1.6-.6c.7 0 1.2.2 1.6.6s.5.9.5 1.5-.2 1.1-.5 1.4-.9.6-1.6.6c-.7 0-1.2-.2-1.6-.6s-.5-.8-.5-1.4zm3.8 26.2h-3.5V46.6h3.5v20.7zM166.7 41.6v5h3.9v2.7h-3.9v12.8c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.4h-3.8v-2.7h3.8v-5h3.5zM181.5 62.1l4.8-15.5h3.8l-8.3 23.9c-1.3 3.4-3.3 5.2-6.1 5.2l-.7-.1-1.3-.2v-2.9l1 .1c1.2 0 2.1-.2 2.8-.7.7-.5 1.2-1.4 1.7-2.7l.8-2.1-7.4-20.5h3.9l5 15.5zM224.1 63.7c-.9 1.4-2.3 2.4-3.9 3-1.7.7-3.7 1-5.9 1-2.3 0-4.3-.5-6-1.6-1.8-1.1-3.1-2.6-4.1-4.5-1-2-1.5-4.2-1.5-6.8v-2.4c0-4.2 1-7.4 2.9-9.8 2-2.3 4.7-3.5 8.3-3.5 2.9 0 5.2.7 7 2.2 1.8 1.5 2.9 3.6 3.2 6.3h-3.7c-.7-3.7-2.9-5.5-6.6-5.5-2.5 0-4.3.9-5.6 2.6-1.3 1.7-1.9 4.2-1.9 7.5v2.3c0 3.1.7 5.6 2.1 7.5 1.4 1.8 3.4 2.8 5.8 2.8 1.4 0 2.6-.2 3.6-.5s1.9-.8 2.6-1.5v-6.2H214v-3h10.1v10.1zM242.4 67.3c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7-1.3-1.2-2-2.6-2-4.4 0-2.2.8-3.8 2.5-5 1.6-1.2 3.9-1.8 6.9-1.8h3.4v-1.6c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3 1.3-.6 2.6-.8 4.1-.8 2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9 1-.6 1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zM255.7 41.6v5h3.9v2.7h-3.9v12.8c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.4h-3.8v-2.7h3.8v-5h3.5zM272.3 67.7c-2.8 0-5.1-.9-6.8-2.8-1.8-1.8-2.6-4.3-2.6-7.4v-.6c0-2.1.4-3.9 1.2-5.5.8-1.6 1.9-2.9 3.3-3.8 1.4-.9 2.9-1.4 4.6-1.4 2.7 0 4.8.9 6.3 2.7 1.5 1.8 2.2 4.3 2.2 7.6V58h-14c.1 2 .6 3.7 1.8 4.9 1.1 1.3 2.6 1.9 4.3 1.9 1.2 0 2.3-.3 3.2-.8.9-.5 1.6-1.2 2.3-2l2.2 1.7c-1.9 2.7-4.5 4-8 4zm-.4-18.6c-1.4 0-2.6.5-3.6 1.6-1 1-1.6 2.5-1.8 4.4h10.4v-.3c-.1-1.8-.6-3.2-1.5-4.2s-2.1-1.5-3.5-1.5z"/>
index 9ddef661f7f35610d68f1e3a19c83df4651b721e..f8267221aa648680febe3ec1c8d9a9ede09426c2 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 262.5" width="128px" height="96px">
+    <!-- SONARCLOUD QUALITY GATE PASS -->
     <path fill="#fff" d="M328.4 259.5H21.5C10.9 259.5 2 250.8 2 240V21.9C2 11.3 10.7 2.4 21.5 2.4h307.1c10.6 0 19.5 8.7 19.5 19.5V240c-.2 10.8-8.8 19.5-19.7 19.5z"/>
     <path fill="#cfd3d7" d="M328.4 260.4H21.5c-11.2 0-20.4-9.2-20.4-20.4V21.9c0-11.2 9-20.4 20.4-20.4h307.1c11.2 0 20.4 9.2 20.4 20.4V240c-.2 11.2-9.2 20.4-20.6 20.4zM21.5 3.3c-10.3 0-18.6 8.3-18.6 18.6V240c0 10.3 8.3 18.6 18.6 18.6h307.1c10.3 0 18.6-8.3 18.6-18.6V21.9c0-10.3-8.3-18.6-18.6-18.6H21.5z"/>
     <path fill="#434447" d="M94.9 54.1c0 2.7-.4 5-1.3 7-.9 1.9-2.1 3.5-3.6 4.6l5 3.9-2.5 2.3-5.9-4.7c-.9.2-1.9.3-2.9.3-2.2 0-4.1-.5-5.8-1.6-1.7-1.1-3-2.6-3.9-4.6-.9-2-1.4-4.3-1.4-6.9v-2c0-2.7.5-5 1.4-7.1.9-2.1 2.2-3.6 3.9-4.7s3.6-1.6 5.8-1.6c2.2 0 4.2.5 5.9 1.6 1.7 1.1 3 2.6 3.9 4.7.9 2 1.4 4.4 1.4 7.1v1.7zm-3.6-1.8c0-3.3-.7-5.8-2-7.6-1.3-1.8-3.2-2.7-5.6-2.7-2.3 0-4.1.9-5.5 2.6-1.3 1.8-2 4.2-2.1 7.4v2c0 3.2.7 5.7 2 7.5 1.3 1.8 3.2 2.8 5.6 2.8s4.2-.9 5.5-2.6c1.3-1.7 2-4.2 2-7.4v-2zM112.8 65.1c-1.4 1.6-3.4 2.4-6.1 2.4-2.2 0-3.9-.6-5-1.9s-1.7-3.2-1.7-5.7V46.5h3.5v13.4c0 3.1 1.3 4.7 3.8 4.7 2.7 0 4.5-1 5.4-3v-15h3.5v20.7h-3.4v-2.2zM134.4 67.1c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7s-2-2.6-2-4.4c0-2.2.8-3.8 2.5-5s3.9-1.8 6.9-1.8h3.4V53c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3 1.3-.6 2.6-.8 4.1-.8 2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9 1-.6 1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zM146.8 67.1h-3.5V37.8h3.5v29.3zM152.5 41c0-.6.2-1.1.5-1.5s.9-.6 1.6-.6 1.2.2 1.6.6.5.9.5 1.5-.2 1.1-.5 1.4-.9.6-1.6.6-1.2-.2-1.6-.6-.5-.9-.5-1.4zm3.8 26.1h-3.5V46.5h3.5v20.6zM166.7 41.4v5h3.9v2.7h-3.9V62c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.2h-3.8v-2.7h3.8v-5h3.5zM181.5 62l4.8-15.5h3.8l-8.3 23.9c-1.3 3.4-3.3 5.2-6.1 5.2l-.7-.1-1.3-.2v-2.9l1 .1c1.2 0 2.1-.2 2.8-.7s1.2-1.4 1.7-2.7l.8-2.1-7.4-20.5h3.9l5 15.5zM224.1 63.5c-.9 1.4-2.3 2.4-3.9 3-1.7.7-3.7 1-5.9 1-2.3 0-4.3-.5-6-1.6s-3.1-2.6-4.1-4.5c-1-2-1.5-4.2-1.5-6.8v-2.4c0-4.2 1-7.4 2.9-9.8 2-2.3 4.7-3.5 8.2-3.5 2.9 0 5.2.7 7 2.2 1.8 1.5 2.9 3.6 3.2 6.3h-3.7c-.7-3.7-2.9-5.5-6.6-5.5-2.5 0-4.3.9-5.6 2.6-1.3 1.7-1.9 4.2-1.9 7.5v2.3c0 3.1.7 5.6 2.1 7.5 1.4 1.8 3.4 2.8 5.8 2.8 1.4 0 2.6-.2 3.6-.5s1.9-.8 2.6-1.5v-6.2H214v-3h10.1v10.1zM242.4 67.1c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7s-2-2.6-2-4.4c0-2.2.8-3.8 2.5-5s3.9-1.8 6.9-1.8h3.4V53c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3 1.3-.6 2.6-.8 4.1-.8 2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9 1-.6 1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zM255.7 41.4v5h3.9v2.7h-3.9V62c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.2h-3.8v-2.7h3.8v-5h3.5zM272.3 67.5c-2.8 0-5.1-.9-6.8-2.8-1.8-1.8-2.6-4.3-2.6-7.4v-.7c0-2.1.4-3.9 1.2-5.5.8-1.6 1.9-2.9 3.3-3.8 1.4-.9 2.9-1.4 4.6-1.4 2.7 0 4.8.9 6.3 2.7 1.5 1.8 2.2 4.3 2.2 7.6v1.5h-14c.1 2 .6 3.7 1.8 4.9 1.1 1.3 2.6 1.9 4.3 1.9 1.2 0 2.3-.3 3.2-.8.9-.5 1.6-1.2 2.3-2l2.2 1.7c-1.9 2.8-4.5 4.1-8 4.1zm-.4-18.5c-1.4 0-2.6.5-3.6 1.6-1 1-1.6 2.5-1.8 4.4h10.4v-.3c-.1-1.8-.6-3.2-1.5-4.2s-2.1-1.5-3.5-1.5z"/>
index 803b767b3b99d12a44db0fa8cddcd51dde59d6e3..386c518bc2353417ce5e1523b9f976ad4ba89f79 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 262.5" width="128px" height="96px">
+    <!-- SONARCLOUD QUALITY GATE WARN -->
     <path fill="#fff" d="M328.4 259.5H21.3c-10.6 0-19.5-8.7-19.5-19.5V22c0-10.6 8.7-19.5 19.5-19.5h307.1c10.6 0 19.5 8.7 19.5 19.5v218c0 10.8-8.9 19.5-19.5 19.5z"/>
     <path fill="#cfd3d7" d="M328.4 260.4H21.3C10.1 260.4.9 251.2.9 240V22c0-11.2 9.2-20.4 20.4-20.4h307.1c11.2 0 20.4 9.2 20.4 20.4v218c0 11.2-9.3 20.4-20.4 20.4zM21.3 3.4C11 3.4 2.7 11.7 2.7 22v218c0 10.3 8.3 18.6 18.6 18.6h307.1c10.3 0 18.6-8.3 18.6-18.6V22c0-10.3-8.3-18.6-18.6-18.6H21.3z"/>
     <path fill="#434447" d="M94.9 54.3c0 2.7-.4 5-1.3 7-.9 1.9-2.1 3.5-3.6 4.6l5 3.9-2.5 2.2-5.9-4.7c-.9.2-1.9.3-2.9.3-2.2 0-4.1-.5-5.8-1.6-1.7-1.1-3-2.6-3.9-4.6s-1.4-4.3-1.4-6.9v-2c0-2.7.5-5 1.4-7.1s2.2-3.6 3.9-4.7 3.6-1.6 5.8-1.6c2.2 0 4.2.5 5.9 1.6 1.7 1.1 3 2.6 3.9 4.7.9 2 1.4 4.4 1.4 7.1v1.8zm-3.6-1.8c0-3.3-.7-5.8-2-7.6s-3.2-2.7-5.6-2.7c-2.3 0-4.1.9-5.5 2.6-1.3 1.8-2 4.2-2.1 7.4v2c0 3.2.7 5.7 2 7.5s3.2 2.8 5.6 2.8 4.2-.9 5.5-2.6c1.3-1.7 2-4.2 2-7.4l.1-2zM112.8 65.3c-1.4 1.6-3.4 2.4-6.1 2.4-2.2 0-3.9-.6-5-1.9-1.2-1.3-1.7-3.2-1.7-5.7V46.6h3.5V60c0 3.1 1.3 4.7 3.8 4.7 2.7 0 4.5-1 5.4-3v-15h3.5v20.7h-3.4v-2.1zM134.4 67.3c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7-1.3-1.2-2-2.6-2-4.4 0-2.2.8-3.8 2.5-5 1.6-1.2 3.9-1.8 6.9-1.8h3.4v-1.6c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3s1.7-1.7 3-2.3 2.6-.8 4.1-.8c2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9s1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zM146.8 67.3h-3.5V37.9h3.5v29.4zM152.5 41.1c0-.6.2-1.1.5-1.5s.9-.6 1.6-.6c.7 0 1.2.2 1.6.6s.5.9.5 1.5-.2 1.1-.5 1.4-.9.6-1.6.6c-.7 0-1.2-.2-1.6-.6s-.5-.8-.5-1.4zm3.8 26.2h-3.5V46.6h3.5v20.7zM166.7 41.6v5h3.9v2.7h-3.9v12.8c0 .8.2 1.5.5 1.9s.9.6 1.8.6c.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.4h-3.8v-2.7h3.8v-5h3.5v-.1zM181.5 62.1l4.8-15.5h3.8l-8.3 23.9c-1.3 3.4-3.3 5.2-6.1 5.2l-.7-.1-1.3-.2v-2.9l1 .1c1.2 0 2.1-.2 2.8-.7s1.2-1.4 1.7-2.7l.8-2.1-7.4-20.5h3.9l5 15.5zM224.1 63.7c-.9 1.4-2.3 2.4-3.9 3-1.7.7-3.7 1-5.9 1-2.3 0-4.3-.5-6-1.6-1.8-1.1-3.1-2.6-4.1-4.5-1-2-1.5-4.2-1.5-6.8v-2.4c0-4.2 1-7.4 2.9-9.8 2-2.3 4.7-3.5 8.3-3.5 2.9 0 5.2.7 7 2.2s2.9 3.6 3.2 6.3h-3.7c-.7-3.7-2.9-5.5-6.6-5.5-2.5 0-4.3.9-5.6 2.6-1.3 1.7-1.9 4.2-1.9 7.5v2.3c0 3.1.7 5.6 2.1 7.5 1.4 1.8 3.4 2.8 5.8 2.8 1.4 0 2.6-.2 3.6-.5s1.9-.8 2.6-1.5v-6.2H214v-3h10.1v10.1zM242.4 67.3c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7-1.3-1.2-2-2.6-2-4.4 0-2.2.8-3.8 2.5-5 1.6-1.2 3.9-1.8 6.9-1.8h3.4v-1.6c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3s2.6-.8 4.1-.8c2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9s1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zM255.7 41.6v5h3.9v2.7h-3.9v12.8c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.4h-3.8v-2.7h3.8v-5h3.5v-.1zM272.3 67.7c-2.8 0-5.1-.9-6.8-2.8-1.8-1.8-2.6-4.3-2.6-7.4v-.6c0-2.1.4-3.9 1.2-5.5.8-1.6 1.9-2.9 3.3-3.8 1.4-.9 2.9-1.4 4.6-1.4 2.7 0 4.8.9 6.3 2.7s2.2 4.3 2.2 7.6V58h-14c.1 2 .6 3.7 1.8 4.9 1.1 1.3 2.6 1.9 4.3 1.9 1.2 0 2.3-.3 3.2-.8.9-.5 1.6-1.2 2.3-2l2.2 1.7c-1.9 2.7-4.5 4-8 4zm-.4-18.6c-1.4 0-2.6.5-3.6 1.6-1 1-1.6 2.5-1.8 4.4h10.4v-.3c-.1-1.8-.6-3.2-1.5-4.2s-2.1-1.5-3.5-1.5z"/>
index 0e8df8281810fab23be622dce3b9c5dc9dd33a5a..4d25c4088735081cb20a52d1e0f915df868e728e 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" height="20" width="${totalWidth}">
+    <!-- SONARQUBE MEASURE -->
     <linearGradient id="b" x2="0" y2="100%">
         <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
         <stop offset="1" stop-opacity=".1"/>
index 38a288fda437063fcbe879efe77a5daeaaf5543b..e04aac0bc93d4c553d7b993ed212a5b64af19376 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 262.5" width="128" height="96">
+       <!-- SONARQUBE QUALITY GATE FAIL -->
        <path fill="#fff" d="M328.4 259.5H21.3c-10.6 0-19.5-8.7-19.5-19.5V22c0-10.6 8.7-19.5 19.5-19.5h307.1c10.6 0 19.5 8.7 19.5 19.5v218c0 10.8-8.9 19.5-19.5 19.5z"/>
        <path fill="#cfd3d7" d="M328.4 260.4H21.3C10.1 260.4.9 251.2.9 240V22c0-11.2 9.2-20.4 20.4-20.4h307.1c11.2 0 20.4 9.2 20.4 20.4v218c0 11.2-9.3 20.4-20.4 20.4zM21.3 3.4C11 3.4 2.7 11.7 2.7 22v218c0 10.3 8.3 18.6 18.6 18.6h307.1c10.3 0 18.6-8.3 18.6-18.6V22c0-10.3-8.3-18.6-18.6-18.6H21.3z"/>
        <path fill="#434447" d="M94.9 54.3c0 2.7-.4 5-1.3 7-.9 1.9-2.1 3.5-3.6 4.6l5 3.9-2.5 2.2-5.9-4.7c-.9.2-1.9.3-2.9.3-2.2 0-4.1-.5-5.8-1.6-1.7-1.1-3-2.6-3.9-4.6-.9-2-1.4-4.3-1.4-6.9v-2c0-2.7.5-5 1.4-7.1.9-2.1 2.2-3.6 3.9-4.7s3.6-1.6 5.8-1.6c2.2 0 4.2.5 5.9 1.6 1.7 1.1 3 2.6 3.9 4.7.9 2 1.4 4.4 1.4 7.1v1.8zm-3.6-1.8c0-3.3-.7-5.8-2-7.6-1.3-1.8-3.2-2.7-5.6-2.7-2.3 0-4.1.9-5.5 2.6-1.3 1.8-2 4.2-2.1 7.4v2c0 3.2.7 5.7 2 7.5 1.3 1.8 3.2 2.8 5.6 2.8 2.4 0 4.2-.9 5.5-2.6 1.3-1.7 2-4.2 2-7.4v-2zm21.5 12.8c-1.4 1.6-3.4 2.4-6.1 2.4-2.2 0-3.9-.6-5-1.9-1.2-1.3-1.7-3.2-1.7-5.7V46.6h3.5V60c0 3.1 1.3 4.7 3.8 4.7 2.7 0 4.5-1 5.4-3v-15h3.5v20.7h-3.4v-2.1zm21.6 2c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7-1.3-1.2-2-2.6-2-4.4 0-2.2.8-3.8 2.5-5 1.6-1.2 3.9-1.8 6.9-1.8h3.4v-1.6c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3 1.3-.6 2.6-.8 4.1-.8 2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9 1-.6 1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zm18.3 2.7h-3.5V37.9h3.5v29.4zm5.7-26.2c0-.6.2-1.1.5-1.5s.9-.6 1.6-.6c.7 0 1.2.2 1.6.6s.5.9.5 1.5-.2 1.1-.5 1.4-.9.6-1.6.6c-.7 0-1.2-.2-1.6-.6s-.5-.8-.5-1.4zm3.8 26.2h-3.5V46.6h3.5v20.7zm10.4-25.7v5h3.9v2.7h-3.9v12.8c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.4h-3.8v-2.7h3.8v-5h3.5zm14.8 20.5l4.8-15.5h3.8l-8.3 23.9c-1.3 3.4-3.3 5.2-6.1 5.2l-.7-.1-1.3-.2v-2.9l1 .1c1.2 0 2.1-.2 2.8-.7.7-.5 1.2-1.4 1.7-2.7l.8-2.1-7.4-20.5h3.9l5 15.5zm42.6 1.6c-.9 1.4-2.3 2.4-3.9 3-1.7.7-3.7 1-5.9 1-2.3 0-4.3-.5-6-1.6-1.8-1.1-3.1-2.6-4.1-4.5-1-2-1.5-4.2-1.5-6.8v-2.4c0-4.2 1-7.4 2.9-9.8 2-2.3 4.7-3.5 8.3-3.5 2.9 0 5.2.7 7 2.2 1.8 1.5 2.9 3.6 3.2 6.3h-3.7c-.7-3.7-2.9-5.5-6.6-5.5-2.5 0-4.3.9-5.6 2.6-1.3 1.7-1.9 4.2-1.9 7.5v2.3c0 3.1.7 5.6 2.1 7.5 1.4 1.8 3.4 2.8 5.8 2.8 1.4 0 2.6-.2 3.6-.5s1.9-.8 2.6-1.5v-6.2H214v-3h10.1v10.1zm18.3 3.6c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7-1.3-1.2-2-2.6-2-4.4 0-2.2.8-3.8 2.5-5 1.6-1.2 3.9-1.8 6.9-1.8h3.4v-1.6c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3 1.3-.6 2.6-.8 4.1-.8 2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9 1-.6 1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zm19.2-23v5h3.9v2.7h-3.9v12.8c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.4h-3.8v-2.7h3.8v-5h3.5zm16.6 26.1c-2.8 0-5.1-.9-6.8-2.8-1.8-1.8-2.6-4.3-2.6-7.4v-.6c0-2.1.4-3.9 1.2-5.5.8-1.6 1.9-2.9 3.3-3.8 1.4-.9 2.9-1.4 4.6-1.4 2.7 0 4.8.9 6.3 2.7 1.5 1.8 2.2 4.3 2.2 7.6V58h-14c.1 2 .6 3.7 1.8 4.9 1.1 1.3 2.6 1.9 4.3 1.9 1.2 0 2.3-.3 3.2-.8.9-.5 1.6-1.2 2.3-2l2.2 1.7c-1.9 2.7-4.5 4-8 4zm-.4-18.6c-1.4 0-2.6.5-3.6 1.6-1 1-1.6 2.5-1.8 4.4h10.4v-.3c-.1-1.8-.6-3.2-1.5-4.2s-2.1-1.5-3.5-1.5z"/>
index 957e85063dd4708399663865dec22c010ab78eb0..23b835da71d4fb80564c3cd74a8a1b0987dc009f 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 262.5" width="128" height="96">
+       <!-- SONARQUBE QUALITY GATE PASS -->
        <path fill="#fff" d="M328.4 259.5H21.5C10.9 259.5 2 250.8 2 240V21.9C2 11.3 10.7 2.4 21.5 2.4h307.1c10.6 0 19.5 8.7 19.5 19.5V240c-.2 10.8-8.8 19.5-19.7 19.5z"/>
        <path fill="#cfd3d7" d="M328.4 260.4H21.5c-11.2 0-20.4-9.2-20.4-20.4V21.9c0-11.2 9-20.4 20.4-20.4h307.1c11.2 0 20.4 9.2 20.4 20.4V240c-.2 11.2-9.2 20.4-20.6 20.4zM21.5 3.3c-10.3 0-18.6 8.3-18.6 18.6V240c0 10.3 8.3 18.6 18.6 18.6h307.1c10.3 0 18.6-8.3 18.6-18.6V21.9c0-10.3-8.3-18.6-18.6-18.6H21.5z"/>
        <path fill="#434447" d="M94.9 54.1c0 2.7-.4 5-1.3 7-.9 1.9-2.1 3.5-3.6 4.6l5 3.9-2.5 2.3-5.9-4.7c-.9.2-1.9.3-2.9.3-2.2 0-4.1-.5-5.8-1.6-1.7-1.1-3-2.6-3.9-4.6-.9-2-1.4-4.3-1.4-6.9v-2c0-2.7.5-5 1.4-7.1.9-2.1 2.2-3.6 3.9-4.7s3.6-1.6 5.8-1.6c2.2 0 4.2.5 5.9 1.6 1.7 1.1 3 2.6 3.9 4.7.9 2 1.4 4.4 1.4 7.1v1.7zm-3.6-1.8c0-3.3-.7-5.8-2-7.6-1.3-1.8-3.2-2.7-5.6-2.7-2.3 0-4.1.9-5.5 2.6-1.3 1.8-2 4.2-2.1 7.4v2c0 3.2.7 5.7 2 7.5 1.3 1.8 3.2 2.8 5.6 2.8s4.2-.9 5.5-2.6c1.3-1.7 2-4.2 2-7.4v-2zm21.5 12.8c-1.4 1.6-3.4 2.4-6.1 2.4-2.2 0-3.9-.6-5-1.9s-1.7-3.2-1.7-5.7V46.5h3.5v13.4c0 3.1 1.3 4.7 3.8 4.7 2.7 0 4.5-1 5.4-3v-15h3.5v20.7h-3.4v-2.2zm21.6 2c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7s-2-2.6-2-4.4c0-2.2.8-3.8 2.5-5s3.9-1.8 6.9-1.8h3.4V53c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3 1.3-.6 2.6-.8 4.1-.8 2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9 1-.6 1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zm18.3 2.7h-3.5V37.8h3.5v29.3zm5.7-26.1c0-.6.2-1.1.5-1.5s.9-.6 1.6-.6 1.2.2 1.6.6.5.9.5 1.5-.2 1.1-.5 1.4-.9.6-1.6.6-1.2-.2-1.6-.6-.5-.9-.5-1.4zm3.8 26.1h-3.5V46.5h3.5v20.6zm10.4-25.7v5h3.9v2.7h-3.9V62c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.2h-3.8v-2.7h3.8v-5h3.5zM181.5 62l4.8-15.5h3.8l-8.3 23.9c-1.3 3.4-3.3 5.2-6.1 5.2l-.7-.1-1.3-.2v-2.9l1 .1c1.2 0 2.1-.2 2.8-.7s1.2-1.4 1.7-2.7l.8-2.1-7.4-20.5h3.9l5 15.5zm42.6 1.5c-.9 1.4-2.3 2.4-3.9 3-1.7.7-3.7 1-5.9 1-2.3 0-4.3-.5-6-1.6s-3.1-2.6-4.1-4.5c-1-2-1.5-4.2-1.5-6.8v-2.4c0-4.2 1-7.4 2.9-9.8 2-2.3 4.7-3.5 8.2-3.5 2.9 0 5.2.7 7 2.2 1.8 1.5 2.9 3.6 3.2 6.3h-3.7c-.7-3.7-2.9-5.5-6.6-5.5-2.5 0-4.3.9-5.6 2.6-1.3 1.7-1.9 4.2-1.9 7.5v2.3c0 3.1.7 5.6 2.1 7.5 1.4 1.8 3.4 2.8 5.8 2.8 1.4 0 2.6-.2 3.6-.5s1.9-.8 2.6-1.5v-6.2H214v-3h10.1v10.1zm18.3 3.6c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7s-2-2.6-2-4.4c0-2.2.8-3.8 2.5-5s3.9-1.8 6.9-1.8h3.4V53c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3 1.3-.6 2.6-.8 4.1-.8 2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9 1-.6 1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zm19.2-23v5h3.9v2.7h-3.9V62c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.2h-3.8v-2.7h3.8v-5h3.5zm16.6 26.1c-2.8 0-5.1-.9-6.8-2.8-1.8-1.8-2.6-4.3-2.6-7.4v-.7c0-2.1.4-3.9 1.2-5.5.8-1.6 1.9-2.9 3.3-3.8 1.4-.9 2.9-1.4 4.6-1.4 2.7 0 4.8.9 6.3 2.7 1.5 1.8 2.2 4.3 2.2 7.6v1.5h-14c.1 2 .6 3.7 1.8 4.9 1.1 1.3 2.6 1.9 4.3 1.9 1.2 0 2.3-.3 3.2-.8.9-.5 1.6-1.2 2.3-2l2.2 1.7c-1.9 2.8-4.5 4.1-8 4.1zm-.4-18.5c-1.4 0-2.6.5-3.6 1.6-1 1-1.6 2.5-1.8 4.4h10.4v-.3c-.1-1.8-.6-3.2-1.5-4.2s-2.1-1.5-3.5-1.5z"/>
index 629a648a07923341eb4907d4ba61200dcd544261..a0c22703d15e0c70fe5748c0228baf5b8f6b1129 100644 (file)
@@ -1,4 +1,5 @@
 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 262.5" width="128" height="96">
+       <!-- SONARQUBE QUALITY GATE WARN -->
        <path fill="#fff" d="M328.4 259.5H21.3c-10.6 0-19.5-8.7-19.5-19.5V22c0-10.6 8.7-19.5 19.5-19.5h307.1c10.6 0 19.5 8.7 19.5 19.5v218c0 10.8-8.9 19.5-19.5 19.5z"/>
        <path fill="#cfd3d7" d="M328.4 260.4H21.3C10.1 260.4.9 251.2.9 240V22c0-11.2 9.2-20.4 20.4-20.4h307.1c11.2 0 20.4 9.2 20.4 20.4v218c0 11.2-9.3 20.4-20.4 20.4zM21.3 3.4C11 3.4 2.7 11.7 2.7 22v218c0 10.3 8.3 18.6 18.6 18.6h307.1c10.3 0 18.6-8.3 18.6-18.6V22c0-10.3-8.3-18.6-18.6-18.6H21.3z"/>
        <path fill="#434447" d="M94.9 54.3c0 2.7-.4 5-1.3 7-.9 1.9-2.1 3.5-3.6 4.6l5 3.9-2.5 2.2-5.9-4.7c-.9.2-1.9.3-2.9.3-2.2 0-4.1-.5-5.8-1.6-1.7-1.1-3-2.6-3.9-4.6s-1.4-4.3-1.4-6.9v-2c0-2.7.5-5 1.4-7.1s2.2-3.6 3.9-4.7 3.6-1.6 5.8-1.6c2.2 0 4.2.5 5.9 1.6 1.7 1.1 3 2.6 3.9 4.7.9 2 1.4 4.4 1.4 7.1v1.8zm-3.6-1.8c0-3.3-.7-5.8-2-7.6s-3.2-2.7-5.6-2.7c-2.3 0-4.1.9-5.5 2.6-1.3 1.8-2 4.2-2.1 7.4v2c0 3.2.7 5.7 2 7.5s3.2 2.8 5.6 2.8 4.2-.9 5.5-2.6c1.3-1.7 2-4.2 2-7.4l.1-2zm21.5 12.8c-1.4 1.6-3.4 2.4-6.1 2.4-2.2 0-3.9-.6-5-1.9-1.2-1.3-1.7-3.2-1.7-5.7V46.6h3.5V60c0 3.1 1.3 4.7 3.8 4.7 2.7 0 4.5-1 5.4-3v-15h3.5v20.7h-3.4v-2.1zm21.6 2c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7-1.3-1.2-2-2.6-2-4.4 0-2.2.8-3.8 2.5-5 1.6-1.2 3.9-1.8 6.9-1.8h3.4v-1.6c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3s1.7-1.7 3-2.3 2.6-.8 4.1-.8c2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9s1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zm18.3 2.7h-3.5V37.9h3.5v29.4zm5.7-26.2c0-.6.2-1.1.5-1.5s.9-.6 1.6-.6c.7 0 1.2.2 1.6.6s.5.9.5 1.5-.2 1.1-.5 1.4-.9.6-1.6.6c-.7 0-1.2-.2-1.6-.6s-.5-.8-.5-1.4zm3.8 26.2h-3.5V46.6h3.5v20.7zm10.4-25.7v5h3.9v2.7h-3.9v12.8c0 .8.2 1.5.5 1.9s.9.6 1.8.6c.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.4h-3.8v-2.7h3.8v-5h3.5v-.1zm14.8 20.5l4.8-15.5h3.8l-8.3 23.9c-1.3 3.4-3.3 5.2-6.1 5.2l-.7-.1-1.3-.2v-2.9l1 .1c1.2 0 2.1-.2 2.8-.7s1.2-1.4 1.7-2.7l.8-2.1-7.4-20.5h3.9l5 15.5zm42.6 1.6c-.9 1.4-2.3 2.4-3.9 3-1.7.7-3.7 1-5.9 1-2.3 0-4.3-.5-6-1.6-1.8-1.1-3.1-2.6-4.1-4.5-1-2-1.5-4.2-1.5-6.8v-2.4c0-4.2 1-7.4 2.9-9.8 2-2.3 4.7-3.5 8.3-3.5 2.9 0 5.2.7 7 2.2s2.9 3.6 3.2 6.3h-3.7c-.7-3.7-2.9-5.5-6.6-5.5-2.5 0-4.3.9-5.6 2.6-1.3 1.7-1.9 4.2-1.9 7.5v2.3c0 3.1.7 5.6 2.1 7.5 1.4 1.8 3.4 2.8 5.8 2.8 1.4 0 2.6-.2 3.6-.5s1.9-.8 2.6-1.5v-6.2H214v-3h10.1v10.1zm18.3 3.6c-.2-.4-.4-1.1-.5-2.2-1.6 1.7-3.6 2.6-5.9 2.6-2 0-3.7-.6-5-1.7-1.3-1.2-2-2.6-2-4.4 0-2.2.8-3.8 2.5-5 1.6-1.2 3.9-1.8 6.9-1.8h3.4v-1.6c0-1.2-.4-2.2-1.1-3-.7-.7-1.8-1.1-3.3-1.1-1.3 0-2.3.3-3.2 1-.9.6-1.3 1.4-1.3 2.3h-3.6c0-1 .4-2 1.1-3 .7-1 1.7-1.7 3-2.3s2.6-.8 4.1-.8c2.4 0 4.3.6 5.6 1.8 1.4 1.2 2.1 2.8 2.1 4.9v9.5c0 1.9.2 3.4.7 4.5v.3h-3.5zm-5.9-2.7c1.1 0 2.2-.3 3.2-.9s1.7-1.3 2.2-2.2v-4.2h-2.8c-4.3 0-6.5 1.3-6.5 3.8 0 1.1.4 2 1.1 2.6.7.6 1.7.9 2.8.9zm19.2-23v5h3.9v2.7h-3.9v12.8c0 .8.2 1.5.5 1.9.3.4.9.6 1.8.6.4 0 1-.1 1.7-.2v2.9c-.9.3-1.8.4-2.7.4-1.6 0-2.8-.5-3.6-1.4-.8-1-1.2-2.3-1.2-4.1V49.4h-3.8v-2.7h3.8v-5h3.5v-.1zm16.6 26.1c-2.8 0-5.1-.9-6.8-2.8-1.8-1.8-2.6-4.3-2.6-7.4v-.6c0-2.1.4-3.9 1.2-5.5.8-1.6 1.9-2.9 3.3-3.8 1.4-.9 2.9-1.4 4.6-1.4 2.7 0 4.8.9 6.3 2.7s2.2 4.3 2.2 7.6V58h-14c.1 2 .6 3.7 1.8 4.9 1.1 1.3 2.6 1.9 4.3 1.9 1.2 0 2.3-.3 3.2-.8.9-.5 1.6-1.2 2.3-2l2.2 1.7c-1.9 2.7-4.5 4-8 4zm-.4-18.6c-1.4 0-2.6.5-3.6 1.6-1 1-1.6 2.5-1.8 4.4h10.4v-.3c-.1-1.8-.6-3.2-1.5-4.2s-2.1-1.5-3.5-1.5z"/>
index 3691bbdfb877ceb78cf029197f2f4e15b494d670..652675893f845b02a6aab151c814d61cec00e56b 100644 (file)
@@ -31,11 +31,13 @@ import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric.Level;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.web.UserRole;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.BranchType;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.badge.ws.SvgGenerator.Color;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.computation.task.projectanalysis.qualitymodel.Rating;
@@ -56,6 +58,9 @@ import static org.sonar.api.measures.Metric.ValueType.LEVEL;
 import static org.sonar.api.measures.Metric.ValueType.PERCENT;
 import static org.sonar.api.measures.Metric.ValueType.RATING;
 import static org.sonar.api.measures.Metric.ValueType.WORK_DUR;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.db.component.BranchType.LONG;
+import static org.sonar.db.component.BranchType.SHORT;
 import static org.sonar.server.badge.ws.SvgGenerator.Color.DEFAULT;
 import static org.sonar.server.badge.ws.SvgGenerator.Color.QUALITY_GATE_ERROR;
 import static org.sonar.server.badge.ws.SvgGenerator.Color.QUALITY_GATE_OK;
@@ -74,7 +79,10 @@ public class MeasureActionTest {
   private MapSettings mapSettings = new MapSettings().setProperty("sonar.sonarcloud.enabled", false);
 
   private WsActionTester ws = new WsActionTester(
-    new MeasureAction(userSession, db.getDbClient(), new ComponentFinder(db.getDbClient(), null), new SvgGenerator(mapSettings.asConfig())));
+    new MeasureAction(
+      db.getDbClient(),
+      new ProjectBadgesSupport(userSession, db.getDbClient(), new ComponentFinder(db.getDbClient(), null)),
+      new SvgGenerator(mapSettings.asConfig())));
 
   @Test
   public void int_measure() {
@@ -174,39 +182,41 @@ public class MeasureActionTest {
   }
 
   @Test
-  public void fail_on_invalid_quality_gate() {
-    ComponentDto project = db.components().insertMainBranch();
-    userSession.addProjectPermission(UserRole.USER, project);
-    MetricDto metric = createQualityGateMetric();
-    db.measures().insertLiveMeasure(project, metric, m -> m.setData("UNKNOWN"));
-
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("No enum constant org.sonar.api.measures.Metric.Level.UNKNOWN");
+  public void measure_on_long_living_branch() {
+    ComponentDto project = db.components().insertMainBranch(p -> p.setPrivate(false));
+    userSession.registerComponents(project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name()));
+    db.measures().insertLiveMeasure(project, metric, m -> m.setValue(5_000d));
+    ComponentDto longBranch = db.components().insertProjectBranch(project, b -> b.setBranchType(LONG));
+    db.measures().insertLiveMeasure(longBranch, metric, m -> m.setValue(10_000d));
 
-    ws.newRequest()
-      .setParam("project", project.getKey())
+    String response = ws.newRequest()
+      .setParam("project", longBranch.getKey())
+      .setParam("branch", longBranch.getBranch())
       .setParam("metric", metric.getKey())
-      .execute();
+      .execute().getInput();
+
+    checkSvg(response, "bugs", "10k", DEFAULT);
   }
 
   @Test
-  public void fail_when_measure_value_is_null() {
-    ComponentDto project = db.components().insertPublicProject();
-    userSession.registerComponents(project);
+  public void measure_on_application() {
+    OrganizationDto organization = db.organizations().insert();
+    ComponentDto application = db.components().insertPublicApplication(organization);
+    userSession.registerComponents(application);
     MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name()));
-    db.measures().insertLiveMeasure(project, metric, m -> m.setValue(null));
+    db.measures().insertLiveMeasure(application, metric, m -> m.setValue(10_000d));
 
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Measure not found");
-
-    ws.newRequest()
-      .setParam("project", project.getKey())
+    String response = ws.newRequest()
+      .setParam("project", application.getKey())
       .setParam("metric", metric.getKey())
-      .execute();
+      .execute().getInput();
+
+    checkSvg(response, "bugs", "10k", DEFAULT);
   }
 
   @Test
-  public void project_does_not_exist() {
+  public void return_error_if_project_does_not_exist() {
     MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY));
 
     String response = ws.newRequest()
@@ -214,16 +224,15 @@ public class MeasureActionTest {
       .setParam("metric", metric.getKey())
       .execute().getInput();
 
-    checkError(response, "Component not found");
+    checkError(response, "Project has not been found");
   }
 
   @Test
-  public void branch_does_not_exist() {
+  public void return_error_if_branch_does_not_exist() {
     ComponentDto project = db.components().insertMainBranch();
     ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.LONG));
-    userSession.addProjectPermission(UserRole.USER, project);
+    userSession.addProjectPermission(USER, project);
     MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY));
-    db.measures().insertLiveMeasure(project, metric, m -> m.setValue(10d));
 
     String response = ws.newRequest()
       .setParam("project", branch.getKey())
@@ -231,11 +240,11 @@ public class MeasureActionTest {
       .setParam("metric", metric.getKey())
       .execute().getInput();
 
-    checkError(response, "Component not found");
+    checkError(response, "Project has not been found");
   }
 
   @Test
-  public void measure_not_found() {
+  public void return_error_if_measure_not_found() {
     ComponentDto project = db.components().insertPublicProject();
     userSession.registerComponents(project);
     MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY));
@@ -249,8 +258,69 @@ public class MeasureActionTest {
   }
 
   @Test
-  public void unauthorized() {
+  public void return_error_on_directory() {
+    ComponentDto project = db.components().insertPublicProject();
+    ComponentDto directory = db.components().insertComponent(ComponentTesting.newDirectory(project, "path"));
+    userSession.registerComponents(project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name()));
+
+    String response = ws.newRequest()
+      .setParam("project", directory.getKey())
+      .setParam("metric", metric.getKey())
+      .execute().getInput();
+
+    checkError(response, "Project is invalid");
+  }
+
+  @Test
+  public void return_error_on_short_living_branch() {
+    ComponentDto project = db.components().insertMainBranch();
+    ComponentDto shortBranch = db.components().insertProjectBranch(project, b -> b.setBranchType(SHORT));
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(USER, project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name()));
+
+    String response = ws.newRequest()
+      .setParam("project", shortBranch.getKey())
+      .setParam("branch", shortBranch.getBranch())
+      .setParam("metric", metric.getKey())
+      .execute().getInput();
+
+    checkError(response, "Project is invalid");
+  }
+
+  @Test
+  public void return_error_on_private_project() {
     ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(USER, project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name()));
+
+    String response = ws.newRequest()
+      .setParam("project", project.getKey())
+      .setParam("metric", metric.getKey())
+      .execute().getInput();
+
+    checkError(response, "Project is invalid");
+  }
+
+  @Test
+  public void return_error_on_provisioned_project() {
+    ComponentDto project = db.components().insertPublicProject();
+    userSession.registerComponents(project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name()));
+
+    String response = ws.newRequest()
+      .setParam("project", project.getKey())
+      .setParam("metric", metric.getKey())
+      .execute().getInput();
+
+    checkError(response, "Measure has not been found");
+  }
+
+  @Test
+  public void return_error_if_unauthorized() {
+    ComponentDto project = db.components().insertPublicProject();
     MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY));
 
     String response = ws.newRequest()
@@ -261,10 +331,42 @@ public class MeasureActionTest {
     checkError(response, "Insufficient privileges");
   }
 
+  @Test
+  public void fail_on_invalid_quality_gate() {
+    ComponentDto project = db.components().insertPublicProject();
+    userSession.registerComponents(project);
+    MetricDto metric = createQualityGateMetric();
+    db.measures().insertLiveMeasure(project, metric, m -> m.setData("UNKNOWN"));
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("No enum constant org.sonar.api.measures.Metric.Level.UNKNOWN");
+
+    ws.newRequest()
+      .setParam("project", project.getKey())
+      .setParam("metric", metric.getKey())
+      .execute();
+  }
+
+  @Test
+  public void fail_when_measure_value_is_null() {
+    ComponentDto project = db.components().insertPublicProject();
+    userSession.registerComponents(project);
+    MetricDto metric = db.measures().insertMetric(m -> m.setKey(BUGS_KEY).setValueType(INT.name()));
+    db.measures().insertLiveMeasure(project, metric, m -> m.setValue(null));
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Measure has not been found");
+
+    ws.newRequest()
+      .setParam("project", project.getKey())
+      .setParam("metric", metric.getKey())
+      .execute();
+  }
+
   @Test
   public void fail_when_metric_not_found() {
-    ComponentDto project = db.components().insertMainBranch();
-    userSession.addProjectPermission(UserRole.USER, project);
+    ComponentDto project = db.components().insertPublicProject();
+    userSession.registerComponents(project);
 
     expectedException.expect(IllegalStateException.class);
     expectedException.expectMessage("Metric 'bugs' hasn't been found");
@@ -289,7 +391,6 @@ public class MeasureActionTest {
       .containsExactlyInAnyOrder(
         tuple("project", true),
         tuple("branch", false),
-        tuple("pullRequest", false),
         tuple("metric", true));
   }
 
index 856b0c7dc8b3269548e80a2347267f04c35d25f9..ab318000c076ba8e01e47f4ea04ecd011dbd810d 100644 (file)
@@ -34,7 +34,7 @@ public class ProjectBadgesWsModuleTest {
   public void verify_count_of_added_components() {
     underTest.configure(container);
 
-    assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 4);
+    assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5);
   }
 
 }
index 1daf402058396a9664b74f92fb736aa0f170ffdf..52cedacbf863fa624221601d14e36139b35ea005 100644 (file)
@@ -19,8 +19,6 @@
  */
 package org.sonar.server.badge.ws;
 
-import java.io.IOException;
-import org.apache.commons.io.IOUtils;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -28,17 +26,16 @@ import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.measures.Metric.Level;
 import org.sonar.api.server.ws.WebService;
 import org.sonar.api.server.ws.WebService.Param;
-import org.sonar.api.web.UserRole;
 import org.sonar.db.DbTester;
-import org.sonar.db.component.BranchType;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.component.ComponentFinder;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsActionTester;
 
-import static java.lang.String.format;
-import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
@@ -46,6 +43,9 @@ import static org.sonar.api.measures.Metric.Level.ERROR;
 import static org.sonar.api.measures.Metric.Level.OK;
 import static org.sonar.api.measures.Metric.Level.WARN;
 import static org.sonar.api.measures.Metric.ValueType.LEVEL;
+import static org.sonar.api.web.UserRole.USER;
+import static org.sonar.db.component.BranchType.LONG;
+import static org.sonar.db.component.BranchType.SHORT;
 
 public class QualityGateActionTest {
 
@@ -59,7 +59,9 @@ public class QualityGateActionTest {
   private MapSettings mapSettings = new MapSettings().setProperty("sonar.sonarcloud.enabled", false);
 
   private WsActionTester ws = new WsActionTester(
-    new QualityGateAction(userSession, db.getDbClient(), new ComponentFinder(db.getDbClient(), null), new SvgGenerator(mapSettings.asConfig())));
+    new QualityGateAction(db.getDbClient(),
+      new ProjectBadgesSupport(userSession, db.getDbClient(), new ComponentFinder(db.getDbClient(), null)),
+      new SvgGenerator(mapSettings.asConfig())));
 
   @Test
   public void quality_gate_passed() {
@@ -104,45 +106,114 @@ public class QualityGateActionTest {
   }
 
   @Test
-  public void project_does_not_exist() {
+  public void quality_gate_on_long_living_branch() {
+    ComponentDto project = db.components().insertMainBranch(p -> p.setPrivate(false));
+    userSession.registerComponents(project);
+    MetricDto metric = createQualityGateMetric();
+    db.measures().insertLiveMeasure(project, metric, m -> m.setData(OK.name()));
+    ComponentDto longBranch = db.components().insertProjectBranch(project, b -> b.setBranchType(LONG));
+    db.measures().insertLiveMeasure(longBranch, metric, m -> m.setData(WARN.name()));
+
     String response = ws.newRequest()
-      .setParam("project", "unknown")
+      .setParam("project", longBranch.getKey())
+      .setParam("branch", longBranch.getBranch())
       .execute().getInput();
 
-    checkError(response, "Component not found");
+    checkResponse(response, WARN);
   }
 
   @Test
-  public void branch_does_not_exist() {
-    ComponentDto project = db.components().insertMainBranch();
-    ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.LONG));
-    userSession.addProjectPermission(UserRole.USER, project);
+  public void quality_gate_on_application() {
+    OrganizationDto organization = db.organizations().insert();
+    ComponentDto application = db.components().insertPublicApplication(organization);
+    userSession.registerComponents(application);
+    MetricDto metric = createQualityGateMetric();
+    db.measures().insertLiveMeasure(application, metric, m -> m.setData(WARN.name()));
 
     String response = ws.newRequest()
-      .setParam("project", branch.getKey())
-      .setParam("branch", "unknown")
+      .setParam("project", application.getKey())
       .execute().getInput();
 
-    checkError(response, format("Component not found", branch.getKey()));
+    checkResponse(response, WARN);
   }
 
   @Test
-  public void fail_on_invalid_quality_gate() {
-    ComponentDto project = db.components().insertMainBranch();
-    userSession.addProjectPermission(UserRole.USER, project);
-    MetricDto metric = createQualityGateMetric();
-    db.measures().insertLiveMeasure(project, metric, m -> m.setData("UNKNOWN"));
+  public void return_error_on_directory() {
+    ComponentDto project = db.components().insertPublicProject();
+    ComponentDto directory = db.components().insertComponent(ComponentTesting.newDirectory(project, "path"));
+    userSession.registerComponents(project);
 
-    expectedException.expect(IllegalArgumentException.class);
-    expectedException.expectMessage("No enum constant org.sonar.api.measures.Metric.Level.UNKNOWN");
+    String response = ws.newRequest()
+      .setParam("project", directory.getKey())
+      .execute().getInput();
 
-    ws.newRequest()
+    checkError(response, "Project is invalid");
+  }
+
+  @Test
+  public void return_error_on_short_living_branch() {
+    ComponentDto project = db.components().insertMainBranch(p -> p.setPrivate(false));
+    userSession.registerComponents(project);
+    ComponentDto shortBranch = db.components().insertProjectBranch(project, b -> b.setBranchType(SHORT));
+
+    String response = ws.newRequest()
+      .setParam("project", shortBranch.getKey())
+      .setParam("branch", shortBranch.getBranch())
+      .execute().getInput();
+
+    checkError(response, "Project is invalid");
+  }
+
+  @Test
+  public void return_error_on_private_project() {
+    ComponentDto project = db.components().insertPrivateProject();
+    UserDto user = db.users().insertUser();
+    userSession.logIn(user).addProjectPermission(USER, project);
+
+    String response = ws.newRequest()
       .setParam("project", project.getKey())
-      .execute();
+      .execute().getInput();
+
+    checkError(response, "Project is invalid");
+  }
+
+  @Test
+  public void return_error_on_provisioned_project() {
+    ComponentDto project = db.components().insertPublicProject();
+    userSession.registerComponents(project);
+
+    String response = ws.newRequest()
+      .setParam("project", project.getKey())
+      .execute().getInput();
+
+    checkError(response, "Quality gate has not been found");
+  }
+
+  @Test
+  public void return_error_on_not_existing_project() {
+    String response = ws.newRequest()
+      .setParam("project", "unknown")
+      .execute().getInput();
+
+    checkError(response, "Project has not been found");
+  }
+
+  @Test
+  public void return_error_on_not_existing_branch() {
+    ComponentDto project = db.components().insertMainBranch(p -> p.setPrivate(false));
+    userSession.registerComponents(project);
+    ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(LONG));
+
+    String response = ws.newRequest()
+      .setParam("project", branch.getKey())
+      .setParam("branch", "unknown")
+      .execute().getInput();
+
+    checkError(response, "Project has not been found");
   }
 
   @Test
-  public void measure_not_found() {
+  public void return_error_if_measure_not_found() {
     ComponentDto project = db.components().insertPublicProject();
     userSession.registerComponents(project);
 
@@ -150,11 +221,11 @@ public class QualityGateActionTest {
       .setParam("project", project.getKey())
       .execute().getInput();
 
-    checkError(response, format("Quality gate has not been found for project '%s' and branch 'null'", project.getKey()));
+    checkError(response, "Quality gate has not been found");
   }
 
   @Test
-  public void measure_value_is_null() {
+  public void return_error_if_measure_value_is_null() {
     ComponentDto project = db.components().insertPublicProject();
     userSession.registerComponents(project);
     MetricDto metric = createQualityGateMetric();
@@ -165,18 +236,22 @@ public class QualityGateActionTest {
       .setParam("metric", metric.getKey())
       .execute().getInput();
 
-    checkError(response, format("Quality gate has not been found for project '%s' and branch 'null'", project.getKey()));
+    checkError(response, "Quality gate has not been found");
   }
 
   @Test
-  public void unauthorized() {
-    ComponentDto project = db.components().insertPrivateProject();
+  public void fail_on_invalid_quality_gate() {
+    ComponentDto project = db.components().insertPublicProject();
+    userSession.registerComponents(project);
+    MetricDto metric = createQualityGateMetric();
+    db.measures().insertLiveMeasure(project, metric, m -> m.setData("UNKNOWN"));
 
-    String response = ws.newRequest()
-      .setParam("project", project.getKey())
-      .execute().getInput();
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("No enum constant org.sonar.api.measures.Metric.Level.UNKNOWN");
 
-    checkError(response, "Insufficient privileges");
+    ws.newRequest()
+      .setParam("project", project.getKey())
+      .execute();
   }
 
   @Test
@@ -192,8 +267,7 @@ public class QualityGateActionTest {
       .extracting(Param::key, Param::isRequired)
       .containsExactlyInAnyOrder(
         tuple("project", true),
-        tuple("branch", false),
-        tuple("pullRequest", false));
+        tuple("branch", false));
   }
 
   private MetricDto createQualityGateMetric() {
@@ -207,22 +281,15 @@ public class QualityGateActionTest {
   private void checkResponse(String response, Level status) {
     switch (status) {
       case OK:
-        assertThat(response).isEqualTo(readTemplate("quality_gate_passed.svg"));
+        assertThat(response).contains("<!-- SONARQUBE QUALITY GATE PASS -->");
         break;
       case WARN:
-        assertThat(response).isEqualTo(readTemplate("quality_gate_warn.svg"));
+        assertThat(response).contains("<!-- SONARQUBE QUALITY GATE WARN -->");
         break;
       case ERROR:
-        assertThat(response).isEqualTo(readTemplate("quality_gate_failed.svg"));
+        assertThat(response).contains("<!-- SONARQUBE QUALITY GATE FAIL -->");
         break;
     }
   }
 
-  private String readTemplate(String template) {
-    try {
-      return IOUtils.toString(getClass().getResource("templates/sonarqube/" + template), UTF_8);
-    } catch (IOException e) {
-      throw new IllegalStateException(String.format("Can't read svg template '%s'", template), e);
-    }
-  }
 }
index 8c232851c21344f9294c5c952c432378123ec472..b9ccb41c9bdd7fe66df071e7b18dbec5bfc16a11 100644 (file)
@@ -36,7 +36,10 @@ public class ApiDefinitionDownloader {
     OrchestratorBuilder builder = Orchestrator.builderEnv();
     builder.setZipFile(FileLocation.byWildcardMavenFilename(new File("../sonar-application/build/distributions"), "sonar-application-*.zip").getFile())
       .setOrchestratorProperty("orchestrator.workspaceDir", "build");
-    Orchestrator orchestrator = builder.build();
+    Orchestrator orchestrator = builder
+      // Enable organizations ws
+      .setServerProperty("sonar.sonarcloud.enabled", "true")
+      .build();
 
     orchestrator.start();
     try {
index bdbbbf90c62408a6c320365dba233b65ec06e2da..4a078808d03dda8363b736fc1934cc5e0ac3f2a3 100644 (file)
@@ -43,6 +43,7 @@ import org.sonarqube.ws.client.permissions.PermissionsService;
 import org.sonarqube.ws.client.plugins.PluginsService;
 import org.sonarqube.ws.client.profiles.ProfilesService;
 import org.sonarqube.ws.client.projectanalyses.ProjectAnalysesService;
+import org.sonarqube.ws.client.projectbadges.ProjectBadgesService;
 import org.sonarqube.ws.client.projectbranches.ProjectBranchesService;
 import org.sonarqube.ws.client.projectlinks.ProjectLinksService;
 import org.sonarqube.ws.client.projectpullrequests.ProjectPullRequestsService;
@@ -101,6 +102,7 @@ class DefaultWsClient implements WsClient {
   private final PluginsService pluginsService;
   private final ProfilesService profilesService;
   private final ProjectAnalysesService projectAnalysesService;
+  private final ProjectBadgesService projectBadgesService;
   private final ProjectBranchesService projectBranchesService;
   private final ProjectLinksService projectLinksService;
   private final ProjectPullRequestsService projectPullRequestsService;
@@ -152,6 +154,7 @@ class DefaultWsClient implements WsClient {
     this.pluginsService = new PluginsService(wsConnector);
     this.profilesService = new ProfilesService(wsConnector);
     this.projectAnalysesService = new ProjectAnalysesService(wsConnector);
+    this.projectBadgesService = new ProjectBadgesService(wsConnector);
     this.projectBranchesService = new ProjectBranchesService(wsConnector);
     this.projectLinksService = new ProjectLinksService(wsConnector);
     this.projectPullRequestsService = new ProjectPullRequestsService(wsConnector);
@@ -295,6 +298,11 @@ class DefaultWsClient implements WsClient {
     return projectAnalysesService;
   }
 
+  @Override
+  public ProjectBadgesService projectBadges() {
+    return projectBadgesService;
+  }
+
   @Override
   public ProjectBranchesService projectBranches() {
     return projectBranchesService;
index 79ca15098c2133a5bcc8b6811345bdea31f2cd9f..362ee5cdd1b63a48fe08944fd5a099066c3e6173 100644 (file)
@@ -20,9 +20,9 @@
 package org.sonarqube.ws.client;
 
 import javax.annotation.Generated;
-
 import org.sonarqube.ws.client.analysisreports.AnalysisReportsService;
 import org.sonarqube.ws.client.authentication.AuthenticationService;
+import org.sonarqube.ws.client.batch.BatchService;
 import org.sonarqube.ws.client.ce.CeService;
 import org.sonarqube.ws.client.components.ComponentsService;
 import org.sonarqube.ws.client.custommeasures.CustomMeasuresService;
@@ -43,11 +43,12 @@ import org.sonarqube.ws.client.permissions.PermissionsService;
 import org.sonarqube.ws.client.plugins.PluginsService;
 import org.sonarqube.ws.client.profiles.ProfilesService;
 import org.sonarqube.ws.client.projectanalyses.ProjectAnalysesService;
+import org.sonarqube.ws.client.projectbadges.ProjectBadgesService;
 import org.sonarqube.ws.client.projectbranches.ProjectBranchesService;
 import org.sonarqube.ws.client.projectlinks.ProjectLinksService;
 import org.sonarqube.ws.client.projectpullrequests.ProjectPullRequestsService;
-import org.sonarqube.ws.client.projecttags.ProjectTagsService;
 import org.sonarqube.ws.client.projects.ProjectsService;
+import org.sonarqube.ws.client.projecttags.ProjectTagsService;
 import org.sonarqube.ws.client.properties.PropertiesService;
 import org.sonarqube.ws.client.qualitygates.QualitygatesService;
 import org.sonarqube.ws.client.qualityprofiles.QualityprofilesService;
@@ -63,11 +64,10 @@ import org.sonarqube.ws.client.timemachine.TimemachineService;
 import org.sonarqube.ws.client.updatecenter.UpdatecenterService;
 import org.sonarqube.ws.client.usergroups.UserGroupsService;
 import org.sonarqube.ws.client.userproperties.UserPropertiesService;
-import org.sonarqube.ws.client.usertokens.UserTokensService;
 import org.sonarqube.ws.client.users.UsersService;
+import org.sonarqube.ws.client.usertokens.UserTokensService;
 import org.sonarqube.ws.client.webhooks.WebhooksService;
 import org.sonarqube.ws.client.webservices.WebservicesService;
-import org.sonarqube.ws.client.batch.BatchService;
 
 /**
  * Allows to request the web services of SonarQube server. Instance is provided by
@@ -136,6 +136,8 @@ public interface WsClient {
 
   ProjectAnalysesService projectAnalyses();
 
+  ProjectBadgesService projectBadges();
+
   ProjectBranchesService projectBranches();
 
   ProjectLinksService projectLinks();
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/MeasureRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/MeasureRequest.java
new file mode 100644 (file)
index 0000000..4dc8d38
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonarqube.ws.client.projectbadges;
+
+import javax.annotation.Generated;
+
+/**
+ * This is part of the internal API.
+ * This is a POST request.
+ * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/project_badges/measure">Further information about this action online (including a response example)</a>
+ * @since 7.1
+ */
+@Generated("sonar-ws-generator")
+public class MeasureRequest {
+
+  private String branch;
+  private String metric;
+  private String project;
+
+  /**
+   * Example value: "feature/my_branch"
+   */
+  public MeasureRequest setBranch(String branch) {
+    this.branch = branch;
+    return this;
+  }
+
+  public String getBranch() {
+    return branch;
+  }
+
+  /**
+   * This is a mandatory parameter.
+   * Possible values:
+   * <ul>
+   *   <li>"bugs"</li>
+   *   <li>"code_smells"</li>
+   *   <li>"coverage"</li>
+   *   <li>"duplicated_lines_density"</li>
+   *   <li>"ncloc"</li>
+   *   <li>"sqale_rating"</li>
+   *   <li>"alert_status"</li>
+   *   <li>"reliability_rating"</li>
+   *   <li>"security_rating"</li>
+   *   <li>"sqale_index"</li>
+   *   <li>"vulnerabilities"</li>
+   * </ul>
+   */
+  public MeasureRequest setMetric(String metric) {
+    this.metric = metric;
+    return this;
+  }
+
+  public String getMetric() {
+    return metric;
+  }
+
+  /**
+   * This is a mandatory parameter.
+   * Example value: "my_project"
+   */
+  public MeasureRequest setProject(String project) {
+    this.project = project;
+    return this;
+  }
+
+  public String getProject() {
+    return project;
+  }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/ProjectBadgesService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/ProjectBadgesService.java
new file mode 100644 (file)
index 0000000..a9e82db
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonarqube.ws.client.projectbadges;
+
+import javax.annotation.Generated;
+import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsConnector;
+
+/**
+ * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/project_badges">Further information about this web service online</a>
+ */
+@Generated("sonar-ws-generator")
+public class ProjectBadgesService extends BaseService {
+
+  public ProjectBadgesService(WsConnector wsConnector) {
+    super(wsConnector, "api/project_badges");
+  }
+
+  /**
+   *
+   * This is part of the internal API.
+   * This is a GET request.
+   * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/project_badges/measure">Further information about this action online (including a response example)</a>
+   * @since 7.1
+   */
+  public String measure(MeasureRequest request) {
+    return call(
+      new GetRequest(path("measure"))
+        .setParam("branch", request.getBranch())
+        .setParam("metric", request.getMetric())
+        .setParam("project", request.getProject())
+        .setMediaType(MediaTypes.JSON)
+      ).content();
+  }
+
+  /**
+   *
+   * This is part of the internal API.
+   * This is a GET request.
+   * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/project_badges/quality_gate">Further information about this action online (including a response example)</a>
+   * @since 7.1
+   */
+  public String qualityGate(QualityGateRequest request) {
+    return call(
+      new GetRequest(path("quality_gate"))
+        .setParam("branch", request.getBranch())
+        .setParam("project", request.getProject())
+        .setMediaType(MediaTypes.JSON)
+      ).content();
+  }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/QualityGateRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/QualityGateRequest.java
new file mode 100644 (file)
index 0000000..2028040
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonarqube.ws.client.projectbadges;
+
+import javax.annotation.Generated;
+
+/**
+ * This is part of the internal API.
+ * This is a POST request.
+ * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/project_badges/quality_gate">Further information about this action online (including a response example)</a>
+ * @since 7.1
+ */
+@Generated("sonar-ws-generator")
+public class QualityGateRequest {
+
+  private String branch;
+  private String project;
+
+  /**
+   * Example value: "feature/my_branch"
+   */
+  public QualityGateRequest setBranch(String branch) {
+    this.branch = branch;
+    return this;
+  }
+
+  public String getBranch() {
+    return branch;
+  }
+
+  /**
+   * This is a mandatory parameter.
+   * Example value: "my_project"
+   */
+  public QualityGateRequest setProject(String project) {
+    this.project = project;
+    return this;
+  }
+
+  public String getProject() {
+    return project;
+  }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/package-info.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/package-info.java
new file mode 100644 (file)
index 0000000..6587f21
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.
+ */
+@ParametersAreNonnullByDefault
+@Generated("sonar-ws-generator")
+package org.sonarqube.ws.client.projectbadges;
+
+import javax.annotation.Generated;
+import javax.annotation.ParametersAreNonnullByDefault;
+
index 05d243af6e3fccec3a916f0ac45b77ab83f06e81..0de9001680f6f01f73af38ab6086f59bf2994cc3 100644 (file)
@@ -28,21 +28,18 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonarqube.qa.util.Tester;
-import org.sonarqube.ws.Organizations.Organization;
 import org.sonarqube.ws.Users.CreateWsResponse.User;
-import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.projectbadges.MeasureRequest;
+import org.sonarqube.ws.client.projectbadges.QualityGateRequest;
 import org.sonarqube.ws.client.projects.UpdateVisibilityRequest;
 
 import static com.codeborne.selenide.Selenide.$;
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Java6Assertions.assertThat;
 import static util.ItUtils.projectDir;
 
 public class ProjectBadgesTest {
 
   private static final String PROJECT_KEY = "sample";
-  private static final String WS_MEASURE_BADGES_ON_QUALITY_GATE = "api/project_badges/measure?project=" + PROJECT_KEY + "&metric=alert_status";
-  private static final String WS_MEASURE_BADGES_ON_BUGS = "api/project_badges/measure?project=" + PROJECT_KEY + "&metric=bugs";
-  private static final String WS_QUALITY_GATE_BADGE = "api/project_badges/quality_gate?project=" + PROJECT_KEY;
 
   @ClassRule
   public static Orchestrator orchestrator = ProjectSuite.ORCHESTRATOR;
@@ -59,15 +56,15 @@ public class ProjectBadgesTest {
     ElementsCollection badgeButtons = badgesModal.$$(".badge-button").shouldHaveSize(2);
 
     // Check quality gate badge
-    shouldHaveUrl(badgesModal, WS_MEASURE_BADGES_ON_QUALITY_GATE);
+    shouldHaveUrl(badgesModal, "api/project_badges/measure?project=" + PROJECT_KEY + "&metric=alert_status");
 
     // Check bugs badge
     selectOption("Bugs");
-    shouldHaveUrl(badgesModal, WS_MEASURE_BADGES_ON_BUGS);
+    shouldHaveUrl(badgesModal, "api/project_badges/measure?project=" + PROJECT_KEY + "&metric=bugs");
 
     // Check marketing quality gate badge
     badgeButtons.get(1).click();
-    shouldHaveUrl(badgesModal, WS_QUALITY_GATE_BADGE);
+    shouldHaveUrl(badgesModal, "api/project_badges/quality_gate?project=" + PROJECT_KEY);
   }
 
   @Test
@@ -76,8 +73,7 @@ public class ProjectBadgesTest {
     orchestrator.executeBuild(
       SonarScanner
         .create(projectDir("shared/xoo-sample"))
-        .setProperties("sonar.login", user.getLogin(), "sonar.password", user.getLogin())
-    );
+        .setProperties("sonar.login", user.getLogin(), "sonar.password", user.getLogin()));
     tester.wsClient().projects().updateVisibility(new UpdateVisibilityRequest().setProject("sample").setVisibility("private"));
     tester.openBrowser().logIn().submitCredentials(user.getLogin()).openProjectDashboard(PROJECT_KEY);
     shouldNotHaveBadges();
@@ -86,9 +82,14 @@ public class ProjectBadgesTest {
   @Test
   public void project_badges_ws() {
     orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-sample")));
-    assertThat(tester.wsClient().wsConnector().call(new GetRequest(WS_MEASURE_BADGES_ON_QUALITY_GATE)).failIfNotSuccessful().contentType()).isEqualTo("image/svg+xml");
-    assertThat(tester.wsClient().wsConnector().call(new GetRequest(WS_MEASURE_BADGES_ON_BUGS)).failIfNotSuccessful().contentType()).isEqualTo("image/svg+xml");
-    assertThat(tester.wsClient().wsConnector().call(new GetRequest(WS_QUALITY_GATE_BADGE)).failIfNotSuccessful().contentType()).isEqualTo("image/svg+xml");
+    assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(PROJECT_KEY).setMetric("alert_status"))).contains("<!-- SONARQUBE MEASURE -->");
+    assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(PROJECT_KEY).setMetric("bugs"))).contains("<!-- SONARQUBE MEASURE -->");
+    assertThat(tester.wsClient().projectBadges().qualityGate(new QualityGateRequest().setProject(PROJECT_KEY))).contains("<!-- SONARQUBE QUALITY GATE PASS -->");
+
+    String directory = "sample:src/main/xoo/sample";
+    assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(directory).setMetric("alert_status"))).contains("Project is invalid");
+    assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(directory).setMetric("bugs"))).contains("Project is invalid");
+    assertThat(tester.wsClient().projectBadges().qualityGate(new QualityGateRequest().setProject(directory))).contains("Project is invalid");
   }
 
   private void shouldNotHaveBadges() {
index f8a026857e98522c98a1d9eae1aa36564955a816..99eee6e263a600fa72f6a26e0bf2be5c0c444b80 100644 (file)
@@ -31,6 +31,8 @@ import org.sonarqube.qa.util.Tester;
 import org.sonarqube.ws.Organizations.Organization;
 import org.sonarqube.ws.Users.CreateWsResponse.User;
 import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.projectbadges.MeasureRequest;
+import org.sonarqube.ws.client.projectbadges.QualityGateRequest;
 import org.sonarqube.ws.client.projects.UpdateVisibilityRequest;
 
 import static com.codeborne.selenide.Selenide.$;
@@ -40,9 +42,6 @@ import static util.ItUtils.projectDir;
 public class SonarCloudProjectBadgesTest {
 
   private static final String PROJECT_KEY = "sample";
-  private static final String WS_MEASURE_BADGES_ON_QUALITY_GATE = "api/project_badges/measure?project=" + PROJECT_KEY + "&metric=alert_status";
-  private static final String WS_MEASURE_BADGES_ON_BUGS = "api/project_badges/measure?project=" + PROJECT_KEY + "&metric=bugs";
-  private static final String WS_QUALITY_GATE_BADGE = "api/project_badges/quality_gate?project=" + PROJECT_KEY;
   private static final String SONAR_CLOUD_ORANGE_BADGE = "images/project_badges/sonarcloud-orange.svg";
 
   @ClassRule
@@ -60,15 +59,15 @@ public class SonarCloudProjectBadgesTest {
     ElementsCollection badgeButtons = badgesModal.$$(".badge-button").shouldHaveSize(3);
 
     // Check quality gate badge
-    shouldHaveUrl(badgesModal, WS_MEASURE_BADGES_ON_QUALITY_GATE);
+    shouldHaveUrl(badgesModal, "api/project_badges/measure?project=" + PROJECT_KEY + "&metric=alert_status");
 
     // Check bugs badge
     selectOption("Bugs");
-    shouldHaveUrl(badgesModal, WS_MEASURE_BADGES_ON_BUGS);
+    shouldHaveUrl(badgesModal, "api/project_badges/measure?project=" + PROJECT_KEY + "&metric=bugs");
 
     // Check marketing quality gate badge
     badgeButtons.get(1).click();
-    shouldHaveUrl(badgesModal, WS_QUALITY_GATE_BADGE);
+    shouldHaveUrl(badgesModal, "api/project_badges/quality_gate?project=" + PROJECT_KEY);
 
     // Check scanned on SonarCloud badge
     badgeButtons.get(2).click();
@@ -83,8 +82,7 @@ public class SonarCloudProjectBadgesTest {
     orchestrator.executeBuild(
       SonarScanner
         .create(projectDir("shared/xoo-sample"))
-        .setProperties("sonar.organization", org.getKey(), "sonar.login", user.getLogin(), "sonar.password", user.getLogin())
-    );
+        .setProperties("sonar.organization", org.getKey(), "sonar.login", user.getLogin(), "sonar.password", user.getLogin()));
     tester.wsClient().projects().updateVisibility(new UpdateVisibilityRequest().setProject("sample").setVisibility("private"));
     tester.openBrowser().logIn().submitCredentials(user.getLogin()).openProjectDashboard(PROJECT_KEY);
     shouldNotHaveBadges();
@@ -93,10 +91,16 @@ public class SonarCloudProjectBadgesTest {
   @Test
   public void project_badges_ws() {
     orchestrator.executeBuild(SonarScanner.create(projectDir("shared/xoo-sample")));
-    assertThat(tester.wsClient().wsConnector().call(new GetRequest(WS_MEASURE_BADGES_ON_QUALITY_GATE)).failIfNotSuccessful().contentType()).isEqualTo("image/svg+xml");
-    assertThat(tester.wsClient().wsConnector().call(new GetRequest(WS_MEASURE_BADGES_ON_BUGS)).failIfNotSuccessful().contentType()).isEqualTo("image/svg+xml");
-    assertThat(tester.wsClient().wsConnector().call(new GetRequest(WS_QUALITY_GATE_BADGE)).failIfNotSuccessful().contentType()).isEqualTo("image/svg+xml");
     assertThat(tester.wsClient().wsConnector().call(new GetRequest(SONAR_CLOUD_ORANGE_BADGE)).failIfNotSuccessful().contentType()).isEqualTo("image/svg+xml");
+    assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(PROJECT_KEY).setMetric("alert_status")))
+      .contains("<!-- SONARCLOUD MEASURE -->");
+    assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(PROJECT_KEY).setMetric("bugs"))).contains("<!-- SONARCLOUD MEASURE -->");
+    assertThat(tester.wsClient().projectBadges().qualityGate(new QualityGateRequest().setProject(PROJECT_KEY))).contains("<!-- SONARCLOUD QUALITY GATE PASS -->");
+
+    String directory = "sample:src/main/xoo/sample";
+    assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(directory).setMetric("alert_status"))).contains("Project is invalid");
+    assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(directory).setMetric("bugs"))).contains("Project is invalid");
+    assertThat(tester.wsClient().projectBadges().qualityGate(new QualityGateRequest().setProject(directory))).contains("Project is invalid");
   }
 
   private void shouldNotHaveBadges() {