aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl8
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java24
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java12
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java4
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java2
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml42
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml9
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java83
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java14
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDbTester.java8
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/CreateProjectQualityGatesTable.java79
-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/test/java/org/sonar/server/platform/db/migration/version/v80/CreateProjectQualityGatesTableTest.java55
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/DbVersion80Test.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java14
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java1
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java13
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java36
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DestroyActionTest.java5
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java53
21 files changed, 427 insertions, 44 deletions
diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
index b4553e23eaa..af7c91f6c75 100644
--- a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
+++ b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
@@ -313,6 +313,14 @@ CREATE TABLE "ORG_QUALITY_GATES" (
);
CREATE UNIQUE INDEX "UNIQ_ORG_QUALITY_GATES" ON "ORG_QUALITY_GATES" ("ORGANIZATION_UUID","QUALITY_GATE_UUID");
+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");
+
CREATE TABLE "PROPERTIES" (
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"PROP_KEY" VARCHAR(512) NOT NULL,
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java
index 1cd23ae5d46..9e9152935fe 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java
@@ -40,8 +40,32 @@ public class ProjectQgateAssociationDao implements Dao {
return id == null ? Optional.empty() : Optional.of(Long.valueOf(id));
}
+ /**
+ * @return quality gate uuid if a specific Quality Gate has been defined for the given component uuid. <br>
+ * Returns <code>{@link Optional#empty()}</code> otherwise (ex: default quality gate applies)
+ */
+ public Optional<String> selectQGateUuidByComponentUuid(DbSession dbSession, String componentUuid) {
+ String uuid = mapper(dbSession).selectQGateUuidByComponentUuid(componentUuid);
+ return Optional.ofNullable(uuid);
+ }
+
private static ProjectQgateAssociationMapper mapper(DbSession session) {
return session.getMapper(ProjectQgateAssociationMapper.class);
}
+ public void deleteByProjectUuid(DbSession dbSession, String projectUuid) {
+ mapper(dbSession).deleteByProjectUuid(projectUuid);
+ }
+
+ public void deleteByQGateUuid(DbSession dbSession, String qGateUuid) {
+ mapper(dbSession).deleteByQGateUuid(qGateUuid);
+ }
+
+ public void insertProjectQGateAssociation(DbSession dbSession, String projectUuid, String qGateUuid) {
+ mapper(dbSession).insertProjectQGateAssociation(projectUuid, qGateUuid);
+ }
+
+ public void updateProjectQGateAssociation(DbSession dbSession, String projectUuid, String qGateUuid) {
+ mapper(dbSession).updateProjectQGateAssociation(projectUuid, qGateUuid);
+ }
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java
index d1f8ab689f5..4d282c6a091 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java
@@ -29,4 +29,16 @@ public interface ProjectQgateAssociationMapper {
@CheckForNull
String selectQGateIdByComponentId(long componentId);
+
+ @CheckForNull
+ String selectQGateUuidByComponentUuid(String componentUuid);
+
+ void deleteByProjectUuid(String projectUuid);
+
+ void insertProjectQGateAssociation(@Param("projectUuid") String projectUuid, @Param("qGateUuid") String qGateUuid);
+
+ void deleteByQGateUuid(String qGateUuid);
+
+ void updateProjectQGateAssociation(@Param("projectUuid") String projectUuid, @Param("qGateUuid") String qGateUuid);
+
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java
index b73dd5ceb96..cc9e7a2b415 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java
@@ -101,4 +101,8 @@ public class QualityGateDao implements Dao {
private static QualityGateMapper mapper(DbSession session) {
return session.getMapper(QualityGateMapper.class);
}
+
+ public QualityGateDto selectByProjectUuid(DbSession dbSession, String uuid) {
+ return mapper(dbSession).selectByProjectUuid(uuid);
+ }
}
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java
index bdcc9c121f4..490f3bbbadc 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java
@@ -56,4 +56,6 @@ public interface QualityGateMapper {
void update(QualityGateDto qGate);
void ensureOneBuiltInQualityGate(String builtInQualityName);
+
+ QualityGateDto selectByProjectUuid(@Param("projectUuid") String projectUuid);
}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml
index 5d9239182ed..ac1a2960ac8 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml
@@ -36,4 +36,46 @@
</where>
</select>
+ <select id="selectQGateUuidByComponentUuid" parameterType="String" resultType="string">
+ SELECT quality_gate_uuid
+ FROM project_qgates
+ <where>
+ AND project_uuid=#{componentUuid}
+ </where>
+ </select>
+
+ <delete id="deleteByProjectUuid" parameterType="String">
+ DELETE
+ FROM project_qgates
+ WHERE
+ project_uuid=#{uuid,jdbcType=VARCHAR}
+ </delete>
+
+ <delete id="deleteByQGateUuid" parameterType="String">
+ DELETE
+ FROM project_qgates
+ WHERE
+ quality_gate_uuid=#{uuid,jdbcType=VARCHAR}
+ </delete>
+
+ <insert id="insertProjectQGateAssociation" parameterType="map">
+ INSERT into project_qgates
+ (
+ project_uuid,
+ quality_gate_uuid
+ )
+ VALUES (
+ #{projectUuid,jdbcType=VARCHAR},
+ #{qGateUuid,jdbcType=VARCHAR}
+ )
+ </insert>
+
+ <update id="updateProjectQGateAssociation" parameterType="map">
+ UPDATE project_qgates
+ SET
+ quality_gate_uuid=#{qGateUuid,jdbcType=VARCHAR}
+ WHERE
+ project_uuid = #{projectUuid,jdbcType=VARCHAR}
+ </update>
+
</mapper>
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml
index f7ea50278a6..4d46494c2ff 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/qualitygate/QualityGateMapper.xml
@@ -76,6 +76,15 @@
qg.id = #{id, jdbcType=BIGINT}
</select>
+ <select id="selectByProjectUuid" parameterType="Map" resultType="org.sonar.db.qualitygate.QualityGateDto">
+ SELECT
+ <include refid="gateColumns"/>
+ FROM
+ quality_gates qg
+ INNER JOIN
+ project_qgates pqg ON pqg.quality_gate_uuid = qg.uuid AND pqg.project_uuid = #{projectUuid, jdbcType=VARCHAR}
+ </select>
+
<select id="selectById" parameterType="long" resultType="QualityGate">
select
<include refid="gateColumns"/>
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java
index 2f0a99162fa..77dae851284 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java
@@ -77,17 +77,17 @@ public class ProjectQgateAssociationDaoTest {
.qualityGate(qualityGate)
.membership(ProjectQgateAssociationQuery.IN)
.build()))
- .extracting(ProjectQgateAssociationDto::getId, ProjectQgateAssociationDto::getName, ProjectQgateAssociationDto::getGateId)
- .containsExactlyInAnyOrder(
- tuple(project1.getId(), project1.name(), qualityGate.getId().toString()),
- tuple(project2.getId(), project2.name(), qualityGate.getId().toString()));
+ .extracting(ProjectQgateAssociationDto::getId, ProjectQgateAssociationDto::getName, ProjectQgateAssociationDto::getGateId)
+ .containsExactlyInAnyOrder(
+ tuple(project1.getId(), project1.name(), qualityGate.getId().toString()),
+ tuple(project2.getId(), project2.name(), qualityGate.getId().toString()));
assertThat(underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder()
.qualityGate(qualityGate)
.membership(ProjectQgateAssociationQuery.OUT)
.build()))
- .extracting(ProjectQgateAssociationDto::getId, ProjectQgateAssociationDto::getName, ProjectQgateAssociationDto::getGateId)
- .containsExactlyInAnyOrder(tuple(project3.getId(), project3.name(), null));
+ .extracting(ProjectQgateAssociationDto::getId, ProjectQgateAssociationDto::getName, ProjectQgateAssociationDto::getGateId)
+ .containsExactlyInAnyOrder(tuple(project3.getId(), project3.name(), null));
}
@Test
@@ -104,15 +104,15 @@ public class ProjectQgateAssociationDaoTest {
.qualityGate(qualityGate)
.projectSearch("one")
.build()))
- .extracting(ProjectQgateAssociationDto::getId)
- .containsExactlyInAnyOrder(project1.getId());
+ .extracting(ProjectQgateAssociationDto::getId)
+ .containsExactlyInAnyOrder(project1.getId());
assertThat(underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder()
.qualityGate(qualityGate)
.projectSearch("project")
.build()))
- .extracting(ProjectQgateAssociationDto::getId)
- .containsExactlyInAnyOrder(project1.getId(), project2.getId(), project3.getId());
+ .extracting(ProjectQgateAssociationDto::getId)
+ .containsExactlyInAnyOrder(project1.getId(), project2.getId(), project3.getId());
}
@Test
@@ -126,8 +126,8 @@ public class ProjectQgateAssociationDaoTest {
assertThat(underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder()
.qualityGate(qualityGate)
.build()))
- .extracting(ProjectQgateAssociationDto::getId)
- .containsExactly(project1.getId(), project3.getId(), project2.getId());
+ .extracting(ProjectQgateAssociationDto::getId)
+ .containsExactly(project1.getId(), project3.getId(), project2.getId());
}
@Test
@@ -174,4 +174,63 @@ public class ProjectQgateAssociationDaoTest {
assertThat(result).contains(qualityGate1.getId());
}
+ @Test
+ public void select_qgate_uuid_by_component_uuid() {
+ OrganizationDto organization = db.organizations().insert();
+ QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
+ ComponentDto project = db.components().insertPrivateProject(organization);
+
+ db.qualityGates().associateProjectToQualityGate(project, qualityGate);
+
+ Optional<String> qGateUuid = underTest.selectQGateUuidByComponentUuid(dbSession, project.uuid());
+
+ assertThat(qGateUuid).contains(qualityGate.getUuid());
+ }
+
+
+ @Test
+ public void delete_by_project_uuid() {
+ OrganizationDto organization = db.organizations().insert();
+ QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
+ ComponentDto project = db.components().insertPrivateProject(organization);
+
+ db.qualityGates().associateProjectToQualityGate(project, qualityGate);
+
+ underTest.deleteByProjectUuid(dbSession, project.uuid());
+
+ Optional<String> deletedQualityGate = db.qualityGates().selectQGateUuidByComponentUuid(project.uuid());
+
+ assertThat(deletedQualityGate).isEmpty();
+ }
+
+ @Test
+ public void delete_by_qgate_uuid() {
+ OrganizationDto organization = db.organizations().insert();
+ QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
+ ComponentDto project = db.components().insertPrivateProject(organization);
+
+ db.qualityGates().associateProjectToQualityGate(project, qualityGate);
+
+ underTest.deleteByQGateUuid(dbSession, qualityGate.getUuid());
+
+ Optional<String> deletedQualityGate = db.qualityGates().selectQGateUuidByComponentUuid(project.uuid());
+
+ assertThat(deletedQualityGate).isEmpty();
+ }
+
+ @Test
+ public void update_project_qgate_association() {
+ OrganizationDto organization = db.organizations().insert();
+ QGateWithOrgDto firstQualityGate = db.qualityGates().insertQualityGate(organization);
+ QGateWithOrgDto secondQualityGate = db.qualityGates().insertQualityGate(organization);
+ ComponentDto project = db.components().insertPrivateProject(organization);
+
+ db.qualityGates().associateProjectToQualityGate(project, firstQualityGate);
+
+ underTest.updateProjectQGateAssociation(dbSession, project.uuid(), secondQualityGate.getUuid());
+
+ Optional<String> updatedQualityGateUuid = db.qualityGates().selectQGateUuidByComponentUuid(project.uuid());
+
+ assertThat(updatedQualityGateUuid).contains(secondQualityGate.getUuid());
+ }
}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java
index 63e588e2249..824390141e5 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDaoTest.java
@@ -27,6 +27,7 @@ import org.sonar.api.utils.System2;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
import static java.lang.String.format;
@@ -111,6 +112,19 @@ public class QualityGateDaoTest {
}
@Test
+ public void select_by_uuid() {
+ QGateWithOrgDto dto = qualityGateDbTester.insertQualityGate(db.getDefaultOrganization(), g -> g.setName("QG Name").setBuiltIn(false));
+ QualityGateDto qualityGateToAssociate = underTest.selectById(dbSession, dto.getId());
+ ComponentDto project = db.components().insertPrivateProject();
+
+ qualityGateDbTester.associateProjectToQualityGate(project, qualityGateToAssociate);
+
+ QualityGateDto qualityGateFromSelect = underTest.selectByProjectUuid(dbSession, project.uuid());
+
+ assertThat(qualityGateFromSelect.getUuid()).isEqualTo(qualityGateToAssociate.getUuid());
+ }
+
+ @Test
public void select_by_organization_and_uuid() {
OrganizationDto organization = db.organizations().insert();
QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDbTester.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDbTester.java
index 872e495e950..01727b4c215 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDbTester.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateDbTester.java
@@ -21,6 +21,7 @@ package org.sonar.db.qualitygate;
import java.util.Arrays;
import java.util.Date;
+import java.util.Optional;
import java.util.function.Consumer;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
@@ -74,6 +75,9 @@ public class QualityGateDbTester {
.setKey("sonar.qualitygate")
.setResourceId(component.getId())
.setValue(String.valueOf(qualityGate.getId())));
+
+ dbClient.projectQgateAssociationDao().insertProjectQGateAssociation(dbSession, component.uuid(), qualityGate.getUuid());
+
db.commit();
}
@@ -105,4 +109,8 @@ public class QualityGateDbTester {
db.commit();
return condition;
}
+
+ public Optional<String> selectQGateUuidByComponentUuid(String uuid) {
+ return dbClient.projectQgateAssociationDao().selectQGateUuidByComponentUuid(dbSession, uuid);
+ }
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/CreateProjectQualityGatesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/CreateProjectQualityGatesTable.java
new file mode 100644
index 00000000000..f8a7615e062
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v80/CreateProjectQualityGatesTable.java
@@ -0,0 +1,79 @@
+/*
+ * 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.Connection;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.SupportsBlueGreen;
+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;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+@SupportsBlueGreen
+public class CreateProjectQualityGatesTable extends DdlChange {
+
+ private static final String TABLE_NAME = "project_qgates";
+
+ private static final VarcharColumnDef PROJECT_UUID_COLUMN = newVarcharColumnDefBuilder()
+ .setColumnName("project_uuid")
+ .setIsNullable(false)
+ .setLimit(UUID_SIZE)
+ .build();
+ private static final VarcharColumnDef QUALITY_GATE_UUID_COLUMN = newVarcharColumnDefBuilder()
+ .setColumnName("quality_gate_uuid")
+ .setIsNullable(false)
+ .setLimit(UUID_SIZE)
+ .build();
+
+ public CreateProjectQualityGatesTable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ if (tableExists()) {
+ return;
+ }
+ context.execute(new CreateTableBuilder(getDialect(), TABLE_NAME)
+ .addPkColumn(PROJECT_UUID_COLUMN)
+ .addColumn(QUALITY_GATE_UUID_COLUMN)
+ .build());
+
+ context.execute(new CreateIndexBuilder()
+ .setTable(TABLE_NAME)
+ .setName("uniq_project_qgates")
+ .setUnique(true)
+ .addColumn(PROJECT_UUID_COLUMN)
+ .addColumn(QUALITY_GATE_UUID_COLUMN)
+ .build());
+ }
+
+ private boolean tableExists() throws SQLException {
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ return DatabaseUtils.tableExists(TABLE_NAME, connection);
+ }
+ }
+}
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 a2f5956c7bb..f3f0a818d1e 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
@@ -26,6 +26,7 @@ public class DbVersion80 implements DbVersion {
@Override
public void addSteps(MigrationStepRegistry registry) {
registry
- .add(3000, "Set Organizations#guarded column nullable", MakeOrganizationsGuardedNullable.class);
+ .add(3000, "Set Organizations#guarded column nullable", MakeOrganizationsGuardedNullable.class)
+ .add(3001, "Create ProjectQualityGates table", CreateProjectQualityGatesTable.class);
}
}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/CreateProjectQualityGatesTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/CreateProjectQualityGatesTableTest.java
new file mode 100644
index 00000000000..72b507502b0
--- /dev/null
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v80/CreateProjectQualityGatesTableTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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 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 CreateProjectQualityGatesTableTest {
+ private static final String TABLE_NAME = "project_qgates";
+
+ @Rule
+ public CoreDbTester dbTester = CoreDbTester.createEmpty();
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private CreateProjectQualityGatesTable underTest = new CreateProjectQualityGatesTable(dbTester.database());
+
+ @Test
+ public void table_has_been_created() throws SQLException {
+ underTest.execute();
+
+ dbTester.assertTableExists(TABLE_NAME);
+ dbTester.assertPrimaryKey(TABLE_NAME, "pk_project_qgates", "project_uuid");
+ dbTester.assertUniqueIndex(TABLE_NAME, "uniq_project_qgates", "project_uuid", "quality_gate_uuid");
+
+ dbTester.assertColumnDefinition(TABLE_NAME, "project_uuid", VARCHAR, 40, false);
+ dbTester.assertColumnDefinition(TABLE_NAME, "quality_gate_uuid", VARCHAR, 40, false);
+
+ //script should not fail if executed twice
+ underTest.execute();
+ }
+}
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 9e64b803eea..3552b825d63 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
@@ -21,7 +21,6 @@ package org.sonar.server.platform.db.migration.version.v80;
import org.junit.Test;
import org.sonar.server.platform.db.migration.version.DbVersion;
-import org.sonar.server.platform.db.migration.version.v79.DbVersion79;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationCount;
import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
@@ -36,7 +35,7 @@ public class DbVersion80Test {
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 1);
+ verifyMigrationCount(underTest, 2);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java
index 8fa1bc68464..93658d2aa27 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateUpdater.java
@@ -22,14 +22,11 @@ package org.sonar.server.qualitygate;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
-import org.sonar.db.property.PropertyDto;
import org.sonar.db.qualitygate.QualityGateConditionDto;
import org.sonar.db.qualitygate.QualityGateDto;
import static com.google.common.base.Preconditions.checkArgument;
-import static org.sonar.server.qualitygate.QualityGateFinder.SONAR_QUALITYGATE_PROPERTY;
import static org.sonar.server.util.Validation.IS_ALREADY_USED_MESSAGE;
public class QualityGateUpdater {
@@ -78,17 +75,6 @@ public class QualityGateUpdater {
dbClient.qualityGateDao().update(qualityGateDto, dbSession);
}
- public void dissociateProject(DbSession dbSession, ComponentDto project) {
- dbClient.propertiesDao().deleteProjectProperty(SONAR_QUALITYGATE_PROPERTY, project.getId(), dbSession);
- }
-
- public void associateProject(DbSession dbSession, ComponentDto project, QualityGateDto qualityGate) {
- dbClient.propertiesDao().saveProperty(dbSession, new PropertyDto()
- .setKey(SONAR_QUALITYGATE_PROPERTY)
- .setResourceId(project.getId())
- .setValue(String.valueOf(qualityGate.getId())));
- }
-
private void checkQualityGateDoesNotAlreadyExist(DbSession dbSession, OrganizationDto organizationDto, String name) {
QualityGateDto existingQgate = dbClient.qualityGateDao().selectByOrganizationAndName(dbSession, organizationDto, name);
checkArgument(existingQgate == null, IS_ALREADY_USED_MESSAGE, "Name");
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java
index d5a5392df6b..8bcf5a39e78 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java
@@ -89,6 +89,7 @@ public class DeselectAction implements QualityGatesWsAction {
private void dissociateProject(DbSession dbSession, OrganizationDto organization, ComponentDto project) {
wsSupport.checkCanAdminProject(organization, project);
dbClient.propertiesDao().deleteProjectProperty(SONAR_QUALITYGATE_PROPERTY, project.getId(), dbSession);
+ dbClient.projectQgateAssociationDao().deleteByProjectUuid(dbSession, project.uuid());
dbSession.commit();
}
@@ -106,7 +107,7 @@ public class DeselectAction implements QualityGatesWsAction {
try {
long dbId = Long.parseLong(projectId);
- return Optional.ofNullable(dbClient.componentDao().selectById(dbSession, dbId).orElse(null));
+ return dbClient.componentDao().selectById(dbSession, dbId);
} catch (NumberFormatException e) {
return Optional.empty();
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java
index e9279870565..ce098eaa65f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java
@@ -72,6 +72,7 @@ public class DestroyAction implements QualityGatesWsAction {
wsSupport.checkCanEdit(qualityGate);
dbClient.propertiesDao().deleteByKeyAndValue(dbSession, SONAR_QUALITYGATE_PROPERTY, String.valueOf(qualityGate.getId()));
+ dbClient.projectQgateAssociationDao().deleteByQGateUuid(dbSession, qualityGate.getUuid());
dbClient.qualityGateDao().delete(qualityGate, dbSession);
dbSession.commit();
response.noContent();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java
index 71c38ad77a2..e8fc3e5eb64 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java
@@ -31,6 +31,7 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.property.PropertyDto;
import org.sonar.db.qualitygate.QGateWithOrgDto;
+import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.component.ComponentFinder.ParamNames;
@@ -99,6 +100,16 @@ public class SelectAction implements QualityGatesWsAction {
.setResourceId(project.getId())
.setValue(String.valueOf(qualityGate.getId())));
+ QualityGateDto currentQualityGate = dbClient.qualityGateDao().selectByProjectUuid(dbSession, project.uuid());
+ if (currentQualityGate == null) {
+ // project uses the default profile
+ dbClient.projectQgateAssociationDao()
+ .insertProjectQGateAssociation(dbSession, project.uuid(), qualityGate.getUuid());
+ } else if (!qualityGate.getUuid().equals(currentQualityGate.getUuid())) {
+ dbClient.projectQgateAssociationDao()
+ .updateProjectQGateAssociation(dbSession, project.uuid(), qualityGate.getUuid());
+ }
+
dbSession.commit();
}
response.noContent();
@@ -118,7 +129,7 @@ public class SelectAction implements QualityGatesWsAction {
try {
long dbId = Long.parseLong(projectId);
- return Optional.ofNullable(dbClient.componentDao().selectById(dbSession, dbId).orElse(null));
+ return dbClient.componentDao().selectById(dbSession, dbId);
} catch (NumberFormatException e) {
return Optional.empty();
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java
index e3ced0d69dc..8ef3fedbd48 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DeselectActionTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.qualitygate.ws;
+import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -77,7 +78,7 @@ public class DeselectActionTest {
.setParam("organization", organization.getKey())
.execute();
- assertDeselected(project.getId());
+ assertDeselected(project);
}
@Test
@@ -93,7 +94,7 @@ public class DeselectActionTest {
.setParam("organization", organization.getKey())
.execute();
- assertDeselected(project.getId());
+ assertDeselected(project);
}
@Test
@@ -109,7 +110,7 @@ public class DeselectActionTest {
.setParam("organization", organization.getKey())
.execute();
- assertDeselected(project.getId());
+ assertDeselected(project);
}
@Test
@@ -125,7 +126,7 @@ public class DeselectActionTest {
.setParam("organization", organization.getKey())
.execute();
- assertDeselected(project.getId());
+ assertDeselected(project);
}
@Test
@@ -134,7 +135,6 @@ public class DeselectActionTest {
userSession.addPermission(ADMINISTER_QUALITY_GATES, organization);
QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
ComponentDto project = db.components().insertPrivateProject(organization);
- String gateId = valueOf(qualityGate.getId());
associateProjectToQualityGate(project, qualityGate);
// Another project
ComponentDto anotherProject = db.components().insertPrivateProject(organization);
@@ -145,8 +145,8 @@ public class DeselectActionTest {
.setParam("organization", organization.getKey())
.execute();
- assertDeselected(project.getId());
- assertSelected(gateId, anotherProject.getId());
+ assertDeselected(project);
+ assertSelected(qualityGate, anotherProject);
}
@Test
@@ -161,7 +161,7 @@ public class DeselectActionTest {
.setParam("projectKey", project.getKey())
.execute();
- assertDeselected(project.getId());
+ assertDeselected(project);
}
@Test
@@ -304,14 +304,26 @@ public class DeselectActionTest {
.setResourceId(project.getId())
.setValue(qualityGate.getId().toString())
.setKey(SONAR_QUALITYGATE_PROPERTY));
+ db.qualityGates().associateProjectToQualityGate(project, qualityGate);
db.commit();
}
- private void assertDeselected(long projectId) {
- assertThat(dbClient.propertiesDao().selectProjectProperty(projectId, SONAR_QUALITYGATE_PROPERTY)).isNull();
+ private void assertDeselected(ComponentDto project) {
+ Optional<String> qGateUuid = db.qualityGates().selectQGateUuidByComponentUuid(project.uuid());
+ assertThat(qGateUuid)
+ .isNotNull()
+ .isEmpty();
+
+ assertThat(dbClient.propertiesDao().selectProjectProperty(project.getId(), SONAR_QUALITYGATE_PROPERTY)).isNull();
}
- private void assertSelected(String qGateId, long projectId) {
- assertThat(dbClient.propertiesDao().selectProjectProperty(projectId, SONAR_QUALITYGATE_PROPERTY).getValue()).isEqualTo(qGateId);
+ private void assertSelected(QGateWithOrgDto qualityGate, ComponentDto project) {
+ Optional<String> qGateUuid = db.qualityGates().selectQGateUuidByComponentUuid(project.uuid());
+ assertThat(qGateUuid)
+ .isNotNull()
+ .isNotEmpty()
+ .hasValue(qualityGate.getUuid());
+ String qGateId = dbClient.propertiesDao().selectProjectProperty(project.getId(), SONAR_QUALITYGATE_PROPERTY).getValue();
+ assertThat(qGateId).isEqualTo(String.valueOf(qualityGate.getId()));
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DestroyActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DestroyActionTest.java
index f11a9191242..9fe569ccaf2 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DestroyActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/DestroyActionTest.java
@@ -119,6 +119,11 @@ public class DestroyActionTest {
.isEmpty();
assertThat(db.getDbClient().propertiesDao().selectProjectProperties(prj2.getDbKey()))
.isEmpty();
+
+ assertThat(db.getDbClient().projectQgateAssociationDao().selectQGateUuidByComponentUuid(dbSession, prj1.uuid()))
+ .isEmpty();
+ assertThat(db.getDbClient().projectQgateAssociationDao().selectQGateUuidByComponentUuid(dbSession, prj2.uuid()))
+ .isEmpty();
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java
index 4c53dcb6a7f..d38f148f5c8 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/SelectActionTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.qualitygate.ws;
+import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -106,6 +107,51 @@ public class SelectActionTest {
}
@Test
+ public void change_quality_gate_for_project() {
+ OrganizationDto organization = db.organizations().insert();
+ userSession.addPermission(ADMINISTER_QUALITY_GATES, organization);
+ QGateWithOrgDto initialQualityGate = db.qualityGates().insertQualityGate(organization);
+ QGateWithOrgDto secondQualityGate = db.qualityGates().insertQualityGate(organization);
+ ComponentDto project = db.components().insertPrivateProject(organization);
+
+ ws.newRequest()
+ .setParam("gateId", initialQualityGate.getId().toString())
+ .setParam("projectKey", project.getKey())
+ .setParam("organization", organization.getKey())
+ .execute();
+
+ ws.newRequest()
+ .setParam("gateId", secondQualityGate.getId().toString())
+ .setParam("projectKey", project.getKey())
+ .setParam("organization", organization.getKey())
+ .execute();
+
+ assertSelected(secondQualityGate, project);
+ }
+
+ @Test
+ public void select_same_quality_gate_for_project_twice() {
+ OrganizationDto organization = db.organizations().insert();
+ userSession.addPermission(ADMINISTER_QUALITY_GATES, organization);
+ QGateWithOrgDto initialQualityGate = db.qualityGates().insertQualityGate(organization);
+ ComponentDto project = db.components().insertPrivateProject(organization);
+
+ ws.newRequest()
+ .setParam("gateId", initialQualityGate.getId().toString())
+ .setParam("projectKey", project.getKey())
+ .setParam("organization", organization.getKey())
+ .execute();
+
+ ws.newRequest()
+ .setParam("gateId", initialQualityGate.getId().toString())
+ .setParam("projectKey", project.getKey())
+ .setParam("organization", organization.getKey())
+ .execute();
+
+ assertSelected(initialQualityGate, project);
+ }
+
+ @Test
public void project_admin() {
OrganizationDto organization = db.organizations().insert();
QGateWithOrgDto qualityGate = db.qualityGates().insertQualityGate(organization);
@@ -179,7 +225,7 @@ public class SelectActionTest {
expectedException.expect(NotFoundException.class);
ws.newRequest()
- .setParam("gateId", String.valueOf("1"))
+ .setParam("gateId", "1")
.setParam("projectKey", project.getKey())
.setParam("organization", organization.getKey())
.execute();
@@ -296,6 +342,11 @@ public class SelectActionTest {
private void assertSelected(QualityGateDto qualityGate, ComponentDto project) {
assertThat(dbClient.propertiesDao().selectProjectProperty(project.getId(), SONAR_QUALITYGATE_PROPERTY).getValue()).isEqualTo(qualityGate.getId().toString());
+ Optional<String> qGateUuid = db.qualityGates().selectQGateUuidByComponentUuid(project.uuid());
+ assertThat(qGateUuid)
+ .isNotNull()
+ .isNotEmpty()
+ .hasValue(qualityGate.getUuid());
}
}