public class ResourcesWs implements WebService {
- private static final String FALSE = "false";
- private static final String TRUE = "true";
-
@Override
public void define(Context context) {
NewController controller = context.createController("api/resources")
action.createParam("verbose")
.setDescription("Add some data to response")
- .setDefaultValue(FALSE)
- .setPossibleValues(TRUE, FALSE);
+ .setBooleanPossibleValues()
+ .setDefaultValue(String.valueOf(false));
action.createParam("limit")
.setDescription("Limit the number of results. Only used if one metric, and only one, is set")
action.createParam("includetrends")
.setDescription("Include period variations in response: add nodes <p*> for period variations")
- .setDefaultValue(FALSE)
- .setPossibleValues(TRUE, FALSE);
+ .setDefaultValue(String.valueOf(false))
+ .setBooleanPossibleValues();
action.createParam("includealerts")
.setDescription("Include alerts data: add nodes <alert> (ERROR, WARN, OK) and <alert_text>")
- .setDefaultValue(FALSE)
- .setPossibleValues(TRUE, FALSE);
+ .setBooleanPossibleValues()
+ .setDefaultValue(String.valueOf(false));
action.createParam("rules")
.setDescription("Filter on rules: setting it to true will return rules id and rule name for measure having such info " +
"(such as 'blocker_violations', 'critical_violations', ..., 'new_blocker_violations', ...). Possible values: true | false | list of rule ids")
- .setDefaultValue(FALSE)
- .setExampleValue(TRUE);
+ .setBooleanPossibleValues()
+ .setDefaultValue(String.valueOf(true));
RailsHandler.addFormatParam(action);
}
action.createParam("display_key")
.setDescription("Return the resource key instead of the resource id")
- .setDefaultValue(FALSE)
- .setPossibleValues(TRUE, FALSE);
+ .setBooleanPossibleValues()
+ .setDefaultValue(String.valueOf(false));
action.createParam("q")
.setDescription("Comma-separated list of qualifiers")
@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction("activity")
- .setInternal(true)
.setDescription(format("Search for past task executions. Requires the system administration permission, " +
"or project administration permission if %s is set.", PARAM_COMPONENT_UUID))
.setResponseExample(getClass().getResource("activity-example.json"))
@Override
protected void configureModule() {
add(
+ CeWs.class,
ActivityAction.class,
CancelAction.class,
CancelAllAction.class,
QueueAction.class,
- CeWs.class,
IsQueueEmptyWs.class,
LogsAction.class,
ComponentAction.class,
WebService.NewAction action = controller.createAction("component")
.setDescription("Get the pending tasks, in-progress tasks and the last executed task of a given component " +
"(usually a project). Requires the administration permission on the component.")
- .setInternal(true)
.setSince("5.2")
.setResponseExample(getClass().getResource("component-example.json"))
.setHandler(this);
package org.sonar.server.computation.ws;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
public static final String ACTION = "task";
public static final String PARAM_TASK_UUID = "id";
+ private static final Set<String> AUTHORIZED_PERMISSIONS = ImmutableSet.of(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.SYSTEM_ADMIN);
private final DbClient dbClient;
private final TaskFormatter wsTaskFormatter;
WebService.NewAction action = controller.createAction(ACTION)
.setDescription("Give Compute Engine task details such as type, status, duration and associated component.<br />" +
"Requires 'Administer System' or 'Execute Analysis' permission.")
- .setInternal(true)
.setResponseExample(getClass().getResource("task-example.json"))
.setSince("5.2")
.setHandler(this);
@Override
public void handle(Request wsRequest, Response wsResponse) throws Exception {
- if (!userSession.hasGlobalPermission(GlobalPermissions.SYSTEM_ADMIN)
- // WS can be used at the end of an analysis to implement a build breaker
- && !userSession.hasGlobalPermission(GlobalPermissions.SCAN_EXECUTION)) {
- userSession.checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
- }
+ userSession.checkAnyGlobalPermissions(AUTHORIZED_PERMISSIONS);
String taskUuid = wsRequest.mandatoryParam(PARAM_TASK_UUID);
DbSession dbSession = dbClient.openSession(false);
builder.setComponentId(dto.getComponentUuid());
buildComponent(builder, componentCache.get(dto.getComponentUuid()));
}
+ if (dto.getSnapshotId() != null) {
+ builder.setAnalysisId(String.valueOf(dto.getSnapshotId()));
+ }
if (dto.getSubmitterLogin() != null) {
builder.setSubmitterLogin(dto.getSubmitterLogin());
}
import org.sonar.server.qualitygate.ws.DeleteConditionAction;
import org.sonar.server.qualitygate.ws.DeselectAction;
import org.sonar.server.qualitygate.ws.DestroyAction;
+import org.sonar.server.qualitygate.ws.ProjectStatusAction;
import org.sonar.server.qualitygate.ws.QGatesWs;
import org.sonar.server.qualitygate.ws.SelectAction;
import org.sonar.server.qualitygate.ws.SetAsDefaultAction;
DeleteConditionAction.class,
UpdateConditionAction.class,
org.sonar.server.qualitygate.ws.AppAction.class,
+ ProjectStatusAction.class,
QGatesWs.class,
// web services
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.qualitygate.ws;
+
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.server.user.UserSession;
+import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse;
+import org.sonarqube.ws.client.qualitygate.ProjectStatusWsRequest;
+
+import static com.google.common.collect.Sets.newHashSet;
+import static org.sonar.server.ws.WsUtils.checkFound;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+
+public class ProjectStatusAction implements QGateWsAction {
+ private final DbClient dbClient;
+ private final UserSession userSession;
+
+ public ProjectStatusAction(DbClient dbClient, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction("project_status")
+ .setDescription("Quality gate status for a given Compute Engine task. <br />" +
+ "Returns a http code 404 if the analysis associated with the task is not found or does not exist.<br />" +
+ "Requires 'Administer System' or 'Execute Analysis' permission.")
+ .setResponseExample(getClass().getResource("project_status-example.json"))
+ .setSince("5.3")
+ .setHandler(this);
+
+ action.createParam("analysisId")
+ .setDescription("Analysis id")
+ .setRequired(true)
+ .setExampleValue("2963");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ ProjectStatusWsResponse projectStatusWsResponse = doHandle(toProjectStatusWsRequest(request));
+ writeProtobuf(projectStatusWsResponse, request, response);
+ }
+
+ private ProjectStatusWsResponse doHandle(ProjectStatusWsRequest request) {
+ checkScanOrAdminPermission();
+
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ String snapshotId = request.getAnalysisId();
+ SnapshotDto snapshotDto = getSnapshot(dbSession, snapshotId);
+ String measureData = getQualityGateDetailsMeasureData(dbSession, snapshotDto);
+
+ return ProjectStatusWsResponse.newBuilder()
+ .setProjectStatus(new QualityGateDetailsFormatter(measureData, snapshotDto).format())
+ .build();
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private SnapshotDto getSnapshot(DbSession dbSession, String snapshotIdFromRequest) {
+ Long snapshotId = null;
+ try {
+ snapshotId = Long.parseLong(snapshotIdFromRequest);
+ } catch (NumberFormatException e) {
+ // checks String is a long
+ }
+
+ SnapshotDto snapshotDto = null;
+ if (snapshotId != null) {
+ snapshotDto = dbClient.snapshotDao().selectById(dbSession, snapshotId);
+ }
+
+ return checkFound(snapshotDto, "Analysis with id '%s' is not found", snapshotIdFromRequest);
+ }
+
+ @CheckForNull
+ private String getQualityGateDetailsMeasureData(DbSession dbSession, SnapshotDto snapshotDto) {
+ List<MeasureDto> measures = dbClient.measureDao().selectBySnapshotIdAndMetricKeys(snapshotDto.getId(),
+ Collections.singleton(CoreMetrics.QUALITY_GATE_DETAILS_KEY), dbSession);
+
+ return measures.isEmpty()
+ ? null
+ : measures.get(0).getData();
+ }
+
+ private static ProjectStatusWsRequest toProjectStatusWsRequest(Request request) {
+ return new ProjectStatusWsRequest()
+ .setAnalysisId(request.mandatoryParam("analysisId"));
+ }
+
+ private void checkScanOrAdminPermission() {
+ userSession.checkAnyGlobalPermissions(newHashSet(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.SYSTEM_ADMIN));
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.qualitygate.ws;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.db.component.SnapshotDto;
+import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.sonar.api.utils.DateUtils.formatDateTime;
+
+public class QualityGateDetailsFormatter {
+ @CheckForNull
+ private final String measureData;
+ private final SnapshotDto snapshot;
+ private final ProjectStatusWsResponse.ProjectStatus.Builder projectStatusBuilder;
+
+ public QualityGateDetailsFormatter(@Nullable String measureData, SnapshotDto snapshot) {
+ this.measureData = measureData;
+ this.snapshot = snapshot;
+ this.projectStatusBuilder = ProjectStatusWsResponse.ProjectStatus.newBuilder();
+ }
+
+ public ProjectStatusWsResponse.ProjectStatus format() {
+ if (isNullOrEmpty(measureData)) {
+ return newResponseWithoutQualityGateDetails();
+ }
+
+ JsonParser parser = new JsonParser();
+ JsonObject json = parser.parse(measureData).getAsJsonObject();
+
+ ProjectStatusWsResponse.Status qualityGateStatus = measureLevelToQualityGateStatus(json.get("level").getAsString());
+ projectStatusBuilder.setStatus(qualityGateStatus);
+
+ formatConditions(json.getAsJsonArray("conditions"));
+ formatPeriods();
+
+ return projectStatusBuilder.build();
+ }
+
+ private void formatPeriods() {
+ ProjectStatusWsResponse.Period.Builder periodBuilder = ProjectStatusWsResponse.Period.newBuilder();
+ for (int i = 1; i <= 5; i++) {
+ periodBuilder.clear();
+ boolean doesPeriodExist = false;
+
+ if (!isNullOrEmpty(snapshot.getPeriodMode(i))) {
+ doesPeriodExist = true;
+ periodBuilder.setIndex(i);
+ periodBuilder.setMode(snapshot.getPeriodMode(i));
+ if (snapshot.getPeriodDate(i) != null) {
+ periodBuilder.setDate(formatDateTime(snapshot.getPeriodDate(i)));
+ }
+ if (!isNullOrEmpty(snapshot.getPeriodModeParameter(i))) {
+ periodBuilder.setParameter(snapshot.getPeriodModeParameter(i));
+ }
+ }
+
+ if (doesPeriodExist) {
+ projectStatusBuilder.addPeriods(periodBuilder);
+ }
+ }
+ }
+
+ private void formatConditions(@Nullable JsonArray jsonConditions) {
+ if (jsonConditions == null) {
+ return;
+ }
+
+ for (JsonElement jsonCondition : jsonConditions) {
+ formatCondition(jsonCondition.getAsJsonObject());
+ }
+ }
+
+ private void formatCondition(JsonObject jsonCondition) {
+ ProjectStatusWsResponse.Condition.Builder conditionBuilder = ProjectStatusWsResponse.Condition.newBuilder();
+
+ JsonElement measureLevel = jsonCondition.get("level");
+ if (measureLevel != null && !isNullOrEmpty(measureLevel.getAsString())) {
+ conditionBuilder.setStatus(measureLevelToQualityGateStatus(measureLevel.getAsString()));
+ }
+
+ JsonElement metric = jsonCondition.get("metric");
+ if (metric != null && !isNullOrEmpty(metric.getAsString())) {
+ conditionBuilder.setMetricKey(metric.getAsString());
+ }
+
+ JsonElement op = jsonCondition.get("op");
+ if (op != null && !isNullOrEmpty(op.getAsString())) {
+ String stringOp = op.getAsString();
+ ProjectStatusWsResponse.Comparator comparator = measureOpToQualityGateComparator(stringOp);
+ conditionBuilder.setComparator(comparator);
+ }
+
+ JsonElement periodIndex = jsonCondition.get("period");
+ if (periodIndex != null && !isNullOrEmpty(periodIndex.getAsString())) {
+ conditionBuilder.setPeriodIndex(periodIndex.getAsInt());
+ }
+
+ JsonElement warning = jsonCondition.get("warning");
+ if (warning != null && !isNullOrEmpty(warning.getAsString())) {
+ conditionBuilder.setWarningThreshold(warning.getAsString());
+ }
+
+ JsonElement error = jsonCondition.get("error");
+ if (error != null && !isNullOrEmpty(error.getAsString())) {
+ conditionBuilder.setErrorThreshold(error.getAsString());
+ }
+
+ JsonElement actual = jsonCondition.get("actual");
+ if (actual != null && !isNullOrEmpty(actual.getAsString())) {
+ conditionBuilder.setActualValue(actual.getAsString());
+ }
+
+ projectStatusBuilder.addConditions(conditionBuilder);
+ }
+
+ private static ProjectStatusWsResponse.Status measureLevelToQualityGateStatus(String measureLevel) {
+ for (ProjectStatusWsResponse.Status status : ProjectStatusWsResponse.Status.values()) {
+ if (status.name().equals(measureLevel)) {
+ return status;
+ }
+ }
+
+ throw new IllegalStateException(String.format("Unknown quality gate status '%s'", measureLevel));
+ }
+
+ private static ProjectStatusWsResponse.Comparator measureOpToQualityGateComparator(String measureOp) {
+ for (ProjectStatusWsResponse.Comparator comparator : ProjectStatusWsResponse.Comparator.values()) {
+ if (comparator.name().equals(measureOp)) {
+ return comparator;
+ }
+ }
+
+ throw new IllegalStateException(String.format("Unknown quality gate comparator '%s'", measureOp));
+ }
+
+ private static ProjectStatusWsResponse.ProjectStatus newResponseWithoutQualityGateDetails() {
+ return ProjectStatusWsResponse.ProjectStatus.newBuilder().setStatus(ProjectStatusWsResponse.Status.NONE).build();
+ }
+}
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Sets;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
return this;
}
+ @Override
+ public UserSession checkAnyGlobalPermissions(Collection<String> globalPermissionsToTest) {
+ List<String> userGlobalPermissions = globalPermissions();
+ for (String userGlobalPermission : userGlobalPermissions) {
+ if (globalPermissionsToTest.contains(userGlobalPermission)) {
+ return this;
+ }
+ }
+
+ throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
+ }
+
@Override
public boolean hasGlobalPermission(String globalPermission) {
return globalPermissions().contains(globalPermission);
package org.sonar.server.user;
import com.google.common.base.Objects;
+import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Set;
return get().checkGlobalPermission(globalPermission, errorMessage);
}
+ @Override
+ public UserSession checkAnyGlobalPermissions(Collection<String> globalPermissions) {
+ return get().checkAnyGlobalPermissions(globalPermissions);
+ }
+
@Override
public boolean hasGlobalPermission(String globalPermission) {
return get().hasGlobalPermission(globalPermission);
*/
package org.sonar.server.user;
+import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Set;
*/
UserSession checkGlobalPermission(String globalPermission, @Nullable String errorMessage);
+ /**
+ * Ensures that user implies any of the specified global permissions, otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException} with
+ * the specified error message.
+ */
+ UserSession checkAnyGlobalPermissions(Collection<String> globalPermissions);
+
/**
* Does the user have the given permission ?
*/
"componentKey": "project_1",
"componentName": "Project One",
"componentQualifier": "TRK",
+ "analysisId": "123456",
"status": "SUCCESS",
"submittedAt": "2015-08-13T23:34:59+0200",
"submitterLogin": "john",
"componentKey": "com.github.kevinsawicki:http-request-parent",
"componentName": "HttpRequest",
"componentQualifier": "TRK",
+ "analysisId": "123456",
"status": "SUCCESS",
"submittedAt": "2015-09-21T19:25:49+0200",
"startedAt": "2015-09-21T19:25:57+0200",
"componentKey": "project_1",
"componentName": "Project One",
"componentQualifier": "TRK",
+ "analysisId": "123456",
"status": "SUCCESS",
"submittedAt": "2015-10-02T11:32:15+0200",
"startedAt": "2015-10-02T11:32:16+0200",
--- /dev/null
+{
+ "projectStatus": {
+ "status": "ERROR",
+ "conditions": [
+ {
+ "status": "ERROR",
+ "metricKey": "new_coverage",
+ "comparator": "LT",
+ "periodIndex": 1,
+ "errorThreshold": "85",
+ "actualValue": "82.50562381034781"
+ },
+ {
+ "status": "ERROR",
+ "metricKey": "new_blocker_violations",
+ "comparator": "GT",
+ "periodIndex": 1,
+ "errorThreshold": "0",
+ "actualValue": "14"
+ },
+ {
+ "status": "ERROR",
+ "metricKey": "new_critical_violations",
+ "comparator": "GT",
+ "periodIndex": 1,
+ "errorThreshold": "0",
+ "actualValue": "1"
+ },
+ {
+ "status": "OK",
+ "metricKey": "new_sqale_debt_ratio",
+ "comparator": "GT",
+ "periodIndex": 2,
+ "errorThreshold": "5",
+ "actualValue": "0.6562109862671661"
+ },
+ {
+ "status": "OK",
+ "metricKey": "reopened_issues",
+ "comparator": "GT",
+ "periodIndex": 3,
+ "warningThreshold": "0",
+ "actualValue": "0"
+ },
+ {
+ "status": "WARN",
+ "metricKey": "open_issues",
+ "comparator": "GT",
+ "periodIndex": 3,
+ "warningThreshold": "0",
+ "actualValue": "17"
+ },
+ {
+ "status": "OK",
+ "metricKey": "skipped_tests",
+ "comparator": "GT",
+ "periodIndex": 5,
+ "warningThreshold": "0",
+ "actualValue": "0"
+ }
+ ],
+ "periods": [
+ {
+ "index": 1,
+ "mode": "last_period",
+ "date": "2000-04-27T00:45:23+0200"
+ },
+ {
+ "index": 2,
+ "mode": "last_version",
+ "date": "2000-04-27T00:45:23+0200",
+ "parameter": "2015-12-07"
+ },
+ {
+ "index": 3,
+ "mode": "last_analysis"
+ },
+ {
+ "index": 5,
+ "mode": "last_30_days",
+ "parameter": "2015-11-07"
+ }
+ ]
+ }
+}
assertThat(activityResponse.getTasks(0).getId()).isEqualTo("T2");
assertThat(activityResponse.getTasks(0).getStatus()).isEqualTo(WsCe.TaskStatus.FAILED);
assertThat(activityResponse.getTasks(0).getComponentId()).isEqualTo("PROJECT_2");
+ assertThat(activityResponse.getTasks(0).getAnalysisId()).isEqualTo("123456");
assertThat(activityResponse.getTasks(0).getExecutionTimeMs()).isEqualTo(500L);
assertThat(activityResponse.getTasks(0).getLogs()).isFalse();
assertThat(activityResponse.getTasks(1).getId()).isEqualTo("T1");
CeActivityDto activityDto = new CeActivityDto(queueDto);
activityDto.setStatus(status);
activityDto.setExecutionTimeMs(500L);
+ activityDto.setSnapshotId(123_456L);
dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
dbTester.commit();
return activityDto;
.setMediaType(MediaTypes.PROTOBUF)
.execute();
- WsCe.ProjectResponse response = Protobuf.read(wsResponse.getInputStream(), WsCe.ProjectResponse.PARSER);
+ WsCe.ProjectResponse response = Protobuf.read(wsResponse.getInputStream(), WsCe.ProjectResponse.parser());
assertThat(response.getQueueCount()).isEqualTo(0);
assertThat(response.hasCurrent()).isFalse();
}
.setMediaType(MediaTypes.PROTOBUF)
.execute();
- WsCe.ProjectResponse response = Protobuf.read(wsResponse.getInputStream(), WsCe.ProjectResponse.PARSER);
+ WsCe.ProjectResponse response = Protobuf.read(wsResponse.getInputStream(), WsCe.ProjectResponse.parser());
assertThat(response.getQueueCount()).isEqualTo(2);
assertThat(response.getQueue(0).getId()).isEqualTo("T4");
assertThat(response.getQueue(1).getId()).isEqualTo("T5");
.setMediaType(MediaTypes.PROTOBUF)
.execute();
- WsCe.ProjectResponse response = Protobuf.read(wsResponse.getInputStream(), WsCe.ProjectResponse.PARSER);
+ WsCe.ProjectResponse response = Protobuf.read(wsResponse.getInputStream(), WsCe.ProjectResponse.parser());
assertThat(response.getQueueCount()).isEqualTo(0);
// T3 is the latest task executed on PROJECT_1 ignoring Canceled ones
assertThat(response.hasCurrent()).isTrue();
CeActivityDto activityDto = new CeActivityDto(queueDto);
activityDto.setStatus(status);
activityDto.setExecutionTimeMs(500L);
+ activityDto.setSnapshotId(123_456L);
dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
dbTester.getSession().commit();
return activityDto;
CeActivityDto activityDto = new CeActivityDto(queueDto);
activityDto.setStatus(CeActivityDto.Status.FAILED);
activityDto.setExecutionTimeMs(500L);
+ activityDto.setSnapshotId(123_456L);
dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
dbTester.commit();
.execute();
WsCe.TaskResponse taskResponse = Protobuf.read(wsResponse.getInputStream(), WsCe.TaskResponse.PARSER);
- assertThat(taskResponse.getTask().getId()).isEqualTo("TASK_1");
- assertThat(taskResponse.getTask().getStatus()).isEqualTo(WsCe.TaskStatus.FAILED);
- assertThat(taskResponse.getTask().getComponentId()).isEqualTo(project.uuid());
- assertThat(taskResponse.getTask().getComponentKey()).isEqualTo(project.key());
- assertThat(taskResponse.getTask().getComponentName()).isEqualTo(project.name());
- assertThat(taskResponse.getTask().getExecutionTimeMs()).isEqualTo(500L);
- assertThat(taskResponse.getTask().getLogs()).isFalse();
+ WsCe.Task task = taskResponse.getTask();
+ assertThat(task.getId()).isEqualTo("TASK_1");
+ assertThat(task.getStatus()).isEqualTo(WsCe.TaskStatus.FAILED);
+ assertThat(task.getComponentId()).isEqualTo(project.uuid());
+ assertThat(task.getComponentKey()).isEqualTo(project.key());
+ assertThat(task.getComponentName()).isEqualTo(project.name());
+ assertThat(task.getAnalysisId()).isEqualTo("123456");
+ assertThat(task.getExecutionTimeMs()).isEqualTo(500L);
+ assertThat(task.getLogs()).isFalse();
}
@Test
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
import org.sonar.db.DbTester;
import org.sonar.db.ce.CeActivityDto;
import org.sonar.db.ce.CeQueueDto;
assertThat(wsTask.getLogs()).isFalse();
assertThat(wsTask.getSubmittedAt()).isEqualTo(DateUtils.formatDateTime(new Date(1_450_000_000_000L)));
assertThat(wsTask.getExecutionTimeMs()).isEqualTo(500L);
+ assertThat(wsTask.getAnalysisId()).isEqualTo("123456");
assertThat(wsTask.getLogs()).isFalse();
}
CeActivityDto activityDto = new CeActivityDto(queueDto);
activityDto.setStatus(status);
activityDto.setExecutionTimeMs(500L);
+ activityDto.setSnapshotId(123_456L);
return activityDto;
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.qualitygate.ws;
+
+import com.google.common.base.Throwables;
+import java.io.IOException;
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+import org.sonarqube.ws.MediaTypes;
+import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse;
+import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse.Status;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.db.component.SnapshotTesting.newSnapshotForProject;
+import static org.sonar.db.measure.MeasureTesting.newMeasureDto;
+import static org.sonar.db.metric.MetricTesting.newMetricDto;
+import static org.sonar.test.JsonAssert.assertJson;
+
+@Category(DbTests.class)
+public class ProjectStatusActionTest {
+ private static final String ANALYSIS_ID = "task-uuid";
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+
+ WsActionTester ws;
+ DbClient dbClient;
+ DbSession dbSession;
+
+ @Before
+ public void setUp() {
+ dbClient = db.getDbClient();
+ dbSession = db.getSession();
+
+ ws = new WsActionTester(new ProjectStatusAction(dbClient, userSession));
+ userSession.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+ }
+
+ @Test
+ public void json_example() throws IOException {
+ ComponentDto project = newProjectDto("project-uuid");
+ dbClient.componentDao().insert(dbSession, project);
+ SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newSnapshotForProject(project)
+ .setPeriodMode(1, "last_period")
+ .setPeriodDate(1, 956789123456L)
+ .setPeriodMode(2, "last_version")
+ .setPeriodParam(2, "2015-12-07")
+ .setPeriodDate(2, 956789123987L)
+ .setPeriodMode(3, "last_analysis")
+ .setPeriodMode(5, "last_30_days")
+ .setPeriodParam(5, "2015-11-07"));
+ MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDto()
+ .setEnabled(true)
+ .setKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY));
+ dbClient.measureDao().insert(dbSession,
+ newMeasureDto(metric, snapshot.getId())
+ .setData(IOUtils.toString(getClass().getResource("ProjectStatusActionTest/measure_data.json"))));
+ dbSession.commit();
+
+ String response = ws.newRequest()
+ .setParam("analysisId", snapshot.getId().toString())
+ .execute().getInput();
+
+ assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json"));
+ }
+
+ @Test
+ public void fail_if_no_snapshot_id_found() {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Analysis with id 'task-uuid' is not found");
+
+ newRequest(ANALYSIS_ID);
+ }
+
+ @Test
+ public void return_undefined_status_if_measure_is_not_found() {
+ ComponentDto project = newProjectDto("project-uuid");
+ dbClient.componentDao().insert(dbSession, project);
+ SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newSnapshotForProject(project));
+ dbSession.commit();
+
+ ProjectStatusWsResponse result = newRequest(snapshot.getId().toString());
+
+ assertThat(result.getProjectStatus().getStatus()).isEqualTo(Status.NONE);
+ assertThat(result.getProjectStatus().getConditionsCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void return_undefined_status_if_measure_data_is_not_well_formatted() {
+ userSession.setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+ ComponentDto project = newProjectDto("project-uuid");
+ dbClient.componentDao().insert(dbSession, project);
+ SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newSnapshotForProject(project));
+ MetricDto metric = dbClient.metricDao().insert(dbSession, newMetricDto()
+ .setEnabled(true)
+ .setKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY));
+ MeasureDto measure = newMeasureDto(metric, snapshot.getId()).setData("");
+ dbClient.measureDao().insert(dbSession, measure);
+ dbSession.commit();
+
+ ProjectStatusWsResponse result = newRequest(String.valueOf(snapshot.getId()));
+
+ assertThat(result.getProjectStatus().getStatus()).isEqualTo(Status.NONE);
+ assertThat(result.getProjectStatus().getConditionsCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void fail_if_insufficient_privileges() {
+ userSession.setGlobalPermissions(GlobalPermissions.PREVIEW_EXECUTION);
+ expectedException.expect(ForbiddenException.class);
+
+ newRequest(ANALYSIS_ID);
+ }
+
+ private ProjectStatusWsResponse newRequest(String taskId) {
+ try {
+ return ProjectStatusWsResponse.parseFrom(
+ ws.newRequest()
+ .setParam("analysisId", taskId)
+ .setMediaType(MediaTypes.PROTOBUF)
+ .execute().getInputStream());
+ } catch (IOException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.qualitygate.ws;
+
+import java.io.IOException;
+import java.util.List;
+import org.apache.commons.io.IOUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.component.SnapshotDto;
+import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse;
+import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse.ProjectStatus;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class QualityGateDetailsFormatterTest {
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ QualityGateDetailsFormatter underTest;
+
+ @Test
+ public void map_level_conditions_and_periods() throws IOException {
+ String measureData = IOUtils.toString(getClass().getResource("QualityGateDetailsFormatterTest/quality_gate_details.json"));
+ SnapshotDto snapshot = new SnapshotDto()
+ .setPeriodMode(1, "last_period")
+ .setPeriodDate(1, 1449490731764L)
+ .setPeriodMode(2, "last_version")
+ .setPeriodParam(2, "2015-12-07")
+ .setPeriodDate(2, 1449404331764L)
+ .setPeriodMode(3, "last_analysis")
+ .setPeriodMode(5, "last_30_days")
+ .setPeriodParam(5, "2015-11-07");
+ underTest = new QualityGateDetailsFormatter(measureData, snapshot);
+
+ ProjectStatus result = underTest.format();
+
+ assertThat(result.getStatus()).isEqualTo(ProjectStatusWsResponse.Status.ERROR);
+ // check conditions
+ assertThat(result.getConditionsCount()).isEqualTo(5);
+ List<ProjectStatusWsResponse.Condition> conditions = result.getConditionsList();
+ assertThat(conditions).extracting("status").containsExactly(
+ ProjectStatusWsResponse.Status.ERROR,
+ ProjectStatusWsResponse.Status.ERROR,
+ ProjectStatusWsResponse.Status.OK,
+ ProjectStatusWsResponse.Status.OK,
+ ProjectStatusWsResponse.Status.WARN);
+ assertThat(conditions).extracting("metricKey").containsExactly("new_coverage", "new_blocker_violations", "new_critical_violations", "new_sqale_debt_ratio",
+ "new_sqale_debt_ratio");
+ assertThat(conditions).extracting("comparator").containsExactly(
+ ProjectStatusWsResponse.Comparator.LT,
+ ProjectStatusWsResponse.Comparator.GT,
+ ProjectStatusWsResponse.Comparator.NE,
+ ProjectStatusWsResponse.Comparator.EQ,
+ ProjectStatusWsResponse.Comparator.LT);
+ assertThat(conditions).extracting("periodIndex").containsExactly(1, 2, 3, 4, 5);
+ assertThat(conditions).extracting("warningThreshold").containsOnly("80", "");
+ assertThat(conditions).extracting("errorThreshold").containsOnly("85", "0", "5");
+ assertThat(conditions).extracting("actualValue").containsExactly("82.2985024398452", "1", "0", "0.5670339761248853", "0.5670339761248853");
+
+ // check periods
+ assertThat(result.getPeriodsCount()).isEqualTo(4);
+ List<ProjectStatusWsResponse.Period> periods = result.getPeriodsList();
+ assertThat(periods).extracting("index").containsExactly(1, 2, 3, 5);
+ assertThat(periods).extracting("mode").containsExactly("last_period", "last_version", "last_analysis", "last_30_days");
+ assertThat(periods).extracting("parameter").containsExactly("", "2015-12-07", "", "2015-11-07");
+ System.out.println(System.currentTimeMillis());
+ assertThat(periods.get(0).getDate()).startsWith("2015-12-07T");
+ assertThat(periods.get(1).getDate()).startsWith("2015-12-06T");
+ }
+
+ @Test
+ public void undefined_quality_gate_when_ill_formatted_measure_data() {
+ underTest = new QualityGateDetailsFormatter("", new SnapshotDto());
+
+ ProjectStatus result = underTest.format();
+
+ assertThat(result.getStatus()).isEqualTo(ProjectStatusWsResponse.Status.NONE);
+ assertThat(result.getPeriodsCount()).isEqualTo(0);
+ assertThat(result.getConditionsCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void fail_when_measure_level_is_unknown() {
+ String measureData = "{\n" +
+ " \"level\": \"UNKNOWN\",\n" +
+ " \"conditions\": [\n" +
+ " {\n" +
+ " \"metric\": \"new_coverage\",\n" +
+ " \"op\": \"LT\",\n" +
+ " \"period\": 1,\n" +
+ " \"warning\": \"80\",\n" +
+ " \"error\": \"85\",\n" +
+ " \"actual\": \"82.2985024398452\",\n" +
+ " \"level\": \"ERROR\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ underTest = new QualityGateDetailsFormatter(measureData, new SnapshotDto());
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Unknown quality gate status 'UNKNOWN'");
+
+ underTest.format();
+ }
+
+ @Test
+ public void fail_when_measure_op_is_unknown() {
+ String measureData = "{\n" +
+ " \"level\": \"ERROR\",\n" +
+ " \"conditions\": [\n" +
+ " {\n" +
+ " \"metric\": \"new_coverage\",\n" +
+ " \"op\": \"UNKNOWN\",\n" +
+ " \"period\": 1,\n" +
+ " \"warning\": \"80\",\n" +
+ " \"error\": \"85\",\n" +
+ " \"actual\": \"82.2985024398452\",\n" +
+ " \"level\": \"ERROR\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ underTest = new QualityGateDetailsFormatter(measureData, new SnapshotDto());
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Unknown quality gate comparator 'UNKNOWN'");
+
+ underTest.format();
+ }
+}
package org.sonar.server.tester;
import com.google.common.base.Preconditions;
+import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Set;
return currentUserSession.checkGlobalPermission(globalPermission, errorMessage);
}
+ @Override
+ public UserSession checkAnyGlobalPermissions(Collection<String> globalPermissions) {
+ return currentUserSession.checkAnyGlobalPermissions(globalPermissions);
+ }
+
@Override
public boolean hasGlobalPermission(String globalPermission) {
return currentUserSession.hasGlobalPermission(globalPermission);
--- /dev/null
+{
+ "level": "ERROR",
+ "conditions": [
+ {
+ "metric": "new_coverage",
+ "op": "LT",
+ "period": 1,
+ "error": "85",
+ "actual": "82.50562381034781",
+ "level": "ERROR"
+ },
+ {
+ "metric": "new_blocker_violations",
+ "op": "GT",
+ "period": 1,
+ "warning": "",
+ "error": "0",
+ "actual": "14",
+ "level": "ERROR"
+ },
+ {
+ "metric": "new_critical_violations",
+ "op": "GT",
+ "period": 1,
+ "warning": "",
+ "error": "0",
+ "actual": "1",
+ "level": "ERROR"
+ },
+ {
+ "metric": "new_sqale_debt_ratio",
+ "op": "GT",
+ "period": 2,
+ "warning": "",
+ "error": "5",
+ "actual": "0.6562109862671661",
+ "level": "OK"
+ },
+ {
+ "metric": "reopened_issues",
+ "op": "GT",
+ "period": 3,
+ "warning": "0",
+ "actual": "0",
+ "level": "OK"
+ },
+ {
+ "metric": "open_issues",
+ "op": "GT",
+ "period": 3,
+ "warning": "0",
+ "error": "",
+ "actual": "17",
+ "level": "WARN"
+ },
+ {
+ "metric": "skipped_tests",
+ "op": "GT",
+ "period": 5,
+ "warning": "0",
+ "error": "",
+ "actual": "0",
+ "level": "OK"
+ }
+ ]
+}
--- /dev/null
+{
+ "level": "ERROR",
+ "conditions": [
+ {
+ "metric": "new_coverage",
+ "op": "LT",
+ "period": 1,
+ "warning": "80",
+ "error": "85",
+ "actual": "82.2985024398452",
+ "level": "ERROR"
+ },
+ {
+ "metric": "new_blocker_violations",
+ "op": "GT",
+ "period": 2,
+ "warning": "",
+ "error": "0",
+ "actual": "1",
+ "level": "ERROR"
+ },
+ {
+ "metric": "new_critical_violations",
+ "op": "NE",
+ "period": 3,
+ "warning": "",
+ "error": "0",
+ "actual": "0",
+ "level": "OK"
+ },
+ {
+ "metric": "new_sqale_debt_ratio",
+ "op": "EQ",
+ "period": 4,
+ "warning": "",
+ "error": "5",
+ "actual": "0.5670339761248853",
+ "level": "OK"
+ },
+ {
+ "metric": "new_sqale_debt_ratio",
+ "op": "LT",
+ "period": 5,
+ "warning": "",
+ "error": "5",
+ "actual": "0.5670339761248853",
+ "level": "WARN"
+ }
+ ]
+}
class AddCeActivitySnapshotId < ActiveRecord::Migration
def self.up
- add_column 'ce_activity', :snapshot_id, :integer, :null => true
+ add_column 'ce_activity', :snapshot_id, :big_integer, :null => true
end
end
return uuid;
}
- public void setUuid(String s) {
+ public CeActivityDto setUuid(String s) {
checkArgument(s.length() <= 40, "Value is too long for column CE_ACTIVITY.UUID: %s", s);
this.uuid = s;
+ return this;
}
public String getTaskType() {
return taskType;
}
- public void setTaskType(String s) {
+ public CeActivityDto setTaskType(String s) {
this.taskType = s;
+ return this;
}
@CheckForNull
return componentUuid;
}
- public void setComponentUuid(@Nullable String s) {
+ public CeActivityDto setComponentUuid(@Nullable String s) {
checkArgument(s == null || s.length() <= 40, "Value is too long for column CE_ACTIVITY.COMPONENT_UUID: %s", s);
this.componentUuid = s;
+ return this;
}
public Status getStatus() {
return status;
}
- public void setStatus(Status s) {
+ public CeActivityDto setStatus(Status s) {
this.status = s;
+ return this;
}
public boolean getIsLast() {
return isLast;
}
- void setIsLast(boolean b) {
+ CeActivityDto setIsLast(boolean b) {
this.isLast = b;
+ return this;
}
public String getIsLastKey() {
return submittedAt;
}
- public void setSubmittedAt(long submittedAt) {
+ public CeActivityDto setSubmittedAt(long submittedAt) {
this.submittedAt = submittedAt;
+ return this;
}
@CheckForNull
return startedAt;
}
- public void setStartedAt(@Nullable Long l) {
+ public CeActivityDto setStartedAt(@Nullable Long l) {
this.startedAt = l;
+ return this;
}
@CheckForNull
return executedAt;
}
- public void setExecutedAt(@Nullable Long l) {
+ public CeActivityDto setExecutedAt(@Nullable Long l) {
this.executedAt = l;
+ return this;
}
public long getCreatedAt() {
return createdAt;
}
- public void setCreatedAt(long l) {
+ public CeActivityDto setCreatedAt(long l) {
this.createdAt = l;
+ return this;
}
public long getUpdatedAt() {
return updatedAt;
}
- public void setUpdatedAt(long l) {
+ public CeActivityDto setUpdatedAt(long l) {
this.updatedAt = l;
+ return this;
}
@CheckForNull
return executionTimeMs;
}
- public void setExecutionTimeMs(@Nullable Long l) {
+ public CeActivityDto setExecutionTimeMs(@Nullable Long l) {
checkArgument(l == null || l >= 0, "Execution time must be positive: %s", l);
this.executionTimeMs = l;
+ return this;
}
@CheckForNull
return uuid;
}
- public void setUuid(String s) {
+ public CeQueueDto setUuid(String s) {
checkArgument(s.length() <= 40, "Value of UUID is too long: %s", s);
this.uuid = s;
+ return this;
}
@CheckForNull
return componentUuid;
}
- public void setComponentUuid(@Nullable String s) {
+ public CeQueueDto setComponentUuid(@Nullable String s) {
checkArgument(s == null || s.length() <= 40, "Value of component UUID is too long: %s", s);
this.componentUuid = s;
+ return this;
}
public Status getStatus() {
return status;
}
- public void setStatus(Status s) {
+ public CeQueueDto setStatus(Status s) {
this.status = s;
+ return this;
}
public String getTaskType() {
return taskType;
}
- public void setTaskType(String s) {
+ public CeQueueDto setTaskType(String s) {
checkArgument(s.length() <= 15, "Value of task type is too long: %s", s);
this.taskType = s;
+ return this;
}
@CheckForNull
return submitterLogin;
}
- public void setSubmitterLogin(@Nullable String s) {
+ public CeQueueDto setSubmitterLogin(@Nullable String s) {
checkArgument(s == null || s.length() <= 255, "Value of submitter login is too long: %s", s);
this.submitterLogin = s;
+ return this;
}
@CheckForNull
return startedAt;
}
- public void setStartedAt(@Nullable Long l) {
+ public CeQueueDto setStartedAt(@Nullable Long l) {
this.startedAt = l;
+ return this;
}
public long getCreatedAt() {
return createdAt;
}
- public void setCreatedAt(long l) {
+ public CeQueueDto setCreatedAt(long l) {
this.createdAt = l;
+ return this;
}
public long getUpdatedAt() {
return updatedAt;
}
- public void setUpdatedAt(long l) {
+ public CeQueueDto setUpdatedAt(long l) {
this.updatedAt = l;
+ return this;
}
@Override
values (
#{uuid,jdbcType=VARCHAR},
#{componentUuid,jdbcType=VARCHAR},
- #{snapshotId,jdbcType=INTEGER},
+ #{snapshotId,jdbcType=BIGINT},
#{status,jdbcType=VARCHAR},
#{taskType,jdbcType=VARCHAR},
#{isLast,jdbcType=BOOLEAN},
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.db.ce;
+
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
+import static org.apache.commons.lang.math.RandomUtils.nextLong;
+
+public class CeQueueTesting {
+ private CeQueueTesting() {
+ // static methods only
+ }
+
+ public static CeQueueDto newCeQueueDto(String uuid) {
+ return new CeQueueDto()
+ .setUuid(uuid)
+ .setComponentUuid(randomAlphanumeric(40))
+ .setStatus(CeQueueDto.Status.PENDING)
+ .setTaskType(CeTaskTypes.REPORT)
+ .setSubmitterLogin(randomAlphanumeric(255))
+ .setCreatedAt(nextLong())
+ .setUpdatedAt(nextLong())
+ .setStartedAt(nextLong());
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.db.measure;
+
+import org.sonar.db.metric.MetricDto;
+
+import static org.apache.commons.lang.math.RandomUtils.nextInt;
+
+public class MeasureTesting {
+ private MeasureTesting() {
+ // static methods only
+ }
+
+ public static MeasureDto newMeasureDto(MetricDto metricDto, long snapshotId) {
+ return new MeasureDto()
+ .setMetricId(metricDto.getId())
+ .setMetricKey(metricDto.getKey())
+ .setSnapshotId((long) nextInt())
+ .setComponentId((long) nextInt())
+ .setSnapshotId(snapshotId);
+ }
+}
import org.sonarqube.ws.client.component.ComponentsService;
import org.sonarqube.ws.client.issue.IssuesService;
import org.sonarqube.ws.client.permission.PermissionsService;
+import org.sonarqube.ws.client.qualitygate.QualityGatesService;
import org.sonarqube.ws.client.qualityprofile.QualityProfilesService;
import org.sonarqube.ws.client.usertoken.UserTokensService;
private final QualityProfilesService qualityProfilesService;
private final IssuesService issuesService;
private final UserTokensService userTokensService;
+ private final QualityGatesService qualityGatesService;
private final WsConnector wsConnector;
public HttpWsClient(WsConnector wsConnector) {
this.qualityProfilesService = new QualityProfilesService(wsConnector);
this.issuesService = new IssuesService(wsConnector);
this.userTokensService = new UserTokensService(wsConnector);
+ this.qualityGatesService = new QualityGatesService(wsConnector);
}
@Override
public UserTokensService userTokens() {
return userTokensService;
}
+
+ @Override
+ public QualityGatesService qualityGates() {
+ return qualityGatesService;
+ }
}
import org.sonarqube.ws.client.component.ComponentsService;
import org.sonarqube.ws.client.issue.IssuesService;
import org.sonarqube.ws.client.permission.PermissionsService;
+import org.sonarqube.ws.client.qualitygate.QualityGatesService;
import org.sonarqube.ws.client.qualityprofile.QualityProfilesService;
import org.sonarqube.ws.client.usertoken.UserTokensService;
UserTokensService userTokens();
+ QualityGatesService qualityGates();
+
WsConnector wsConnector();
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.qualitygate;
+
+public class ProjectStatusWsRequest {
+ private String taskId;
+
+ public String getAnalysisId() {
+ return taskId;
+ }
+
+ public ProjectStatusWsRequest setAnalysisId(String taskId) {
+ this.taskId = taskId;
+ return this;
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.qualitygate;
+
+import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.WsConnector;
+
+public class QualityGatesService extends BaseService {
+
+ public QualityGatesService(WsConnector wsConnector) {
+ super(wsConnector, "api/qualitygates");
+ }
+
+ public ProjectStatusWsResponse projectStatus(ProjectStatusWsRequest request) {
+ return call(new GetRequest(path("project_status"))
+ .setParam("analysisId", request.getAnalysisId()),
+ ProjectStatusWsResponse.parser());
+ }
+}
--- /dev/null
+
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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
+package org.sonarqube.ws.client.qualitygate;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
optional string componentKey = 4;
optional string componentName = 5;
optional string componentQualifier = 6;
- optional TaskStatus status = 7;
- optional string submittedAt = 8;
- optional string submitterLogin = 9;
- optional string startedAt = 10;
- optional string executedAt = 11;
- optional bool isLastExecuted = 12;
- optional int64 executionTimeMs = 13;
- optional bool logs = 14;
+ optional string analysisId = 7;
+ optional TaskStatus status = 8;
+ optional string submittedAt = 9;
+ optional string submitterLogin = 10;
+ optional string startedAt = 11;
+ optional string executedAt = 12;
+ optional bool isLastExecuted = 13;
+ optional int64 executionTimeMs = 14;
+ optional bool logs = 15;
}
enum TaskStatus {
--- /dev/null
+// SonarQube, open source software quality management tool.
+// Copyright (C) 2008-2015 SonarSource
+// mailto:contact AT sonarsource DOT com
+//
+// SonarQube 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.
+//
+// SonarQube 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.
+
+syntax = "proto2";
+
+package sonarqube.ws.qualitygate;
+
+import "ws-commons.proto";
+
+option java_package = "org.sonarqube.ws";
+option java_outer_classname = "WsQualityGates";
+option optimize_for = SPEED;
+
+// GET api/qualitygates/project_status
+message ProjectStatusWsResponse {
+ optional ProjectStatus projectStatus = 1;
+
+ message ProjectStatus {
+ optional Status status = 1;
+ repeated Condition conditions = 2;
+ repeated Period periods = 3;
+ }
+
+ message Condition {
+ optional Status status = 1;
+ optional string metricKey = 2;
+ optional Comparator comparator = 3;
+ optional int32 periodIndex = 4;
+ optional string warningThreshold = 5;
+ optional string errorThreshold = 6;
+ optional string actualValue = 7;
+ }
+
+ message Period {
+ optional int32 index = 1;
+ optional string mode = 2;
+ optional string date = 3;
+ optional string parameter = 4;
+ }
+
+ enum Status {
+ OK = 1;
+ WARN = 2;
+ ERROR = 3;
+ NONE = 4;
+ }
+
+ enum Comparator {
+ GT = 1;
+ LT = 2;
+ EQ = 3;
+ NE = 4;
+ }
+}