]> source.dussan.org Git - sonarqube.git/commitdiff
Add WS to copy a quality gate
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Mon, 3 Mar 2014 10:22:38 +0000 (11:22 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Mon, 3 Mar 2014 10:44:20 +0000 (11:44 +0100)
sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java
sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java
sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java
sonar-server/src/test/java/org/sonar/server/qualitygate/ws/QualityGatesWsTest.java

index fc15784b0f6b7772f63238acbc47f49c94d1efb5..9047bd1596c300b4e29d1e3df41825c685e0abee 100644 (file)
@@ -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<QualityGateDto> list() {
     return dao.selectAll();
   }
index e71f697ce93d0c105f32437fc8114569abc590bc..427e1578ad723ba0a92bc35ce5779ef4182ef3fa 100644 (file)
@@ -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()) {
index f99d3578b1fadcfe3bb5d64c6df185b0b65ad079..cd49838ab9187254d603678fa4fc1caecfb4c9e2 100644 (file)
@@ -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<QualityGateConditionDto> 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<Object>() {
+      @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));
+  }
+
 }
index 0fc8b3d047d8e93feeb5486f80e67e34c4162159..9242209e18f9f530b7b1b5ecb9934d89144c2ec3 100644 (file)
@@ -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();