]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10134 Add ORG_QUALITY_GATES table
authorEric Hartmann <hartmann.eric@gmail.com>
Wed, 29 Nov 2017 16:06:37 +0000 (17:06 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 14 Dec 2017 16:03:35 +0000 (17:03 +0100)
Add column DEFAULT_QUALITY_GATE_UUID on ORGANIZATIONS table

34 files changed:
server/sonar-db-core/src/main/java/org/sonar/db/version/SqTables.java
server/sonar-db-core/src/main/resources/org/sonar/db/version/rows-h2.sql
server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDto.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoWithDuplicatedKeysTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationTesting.java
server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/user/GroupDaoTest.java
server/sonar-db-dao/src/test/resources/org/sonar/db/component/ComponentDaoWithDuplicatedKeysTest/schema.sql
server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/delete-result.xml [deleted file]
server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert-result.xml [deleted file]
server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert.xml [deleted file]
server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/selectAll.xml [deleted file]
server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/update-result.xml [deleted file]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizations.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTable.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70.java
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizationsTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTableTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70Test.java
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizationsTest/organizations.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTableTest/empty.sql [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateFinder.java
server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java
server/sonar-server/src/test/resources/org/sonar/server/source/ws/HashActionTest/no_source.xml
server/sonar-server/src/test/resources/org/sonar/server/source/ws/HashActionTest/shared.xml
server/sonar-server/src/test/resources/org/sonar/server/source/ws/HashActionTest/show_hashes_on_test_file.xml

index 421e67fa5e8fa947673247c259e3e94cf386b774..4361ae44ea9aed09c8472dc8c31bea63e7bfed59 100644 (file)
@@ -76,6 +76,7 @@ public final class SqTables {
     "organizations",
     "organization_members",
     "org_qprofiles",
+    "org_quality_gates",
     "permission_templates",
     "perm_templates_users",
     "perm_templates_groups",
index cd82a9bb62d60ab6d5903a47085bd3a9f80e76b4..62b162cb561cc9d5baddd64f5a27341c4793d449 100644 (file)
@@ -5,7 +5,9 @@ INSERT INTO GROUPS(ID, ORGANIZATION_UUID, NAME, DESCRIPTION, CREATED_AT, UPDATED
 INSERT INTO GROUPS(ID, ORGANIZATION_UUID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (2, 'AVdqnciQUUs7Zd3KPvFD', 'sonar-users', 'Any new users created will automatically join this group', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
 ALTER TABLE GROUPS ALTER COLUMN ID RESTART WITH 3;
 
-INSERT INTO ORGANIZATIONS (UUID, KEE, NAME, GUARDED, NEW_PROJECT_PRIVATE, DEFAULT_GROUP_ID, CREATED_AT, UPDATED_AT) VALUES ('AVdqnciQUUs7Zd3KPvFD', 'default-organization', 'Default Organization', true, false, 2, '1474962596482', '1474962596482');
+INSERT INTO QUALITY_GATES(ID, NAME, IS_BUILT_IN, CREATED_AT, UPDATED_AT) VALUES (1, 'Sonar Way', true, '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
+
+INSERT INTO ORGANIZATIONS (UUID, KEE, NAME, GUARDED, NEW_PROJECT_PRIVATE, DEFAULT_GROUP_ID, DEFAULT_QUALITY_GATE_UUID, CREATED_AT, UPDATED_AT) VALUES ('AVdqnciQUUs7Zd3KPvFD', 'default-organization', 'Default Organization', true, false, 2, 1, '1474962596482', '1474962596482');
 INSERT INTO INTERNAL_PROPERTIES (KEE, IS_EMPTY, TEXT_VALUE, CREATED_AT) VALUES ('organization.default', false, 'AVdqnciQUUs7Zd3KPvFD', '1474962596482');
 
 INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (1, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'admin');
index 1e43bd3cfbb4d2e0f9ff34846796323d5cfa0a17..45c29bee706b24139bca25b0cb6b7a13904b2b52 100644 (file)
@@ -10,6 +10,7 @@ CREATE TABLE "ORGANIZATIONS" (
   "DEFAULT_PERM_TEMPLATE_PROJECT" VARCHAR(40),
   "DEFAULT_PERM_TEMPLATE_VIEW" VARCHAR(40),
   "DEFAULT_GROUP_ID" INTEGER,
+  "DEFAULT_QUALITY_GATE_UUID" VARCHAR(40), // TODO : NOT NULL
   "NEW_PROJECT_PRIVATE" BOOLEAN NOT NULL,
   "CREATED_AT" BIGINT NOT NULL,
   "UPDATED_AT" BIGINT NOT NULL
@@ -248,6 +249,12 @@ CREATE TABLE "QUALITY_GATE_CONDITIONS" (
   "UPDATED_AT" TIMESTAMP,
 );
 
+CREATE TABLE "ORG_QUALITY_GATES" (
+  "UUID" VARCHAR(40) NOT NULL PRIMARY KEY,
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "QUALITY_GATE_UUID" VARCHAR(40) NOT NULL
+);
+CREATE UNIQUE INDEX "UNIQ_ORG_QUALITY_GATES" ON "ORG_QUALITY_GATES" ("ORGANIZATION_UUID","QUALITY_GATE_UUID");
 
 CREATE TABLE "PROPERTIES" (
   "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
index 2cd090b753daa8fad31ee1e0ad08d12882c60791..f026e6b33298d42884d78efaeadde719c7021dd1 100644 (file)
@@ -35,6 +35,7 @@ public class OrganizationDto {
   private String url;
   /** avatar url can be null */
   private String avatarUrl;
+
   /**
    * Flag indicated whether being root is required to be able to delete this organization.
    */
@@ -42,6 +43,7 @@ public class OrganizationDto {
   /** If of the user for whom the organization was created, can be null. */
   private Integer userId;
   private Integer defaultGroupId;
+  private String defaultQualityGateUuid;
   private long createdAt;
   private long updatedAt;
 
@@ -146,6 +148,15 @@ public class OrganizationDto {
     return this;
   }
 
+  public String getDefaultQualityGateUuid() {
+    return defaultQualityGateUuid;
+  }
+
+  public OrganizationDto setDefaultQualityGateUuid(String defaultQualityGateUuid) {
+    this.defaultQualityGateUuid = defaultQualityGateUuid;
+    return this;
+  }
+
   @Override
   public String toString() {
     return "OrganizationDto{" +
@@ -157,6 +168,7 @@ public class OrganizationDto {
       ", avatarUrl='" + avatarUrl + '\'' +
       ", guarded=" + guarded +
       ", userId=" + userId +
+      ", defaultQualityGateUuid=" + defaultQualityGateUuid +
       ", createdAt=" + createdAt +
       ", updatedAt=" + updatedAt +
       '}';
index 345538bfc8abe49c63390088a74b5a1e431fc285..0a9d4e314a5aaeb3bde5a58dabc846f7f5a53b38 100644 (file)
@@ -59,6 +59,10 @@ public class QualityGateDao implements Dao {
     mapper(dbSession).ensureOneBuiltInQualityGate(builtInName);
   }
 
+  public QualityGateDto selectBuiltIn(DbSession dbSession) {
+    return mapper(dbSession).selectBuiltIn();
+  }
+
   private static QualityGateMapper mapper(DbSession session) {
     return session.getMapper(QualityGateMapper.class);
   }
index 9347308d3c5b5b4a64b18f0b73edec6693c37058..39d91acd1f3a48535076cfbb1c76ca0e0d40a567 100644 (file)
@@ -31,6 +31,8 @@ public interface QualityGateMapper {
 
   QualityGateDto selectById(long id);
 
+  QualityGateDto selectBuiltIn();
+
   void delete(long id);
 
   void update(QualityGateDto qGate);
index 4f23af35bea600005cbfa73724924656ec82bdd2..fcdacde0253a72dd394b2345fc1a3958916ab7ef 100644 (file)
       guarded,
       new_project_private,
       user_id,
+      default_quality_gate_uuid,
       created_at,
       updated_at
     )
       #{organization.guarded, jdbcType=BOOLEAN},
       #{newProjectPrivate, jdbcType=BOOLEAN},
       #{organization.userId, jdbcType=INTEGER},
+      #{organization.defaultQualityGateUuid, jdbcType=VARCHAR},
       #{organization.createdAt, jdbcType=BIGINT},
       #{organization.updatedAt, jdbcType=BIGINT}
     )
index 332414e8b710865c4634d76543c405a84c0cd79b..9454c6a507088ff5a929f7e22a0d76d78818993f 100644 (file)
     where id=#{id}
   </select>
 
+  <select id="selectBuiltIn" resultType="org.sonar.db.qualitygate.QualityGateDto">
+    SELECT
+      <include refid="gateColumns"/>
+    FROM quality_gates
+    WHERE
+      is_built_in = ${_true}
+  </select>
+
   <update id="delete" parameterType="long">
     delete from quality_gates where id=#{id}
   </update>
index 9e9fe02e8f95ad06549be97fbf7220bbac98277a..7e7870e09ead53fc8ac7e01960395e19197724a3 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.db;
 
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import javax.annotation.Nullable;
@@ -42,6 +43,7 @@ import org.sonar.db.permission.template.PermissionTemplateDbTester;
 import org.sonar.db.plugin.PluginDbTester;
 import org.sonar.db.property.PropertyDbTester;
 import org.sonar.db.qualitygate.QualityGateDbTester;
+import org.sonar.db.qualitygate.QualityGateDto;
 import org.sonar.db.qualityprofile.QualityProfileDbTester;
 import org.sonar.db.rule.RuleDbTester;
 import org.sonar.db.source.FileSourceTester;
@@ -64,6 +66,7 @@ public class DbTester extends AbstractDbTester<TestDb> {
   private boolean started = false;
   private String defaultOrganizationUuid = randomAlphanumeric(40);
   private OrganizationDto defaultOrganization;
+  private QualityGateDto builtInQualityGate;
 
   private final UserDbTester userTester;
   private final ComponentDbTester componentTester;
@@ -149,16 +152,32 @@ public class DbTester extends AbstractDbTester<TestDb> {
   }
 
   @Override
-  protected void before() throws Throwable {
+  protected void before() {
     db.start();
     db.truncateTables();
     initDbClient();
+    // TODO : insertBuiltInQualityGateIfTableExists();
+
     if (!disableDefaultOrganization) {
       insertDefaultOrganization();
     }
     started = true;
   }
 
+  private void insertBuiltInQualityGateIfTableExists() {
+    try (DbSession dbSession = db.getMyBatis().openSession(false)) {
+      if (DatabaseUtils.tableExists("quality_gates", dbSession.getConnection())) {
+        builtInQualityGate = new QualityGateDto()
+          .setName("Sonar way")
+          .setBuiltIn(true)
+          .setCreatedAt(new Date(system2.now()))
+          .setCreatedAt(new Date(system2.now()));
+        client.qualityGateDao().insert(dbSession, builtInQualityGate);
+        dbSession.commit();
+      }
+    }
+  }
+
   private void insertDefaultOrganization() {
     defaultOrganization = OrganizationTesting.newOrganizationDto().setUuid(defaultOrganizationUuid);
     try (DbSession dbSession = db.getMyBatis().openSession(false)) {
index 95799460b009faabcbfcf7d26a61e879ec8048f2..487ff88107ef48f1f7d3ece5e8a513744ea71215 100644 (file)
@@ -58,7 +58,7 @@ public class ComponentDaoWithDuplicatedKeysTest {
   }
 
   @Test
-  public void return_nothing() throws Exception {
+  public void return_nothing()  {
     assertThat(underTest.selectComponentsHavingSameKeyOrderedById(db.getSession(), PROJECT_KEY)).isEmpty();
   }
 
index a747b2a82bf11b58fc0aae30e53f247744355f16..fc65f74dc38d8aec2a60f3939b84d2acbdff8951 100644 (file)
@@ -68,6 +68,7 @@ public class OrganizationDaoTest {
     .setUrl("the url 1")
     .setAvatarUrl("the avatar url 1")
     .setGuarded(false)
+    .setDefaultQualityGateUuid("1")
     .setUserId(1_000);
   private static final OrganizationDto ORGANIZATION_DTO_2 = new OrganizationDto()
     .setUuid("uuid 2")
@@ -77,6 +78,7 @@ public class OrganizationDaoTest {
     .setUrl("the url 2")
     .setAvatarUrl("the avatar url 2")
     .setGuarded(true)
+    .setDefaultQualityGateUuid("1")
     .setUserId(2_000);
   private static final String PERMISSION_1 = "foo";
   private static final String PERMISSION_2 = "bar";
@@ -930,6 +932,7 @@ public class OrganizationDaoTest {
           "      default_perm_template_view," +
           "      new_project_private," +
           "      guarded," +
+          "      default_quality_gate_uuid," +
           "      created_at," +
           "      updated_at" +
           "    )" +
@@ -943,6 +946,7 @@ public class OrganizationDaoTest {
           "      ?," +
           "      ?," +
           "      ?," +
+          "      ?," +
           "      ?" +
           "    )")) {
       preparedStatement.setString(1, organizationUuid);
@@ -952,8 +956,9 @@ public class OrganizationDaoTest {
       preparedStatement.setString(5, view);
       preparedStatement.setBoolean(6, false);
       preparedStatement.setBoolean(7, false);
-      preparedStatement.setLong(8, 1000L);
-      preparedStatement.setLong(9, 2000L);
+      preparedStatement.setString(8, "1"); // TODO check ok ?
+      preparedStatement.setLong(9, 1000L);
+      preparedStatement.setLong(10, 2000L);
       preparedStatement.execute();
     } catch (SQLException e) {
       throw new RuntimeException("dirty insert failed", e);
@@ -1008,13 +1013,14 @@ public class OrganizationDaoTest {
     return rows.get(0);
   }
 
-  private static OrganizationDto copyOf(OrganizationDto organizationDto) {
+  private OrganizationDto copyOf(OrganizationDto organizationDto) {
     return new OrganizationDto()
       .setUuid(organizationDto.getUuid())
       .setKey(organizationDto.getKey())
       .setName(organizationDto.getName())
       .setDescription(organizationDto.getDescription())
       .setUrl(organizationDto.getUrl())
+      // TODO : .setDefaultQualityGateUuid(dbClient.qualityGateDao().selectBuiltIn(dbSession).getId().toString())
       .setAvatarUrl(organizationDto.getAvatarUrl());
   }
 
index 703b5ae10cd50869bbf643e8a2b936e1f72a17d2..28e35ed2eb9d60d5539b1fa7b75a18d4a2217a4b 100644 (file)
@@ -37,6 +37,7 @@ public class OrganizationTesting {
       .setName(randomAlphanumeric(64))
       .setDescription(randomAlphanumeric(256))
       .setAvatarUrl(randomAlphanumeric(256))
+      .setDefaultQualityGateUuid("1") // TODO check that using it directly is ok
       .setUrl(randomAlphanumeric(256));
   }
 }
index fc1a907e78685d4af555c5a11da456c14f04e76e..b9c2b7c98a67dcb3f47b8fbbdadacb2dbf7f9506 100644 (file)
@@ -19,8 +19,6 @@
  */
 package org.sonar.db.qualitygate;
 
-import java.util.Collection;
-import java.util.Iterator;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
@@ -28,24 +26,28 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
 
 public class QualityGateDaoTest {
 
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
 
+  private QualityGateDbTester qualityGateDbTester = new QualityGateDbTester(db);
   private DbSession dbSession = db.getSession();
   private QualityGateDao underTest = db.getDbClient().qualityGateDao();
 
   @Test
-  public void testInsert() throws Exception {
-    db.prepareDbUnit(getClass(), "insert.xml");
+  public void testInsert() {
     QualityGateDto newQgate = new QualityGateDto().setName("My Quality Gate");
 
     underTest.insert(dbSession, newQgate);
     dbSession.commit();
 
-    db.assertDbUnitTable(getClass(), "insert-result.xml", "quality_gates", "name");
+    assertThat(underTest.selectAll(dbSession)).extracting(QualityGateDto::getName, QualityGateDto::isBuiltIn)
+      .containsExactlyInAnyOrder(
+        // TODO : tuple("Sonar way", true),
+        tuple("My Quality Gate", false));
     assertThat(newQgate.getId()).isNotNull();
   }
 
@@ -59,49 +61,63 @@ public class QualityGateDaoTest {
   }
 
   @Test
-  public void testSelectAll() throws Exception {
-    db.prepareDbUnit(getClass(), "selectAll.xml");
-
-    Collection<QualityGateDto> allQualityGates = underTest.selectAll(dbSession);
-
-    assertThat(allQualityGates).hasSize(3);
-    Iterator<QualityGateDto> gatesIterator = allQualityGates.iterator();
-    assertThat(gatesIterator.next().getName()).isEqualTo("Balanced");
-    assertThat(gatesIterator.next().getName()).isEqualTo("Lenient");
-    assertThat(gatesIterator.next().getName()).isEqualTo("Very strict");
+  public void testSelectAll() {
+    insertQualityGates();
+
+    assertThat(underTest.selectAll(dbSession)).extracting(QualityGateDto::getName, QualityGateDto::isBuiltIn)
+      .containsExactlyInAnyOrder(
+        // TODO : tuple("Sonar Way", true),
+        tuple("Balanced", false),
+        tuple("Lenient", false),
+        tuple("Very strict", false));
   }
 
   @Test
-  public void testSelectByName() throws Exception {
-    db.prepareDbUnit(getClass(), "selectAll.xml");
+  public void testSelectByName() {
+    insertQualityGates();
     assertThat(underTest.selectByName(dbSession, "Balanced").getName()).isEqualTo("Balanced");
     assertThat(underTest.selectByName(dbSession, "Unknown")).isNull();
   }
 
   @Test
-  public void testSelectById() throws Exception {
-    db.prepareDbUnit(getClass(), "selectAll.xml");
-    assertThat(underTest.selectById(dbSession, 1L).getName()).isEqualTo("Very strict");
+  public void testSelectById() {
+    insertQualityGates();
+    assertThat(underTest.selectById(dbSession, underTest.selectByName(dbSession, "Very strict").getId()).getName()).isEqualTo("Very strict");
     assertThat(underTest.selectById(dbSession, 42L)).isNull();
   }
 
   @Test
-  public void testDelete() throws Exception {
-    db.prepareDbUnit(getClass(), "selectAll.xml");
+  public void testDelete() {
+    insertQualityGates();
 
-    underTest.delete(new QualityGateDto().setId(1L), dbSession);
+    underTest.delete(underTest.selectByName(dbSession, "Very strict"), dbSession);
     dbSession.commit();
 
-    db.assertDbUnitTable(getClass(), "delete-result.xml", "quality_gates", "id", "name");
+    assertThat(underTest.selectAll(dbSession)).extracting(QualityGateDto::getName, QualityGateDto::isBuiltIn)
+      .containsExactlyInAnyOrder(
+        // TODO : tuple("Sonar Way", true),
+        tuple("Balanced", false),
+        tuple("Lenient", false));
   }
 
   @Test
-  public void testUpdate() throws Exception {
-    db.prepareDbUnit(getClass(), "selectAll.xml");
+  public void testUpdate() {
+    insertQualityGates();
 
-    underTest.update(new QualityGateDto().setId(1L).setName("Not so strict"), dbSession);
+    underTest.update(underTest.selectByName(dbSession, "Very strict").setName("Not so strict"), dbSession);
     dbSession.commit();
 
-    db.assertDbUnitTable(getClass(), "update-result.xml", "quality_gates", "id", "name");
+    assertThat(underTest.selectAll(dbSession)).extracting(QualityGateDto::getName, QualityGateDto::isBuiltIn)
+      .containsExactlyInAnyOrder(
+        // TODO :  tuple("Sonar Way", true),
+        tuple("Balanced", false),
+        tuple("Lenient", false),
+        tuple("Not so strict", false));
+  }
+
+  private void insertQualityGates() {
+    qualityGateDbTester.insertQualityGate(g -> g.setName("Very strict").setBuiltIn(false));
+    qualityGateDbTester.insertQualityGate(g -> g.setName("Balanced").setBuiltIn(false));
+    qualityGateDbTester.insertQualityGate(g -> g.setName("Lenient").setBuiltIn(false));
   }
 }
index 325da9993d0633ae1e9590433c717de1db91f7cb..ca773494aff0a1fd3cbcf94643168872627a3cec 100644 (file)
@@ -44,6 +44,7 @@ public class GroupDaoTest {
   private static final OrganizationDto AN_ORGANIZATION = new OrganizationDto()
     .setKey("an-org")
     .setName("An Org")
+    .setDefaultQualityGateUuid("1")
     .setUuid("abcde");
 
   private System2 system2 = mock(System2.class);
index 831672702774748118ae30c9bdcb48292d260f83..05022ab88ea32a409661f84c4e18ad9ce9ec45f1 100644 (file)
@@ -8,6 +8,7 @@ CREATE TABLE "ORGANIZATIONS" (
   "NEW_PROJECT_PRIVATE" BOOLEAN,
   "USER_ID" BIGINT,
   "GUARDED" BOOLEAN NOT NULL,
+  "DEFAULT_QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
   "CREATED_AT" BIGINT NOT NULL,
   "UPDATED_AT" BIGINT NOT NULL
 );
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/delete-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/delete-result.xml
deleted file mode 100644 (file)
index 67f4faf..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<dataset>
-
-  <quality_gates id="2" name="Balanced" is_built_in="[false]"/>
-  <quality_gates id="3" name="Lenient" is_built_in="[false]"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert-result.xml
deleted file mode 100644 (file)
index 00c2857..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
-  <quality_gates id="1" name="My Quality Gate" is_built_in="[false]"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/insert.xml
deleted file mode 100644 (file)
index 871dedc..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<dataset>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/selectAll.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/selectAll.xml
deleted file mode 100644 (file)
index 09799b3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<dataset>
-
-  <quality_gates id="1" name="Very strict" is_built_in="[true]"/>
-  <quality_gates id="2" name="Balanced" is_built_in="[false]"/>
-  <quality_gates id="3" name="Lenient" is_built_in="[false]"/>
-
-</dataset>
diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/update-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/qualitygate/QualityGateDaoTest/update-result.xml
deleted file mode 100644 (file)
index 6dfb481..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<dataset>
-
-  <quality_gates id="1" name="Not so strict" is_built_in="[false]"/>
-  <quality_gates id="2" name="Balanced" is_built_in="[false]"/>
-  <quality_gates id="3" name="Lenient" is_built_in="[false]"/>
-
-</dataset>
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizations.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizations.java
new file mode 100644 (file)
index 0000000..ca3f2d8
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.platform.db.migration.version.v70;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddDefaultQualityGateUuidToOrganizations extends DdlChange {
+  public AddDefaultQualityGateUuidToOrganizations(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AddColumnsBuilder(getDialect(), "organizations")
+      .addColumn(newVarcharColumnDefBuilder()
+        .setColumnName("default_quality_gate_uuid")
+        .setIsNullable(true)
+        .setLimit(VarcharColumnDef.UUID_SIZE)
+        .build())
+      .build());
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTable.java
new file mode 100644 (file)
index 0000000..ad71b5b
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.platform.db.migration.version.v70;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.sql.CreateTableBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class CreateOrgQualityGatesTable extends DdlChange {
+
+  private static final String ORG_QUALITY_GATES = "org_quality_gates";
+  private static final VarcharColumnDef ORGANIZATION_UUID_COLUMN = VarcharColumnDef.newVarcharColumnDefBuilder()
+    .setColumnName("organization_uuid")
+    .setIsNullable(false)
+    .setLimit(VarcharColumnDef.UUID_SIZE)
+    .build();
+  private static final VarcharColumnDef QUALITY_GATE_UUID_COLUMN = VarcharColumnDef.newVarcharColumnDefBuilder()
+    .setColumnName("quality_gate_uuid")
+    .setIsNullable(false)
+    .setLimit(VarcharColumnDef.UUID_SIZE)
+    .build();
+
+  private Database db;
+
+  public CreateOrgQualityGatesTable(Database db) {
+    super(db);
+    this.db = db;
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    if (!tableExists()) {
+      context.execute(new CreateTableBuilder(getDialect(), ORG_QUALITY_GATES)
+        .addPkColumn(VarcharColumnDef.newVarcharColumnDefBuilder()
+          .setColumnName("uuid")
+          .setIsNullable(false)
+          .setLimit(VarcharColumnDef.UUID_SIZE)
+          .build())
+        .addColumn(ORGANIZATION_UUID_COLUMN)
+        .addColumn(QUALITY_GATE_UUID_COLUMN)
+        .build()
+      );
+
+      context.execute(new CreateIndexBuilder(getDialect())
+        .addColumn(ORGANIZATION_UUID_COLUMN)
+        .addColumn(QUALITY_GATE_UUID_COLUMN)
+        .setUnique(true)
+        .setTable(ORG_QUALITY_GATES)
+        .setName("uniq_org_quality_gates")
+        .build()
+      );
+    }
+  }
+
+  private boolean tableExists() throws SQLException {
+    try (Connection connection = db.getDataSource().getConnection()) {
+      return DatabaseUtils.tableExists(ORG_QUALITY_GATES, connection);
+    }
+  }
+}
index e51e2426a93cd740b3e5a90574a93a70ad3d4a33..05261e0d16c091e44b59d6f789a74d5ba321f9e5 100644 (file)
@@ -37,6 +37,8 @@ public class DbVersion70 implements DbVersion {
       .add(1907, "Populate table live_measures", PopulateLiveMeasures.class)
       .add(1908, "Delete person and file measures", DeletePersonAndFileMeasures.class)
       .add(1909, "Drop index on project_measures.person_id", DropIndexOnPersonMeasures.class)
+      .add(1910, "Create ORG_QUALITY_GATES table", CreateOrgQualityGatesTable.class)
+      .add(1911, "Add ORGANIZATIONS.DEFAULT_QUALITY_GATE_UUID", AddDefaultQualityGateUuidToOrganizations.class)
     ;
   }
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizationsTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizationsTest.java
new file mode 100644 (file)
index 0000000..6259e19
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.platform.db.migration.version.v70;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static java.sql.Types.VARCHAR;
+
+public class AddDefaultQualityGateUuidToOrganizationsTest {
+
+  @Rule
+  public final CoreDbTester dbTester = CoreDbTester.createForSchema(AddDefaultQualityGateUuidToOrganizationsTest.class, "organizations.sql");
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private AddDefaultQualityGateUuidToOrganizations underTest = new AddDefaultQualityGateUuidToOrganizations(dbTester.database());
+
+  @Test
+  public void column_is_added_to_table() throws SQLException {
+    underTest.execute();
+
+    dbTester.assertColumnDefinition("organizations", "default_quality_gate_uuid", VARCHAR, 40, true);
+  }
+
+  @Test
+  public void migration_is_not_reentrant() throws SQLException {
+    underTest.execute();
+
+    expectedException.expect(IllegalStateException.class);
+
+    underTest.execute();
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTableTest.java
new file mode 100644 (file)
index 0000000..6d489bb
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.platform.db.migration.version.v70;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.version.v67.CreateTableAnalysisPropertiesTest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CreateOrgQualityGatesTableTest {
+
+  private static final String TABLE = "org_quality_gates";
+
+  @Rule
+  public final CoreDbTester db = CoreDbTester.createForSchema(CreateTableAnalysisPropertiesTest.class, "empty.sql");
+
+  private CreateOrgQualityGatesTable underTest = new CreateOrgQualityGatesTable(db.database());
+
+  @Test
+  public void creates_table_on_empty_db() throws SQLException {
+    underTest.execute();
+
+    db.assertColumnDefinition(TABLE, "uuid", Types.VARCHAR, 40, false);
+    db.assertColumnDefinition(TABLE, "organization_uuid", Types.VARCHAR, 40, false);
+    db.assertColumnDefinition(TABLE, "quality_gate_uuid", Types.VARCHAR, 40, false);
+
+    db.assertUniqueIndex(TABLE, "uniq_org_quality_gates", "organization_uuid", "quality_gate_uuid");
+    assertThat(db.countRowsOfTable(TABLE)).isEqualTo(0);
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    underTest.execute();
+    underTest.execute();
+
+    db.assertColumnDefinition(TABLE, "uuid", Types.VARCHAR, 40, false);
+    db.assertColumnDefinition(TABLE, "organization_uuid", Types.VARCHAR, 40, false);
+    db.assertColumnDefinition(TABLE, "quality_gate_uuid", Types.VARCHAR, 40, false);
+
+    db.assertUniqueIndex(TABLE, "uniq_org_quality_gates", "organization_uuid", "quality_gate_uuid");
+    assertThat(db.countRowsOfTable(TABLE)).isEqualTo(0);
+  }
+}
index fa47fed02ed2d161845b66bcb62d967e13ad16d9..ff36b7f85f763a3cd9c480cf2d33429f55e7ac72 100644 (file)
@@ -35,7 +35,7 @@ public class DbVersion70Test {
 
   @Test
   public void verify_migration_count() {
-    verifyMigrationCount(underTest, 10);
+    verifyMigrationCount(underTest, 11);
   }
 
 }
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizationsTest/organizations.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/AddDefaultQualityGateUuidToOrganizationsTest/organizations.sql
new file mode 100644 (file)
index 0000000..406f629
--- /dev/null
@@ -0,0 +1,18 @@
+CREATE TABLE "ORGANIZATIONS" (
+"UUID" VARCHAR(40) NOT NULL PRIMARY KEY,
+"KEE" VARCHAR(32) NOT NULL,
+"NAME" VARCHAR(64) NOT NULL,
+"DESCRIPTION" VARCHAR(256),
+"URL" VARCHAR(256),
+"AVATAR_URL" VARCHAR(256),
+"GUARDED" BOOLEAN NOT NULL,
+"USER_ID" INTEGER,
+"DEFAULT_PERM_TEMPLATE_PROJECT" VARCHAR(40),
+"DEFAULT_PERM_TEMPLATE_VIEW" VARCHAR(40),
+"DEFAULT_GROUP_ID" INTEGER,
+"NEW_PROJECT_PRIVATE" BOOLEAN NOT NULL,
+"CREATED_AT" BIGINT NOT NULL,
+"UPDATED_AT" BIGINT NOT NULL
+);
+CREATE UNIQUE INDEX "PK_ORGANIZATIONS" ON "ORGANIZATIONS" ("UUID");
+CREATE UNIQUE INDEX "ORGANIZATION_KEY" ON "ORGANIZATIONS" ("KEE");
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTableTest/empty.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/CreateOrgQualityGatesTableTest/empty.sql
new file mode 100644 (file)
index 0000000..e69de29
index 010d6dfafad515bf403fff08972facc2a440a90d..fa5ff5a23e7ebad00976d644a30d2a6ee8d7a645 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.organization;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -75,8 +76,7 @@ public class OrganizationCreationImpl implements OrganizationCreation {
 
   public OrganizationCreationImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory,
     OrganizationValidation organizationValidation, Configuration config, UserIndexer userIndexer,
-    BuiltInQProfileRepository builtInQProfileRepository,
-    DefaultGroupCreator defaultGroupCreator) {
+    BuiltInQProfileRepository builtInQProfileRepository, DefaultGroupCreator defaultGroupCreator) {
     this.dbClient = dbClient;
     this.system2 = system2;
     this.uuidFactory = uuidFactory;
@@ -95,8 +95,7 @@ public class OrganizationCreationImpl implements OrganizationCreation {
       throw new KeyConflictException(format("Organization key '%s' is already used", key));
     }
 
-    OrganizationDto organization = insertOrganization(dbSession, newOrganization, dto -> {
-    });
+    OrganizationDto organization = insertOrganization(dbSession, newOrganization);
     insertOrganizationMember(dbSession, organization, userCreator.getId());
     GroupDto ownerGroup = insertOwnersGroup(dbSession, organization);
     GroupDto defaultGroup = defaultGroupCreator.create(dbSession, organization.getUuid());
@@ -180,15 +179,16 @@ public class OrganizationCreationImpl implements OrganizationCreation {
     organizationValidation.checkAvatar(newOrganization.getAvatar());
   }
 
-  private OrganizationDto insertOrganization(DbSession dbSession, NewOrganization newOrganization, Consumer<OrganizationDto> extendCreation) {
+  private OrganizationDto insertOrganization(DbSession dbSession, NewOrganization newOrganization, Consumer<OrganizationDto>... extendCreation) {
     OrganizationDto res = new OrganizationDto()
       .setUuid(uuidFactory.create())
       .setName(newOrganization.getName())
       .setKey(newOrganization.getKey())
       .setDescription(newOrganization.getDescription())
       .setUrl(newOrganization.getUrl())
+      // TODO .setDefaultQualityGateUuid("" + qualityGateFinder.getBuiltInQualityGate(dbSession).getId())
       .setAvatarUrl(newOrganization.getAvatar());
-    extendCreation.accept(res);
+    Arrays.stream(extendCreation).forEach(c -> c.accept(res));
     dbClient.organizationDao().insert(dbSession, res, false);
     return res;
   }
index b6b3ad0d8d1bfabb106cdf601006690232b8e9cd..8897b72e1c9f69d92a96b4de6a34fe600113ef28 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.db.DbSession;
 import org.sonar.db.property.PropertyDto;
 import org.sonar.db.qualitygate.QualityGateDto;
 
+import static com.google.common.base.Preconditions.checkState;
 import static org.sonar.server.qualitygate.QualityGates.SONAR_QUALITYGATE_PROPERTY;
 import static org.sonar.server.ws.WsUtils.checkFound;
 
@@ -83,6 +84,12 @@ public class QualityGateFinder {
     }
   }
 
+  public QualityGateDto getBuiltInQualityGate(DbSession dbSession) {
+    QualityGateDto builtIn = dbClient.qualityGateDao().selectBuiltIn(dbSession);
+    checkState(builtIn != null, "Builtin quality gate is missing.");
+    return builtIn;
+  }
+
   private Optional<Long> getDefaultId(DbSession dbSession) {
     PropertyDto defaultQualityGateId = dbClient.propertiesDao().selectGlobalProperty(dbSession, SONAR_QUALITYGATE_PROPERTY);
 
index 675444ac1ef6b42999df4df4ee938478f1049596..bb7c05a1df57d9d47b1818fe3129bcac90b1547e 100644 (file)
@@ -52,6 +52,7 @@ import org.sonar.db.user.UserMembershipDto;
 import org.sonar.db.user.UserMembershipQuery;
 import org.sonar.server.es.EsTester;
 import org.sonar.server.es.SearchOptions;
+import org.sonar.server.qualitygate.QualityGateFinder;
 import org.sonar.server.qualityprofile.BuiltInQProfile;
 import org.sonar.server.qualityprofile.BuiltInQProfileRepositoryRule;
 import org.sonar.server.qualityprofile.QProfileName;
index 27d6d23da30a093dc6f54bc10be4540222f48f77..cbb59f48c18021139add5d71246b31af6254a65f 100644 (file)
@@ -5,6 +5,7 @@
                  name="org1_name"
                  guarded="[false]"
                  new_project_private="[false]"
+                 default_quality_gate_uuid="1"
                  created_at="1000"
                  updated_at="2000"/>
 
index 95d3148acb3df7c721d03a48f336222fad04ac37..be57e6c9b98d4792dabbfc62c88b4e954bcea24b 100644 (file)
@@ -5,6 +5,7 @@
                  name="org1_name"
                  guarded="[false]"
                  new_project_private="[false]"
+                 default_quality_gate_uuid="1"
                  created_at="1000"
                  updated_at="2000"/>
 
index c189d2270fa3f47345b38e078d5647b5b4163aa8..71ce93166c6e114b64e77046d58eeed4a9c795e7 100644 (file)
@@ -5,6 +5,7 @@
                  name="org1_name"
                  guarded="[false]"
                  new_project_private="[false]"
+                 default_quality_gate_uuid="1"
                  created_at="1000"
                  updated_at="2000"/>