From: Jean-Baptiste Lievremont Date: Mon, 3 Mar 2014 10:22:38 +0000 (+0100) Subject: Add WS to copy a quality gate X-Git-Tag: 4.3~612 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d06a1221872777c92695a4cb4f6a404901757e35;p=sonarqube.git Add WS to copy a quality gate --- diff --git a/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java b/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java index fc15784b0f6..9047bd1596c 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java +++ b/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java @@ -23,6 +23,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Strings; import com.google.common.collect.Collections2; import org.apache.commons.lang.StringUtils; +import org.apache.ibatis.session.SqlSession; import org.elasticsearch.common.collect.Lists; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; @@ -32,6 +33,7 @@ import org.sonar.api.resources.Qualifiers; import org.sonar.core.component.ComponentQuery; import org.sonar.core.component.db.ComponentDao; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.persistence.MyBatis; import org.sonar.core.properties.PropertiesDao; import org.sonar.core.properties.PropertyDto; import org.sonar.core.qualitygate.db.QualityGateConditionDao; @@ -70,12 +72,16 @@ public class QualityGates { private final ComponentDao componentDao; - public QualityGates(QualityGateDao dao, QualityGateConditionDao conditionDao, MetricFinder metricFinder, PropertiesDao propertiesDao, ComponentDao componentDao) { + private final MyBatis myBatis; + + public QualityGates(QualityGateDao dao, QualityGateConditionDao conditionDao, MetricFinder metricFinder, PropertiesDao propertiesDao, ComponentDao componentDao, + MyBatis myBatis) { this.dao = dao; this.conditionDao = conditionDao; this.metricFinder = metricFinder; this.propertiesDao = propertiesDao; this.componentDao = componentDao; + this.myBatis = myBatis; } public QualityGateDto create(String name) { @@ -99,6 +105,28 @@ public class QualityGates { return toRename; } + public QualityGateDto copy(long sourceId, String destinationName) { + checkPermission(UserSession.get()); + getNonNullQgate(sourceId); + validateQualityGate(null, destinationName); + QualityGateDto destinationGate = new QualityGateDto().setName(destinationName); + SqlSession session = myBatis.openSession(); + try { + dao.insert(destinationGate, session); + for(QualityGateConditionDto sourceCondition: conditionDao.selectForQualityGate(sourceId, session)) { + conditionDao.insert(new QualityGateConditionDto().setQualityGateId(destinationGate.getId()) + .setMetricId(sourceCondition.getMetricId()).setOperator(sourceCondition.getOperator()) + .setWarningThreshold(sourceCondition.getWarningThreshold()).setErrorThreshold(sourceCondition.getErrorThreshold()).setPeriod(sourceCondition.getPeriod()), + session); + } + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + return destinationGate; + } + + public Collection list() { return dao.selectAll(); } diff --git a/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java b/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java index e71f697ce93..427e1578ad7 100644 --- a/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java +++ b/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java @@ -84,7 +84,7 @@ public class QualityGatesWs implements WebService { createCondition(request, response); } }); - createCondition.newParam(PARAM_GATE_ID).setDescription("The numerical ID of the quality gate."); + createCondition.newParam(PARAM_GATE_ID).setDescription("The numerical ID of the quality gate for which the condition will be created."); addConditionParams(createCondition); NewAction updateCondition = controller.newAction("update_condition") @@ -129,6 +129,18 @@ public class QualityGatesWs implements WebService { } }).newParam(PARAM_NAME).setDescription("The name of the quality gate to create."); + NewAction copy = controller.newAction("copy") + .setDescription("Copy a quality gate, given its ID and the name for the new quality gate.") + .setPost(true) + .setHandler(new RequestHandler() { + @Override + public void handle(Request request, Response response) { + copy(request, response); + } + }); + copy.newParam(PARAM_ID).setDescription("The ID of the source quality gate."); + copy.newParam(PARAM_NAME).setDescription("The name of the destination quality gate."); + controller.newAction("set_as_default") .setDescription("Select the default quality gate.") .setPost(true) @@ -206,7 +218,7 @@ public class QualityGatesWs implements WebService { search(request, response); } }); - search.newParam(PARAM_GATE_ID).setDescription("The numerical ID of the quality gate."); + search.newParam(PARAM_GATE_ID).setDescription("The numerical ID of the quality gate considered for association."); search.newParam(PARAM_SELECTED).setDescription("Optionally, to search for projects associated (selected=selected) or not (selected=deselected)."); search.newParam(PARAM_QUERY).setDescription("Optionally, part of the name of the projects to search for."); search.newParam(PARAM_PAGE); @@ -235,6 +247,12 @@ public class QualityGatesWs implements WebService { deselect.newParam(PARAM_PROJECT_ID); } + protected void copy(Request request, Response response) { + QualityGateDto newQualityGate = qualityGates.copy(parseId(request, PARAM_ID), request.requiredParam(PARAM_NAME)); + JsonWriter writer = response.newJsonWriter(); + writeQualityGate(newQualityGate, writer).close(); + } + protected void listMetrics(Request request, Response response) { JsonWriter writer = response.newJsonWriter().beginObject().name("metrics").beginArray(); for (Metric metric: qualityGates.gateMetrics()) { diff --git a/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java b/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java index f99d3578b1f..cd49838ab91 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java @@ -21,13 +21,16 @@ package org.sonar.server.qualitygate; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import org.apache.ibatis.session.SqlSession; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.measures.Metric.ValueType; @@ -36,6 +39,7 @@ import org.sonar.core.component.ComponentDto; import org.sonar.core.component.ComponentQuery; import org.sonar.core.component.db.ComponentDao; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.persistence.MyBatis; import org.sonar.core.properties.PropertiesDao; import org.sonar.core.properties.PropertyDto; import org.sonar.core.qualitygate.db.QualityGateConditionDao; @@ -56,8 +60,11 @@ import java.util.List; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -79,6 +86,9 @@ public class QualityGatesTest { @Mock private ComponentDao componentDao; + @Mock + private MyBatis myBatis; + private QualityGates qGates; UserSession authorizedUserSession = MockUserSession.create().setLogin("gaudol").setName("Olivier").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); @@ -87,7 +97,7 @@ public class QualityGatesTest { @Before public void initialize() { - qGates = new QualityGates(dao, conditionDao, metricFinder, propertiesDao, componentDao); + qGates = new QualityGates(dao, conditionDao, metricFinder, propertiesDao, componentDao, myBatis); UserSessionTestUtils.setUserSession(authorizedUserSession); } @@ -483,4 +493,34 @@ public class QualityGatesTest { verify(propertiesDao).deleteProjectProperty("sonar.qualitygate", projectId); } + @Test + public void should_copy_qgate() throws Exception { + String name = "Atlantis"; + long sourceId = 42L; + final long destId = 43L; + long metric1Id = 1L; + long metric2Id = 2L; + QualityGateConditionDto cond1 = new QualityGateConditionDto().setMetricId(metric1Id); + QualityGateConditionDto cond2 = new QualityGateConditionDto().setMetricId(metric2Id); + Collection conditions = ImmutableList.of(cond1, cond2); + + when(dao.selectById(sourceId)).thenReturn(new QualityGateDto().setId(sourceId).setName("SG-1")); + SqlSession session = mock(SqlSession.class); + when(myBatis.openSession()).thenReturn(session); + Mockito.doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + ((QualityGateDto) invocation.getArguments()[0]).setId(destId); + return null; + } + }).when(dao).insert(any(QualityGateDto.class), eq(session)); + when(conditionDao.selectForQualityGate(anyLong(), eq(session))).thenReturn(conditions); + QualityGateDto atlantis = qGates.copy(sourceId, name); + assertThat(atlantis.getName()).isEqualTo(name); + verify(dao).selectByName(name); + verify(dao).insert(atlantis, session); + verify(conditionDao).selectForQualityGate(anyLong(), eq(session)); + verify(conditionDao, times(conditions.size())).insert(any(QualityGateConditionDto.class), eq(session)); + } + } diff --git a/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java b/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java index 0fc8b3d047d..9242209e18f 100644 --- a/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java @@ -60,7 +60,7 @@ public class QualityGatesWsTest { assertThat(controller).isNotNull(); assertThat(controller.path()).isEqualTo("api/qualitygates"); assertThat(controller.description()).isNotEmpty(); - assertThat(controller.actions()).hasSize(14); + assertThat(controller.actions()).hasSize(15); WebService.Action list = controller.action("list"); assertThat(list).isNotNull(); @@ -85,6 +85,15 @@ public class QualityGatesWsTest { assertThat(create.param("name")).isNotNull(); assertThat(create.isPrivate()).isFalse(); + WebService.Action copy = controller.action("copy"); + assertThat(copy).isNotNull(); + assertThat(copy.handler()).isNotNull(); + assertThat(copy.since()).isEqualTo("4.3"); + assertThat(copy.isPost()).isTrue(); + assertThat(copy.param("id")).isNotNull(); + assertThat(copy.param("name")).isNotNull(); + assertThat(copy.isPrivate()).isFalse(); + WebService.Action destroy = controller.action("destroy"); assertThat(destroy).isNotNull(); assertThat(destroy.handler()).isNotNull();