diff --git a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/MeasureAction.java b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/MeasureAction.java index 083e858ed3f9..5a2f9406a6bb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/MeasureAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/MeasureAction.java @@ -34,11 +34,9 @@ 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.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.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 METRIC_NAME_BY_KEY = ImmutableMap.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 void define(WebService.NewController controller) { "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 void handle(Request request, Response response) throws Exception { 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 void handle(Request request, Response response) throws Exception { } } - 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 @@ private String generateBadge(MetricDto metric, String value, Color color) { private static PARAM getNonNullValue(LiveMeasureDto measure, Function 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 index 000000000000..a80bcb4f3e0d --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java @@ -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 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"); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsModule.java index 0a351bf21646..1fead5916771 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsModule.java @@ -29,6 +29,7 @@ protected void configureModule() { ProjectBadgesWs.class, QualityGateAction.class, MeasureAction.class, - SvgGenerator.class); + SvgGenerator.class, + ProjectBadgesSupport.class); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java index 066940e2c1f1..dad88fd643f7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java @@ -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.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 void define(WebService.NewController controller) { .setDescription("Generate badge for project's quality gate as an SVG.
" + "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 void handle(Request request, Response response) throws Exception { } } - 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"))); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java index b486dab9298e..5d7176f84c2f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java @@ -175,7 +175,7 @@ PARAMETER_TOTAL_WIDTH, valueOf(MARGIN + computeWidth(error) + MARGIN), 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); diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/error.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/error.svg index c9a7d35010d6..f088f6fc5a64 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/error.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/error.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/badge.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/badge.svg index b13050ef2307..68877b16b1a1 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/badge.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/badge.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_failed.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_failed.svg index a83f9c79d622..629d3b34baf8 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_failed.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_failed.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_passed.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_passed.svg index 9ddef661f7f3..f8267221aa64 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_passed.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_passed.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_warn.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_warn.svg index 803b767b3b99..386c518bc235 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_warn.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarcloud/quality_gate_warn.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/badge.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/badge.svg index 0e8df8281810..4d25c4088735 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/badge.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/badge.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_failed.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_failed.svg index 38a288fda437..e04aac0bc93d 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_failed.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_failed.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_passed.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_passed.svg index 957e85063dd4..23b835da71d4 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_passed.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_passed.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_warn.svg b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_warn.svg index 629a648a0792..a0c22703d15e 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_warn.svg +++ b/server/sonar-server/src/main/resources/org/sonar/server/badge/ws/templates/sonarqube/quality_gate_warn.svg @@ -1,4 +1,5 @@ + diff --git a/server/sonar-server/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java index 3691bbdfb877..652675893f84 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/badge/ws/MeasureActionTest.java @@ -31,11 +31,13 @@ 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.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 void quality_gate(Level status, String expectedValue, Color expectedColor } @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 void project_does_not_exist() { .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 void branch_does_not_exist() { .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 void measure_not_found() { } @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 void unauthorized() { 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 void test_definition() { .containsExactlyInAnyOrder( tuple("project", true), tuple("branch", false), - tuple("pullRequest", false), tuple("metric", true)); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/badge/ws/ProjectBadgesWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/badge/ws/ProjectBadgesWsModuleTest.java index 856b0c7dc8b3..ab318000c076 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/badge/ws/ProjectBadgesWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/badge/ws/ProjectBadgesWsModuleTest.java @@ -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); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/badge/ws/QualityGateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/badge/ws/QualityGateActionTest.java index 1daf40205839..52cedacbf863 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/badge/ws/QualityGateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/badge/ws/QualityGateActionTest.java @@ -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.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.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 void quality_gate_failed() { } @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 void measure_not_found() { .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 void measure_value_is_null() { .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 void test_definition() { .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 @@ private void checkError(String svg, String expectedError) { private void checkResponse(String response, Level status) { switch (status) { case OK: - assertThat(response).isEqualTo(readTemplate("quality_gate_passed.svg")); + assertThat(response).contains(""); break; case WARN: - assertThat(response).isEqualTo(readTemplate("quality_gate_warn.svg")); + assertThat(response).contains(""); break; case ERROR: - assertThat(response).isEqualTo(readTemplate("quality_gate_failed.svg")); + assertThat(response).contains(""); 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); - } - } } diff --git a/sonar-ws-generator/src/main/java/org/sonarqube/wsgenerator/ApiDefinitionDownloader.java b/sonar-ws-generator/src/main/java/org/sonarqube/wsgenerator/ApiDefinitionDownloader.java index 8c232851c213..b9ccb41c9bdd 100644 --- a/sonar-ws-generator/src/main/java/org/sonarqube/wsgenerator/ApiDefinitionDownloader.java +++ b/sonar-ws-generator/src/main/java/org/sonarqube/wsgenerator/ApiDefinitionDownloader.java @@ -36,7 +36,10 @@ public static String downloadApiDefinition() { 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 { diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java index bdbbbf90c624..4a078808d03d 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java @@ -43,6 +43,7 @@ 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 @@ public ProjectAnalysesService projectAnalyses() { return projectAnalysesService; } + @Override + public ProjectBadgesService projectBadges() { + return projectBadgesService; + } + @Override public ProjectBranchesService projectBranches() { return projectBranchesService; diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java index 79ca15098c21..362ee5cdd1b6 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java @@ -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.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.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 index 000000000000..4dc8d38071c8 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/MeasureRequest.java @@ -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 Further information about this action online (including a response example) + * @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: + *
    + *
  • "bugs"
  • + *
  • "code_smells"
  • + *
  • "coverage"
  • + *
  • "duplicated_lines_density"
  • + *
  • "ncloc"
  • + *
  • "sqale_rating"
  • + *
  • "alert_status"
  • + *
  • "reliability_rating"
  • + *
  • "security_rating"
  • + *
  • "sqale_index"
  • + *
  • "vulnerabilities"
  • + *
+ */ + 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 index 000000000000..a9e82db111a7 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/ProjectBadgesService.java @@ -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 Further information about this web service online + */ +@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 Further information about this action online (including a response example) + * @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 Further information about this action online (including a response example) + * @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 index 000000000000..202804039cd2 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/QualityGateRequest.java @@ -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 Further information about this action online (including a response example) + * @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 index 000000000000..6587f213bb81 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/projectbadges/package-info.java @@ -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; + diff --git a/tests/src/test/java/org/sonarqube/tests/project/ProjectBadgesTest.java b/tests/src/test/java/org/sonarqube/tests/project/ProjectBadgesTest.java index 05d243af6e3f..0de9001680f6 100644 --- a/tests/src/test/java/org/sonarqube/tests/project/ProjectBadgesTest.java +++ b/tests/src/test/java/org/sonarqube/tests/project/ProjectBadgesTest.java @@ -28,21 +28,18 @@ 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 void public_project_badges() { 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 void private_project_do_not_have_badges() { 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 void private_project_do_not_have_badges() { @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(""); + assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(PROJECT_KEY).setMetric("bugs"))).contains(""); + assertThat(tester.wsClient().projectBadges().qualityGate(new QualityGateRequest().setProject(PROJECT_KEY))).contains(""); + + 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() { diff --git a/tests/src/test/java/org/sonarqube/tests/project/SonarCloudProjectBadgesTest.java b/tests/src/test/java/org/sonarqube/tests/project/SonarCloudProjectBadgesTest.java index f8a026857e98..99eee6e263a6 100644 --- a/tests/src/test/java/org/sonarqube/tests/project/SonarCloudProjectBadgesTest.java +++ b/tests/src/test/java/org/sonarqube/tests/project/SonarCloudProjectBadgesTest.java @@ -31,6 +31,8 @@ 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 @@ 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 void public_project_badges() { 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 void private_project_do_not_have_badges() { 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 void private_project_do_not_have_badges() { @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(""); + assertThat(tester.wsClient().projectBadges().measure(new MeasureRequest().setProject(PROJECT_KEY).setMetric("bugs"))).contains(""); + assertThat(tester.wsClient().projectBadges().qualityGate(new QualityGateRequest().setProject(PROJECT_KEY))).contains(""); + + 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() {