]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10089 Add a migration to rename old quality gates
authorEric Hartmann <hartmann.eric@gmail.com>
Fri, 24 Nov 2017 14:22:29 +0000 (15:22 +0100)
committerEric Hartmann <hartmann.eric@gmail.Com>
Mon, 4 Dec 2017 12:44:55 +0000 (13:44 +0100)
"SonarQube way" is renamed as "Sonar way (outdated copy)"

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/RenameOldSonarQubeWayQualityGate.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/RenameOldSonarQubeWayQualityGateTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/RenameOldSonarQubeWayQualityGateTest/quality_gates.sql [new file with mode: 0644]

index bde8d70a4b2e2a6872651841dc77910fe99c9bb0..7d8198577c5d073d0cac06ffbe54812bccaea359 100644 (file)
@@ -31,6 +31,7 @@ public class DbVersion70 implements DbVersion {
       .add(1901, "Populate QUALITY_GATES.IS_BUILT_IN", PopulateQualityGatesIsBuiltIn.class)
       .add(1902, "Make QUALITY_GATES.IS_BUILT_IN not null", MakeQualityGatesIsBuiltInNotNullable.class)
       .add(1903, "Remove quality gates loaded templates", RemoveQualityGateLoadedTemplates.class)
+      .add(1904, "Rename quality gate \"SonarQube way\" to \"Sonar way\"", RenameOldSonarQubeWayQualityGate.class)
     ;
   }
 
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/RenameOldSonarQubeWayQualityGate.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v70/RenameOldSonarQubeWayQualityGate.java
new file mode 100644 (file)
index 0000000..0a0a20b
--- /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 java.util.Date;
+import org.sonar.api.utils.System2;
+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 java.lang.String.format;
+
+public class RenameOldSonarQubeWayQualityGate extends DataChange {
+
+  private static final String SONARQUBE_WAY_QUALITY_GATE = "SonarQube way";
+  private static final String SONARQUBE_WAY_QUALITY_GATE_OUTDATED = "Sonar way (outdated copy)";
+  private final System2 system2;
+
+  public RenameOldSonarQubeWayQualityGate(Database db, System2 system2) {
+    super(db);
+    this.system2 = system2;
+  }
+
+  @Override
+  protected void execute(Context context) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate();
+    massUpdate.select("SELECT id FROM quality_gates WHERE name = ?")
+      .setString(1, SONARQUBE_WAY_QUALITY_GATE);
+    massUpdate.rowPluralName("quality gates");
+    massUpdate.update("UPDATE quality_gates SET name=?, is_built_in=?, updated_at=? WHERE id=?");
+    massUpdate.execute((row, update) -> {
+      update.setString(1, findNewQualityGateName(context));
+      update.setBoolean(2, false);
+      update.setDate(3, new Date(system2.now()));
+      update.setLong(4, row.getLong(1));
+      return true;
+    });
+  }
+
+  private String findNewQualityGateName(Context context) throws SQLException {
+    if (isQualityGateNameAvailable(context, SONARQUBE_WAY_QUALITY_GATE_OUTDATED)) {
+      return SONARQUBE_WAY_QUALITY_GATE_OUTDATED;
+    }
+
+    String newName = SONARQUBE_WAY_QUALITY_GATE_OUTDATED + " " + system2.now();
+    if (isQualityGateNameAvailable(context, newName)) {
+      return newName;
+    }
+
+    // Given up if no name available
+    throw new IllegalStateException(format("There are already two quality profiles with name [%s,%s]", SONARQUBE_WAY_QUALITY_GATE_OUTDATED, newName));
+  }
+
+  private static boolean isQualityGateNameAvailable(Context context, String qualityGateName) throws SQLException {
+    return context.prepareSelect(
+      "SELECT COUNT(id) FROM quality_gates WHERE name = '" + qualityGateName + "'")
+      .get(
+        row -> row.getInt(1) == 0);
+  }
+}
index 2c1870ebe961f00898fa2154bf9abc0690125ebc..7a3313ef31d40fe1ebeb2364f6b85b14e3e423bc 100644 (file)
@@ -35,7 +35,7 @@ public class DbVersion70Test {
 
   @Test
   public void verify_migration_count() {
-    verifyMigrationCount(underTest, 4);
+    verifyMigrationCount(underTest, 5);
   }
 
 }
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/RenameOldSonarQubeWayQualityGateTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v70/RenameOldSonarQubeWayQualityGateTest.java
new file mode 100644 (file)
index 0000000..55aba3d
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * 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 org.assertj.core.groups.Tuple;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+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.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+
+public class RenameOldSonarQubeWayQualityGateTest {
+
+  private final static long PAST = 10_000_000_000L;
+  private final static long NOW = 50_000_000_000L;
+
+  private final static String SONARQUBE_WAY_QUALITY_GATE = "SonarQube way";
+  private final static String SONAR_WAY_OUTDATED_QUALITY_GATE = "Sonar way (outdated copy)";
+  private final static String SONAR_WAY_QUALITY_GATE = "Sonar way";
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(PopulateQualityGatesIsBuiltInTest.class, "quality_gates.sql");
+
+  private System2 system2 = new TestSystem2().setNow(NOW);
+
+  private RenameOldSonarQubeWayQualityGate underTest = new RenameOldSonarQubeWayQualityGate(db.database(), system2);
+
+  @Test
+  public void has_no_effect_if_table_is_empty() throws SQLException {
+    underTest.execute();
+
+    assertThat(db.countRowsOfTable("quality_gates")).isEqualTo(0);
+  }
+
+  @Test
+  public void should_rename_SonarQubeWay_quality_gate() throws SQLException {
+    insertQualityGate(SONARQUBE_WAY_QUALITY_GATE, false);
+
+    underTest.execute();
+
+    assertQualityGates(
+      tuple(SONAR_WAY_OUTDATED_QUALITY_GATE, false, new Date(PAST), new Date(NOW))
+    );
+  }
+
+  @Test
+  public void should_set_builtin_to_false_when_renaming() throws SQLException {
+    insertQualityGate(SONARQUBE_WAY_QUALITY_GATE, true);
+
+    underTest.execute();
+
+    assertQualityGates(
+      tuple(SONAR_WAY_OUTDATED_QUALITY_GATE, false, new Date(PAST), new Date(NOW))
+    );
+  }
+
+  @Test
+  public void should_not_fail_if_a_profile_with_same_name_is_present() throws SQLException {
+    insertQualityGate(SONAR_WAY_OUTDATED_QUALITY_GATE, false);
+    insertQualityGate(SONARQUBE_WAY_QUALITY_GATE, false);
+
+    underTest.execute();
+
+    assertQualityGates(
+      tuple(SONAR_WAY_OUTDATED_QUALITY_GATE, false, new Date(PAST), new Date(PAST)),
+      tuple(SONAR_WAY_OUTDATED_QUALITY_GATE + " " + NOW, false, new Date(PAST), new Date(NOW))
+    );
+  }
+
+  @Test
+  public void should_throw_ISE_if_no_name_is_available() throws SQLException {
+    insertQualityGate(SONARQUBE_WAY_QUALITY_GATE, false);
+    insertQualityGate(SONAR_WAY_OUTDATED_QUALITY_GATE, false);
+    insertQualityGate(SONAR_WAY_OUTDATED_QUALITY_GATE + " " + system2.now(), false);
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Error during processing of row:");
+    expectedException.expectCause(
+      new CauseMatcher(
+        IllegalStateException.class,
+        "There are already two quality profiles with name [Sonar way (outdated copy),Sonar way (outdated copy) 50000000000]"));
+
+    underTest.execute();
+  }
+
+  @Test
+  public void should_update_only_SonarQubeWay() throws SQLException {
+    insertQualityGate("Whatever", true);
+    insertQualityGate("Whatever2", false);
+    insertQualityGate(SONAR_WAY_QUALITY_GATE, true);
+    insertQualityGate(SONARQUBE_WAY_QUALITY_GATE, false);
+
+    underTest.execute();
+
+    assertQualityGates(
+      tuple("Whatever", true, new Date(PAST), new Date(PAST)),
+      tuple("Whatever2", false, new Date(PAST), new Date(PAST)),
+      tuple(SONAR_WAY_QUALITY_GATE, true, new Date(PAST), new Date(PAST)),
+      tuple(SONAR_WAY_OUTDATED_QUALITY_GATE, false, new Date(PAST), new Date(NOW))
+    );
+  }
+
+  @Test
+  public void is_reentrant() throws SQLException {
+    insertQualityGate(SONARQUBE_WAY_QUALITY_GATE, false);
+
+    underTest.execute();
+    underTest.execute();
+
+    assertQualityGates(
+      tuple(SONAR_WAY_OUTDATED_QUALITY_GATE, false, new Date(PAST), new Date(NOW))
+    );
+  }
+
+  private void assertQualityGates(Tuple... expectedTuples) {
+    assertThat(db.select("SELECT NAME, IS_BUILT_IN, CREATED_AT, UPDATED_AT FROM QUALITY_GATES")
+      .stream()
+      .map(map -> new Tuple(map.get("NAME"), map.get("IS_BUILT_IN"), map.get("CREATED_AT"), map.get("UPDATED_AT")))
+      .collect(Collectors.toList()))
+      .containsExactlyInAnyOrder(expectedTuples);
+  }
+
+
+  private void insertQualityGate(String name, boolean builtIn) {
+    db.executeInsert(
+      "QUALITY_GATES",
+      "NAME", name,
+      "IS_BUILT_IN", String.valueOf(builtIn),
+      "CREATED_AT", new Date(PAST),
+      "UPDATED_AT", new Date(PAST));
+  }
+
+  private static class CauseMatcher extends TypeSafeMatcher<Throwable> {
+    private final Class<? extends Throwable> type;
+    private final String expectedMessage;
+
+    public CauseMatcher(Class<? extends Throwable> type, String expectedMessage) {
+      this.type = type;
+      this.expectedMessage = expectedMessage;
+    }
+
+    @Override
+    protected boolean matchesSafely(Throwable item) {
+      return item.getClass().isAssignableFrom(type)
+        && item.getMessage().contains(expectedMessage);
+    }
+
+    @Override
+    public void describeTo(Description description) {
+      description.appendText("expects type ")
+        .appendValue(type)
+        .appendText(" and a message ")
+        .appendValue(expectedMessage);
+    }
+  }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/RenameOldSonarQubeWayQualityGateTest/quality_gates.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v70/RenameOldSonarQubeWayQualityGateTest/quality_gates.sql
new file mode 100644 (file)
index 0000000..52b9423
--- /dev/null
@@ -0,0 +1,8 @@
+CREATE TABLE "QUALITY_GATES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "NAME" VARCHAR(100) NOT NULL,
+  "IS_BUILT_IN" BOOLEAN NULL,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+);
+CREATE UNIQUE INDEX "UNIQ_QUALITY_GATES" ON "QUALITY_GATES" ("NAME");