]> source.dussan.org Git - sonarqube.git/commitdiff
MMF-1074 Read 'sonar.quality' setting and update default organization
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 18 Dec 2017 13:38:55 +0000 (14:38 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 18 Dec 2017 14:46:25 +0000 (15:46 +0100)
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/DbVersion70.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrg.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/java/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrgTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrgTest/initial.sql [new file with mode: 0644]

index 7d355c5753c7cdaa9cbdef88536cb064eb8d98a0..a389efd97090a9971daf7e477704aff96bc366b6 100644 (file)
@@ -47,8 +47,9 @@ public class DbVersion70 implements DbVersion {
       .add(1917, "Populate ORG_QUALITY_GATES table", PopulateOrgQualityGates.class)
       .add(1918, "Populate default quality gate on organization", PopulateDefaultQualityGate.class)
       .add(1919, "Associate existing quality gates to default organization", AssociateQualityGatesToDefaultOrganization.class)
-      .add(1920, "Delete 'sonar.qualitygate' setting at global level", DeleteGlobalSonarQualityGateSetting.class)
-      .add(1921, "Make ORGANIZATIONS.DEFAULT_QUALITY_GATE_UUID not nullable", SetDefaultQualityGateUuidAsNotNullableInOrganizations.class)
+      .add(1920, "Read 'sonar.qualitygate' setting and set the value to default organization", ReadGlobalSonarQualityGateSettingToDefaultOrg.class)
+      .add(1921, "Delete 'sonar.qualitygate' setting at global level", DeleteGlobalSonarQualityGateSetting.class)
+      .add(1922, "Make ORGANIZATIONS.DEFAULT_QUALITY_GATE_UUID not nullable", SetDefaultQualityGateUuidAsNotNullableInOrganizations.class)
     ;
   }
 }
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrg.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrg.java
new file mode 100644 (file)
index 0000000..849a089
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 javax.annotation.CheckForNull;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.Long.parseLong;
+
+public class ReadGlobalSonarQualityGateSettingToDefaultOrg extends DataChange {
+
+  private static final Logger LOGGER = Loggers.get(ReadGlobalSonarQualityGateSettingToDefaultOrg.class);
+  private final System2 system2;
+
+  public ReadGlobalSonarQualityGateSettingToDefaultOrg(Database db, System2 system2) {
+    super(db);
+    this.system2 = system2;
+  }
+
+  @Override
+  protected void execute(Context context) throws SQLException {
+    String defaultOrgUuid = getDefaultOrgUuid(context);
+    String defaultQualityGate = getDefaultQualityGate(context);
+    if (defaultQualityGate == null) {
+      LOGGER.info("No default quality gate set");
+      return;
+    }
+
+    MassUpdate massUpdate = context.prepareMassUpdate();
+    massUpdate.select("select uuid from quality_gates where id=?")
+      .setLong(1, parseLong(defaultQualityGate));
+    massUpdate.update("update organizations set default_quality_gate_uuid = ?, updated_at = ? where uuid=?");
+    massUpdate.execute((row, update) -> {
+      update.setString(1, row.getString(1));
+      update.setLong(2, system2.now());
+      update.setString(3, defaultOrgUuid);
+      return true;
+    });
+  }
+
+  private static String getDefaultOrgUuid(Context context) throws SQLException {
+    String defaultOrgUuid = context.prepareSelect("select text_value from internal_properties where kee = 'organization.default'")
+      .get(row -> row.getString(1));
+    checkState(defaultOrgUuid != null, "Default organization uuid is missing");
+    return defaultOrgUuid;
+  }
+
+  @CheckForNull
+  private static String getDefaultQualityGate(Context context) throws SQLException {
+    return context.prepareSelect("select text_value from properties where prop_key=? and resource_id is null")
+      .setString(1, "sonar.qualitygate")
+      .get(row -> row.getNullableString(1));
+  }
+}
index 5fd33f8206a31f86c0c8bc6834ee1851ce7bc8a4..010a5befb63bcf4f73f38f4b4ab685ffb56f75f5 100644 (file)
@@ -35,7 +35,7 @@ public class DbVersion70Test {
 
   @Test
   public void verify_migration_count() {
-    verifyMigrationCount(underTest, 22);
+    verifyMigrationCount(underTest, 23);
   }
 
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrgTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrgTest.java
new file mode 100644 (file)
index 0000000..7776c3b
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * 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.util.Date;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.assertj.core.groups.Tuple;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+
+public class ReadGlobalSonarQualityGateSettingToDefaultOrgTest {
+
+  private static final long PAST = 10_000_000_000L;
+  private static final long NOW = 20_000_000_000L;
+
+  private System2 system2 = new TestSystem2().setNow(NOW);
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(ReadGlobalSonarQualityGateSettingToDefaultOrgTest.class, "initial.sql");
+
+  private DataChange underTest = new ReadGlobalSonarQualityGateSettingToDefaultOrg(db.database(), system2);
+
+  @Test
+  public void read_sonar_quality_gate_setting_and_update_default_organization() throws SQLException {
+    String defaultQualityGate = insertQualityGate();
+    String otherQualityGate = insertQualityGate();
+    String defaultOrganization = insertOrganization(otherQualityGate);
+    String otherOrganization = insertOrganization(otherQualityGate);
+    insertDefaultOrgProperty(defaultOrganization);
+    insertSetting("sonar.qualitygate", selectQualityGateId(defaultQualityGate));
+
+    underTest.execute();
+
+    assertDefaultQualityGate(defaultOrganization, tuple(defaultQualityGate, NOW));
+  }
+
+  @Test
+  public void does_nothing_when_no_default_quality_gate_setting() throws Exception {
+    String defaultQualityGate = insertQualityGate();
+    String defaultOrganization = insertOrganization(defaultQualityGate);
+    insertDefaultOrgProperty(defaultOrganization);
+    insertQualityGate();
+
+    underTest.execute();
+
+    assertDefaultQualityGate(defaultOrganization, tuple(defaultQualityGate, PAST));
+  }
+
+  @Test
+  public void migration_is_reentrant() throws Exception {
+    String defaultOrganization = insertOrganization(null);
+    insertDefaultOrgProperty(defaultOrganization);
+    String qualityGate = insertQualityGate();
+    insertSetting("sonar.qualitygate", selectQualityGateId(qualityGate));
+
+    underTest.execute();
+    assertDefaultQualityGate(defaultOrganization, tuple(qualityGate, NOW));
+
+    underTest.execute();
+    assertDefaultQualityGate(defaultOrganization, tuple(qualityGate, NOW));
+  }
+
+  @Test
+  public void fail_when_no_default_organization() throws Exception {
+    String qualityGate = insertQualityGate();
+    insertSetting("sonar.qualitygate", selectQualityGateId(qualityGate));
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Default organization uuid is missing");
+
+    underTest.execute();
+  }
+
+  private void assertDefaultQualityGate(String uuid, Tuple... expectedTuples) {
+    assertThat(db.select(String.format("SELECT DEFAULT_QUALITY_GATE_UUID, UPDATED_AT FROM ORGANIZATIONS WHERE UUID='%s'", uuid))
+      .stream()
+      .map(map -> new Tuple(map.get("DEFAULT_QUALITY_GATE_UUID"), map.get("UPDATED_AT")))
+      .collect(Collectors.toList()))
+        .containsExactlyInAnyOrder(expectedTuples);
+  }
+
+  private long selectQualityGateId(String uuid){
+    return ((Long) db.selectFirst("select id as \"ID\" from quality_gates where uuid='" + uuid + "'").get("ID")).intValue();
+  }
+
+  private String insertOrganization(@Nullable String defaultQualityGateUuid) {
+    String uuid = Uuids.createFast();
+    db.executeInsert(
+      "organizations",
+      "UUID", uuid,
+      "KEE", uuid,
+      "NAME", uuid,
+      "GUARDED", String.valueOf(false),
+      "NEW_PROJECT_PRIVATE", String.valueOf(true),
+      "DEFAULT_QUALITY_GATE_UUID", defaultQualityGateUuid,
+      "CREATED_AT", PAST,
+      "UPDATED_AT", PAST);
+    return uuid;
+  }
+
+  private void insertDefaultOrgProperty(String uuid) {
+    db.executeInsert(
+      "internal_properties",
+      "KEE", "organization.default",
+      "IS_EMPTY", String.valueOf(false),
+      "TEXT_VALUE", uuid,
+      "CREATED_AT", PAST);
+  }
+
+  private String insertQualityGate() {
+    String uuid = Uuids.createFast();
+    db.executeInsert(
+      "quality_gates",
+      "UUID", uuid,
+      "NAME", uuid,
+      "IS_BUILT_IN", String.valueOf(false),
+      "CREATED_AT", new Date(PAST),
+      "UPDATED_AT", new Date(PAST));
+    return uuid;
+  }
+
+  private void insertSetting(String key, Long value) {
+    db.executeInsert(
+      "properties",
+      "PROP_KEY", key,
+      "TEXT_VALUE", value,
+      "IS_EMPTY", false,
+      "CREATED_AT", PAST);
+  }
+
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrgTest/initial.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/ReadGlobalSonarQualityGateSettingToDefaultOrgTest/initial.sql
new file mode 100644 (file)
index 0000000..a9959d1
--- /dev/null
@@ -0,0 +1,58 @@
+CREATE TABLE "PROPERTIES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PROP_KEY" VARCHAR(512) NOT NULL,
+  "RESOURCE_ID" INTEGER,
+  "USER_ID" INTEGER,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB,
+  "CREATED_AT" BIGINT
+);
+CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
+
+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,
+  "DEFAULT_QUALITY_GATE_UUID" VARCHAR(40),
+  "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");
+
+CREATE TABLE "QUALITY_GATES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(40) NOT NULL,
+  "NAME" VARCHAR(100) NOT NULL,
+  "IS_BUILT_IN" BOOLEAN NOT NULL,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+);
+CREATE UNIQUE INDEX "UNIQ_QUALITY_GATES_UUID" ON "QUALITY_GATES" ("UUID");
+
+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 "INTERNAL_PROPERTIES" (
+  "KEE" VARCHAR(20) NOT NULL PRIMARY KEY,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB,
+  "CREATED_AT" BIGINT
+);
+CREATE UNIQUE INDEX "UNIQ_INTERNAL_PROPERTIES" ON "INTERNAL_PROPERTIES" ("KEE");
+