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 QUALITY_GATES(ID, UUID, NAME, IS_BUILT_IN, CREATED_AT, UPDATED_AT) VALUES (1, 'AWASGWAKYOI_InFKS3UF', 'Sonar Way', true, '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
+INSERT INTO QUALITY_GATES(ID, UUID, NAME, IS_BUILT_IN, CREATED_AT, UPDATED_AT) VALUES (1, 'AWASGWAKYOI_InFKS3UF', '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, 'AWASGWAKYOI_InFKS3UF', '1474962596482', '1474962596482');
+INSERT INTO ORG_QUALITY_GATES (UUID, ORGANIZATION_UUID, QUALITY_GATE_UUID) VALUES ('AWAwlGzz-5zzlJtFU9G5', 'AVdqnciQUUs7Zd3KPvFD', 'AWASGWAKYOI_InFKS3UF');
-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');
.setName(organizationDto.getName())
.setDescription(organizationDto.getDescription())
.setUrl(organizationDto.getUrl())
- // TODO : .setDefaultQualityGateUuid(dbClient.qualityGateDao().selectBuiltIn(dbSession).getId().toString())
+ .setDefaultQualityGateUuid(organizationDto.getDefaultQualityGateUuid())
.setAvatarUrl(organizationDto.getAvatarUrl());
}
package org.sonar.db.qualitygate;
import java.util.Arrays;
+import java.util.Date;
import java.util.function.Consumer;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
return insertQualityGate(qualityGate -> qualityGate.setName(name));
}
+ public QualityGateDto insertBuiltInQualityGate() {
+ QualityGateDto builtin = dbClient.qualityGateDao().insert(dbSession, new QualityGateDto()
+ .setName("Sonar way")
+ .setUuid(Uuids.createFast())
+ .setBuiltIn(true)
+ .setCreatedAt(new Date()));
+ dbSession.commit();
+ return builtin;
+ }
+
@SafeVarargs
public final QualityGateDto insertQualityGate(Consumer<QualityGateDto>... dtoPopulators) {
return insertQualityGate(db.getDefaultOrganization(), dtoPopulators);
--- /dev/null
+/*
+ * 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.core.util.UuidFactory;
+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;
+
+public class AssociateQualityGatesToDefaultOrganization extends DataChange {
+
+ private final UuidFactory uuidFactory;
+
+ public AssociateQualityGatesToDefaultOrganization(Database db, UuidFactory uuidFactory) {
+ super(db);
+ this.uuidFactory = uuidFactory;
+ }
+
+ @Override
+ protected void execute(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");
+
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("SELECT qg.uuid from quality_gates qg " +
+ " WHERE qg.is_built_in = ? " +
+ " AND NOT EXISTS (SELECT 1 FROM org_quality_gates oqg WHERE oqg.quality_gate_uuid = qg.uuid AND oqg.organization_uuid = ?)")
+ .setBoolean(1, false)
+ .setString(2, defaultOrgUuid);
+ massUpdate.rowPluralName("quality gates");
+ massUpdate.update("insert into org_quality_gates (uuid, quality_gate_uuid, organization_uuid) values(?, ?, ?)");
+ massUpdate.execute((row, update) -> {
+ update.setString(1, uuidFactory.create());
+ update.setString(2, row.getString(1));
+ update.setString(3, defaultOrgUuid);
+ return true;
+ });
+ }
+}
--- /dev/null
+/*
+ * 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.core.util.UuidFactory;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+public class CreateBuiltInQualityGate extends DataChange {
+
+ private static final String SONAR_WAY_QUALITY_GATE = "Sonar way";
+
+ private final System2 system2;
+ private final UuidFactory uuidFactory;
+
+ public CreateBuiltInQualityGate(Database db, System2 system2, UuidFactory uuidFactory) {
+ super(db);
+ this.system2 = system2;
+ this.uuidFactory = uuidFactory;
+ }
+
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ Long nbOfBuiltInQualityGates = context.prepareSelect("select count(uuid) from quality_gates where is_built_in = ?")
+ .setBoolean(1, true)
+ .get(row -> row.getLong(1));
+
+
+ if (nbOfBuiltInQualityGates == 0) {
+ final Date now = new Date(system2.now());
+
+ context.prepareUpsert("insert into quality_gates (uuid, name, is_built_in, created_at) values (?,?,?,?)")
+ .setString(1, uuidFactory.create())
+ .setString(2, SONAR_WAY_QUALITY_GATE)
+ .setBoolean(3, true)
+ .setDate(4, now)
+ .execute()
+ .commit();
+ }
+ }
+}
.add(1913, "Populate QUALITY_GATES.UUID", PopulateUuidOnQualityGates.class)
.add(1914, "Make QUALITY_GATES.UUID not nullable", MakeUuidNotNullableOnQualityGates.class)
.add(1915, "Drop unique index on QUALITY_GATES.NAME", DropUniqueIndexOnQualityGatesName.class)
+ .add(1916, "Create builtin quality gate if required", CreateBuiltInQualityGate.class)
+ .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)
;
}
}
--- /dev/null
+/*
+ * 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.List;
+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 com.google.common.base.Preconditions.checkState;
+
+public class PopulateDefaultQualityGate extends DataChange {
+
+ private final System2 system2;
+
+ public PopulateDefaultQualityGate(Database db, System2 system2) {
+ super(db);
+ this.system2 = system2;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ List<String> builtInQGUuids = context.prepareSelect("select uuid from quality_gates where is_built_in = ?")
+ .setBoolean(1, true)
+ .list(row -> row.getString(1));
+
+ checkState(!builtInQGUuids.isEmpty(), "Unable to find the builtin quality gate");
+ checkState(builtInQGUuids.size() == 1, "There are too many built in quality gates, one and only one is expected");
+
+ final long now = system2.now();
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("select uuid from organizations " +
+ " where default_quality_gate_uuid is null");
+ massUpdate.rowPluralName("organizations");
+ massUpdate.update("update organizations set default_quality_gate_uuid = ?, updated_at=? where uuid = ?");
+ massUpdate.execute((row, update) -> {
+ update.setString(1, builtInQGUuids.get(0));
+ update.setLong(2, now);
+ update.setString(3, row.getString(1));
+ return true;
+ });
+
+ }
+}
--- /dev/null
+/*
+ * 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.List;
+import org.sonar.core.util.UuidFactory;
+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;
+
+public class PopulateOrgQualityGates extends DataChange {
+
+ private final UuidFactory uuidFactory;
+
+ public PopulateOrgQualityGates(Database db, UuidFactory uuidFactory) {
+ super(db);
+ this.uuidFactory = uuidFactory;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ Long nbOfOrganizations = context.prepareSelect("select count(uuid) from organizations")
+ .get(row -> row.getLong(1));
+ if (nbOfOrganizations == 0) {
+ // No need for a migration
+ return;
+ }
+
+ List<String> builtInQGUuids = context.prepareSelect("select uuid from quality_gates where is_built_in = ?")
+ .setBoolean(1, true)
+ .list(row -> row.getString(1));
+
+ checkState(!builtInQGUuids.isEmpty(), "Unable to find the builtin quality gate");
+ checkState(builtInQGUuids.size() == 1, "There are too many built in quality gates, one and only one is expected");
+
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("select uuid from organizations o " +
+ " where " +
+ " not exists (select 1 from org_quality_gates oqg where oqg.quality_gate_uuid = ? and oqg.organization_uuid = o.uuid)")
+ .setString(1, builtInQGUuids.get(0));
+
+ massUpdate.rowPluralName("organizations");
+ massUpdate.update("insert into org_quality_gates (uuid, quality_gate_uuid, organization_uuid) values(?, ?, ?)");
+ massUpdate.execute((row, update) -> {
+ update.setString(1, uuidFactory.create());
+ update.setString(2, builtInQGUuids.get(0));
+ update.setString(3, row.getString(1));
+ return true;
+ });
+ }
+}
--- /dev/null
+/*
+ * 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.List;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+
+public class AssociateQualityGatesToDefaultOrganizationTest {
+ private static final long PAST = 10_000_000_000L;
+ private static final String TABLE_ORGANIZATIONS = "organizations";
+ private static final String TABLE_QUALITY_GATES = "quality_gates";
+ private static final String TABLE_INTERNAL_PROPERTIES = "internal_properties";
+ private static final String DEFAULT_ORGANIZATION_KEE = "organization.default";
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(AssociateQualityGatesToDefaultOrganizationTest.class, "org_quality_gates.sql");
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private final UuidFactory uuidFactory = UuidFactoryFast.getInstance();
+
+ private AssociateQualityGatesToDefaultOrganization underTest = new AssociateQualityGatesToDefaultOrganization(db.database(), uuidFactory);
+
+ @Test
+ public void should_throw_ISE_if_no_default_organization() throws SQLException {
+ insertOrganization(uuidFactory.create());
+ insertOrganization(uuidFactory.create());
+ insertQualityGate(uuidFactory.create(), "QualityGate1", false);
+ insertQualityGate(uuidFactory.create(), "QualityGate2", true);
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Default organization uuid is missing");
+
+ underTest.execute();
+ }
+
+ @Test
+ public void should_associate_all_quality_gates_to_default_organization() throws SQLException {
+ String defaultOrgUuid = uuidFactory.create();
+ String anotherOrgUuid = uuidFactory.create();
+ insertOrganization(defaultOrgUuid);
+ insertOrganization(anotherOrgUuid);
+
+ String qgUuid1 = uuidFactory.create();
+ String qgUuid2 = uuidFactory.create();
+ String qgUuid3 = uuidFactory.create();
+ insertQualityGate(qgUuid1, "QualityGate1", false);
+ insertQualityGate(qgUuid2, "QualityGate2", false);
+ insertQualityGate(qgUuid3, "QualityGate3", true);
+
+ insertDefaultOrgProperty(defaultOrgUuid);
+
+ underTest.execute();
+
+ assertThat(selectAllOrgQualityGates())
+ .extracting(map -> map.get("ORGANIZATION_UUID"), map -> map.get("QUALITY_GATE_UUID"))
+ .containsExactlyInAnyOrder(
+ tuple(defaultOrgUuid, qgUuid1),
+ tuple(defaultOrgUuid, qgUuid2)
+ );
+ }
+
+ @Test
+ public void is_reentrant() throws SQLException {
+ String orgUuid1 = uuidFactory.create();
+ String orgUuid2 = uuidFactory.create();
+ insertOrganization(orgUuid1);
+ insertOrganization(orgUuid2);
+
+ String qgUuid1 = uuidFactory.create();
+ String qgUuid2 = uuidFactory.create();
+ String qgUuid3 = uuidFactory.create();
+ insertQualityGate(qgUuid1, "QualityGate1", false);
+ insertQualityGate(qgUuid2, "QualityGate2", false);
+ insertQualityGate(qgUuid3, "QualityGate3", true);
+
+ insertDefaultOrgProperty(orgUuid1);
+
+ underTest.execute();
+ underTest.execute();
+
+ assertThat(selectAllOrgQualityGates())
+ .extracting(map -> map.get("ORGANIZATION_UUID"), map -> map.get("QUALITY_GATE_UUID"))
+ .containsExactlyInAnyOrder(
+ tuple(orgUuid1, qgUuid1),
+ tuple(orgUuid1, qgUuid2)
+ );
+ }
+
+ private List<Map<String, Object>> selectAllOrgQualityGates() {
+ return db.select("select organization_uuid, quality_gate_uuid from org_quality_gates");
+ }
+
+ private void insertDefaultOrgProperty(String uuid) {
+ db.executeInsert(
+ TABLE_INTERNAL_PROPERTIES,
+ "KEE", DEFAULT_ORGANIZATION_KEE,
+ "IS_EMPTY", String.valueOf(false),
+ "TEXT_VALUE", uuid,
+ "CREATED_AT", PAST);
+ }
+
+ private void insertOrganization(String uuid) {
+ db.executeInsert(
+ TABLE_ORGANIZATIONS,
+ "UUID", uuid,
+ "KEE", uuid,
+ "NAME", uuid,
+ "GUARDED", String.valueOf(false),
+ "NEW_PROJECT_PRIVATE", String.valueOf(true),
+ "CREATED_AT", PAST,
+ "UPDATED_AT", PAST);
+ }
+
+ private void insertQualityGate(String uuid, String name, Boolean builtIn) {
+ db.executeInsert(
+ TABLE_QUALITY_GATES,
+ "UUID", uuid,
+ "NAME", name,
+ "IS_BUILT_IN", builtIn.toString(),
+ "CREATED_AT", new Date(PAST),
+ "UPDATED_AT", new Date(PAST));
+ }
+}
--- /dev/null
+/*
+ * 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.List;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+
+public class CreateBuiltInQualityGateTest {
+ private final static long PAST = 10_000_000_000L;
+ private final static long NOW = 50_000_000_000L;
+
+ private System2 system2 = new TestSystem2().setNow(NOW);
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(CreateBuiltInQualityGateTest.class, "quality_gates.sql");
+
+ private CreateBuiltInQualityGate underTest = new CreateBuiltInQualityGate(db.database(), system2, UuidFactoryFast.getInstance());
+
+ @Test
+ public void should_create_builtin_quality_gate() throws SQLException {
+ underTest.execute();
+
+ assertThat(selectAllQualityGates())
+ .extracting(map -> map.get("NAME"), map -> map.get("IS_BUILT_IN"), map -> map.get("CREATED_AT"))
+ .containsExactlyInAnyOrder(
+ tuple("Sonar way", true, new Date(NOW))
+ );
+ }
+
+ @Test
+ public void should_not_create_builtin_quality_gate_if_existing() throws SQLException {
+ insertQualityGate("Whatever", true);
+
+ underTest.execute();
+
+ assertThat(selectAllQualityGates())
+ .extracting(map -> map.get("NAME"), map -> map.get("IS_BUILT_IN"), map -> map.get("CREATED_AT"))
+ .containsExactlyInAnyOrder(
+ tuple("Whatever", true, new Date(PAST))
+ );
+ }
+
+
+ private List<Map<String, Object>> selectAllQualityGates() {
+ return db.select("select id, uuid, name, is_built_in, created_at, updated_at from quality_gates");
+ }
+
+ private void insertQualityGate(String name, boolean builtIn) {
+ db.executeInsert(
+ "QUALITY_GATES",
+ "UUID", Uuids.createFast(),
+ "NAME", name,
+ "IS_BUILT_IN", String.valueOf(builtIn),
+ "CREATED_AT", new Date(PAST),
+ "UPDATED_AT", new Date(PAST));
+ }
+}
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 16);
+ verifyMigrationCount(underTest, 20);
}
}
--- /dev/null
+/*
+ * 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.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 static org.assertj.core.api.Assertions.assertThat;
+
+public class PopulateDefaultQualityGateTest {
+ private final static long PAST = 10_000_000_000L;
+ private static final long NOW = 50_000_000_000L;
+ private static final String TABLE_ORGANIZATIONS = "organizations";
+ private static final String TABLE_QUALITY_GATES = "quality_gates";
+
+ private System2 system2 = new TestSystem2().setNow(NOW);
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(PopulateDefaultQualityGateTest.class, "organizations.sql");
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private PopulateDefaultQualityGate underTest = new PopulateDefaultQualityGate(db.database(), system2);
+
+
+ @Test
+ public void has_no_effect_if_table_is_empty() throws SQLException {
+ insertQualityGate(Uuids.createFast(), "Sonar way", true);
+
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable("organizations")).isEqualTo(0);
+ }
+
+ @Test
+ public void should_populate_defaultQualityGate_column() throws SQLException {
+ String builtInQGUuid = Uuids.createFast();
+ insertQualityGate(builtInQGUuid, "Sonar way", true);
+ String orgUuid1 = Uuids.createFast();
+ String orgUuid2 = Uuids.createFast();
+ insertOrganization(orgUuid1);
+ insertOrganization(orgUuid2);
+
+ underTest.execute();
+
+ // all organizations have the builtIn quality gate
+ assertThat(
+ db.countSql("select count(uuid) from organizations where default_quality_gate_uuid != '" + builtInQGUuid + "'")
+ ).isEqualTo(0);
+ assertThat(
+ db.countSql("select count(uuid) from organizations where default_quality_gate_uuid = '" + builtInQGUuid + "'")
+ ).isEqualTo(2);
+
+ // updated_at must have been updated
+ assertThat(
+ db.countSql("select count(uuid) from organizations where updated_at = " + NOW )
+ ).isEqualTo(2);
+ }
+
+ @Test
+ public void is_reentrant() throws SQLException {
+ String builtInQGUuid = Uuids.createFast();
+ insertQualityGate(builtInQGUuid, "Sonar way", true);
+ insertOrganization(Uuids.createFast());
+ insertOrganization(Uuids.createFast());
+
+ underTest.execute();
+ underTest.execute();
+
+ assertThat(
+ db.countSql("select count(uuid) from organizations where default_quality_gate_uuid != '" + builtInQGUuid + "'")
+ ).isEqualTo(0);
+
+ assertThat(
+ db.countSql("select count(uuid) from organizations where default_quality_gate_uuid = '" + builtInQGUuid + "'")
+ ).isEqualTo(2);
+ }
+
+ @Test
+ public void should_fail_with_ISE_when_no_builtIn() throws SQLException {
+ insertOrganization(Uuids.createFast());
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Unable to find the builtin quality gate");
+
+ underTest.execute();
+ }
+
+ @Test
+ public void should_fail_if_there_is_multiple_builtin_qualitygates() throws SQLException {
+ insertQualityGate(Uuids.createFast(), "Sonar way", true);
+ insertQualityGate(Uuids.createFast(), "Sonar way2", true);
+ insertOrganization(Uuids.createFast());
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("There are too many built in quality gates, one and only one is expected");
+
+ underTest.execute();
+ }
+
+ private void insertOrganization(String uuid) {
+ db.executeInsert(
+ TABLE_ORGANIZATIONS,
+ "UUID", uuid,
+ "KEE", uuid,
+ "NAME", uuid,
+ "GUARDED", String.valueOf(false),
+ "NEW_PROJECT_PRIVATE", String.valueOf(true),
+ "CREATED_AT", "1000",
+ "UPDATED_AT", "1000");
+ }
+
+ private void insertQualityGate(String uuid, String name, Boolean builtIn) {
+ db.executeInsert(
+ TABLE_QUALITY_GATES,
+ "UUID", uuid,
+ "NAME", name,
+ "IS_BUILT_IN", builtIn.toString(),
+ "CREATED_AT", new Date(PAST),
+ "UPDATED_AT", new Date(PAST));
+ }
+}
--- /dev/null
+/*
+ * 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.List;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.groups.Tuple.tuple;
+
+public class PopulateOrgQualityGatesTest {
+
+ private static final long PAST = 10_000_000_000L;
+ private static final String TABLE_ORGANIZATIONS = "organizations";
+ private static final String TABLE_QUALITY_GATES = "quality_gates";
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(PopulateOrgQualityGates.class, "org_quality_gates.sql");
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private PopulateOrgQualityGates underTest = new PopulateOrgQualityGates(db.database(), UuidFactoryFast.getInstance());
+
+ @Test
+ public void has_no_effect_if_table_is_empty() throws SQLException {
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable("org_quality_gates")).isEqualTo(0);
+ }
+
+ @Test
+ public void should_associate_builtin_to_all_organizations() throws SQLException {
+ String orgUuid1 = Uuids.createFast();
+ String orgUuid2 = Uuids.createFast();
+ String qgUuid = Uuids.createFast();
+ insertOrganization(orgUuid1);
+ insertOrganization(orgUuid2);
+ insertQualityGate(qgUuid, "Sonar way", true);
+
+ underTest.execute();
+
+ assertThat(selectAllOrgQualityGates())
+ .extracting(map -> map.get("ORGANIZATION_UUID"), map -> map.get("QUALITY_GATE_UUID"))
+ .containsExactlyInAnyOrder(
+ tuple(orgUuid1, qgUuid),
+ tuple(orgUuid2, qgUuid));
+ }
+
+ @Test
+ public void is_reentrant() throws SQLException {
+ String orgUuid1 = Uuids.createFast();
+ String orgUuid2 = Uuids.createFast();
+ String qgUuid = Uuids.createFast();
+ insertOrganization(orgUuid1);
+ insertOrganization(orgUuid2);
+ insertQualityGate(qgUuid, "Sonar way", true);
+
+ underTest.execute();
+ underTest.execute();
+
+ assertThat(selectAllOrgQualityGates())
+ .extracting(map -> map.get("ORGANIZATION_UUID"), map -> map.get("QUALITY_GATE_UUID"))
+ .containsExactlyInAnyOrder(
+ tuple(orgUuid1, qgUuid),
+ tuple(orgUuid2, qgUuid));
+ }
+
+ @Test
+ public void should_fail_with_ISE_when_no_builtIn() throws SQLException {
+ insertOrganization(Uuids.createFast());
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Unable to find the builtin quality gate");
+
+ underTest.execute();
+ }
+
+ @Test
+ public void should_fail_if_there_are_two_builtin_qg() throws SQLException {
+ String orgUuid1 = Uuids.createFast();
+ String orgUuid2 = Uuids.createFast();
+ String qgUuid1 = Uuids.createFast();
+ String qgUuid2 = Uuids.createFast();
+ insertOrganization(orgUuid1);
+ insertOrganization(orgUuid2);
+ insertQualityGate(qgUuid1, "Sonar way", true);
+ insertQualityGate(qgUuid2, "Sonar way 2", true);
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("There are too many built in quality gates, one and only one is expected");
+
+ underTest.execute();
+ }
+
+ private List<Map<String, Object>> selectAllOrgQualityGates() {
+ return db.select("select organization_uuid, quality_gate_uuid from org_quality_gates");
+ }
+
+ private void insertOrganization(String uuid) {
+ db.executeInsert(
+ TABLE_ORGANIZATIONS,
+ "UUID", uuid,
+ "KEE", uuid,
+ "NAME", uuid,
+ "GUARDED", String.valueOf(false),
+ "NEW_PROJECT_PRIVATE", String.valueOf(true),
+ "CREATED_AT", "1000",
+ "UPDATED_AT", "1000");
+ }
+
+ private void insertQualityGate(String uuid, String name, Boolean builtIn) {
+ db.executeInsert(
+ TABLE_QUALITY_GATES,
+ "UUID", uuid,
+ "NAME", name,
+ "IS_BUILT_IN", builtIn.toString(),
+ "CREATED_AT", new Date(PAST),
+ "UPDATED_AT", new Date(PAST));
+ }
+}
--- /dev/null
+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 "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 "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 "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");
--- /dev/null
+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");
--- /dev/null
+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");
--- /dev/null
+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 "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 "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");