aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-db-migration
diff options
context:
space:
mode:
authorJacek <52388493+jacek-poreda-sonarsource@users.noreply.github.com>2019-07-31 15:03:39 +0200
committerSonarTech <sonartech@sonarsource.com>2019-07-31 20:21:14 +0200
commiteb9b15871391f10850b2c3ecdad13ef3ef19aaba (patch)
tree6dd32bfe46594f5a80a3332d9b672a7af27f3269 /server/sonar-db-migration
parent1771582bc9977760b66c8e6275f12e5357341746 (diff)
downloadsonarqube-eb9b15871391f10850b2c3ecdad13ef3ef19aaba.tar.gz
sonarqube-eb9b15871391f10850b2c3ecdad13ef3ef19aaba.zip
SONAR-8115 storing project quality gate in table (#1919)
* migrate properties to project_qgate table * use project_qgates table instead of property * change usage of project quality gate in CE
Diffstat (limited to 'server/sonar-db-migration')
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80.java3
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTable.java80
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80Test.java2
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTableTest.java131
-rw-r--r--server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTableTest/schema.sql77
5 files changed, 291 insertions, 2 deletions
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80.java
index a11fd4e4156..f3f4721ef6d 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80.java
@@ -28,6 +28,7 @@ public class DbVersion80 implements DbVersion {
registry
.add(3000, "Set Organizations#guarded column nullable", MakeOrganizationsGuardedNullable.class)
.add(3001, "Create ProjectQualityGates table", CreateProjectQualityGatesTable.class)
- .add(3002, "Make index on DEPRECATED_RULE_KEYS.RULE_ID non unique", MakeDeprecatedRuleKeysRuleIdIndexNonUnique.class);
+ .add(3002, "Make index on DEPRECATED_RULE_KEYS.RULE_ID non unique", MakeDeprecatedRuleKeysRuleIdIndexNonUnique.class)
+ .add(3003, "Populate ProjectQualityGate table from Properties table", PopulateProjectQualityGatesTable.class);
}
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTable.java
new file mode 100644
index 00000000000..ba0ed09cb67
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTable.java
@@ -0,0 +1,80 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.v80;
+
+import java.sql.SQLException;
+import java.util.List;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.Upsert;
+
+public class PopulateProjectQualityGatesTable extends DataChange {
+
+ public PopulateProjectQualityGatesTable(Database db) {
+ super(db);
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ List<ProjectQualityGate> projectQualityGates = context.prepareSelect(
+ "select prj.uuid, qg.uuid from properties p \n" +
+ "join projects prj on p.resource_id = prj.id\n" +
+ "join quality_gates qg on qg.id = CAST(p.text_value AS int)\n" +
+ "where p.prop_key = 'sonar.qualitygate'\n" +
+ "and not exists(select pqg.project_uuid from project_qgates pqg where pqg.project_uuid = prj.uuid)")
+ .list(row -> {
+ String projectUuid = row.getString(1);
+ String qualityGateUuid = row.getString(2);
+ return new ProjectQualityGate(projectUuid, qualityGateUuid);
+ });
+
+ if (!projectQualityGates.isEmpty()) {
+ populateProjectQualityGates(context, projectQualityGates);
+ }
+ }
+
+ private static void populateProjectQualityGates(Context context, List<ProjectQualityGate> projectQualityGates) throws SQLException {
+ Upsert insertQuery = prepareInsertProjectQualityGateQuery(context);
+ for (ProjectQualityGate projectQualityGate : projectQualityGates) {
+ insertQuery
+ .setString(1, projectQualityGate.projectUuid)
+ .setString(2, projectQualityGate.qualityGateUuid)
+ .addBatch();
+ }
+ insertQuery
+ .execute()
+ .commit();
+ }
+
+ private static Upsert prepareInsertProjectQualityGateQuery(Context context) throws SQLException {
+ return context.prepareUpsert("insert into project_qgates(project_uuid, quality_gate_uuid) VALUES (?, ?)");
+ }
+
+ private static class ProjectQualityGate {
+ private final String projectUuid;
+ private final String qualityGateUuid;
+
+ ProjectQualityGate(String projectUuid, String qualityGateUuid) {
+ this.projectUuid = projectUuid;
+ this.qualityGateUuid = qualityGateUuid;
+ }
+ }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80Test.java
index cefa4368acf..f69a48b5e7c 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80Test.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80Test.java
@@ -35,7 +35,7 @@ public class DbVersion80Test {
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 3);
+ verifyMigrationCount(underTest, 4);
}
}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTableTest.java
new file mode 100644
index 00000000000..4b7af24e2cc
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTableTest.java
@@ -0,0 +1,131 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.v80;
+
+import java.sql.SQLException;
+import java.time.Instant;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.db.CoreDbTester;
+
+import static java.lang.String.valueOf;
+
+
+public class PopulateProjectQualityGatesTableTest {
+ private static final String PROJECTS_TABLE_NAME = "projects";
+ private static final String QUALITY_GATES_TABLE_NAME = "quality_gates";
+ private static final String PROPERTIES_TABLE_NAME = "properties";
+ private static final int NUMBER_OF_PROJECTS_TO_INSERT = 5;
+
+ private final Random random = new Random();
+
+ @Rule
+ public CoreDbTester dbTester = CoreDbTester.createForSchema(PopulateProjectQualityGatesTableTest.class, "schema.sql");
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private PopulateProjectQualityGatesTable underTest = new PopulateProjectQualityGatesTable(dbTester.database());
+
+ @Test
+ public void copy_quality_gates_properties_to_project_qgate_table() throws SQLException {
+ long firstQualityGateId = insertQualityGate("qg1");
+ long secondQualityGateId = insertQualityGate("qg2");
+
+ for (long i = 1; i <= NUMBER_OF_PROJECTS_TO_INSERT; i++) {
+ long projectId = insertComponent("p" + i);
+ long qualityGateId = random.nextBoolean() ? firstQualityGateId : secondQualityGateId;
+ insertQualityGateProperty(projectId, qualityGateId);
+ }
+
+ underTest.execute();
+
+ List<ProjectQualityGate> qualityGates = getQualityGates();
+ Assert.assertEquals(NUMBER_OF_PROJECTS_TO_INSERT, qualityGates.size());
+
+ //must not delete properties
+ int propertiesCount = dbTester.countRowsOfTable(PROPERTIES_TABLE_NAME);
+ Assert.assertEquals(5, propertiesCount);
+
+ //should not fail if executed twice
+ underTest.execute();
+ }
+
+ private long insertQualityGate(String qualityGateUuid) {
+ dbTester.executeInsert(
+ QUALITY_GATES_TABLE_NAME,
+ "UUID", qualityGateUuid,
+ "NAME", "name_" + qualityGateUuid,
+ "IS_BUILT_IN", valueOf(true)
+ );
+ return (long) dbTester.selectFirst("select id as \"ID\" from quality_gates where uuid='" + qualityGateUuid + "'").get("ID");
+ }
+
+ private long insertComponent(String uuid) {
+ dbTester.executeInsert(
+ PROJECTS_TABLE_NAME,
+ "ORGANIZATION_UUID", "org_" + uuid,
+ "SCOPE", "PRJ",
+ "QUALIFIER", "TRK",
+ "UUID", uuid,
+ "UUID_PATH", "path_" + uuid,
+ "ROOT_UUID", "root_" + uuid,
+ "PROJECT_UUID", uuid,
+ "PRIVATE", valueOf(false));
+ return (long) dbTester.selectFirst("select id as \"ID\" from projects where uuid='" + uuid + "'").get("ID");
+ }
+
+ private void insertQualityGateProperty(Long projectId, Long qualityGateId) {
+ dbTester.executeInsert(PROPERTIES_TABLE_NAME,
+ "prop_key", "sonar.qualitygate",
+ "resource_id", projectId,
+ "is_empty", false,
+ "text_value", Long.toString(qualityGateId),
+ "created_at", Instant.now().toEpochMilli());
+ }
+
+ private List<ProjectQualityGate> getQualityGates() {
+ return dbTester.select("select pqg.project_uuid, pqg.quality_gate_uuid from project_qgates pqg " +
+ "join projects p on pqg.project_uuid = p.uuid " +
+ "join quality_gates qg on pqg.quality_gate_uuid = qg.uuid")
+ .stream()
+ .map(row -> {
+ String projectUuid = String.valueOf(row.get("PROJECT_UUID"));
+ String qualityGateUuid = String.valueOf(row.get("QUALITY_GATE_UUID"));
+ return new ProjectQualityGate(projectUuid, qualityGateUuid);
+ })
+ .collect(Collectors.toList());
+ }
+
+ private static class ProjectQualityGate {
+ final String projectUuid;
+ final String qualityGateUuid;
+
+ private ProjectQualityGate(String projectUuid, String qualityGateUuid) {
+ this.projectUuid = projectUuid;
+ this.qualityGateUuid = qualityGateUuid;
+ }
+ }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTableTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTableTest/schema.sql
new file mode 100644
index 00000000000..d4dceda5613
--- /dev/null
+++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v80/PopulateProjectQualityGatesTableTest/schema.sql
@@ -0,0 +1,77 @@
+CREATE TABLE "PROJECTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+ "KEE" VARCHAR(400),
+ "UUID" VARCHAR(50) NOT NULL,
+ "UUID_PATH" VARCHAR(1500) NOT NULL,
+ "ROOT_UUID" VARCHAR(50) NOT NULL,
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "MODULE_UUID" VARCHAR(50),
+ "MODULE_UUID_PATH" VARCHAR(1500),
+ "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
+ "NAME" VARCHAR(2000),
+ "DESCRIPTION" VARCHAR(2000),
+ "PRIVATE" BOOLEAN NOT NULL,
+ "TAGS" VARCHAR(500),
+ "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+ "SCOPE" VARCHAR(3),
+ "QUALIFIER" VARCHAR(10),
+ "DEPRECATED_KEE" VARCHAR(400),
+ "PATH" VARCHAR(2000),
+ "LANGUAGE" VARCHAR(20),
+ "COPY_COMPONENT_UUID" VARCHAR(50),
+ "LONG_NAME" VARCHAR(2000),
+ "DEVELOPER_UUID" VARCHAR(50),
+ "CREATED_AT" TIMESTAMP,
+ "AUTHORIZATION_UPDATED_AT" BIGINT,
+ "B_CHANGED" BOOLEAN,
+ "B_COPY_COMPONENT_UUID" VARCHAR(50),
+ "B_DESCRIPTION" VARCHAR(2000),
+ "B_ENABLED" BOOLEAN,
+ "B_UUID_PATH" VARCHAR(1500),
+ "B_LANGUAGE" VARCHAR(20),
+ "B_LONG_NAME" VARCHAR(500),
+ "B_MODULE_UUID" VARCHAR(50),
+ "B_MODULE_UUID_PATH" VARCHAR(1500),
+ "B_NAME" VARCHAR(500),
+ "B_PATH" VARCHAR(2000),
+ "B_QUALIFIER" VARCHAR(10)
+);
+CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID");
+CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
+CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
+CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
+CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
+CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
+CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
+
+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 "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 "PROJECT_QGATES" (
+"PROJECT_UUID" VARCHAR(40) NOT NULL,
+"QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
+
+CONSTRAINT "PK_PROJECT_QGATES" PRIMARY KEY ("PROJECT_UUID")
+);
+CREATE UNIQUE INDEX "UNIQ_PROJECT_QGATES" ON "PROJECT_QGATES" ("PROJECT_UUID", "QUALITY_GATE_UUID");