diff options
author | Claire Villard <claire.villard@sonarsource.com> | 2025-02-20 10:30:53 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2025-02-21 20:03:04 +0000 |
commit | c5b73557ee84d1c9af425d025bf039ce5da586f9 (patch) | |
tree | da4826af6346dc3f0156082fc47d5c0800fe261e | |
parent | d40062530049c05af1f1e8046ce841792fa970e4 (diff) | |
download | sonarqube-c5b73557ee84d1c9af425d025bf039ce5da586f9.tar.gz sonarqube-c5b73557ee84d1c9af425d025bf039ce5da586f9.zip |
SONAR-24321 Remove already migrated branch measures when using the migrate_measures endpoint
3 files changed, 98 insertions, 0 deletions
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/adhoc/AbstractMigrateLiveMeasuresToMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/adhoc/AbstractMigrateLiveMeasuresToMeasures.java index bb23c793172..f6e0f8d66ea 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/adhoc/AbstractMigrateLiveMeasuresToMeasures.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/adhoc/AbstractMigrateLiveMeasuresToMeasures.java @@ -48,6 +48,11 @@ public abstract class AbstractMigrateLiveMeasuresToMeasures extends DataChange { private static final Set<String> TEXT_VALUE_TYPES = Set.of("STRING", "LEVEL", "DATA", "DISTRIB"); private static final Gson GSON = new Gson(); + private static final String CLEANUP_QUERY = """ + DELETE FROM measures + WHERE branch_uuid = ? + """; + private static final String SELECT_QUERY = """ SELECT lm.component_uuid, m.name, @@ -113,6 +118,13 @@ public abstract class AbstractMigrateLiveMeasuresToMeasures extends DataChange { } private void migrateItem(String uuid, Context context) throws SQLException { + LOGGER.debug("Cleaning leftovers from a previous attempt for {} {}...", item, uuid); + + context.prepareUpsert(CLEANUP_QUERY) + .setString(1, uuid) + .execute() + .commit(); + LOGGER.debug("Migrating {} {}...", item, uuid); Map<String, Object> measureValues = new HashMap<>(); diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/adhoc/MigrateBranchesLiveMeasuresToMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/adhoc/MigrateBranchesLiveMeasuresToMeasuresTest.java index b7a251c6ce6..e08f74cc7d9 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/adhoc/MigrateBranchesLiveMeasuresToMeasuresTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/adhoc/MigrateBranchesLiveMeasuresToMeasuresTest.java @@ -83,6 +83,39 @@ public class MigrateBranchesLiveMeasuresToMeasuresTest { } @Test + public void should_migrate_branch_if_previous_attempt_failed() throws SQLException { + String nclocMetricUuid = insertMetric("ncloc", "INT"); + String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING"); + String metricWithDataUuid = insertMetric("metric_with_data", "DATA"); + + String branch1 = "branch_7"; + insertNotMigratedBranch(branch1); + String component1 = uuidFactory.create(); + String component2 = uuidFactory.create(); + insertMeasure(branch1, component1, nclocMetricUuid, Map.of("value", 120)); + insertMeasure(branch1, component1, qgStatusMetricUuid, Map.of("text_value", "ok")); + insertMeasure(branch1, component2, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8))); + + insertMigratedMeasure(branch1, component1); + assertThat(db.countRowsOfTable("measures")).isEqualTo(1); + + underTest.migrate(List.of(branch1)); + + assertBranchMigrated(branch1); + assertThat(db.countRowsOfTable("measures")).isEqualTo(2); + + assertThat(db.select(format(SELECT_MEASURE, component1))) + .hasSize(1) + .extracting(t -> t.get("COMPONENT_UUID"), t -> t.get("BRANCH_UUID"), t -> t.get("JSON_VALUE"), t -> t.get("JSON_VALUE_HASH")) + .containsOnly(tuple(component1, branch1, "{\"ncloc\":120.0,\"quality_gate_status\":\"ok\"}", 6033012287291512746L)); + + assertThat(db.select(format(SELECT_MEASURE, component2))) + .hasSize(1) + .extracting(t -> t.get("COMPONENT_UUID"), t -> t.get("BRANCH_UUID"), t -> t.get("JSON_VALUE"), t -> t.get("JSON_VALUE_HASH")) + .containsOnly(tuple(component2, branch1, "{\"metric_with_data\":\"some data\"}", -4524184678167636687L)); + } + + @Test public void should_migrate_branch_with_measures() throws SQLException { String nclocMetricUuid = insertMetric("ncloc", "INT"); String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING"); @@ -163,6 +196,16 @@ public class MigrateBranchesLiveMeasuresToMeasuresTest { db.executeInsert("live_measures", dataMap); } + private void insertMigratedMeasure(String branch, String componentUuid) { + db.executeInsert("measures", + "component_uuid", componentUuid, + "branch_uuid", branch, + "json_value", "{\"any\":\"thing\"}", + "json_value_hash", "1234", + "created_at", 12, + "updated_at", 12); + } + private void insertNotMigratedBranch(String branchUuid) { db.executeInsert("project_branches", "uuid", branchUuid, diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/adhoc/MigratePortfoliosLiveMeasuresToMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/adhoc/MigratePortfoliosLiveMeasuresToMeasuresTest.java index dd76bd3d735..2d1bf476687 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/adhoc/MigratePortfoliosLiveMeasuresToMeasuresTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/adhoc/MigratePortfoliosLiveMeasuresToMeasuresTest.java @@ -121,6 +121,39 @@ public class MigratePortfoliosLiveMeasuresToMeasuresTest { .containsOnly(tuple(component2, portfolio1, "{\"metric_with_data\":\"some data\"}", -4524184678167636687L)); } + @Test + public void should_migrate_portfolio_if_previous_attempt_failed() throws SQLException { + String nclocMetricUuid = insertMetric("ncloc", "INT"); + String qgStatusMetricUuid = insertMetric("quality_gate_status", "STRING"); + String metricWithDataUuid = insertMetric("metric_with_data", "DATA"); + + String portfolio1 = "portfolio_7"; + insertNotMigratedPortfolio(portfolio1); + String component1 = uuidFactory.create(); + String component2 = uuidFactory.create(); + insertMeasure(portfolio1, component1, nclocMetricUuid, Map.of("value", 120)); + insertMeasure(portfolio1, component1, qgStatusMetricUuid, Map.of("text_value", "ok")); + insertMeasure(portfolio1, component2, metricWithDataUuid, Map.of("measure_data", "some data".getBytes(StandardCharsets.UTF_8))); + + insertMigratedMeasure(portfolio1, component1); + assertThat(db.countRowsOfTable("measures")).isEqualTo(1); + + underTest.migrate(List.of(portfolio1)); + + assertPortfolioMigrated(portfolio1); + assertThat(db.countRowsOfTable("measures")).isEqualTo(2); + + assertThat(db.select(format(SELECT_MEASURE, component1))) + .hasSize(1) + .extracting(t -> t.get("COMPONENT_UUID"), t -> t.get("BRANCH_UUID"), t -> t.get("JSON_VALUE"), t -> t.get("JSON_VALUE_HASH")) + .containsOnly(tuple(component1, portfolio1, "{\"ncloc\":120.0,\"quality_gate_status\":\"ok\"}", 6033012287291512746L)); + + assertThat(db.select(format(SELECT_MEASURE, component2))) + .hasSize(1) + .extracting(t -> t.get("COMPONENT_UUID"), t -> t.get("BRANCH_UUID"), t -> t.get("JSON_VALUE"), t -> t.get("JSON_VALUE_HASH")) + .containsOnly(tuple(component2, portfolio1, "{\"metric_with_data\":\"some data\"}", -4524184678167636687L)); + } + private void assertPortfolioMigrated(String portfolio) { assertMigrationStatus(portfolio, true); } @@ -162,6 +195,16 @@ public class MigratePortfoliosLiveMeasuresToMeasuresTest { db.executeInsert("live_measures", dataMap); } + private void insertMigratedMeasure(String branch, String componentUuid) { + db.executeInsert("measures", + "component_uuid", componentUuid, + "branch_uuid", branch, + "json_value", "{\"any\":\"thing\"}", + "json_value_hash", "1234", + "created_at", 12, + "updated_at", 12); + } + private void insertNotMigratedPortfolio(String portfolioUuid) { db.executeInsert("portfolios", "uuid", portfolioUuid, |