aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/sonar-db-core/src/testFixtures/java/org/sonar/db/AbstractDbTester.java26
-rw-r--r--server/sonar-db-dao/src/schema/schema-sq.ddl1
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/MigratePortfoliosLiveMeasuresToMeasuresIT.java2
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/AddProductionScopeToScaDependenciesTableIT.java (renamed from server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/AddProductionScopeToScaDependenciesTableIT.java)2
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnArchitectureGraphsIT.java55
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnScaReleasesComponentUuidTest.java (renamed from server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuidTest.java)10
-rw-r--r--server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/DropIndexOnScaReleasesComponentTest.java (renamed from server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponentTest.java)2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/AddDeclaredLicenseExpressionToScaReleasesTable.java (renamed from server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/AddDeclaredLicenseExpressionToScaReleasesTable.java)2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/AddProductionScopeToScaDependenciesTable.java (renamed from server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/AddProductionScopeToScaDependenciesTable.java)2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnScaReleasesComponentUuid.java (renamed from server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuid.java)2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/CreateUniqueIndexOnArchitectureGraphs.java60
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/DbVersion202502.java6
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/DropIndexOnScaReleasesComponent.java (renamed from server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponent.java)2
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503.java44
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/package-info.java23
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202502/AddDeclaredLicenseExpressionToScaReleasesTableTest.java (renamed from server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202503/AddDeclaredLicenseExpressionToScaReleasesTableTest.java)2
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503Test.java40
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java2
-rw-r--r--server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/Dimension.java3
-rw-r--r--server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/schema/FixSuggestionMetric.java56
-rw-r--r--server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/DimensionTest.java2
-rw-r--r--server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/schema/FixSuggestionMetricTest.java51
-rw-r--r--server/sonar-webserver-api/src/it/java/org/sonar/server/plugins/DetectPluginChangeIT.java34
-rw-r--r--server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/DetectPluginChange.java14
-rw-r--r--server/sonar-webserver-core/src/main/java/org/sonar/server/startup/PropertiesDBCleaner.java62
-rw-r--r--server/sonar-webserver-core/src/test/java/org/sonar/server/startup/PropertiesDBCleanerTest.java78
-rw-r--r--server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java2
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java28
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java32
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java15
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java84
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java30
-rw-r--r--server/sonar-webserver-webapi/src/main/resources/org/sonar/server/qualityprofile/ws/create-example.json8
-rw-r--r--server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel3.java2
35 files changed, 502 insertions, 284 deletions
diff --git a/server/sonar-db-core/src/testFixtures/java/org/sonar/db/AbstractDbTester.java b/server/sonar-db-core/src/testFixtures/java/org/sonar/db/AbstractDbTester.java
index 10ec76b6d49..737e076950e 100644
--- a/server/sonar-db-core/src/testFixtures/java/org/sonar/db/AbstractDbTester.java
+++ b/server/sonar-db-core/src/testFixtures/java/org/sonar/db/AbstractDbTester.java
@@ -83,7 +83,8 @@ public class AbstractDbTester<T extends TestDb> extends ExternalResource {
private static final Map<Integer, Integer> POSTGRES_TYPE_SUBSTITUTION = Map.of(
BOOLEAN, BIT,
DOUBLE, NUMERIC,
- CLOB, VARCHAR);
+ CLOB, VARCHAR,
+ DECIMAL, NUMERIC);
private static final Map<Integer, Integer> MSSQL_TYPE_SUBSTITUTION = Map.of(
BOOLEAN, BIT,
VARCHAR, NVARCHAR,
@@ -93,7 +94,8 @@ public class AbstractDbTester<T extends TestDb> extends ExternalResource {
BOOLEAN, NUMERIC,
BIGINT, NUMERIC,
INTEGER, NUMERIC,
- DOUBLE, NUMERIC);
+ DOUBLE, NUMERIC,
+ DECIMAL, NUMERIC);
protected final T db;
@@ -125,7 +127,7 @@ public class AbstractDbTester<T extends TestDb> extends ExternalResource {
public void executeDdl(String ddl) {
try (Connection connection = getConnection();
- Statement stmt = connection.createStatement()) {
+ Statement stmt = connection.createStatement()) {
stmt.execute(ddl);
} catch (SQLException e) {
throw new IllegalStateException("Failed to execute DDL: " + ddl, e);
@@ -164,10 +166,10 @@ public class AbstractDbTester<T extends TestDb> extends ExternalResource {
}
String sql = "insert into " + table.toLowerCase(Locale.ENGLISH) + " (" +
- COMMA_JOINER.join(valuesByColumn.keySet().stream().map(t -> t.toLowerCase(Locale.ENGLISH)).toArray(String[]::new)) +
- ") values (" +
- COMMA_JOINER.join(Collections.nCopies(valuesByColumn.size(), '?')) +
- ")";
+ COMMA_JOINER.join(valuesByColumn.keySet().stream().map(t -> t.toLowerCase(Locale.ENGLISH)).toArray(String[]::new)) +
+ ") values (" +
+ COMMA_JOINER.join(Collections.nCopies(valuesByColumn.size(), '?')) +
+ ")";
executeUpdateSql(sql, valuesByColumn.values().toArray(new Object[valuesByColumn.size()]));
}
@@ -290,7 +292,7 @@ public class AbstractDbTester<T extends TestDb> extends ExternalResource {
public void assertColumnDefinition(String table, String column, int expectedType, @Nullable Integer expectedSize,
@Nullable Boolean isNullable) {
try (Connection connection = getConnection();
- ResultSet rs = connection.getMetaData().getColumns(null, null, toVendorCase(table), toVendorCase(column))) {
+ ResultSet rs = connection.getMetaData().getColumns(null, null, toVendorCase(table), toVendorCase(column))) {
boolean exists = false;
while (rs.next()) {
@@ -326,8 +328,8 @@ public class AbstractDbTester<T extends TestDb> extends ExternalResource {
public void assertColumnDoesNotExist(String table, String column) throws SQLException {
try (Connection connection = getConnection();
- PreparedStatement stmt = connection.prepareStatement("select * from " + table);
- ResultSet res = stmt.executeQuery()) {
+ PreparedStatement stmt = connection.prepareStatement("select * from " + table);
+ ResultSet res = stmt.executeQuery()) {
assertThat(getColumnNames(res)).doesNotContain(column);
}
}
@@ -365,7 +367,7 @@ public class AbstractDbTester<T extends TestDb> extends ExternalResource {
private void assertIndexImpl(String tableName, String indexName, boolean expectedUnique, String expectedColumn, String... expectedSecondaryColumns) {
try (Connection connection = getConnection();
- ResultSet rs = connection.getMetaData().getIndexInfo(null, null, toVendorCase(tableName), false, false)) {
+ ResultSet rs = connection.getMetaData().getIndexInfo(null, null, toVendorCase(tableName), false, false)) {
List<String> onColumns = new ArrayList<>();
while (rs.next()) {
@@ -403,7 +405,7 @@ public class AbstractDbTester<T extends TestDb> extends ExternalResource {
*/
public void assertIndexDoesNotExist(String tableName, String indexName) {
try (Connection connection = getConnection();
- ResultSet rs = connection.getMetaData().getIndexInfo(null, null, tableName.toUpperCase(Locale.ENGLISH), false, false)) {
+ ResultSet rs = connection.getMetaData().getIndexInfo(null, null, tableName.toUpperCase(Locale.ENGLISH), false, false)) {
List<String> indices = new ArrayList<>();
while (rs.next()) {
if (rs.getString("INDEX_NAME") != null) {
diff --git a/server/sonar-db-dao/src/schema/schema-sq.ddl b/server/sonar-db-dao/src/schema/schema-sq.ddl
index 78f221a55e4..d2d54a7a8f7 100644
--- a/server/sonar-db-dao/src/schema/schema-sq.ddl
+++ b/server/sonar-db-dao/src/schema/schema-sq.ddl
@@ -126,6 +126,7 @@ CREATE TABLE "ARCHITECTURE_GRAPHS"(
"GRAPH_DATA" CHARACTER LARGE OBJECT NOT NULL
);
ALTER TABLE "ARCHITECTURE_GRAPHS" ADD CONSTRAINT "PK_ARCHITECTURE_GRAPHS" PRIMARY KEY("UUID");
+CREATE UNIQUE NULLS NOT DISTINCT INDEX "UQ_IDX_AG_BRANCH_TYPE_SOURCE" ON "ARCHITECTURE_GRAPHS"("BRANCH_UUID" NULLS FIRST, "TYPE" NULLS FIRST, "SOURCE" NULLS FIRST);
CREATE TABLE "AUDITS"(
"UUID" CHARACTER VARYING(40) NOT NULL,
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/MigratePortfoliosLiveMeasuresToMeasuresIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/MigratePortfoliosLiveMeasuresToMeasuresIT.java
index 79dd5abe808..56acc2f70f9 100644
--- a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/MigratePortfoliosLiveMeasuresToMeasuresIT.java
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v108/MigratePortfoliosLiveMeasuresToMeasuresIT.java
@@ -282,7 +282,7 @@ class MigratePortfoliosLiveMeasuresToMeasuresIT {
"component_uuid", componentUuid,
"branch_uuid", branch,
"json_value", "{\"any\":\"thing\"}",
- "json_value_hash", "1234",
+ "json_value_hash", 1234,
"created_at", 12,
"updated_at", 12);
}
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/AddProductionScopeToScaDependenciesTableIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/AddProductionScopeToScaDependenciesTableIT.java
index b8ec749e66b..8ed2cb41454 100644
--- a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/AddProductionScopeToScaDependenciesTableIT.java
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/AddProductionScopeToScaDependenciesTableIT.java
@@ -17,7 +17,7 @@
* 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.v202503;
+package org.sonar.server.platform.db.migration.version.v202502;
import java.sql.SQLException;
import org.junit.jupiter.api.Test;
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnArchitectureGraphsIT.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnArchitectureGraphsIT.java
new file mode 100644
index 00000000000..cc1d462e536
--- /dev/null
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnArchitectureGraphsIT.java
@@ -0,0 +1,55 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.v202502;
+
+import java.sql.SQLException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.sonar.db.MigrationDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.db.MigrationDbTester.createForMigrationStep;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateUniqueIndexOnArchitectureGraphs.COLUMN_NAME_BRANCH_UUID;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateUniqueIndexOnArchitectureGraphs.COLUMN_NAME_SOURCE;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateUniqueIndexOnArchitectureGraphs.COLUMN_NAME_TYPE;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateUniqueIndexOnArchitectureGraphs.INDEX_NAME;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateUniqueIndexOnArchitectureGraphs.TABLE_NAME;
+
+class CreateIndexOnArchitectureGraphsIT {
+
+ @RegisterExtension
+ public final MigrationDbTester db = createForMigrationStep(CreateUniqueIndexOnArchitectureGraphs.class);
+ private final DdlChange underTest = new CreateUniqueIndexOnArchitectureGraphs(db.database());
+
+ @Test
+ void execute_shouldCreateIndex() throws SQLException {
+ db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+ underTest.execute();
+ db.assertUniqueIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME_BRANCH_UUID, COLUMN_NAME_TYPE, COLUMN_NAME_SOURCE);
+ }
+
+ @Test
+ void execute_shouldBeReentrant() throws SQLException {
+ db.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+ underTest.execute();
+ underTest.execute();
+ db.assertUniqueIndex(TABLE_NAME, INDEX_NAME, COLUMN_NAME_BRANCH_UUID, COLUMN_NAME_TYPE, COLUMN_NAME_SOURCE);
+ }
+}
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuidTest.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnScaReleasesComponentUuidTest.java
index d7630686669..05857305b63 100644
--- a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuidTest.java
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnScaReleasesComponentUuidTest.java
@@ -17,7 +17,7 @@
* 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.v202503;
+package org.sonar.server.platform.db.migration.version.v202502;
import java.sql.SQLException;
import org.junit.jupiter.api.Test;
@@ -26,10 +26,10 @@ import org.sonar.db.MigrationDbTester;
import org.sonar.server.platform.db.migration.step.DdlChange;
import static org.sonar.db.MigrationDbTester.createForMigrationStep;
-import static org.sonar.server.platform.db.migration.version.v202503.CreateIndexOnScaReleasesComponentUuid.COLUMN_NAME_COMPONENT_UUID;
-import static org.sonar.server.platform.db.migration.version.v202503.CreateIndexOnScaReleasesComponentUuid.COLUMN_NAME_UUID;
-import static org.sonar.server.platform.db.migration.version.v202503.CreateIndexOnScaReleasesComponentUuid.INDEX_NAME;
-import static org.sonar.server.platform.db.migration.version.v202503.CreateIndexOnScaReleasesComponentUuid.TABLE_NAME;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateIndexOnScaReleasesComponentUuid.COLUMN_NAME_COMPONENT_UUID;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateIndexOnScaReleasesComponentUuid.COLUMN_NAME_UUID;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateIndexOnScaReleasesComponentUuid.INDEX_NAME;
+import static org.sonar.server.platform.db.migration.version.v202502.CreateIndexOnScaReleasesComponentUuid.TABLE_NAME;
class CreateIndexOnScaReleasesComponentUuidTest {
@RegisterExtension
diff --git a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponentTest.java b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/DropIndexOnScaReleasesComponentTest.java
index 97f8a4d557d..ec377d5fb96 100644
--- a/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponentTest.java
+++ b/server/sonar-db-migration/src/it/java/org/sonar/server/platform/db/migration/version/v202502/DropIndexOnScaReleasesComponentTest.java
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.server.platform.db.migration.version.v202503;
+package org.sonar.server.platform.db.migration.version.v202502;
import java.sql.SQLException;
import org.junit.jupiter.api.Test;
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
index 5b5af55fd0b..f844369bf02 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/MigrationConfigurationModule.java
@@ -39,7 +39,6 @@ import org.sonar.server.platform.db.migration.version.v107.DbVersion107;
import org.sonar.server.platform.db.migration.version.v108.DbVersion108;
import org.sonar.server.platform.db.migration.version.v202501.DbVersion202501;
import org.sonar.server.platform.db.migration.version.v202502.DbVersion202502;
-import org.sonar.server.platform.db.migration.version.v202503.DbVersion202503;
public class MigrationConfigurationModule extends Module {
@Override
@@ -59,7 +58,6 @@ public class MigrationConfigurationModule extends Module {
DbVersion108.class,
DbVersion202501.class,
DbVersion202502.class,
- DbVersion202503.class,
// migration steps
MigrationStepRegistryImpl.class,
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/AddDeclaredLicenseExpressionToScaReleasesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/AddDeclaredLicenseExpressionToScaReleasesTable.java
index b8a0c26e52b..c44a3dc006c 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/AddDeclaredLicenseExpressionToScaReleasesTable.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/AddDeclaredLicenseExpressionToScaReleasesTable.java
@@ -17,7 +17,7 @@
* 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.v202503;
+package org.sonar.server.platform.db.migration.version.v202502;
import java.sql.SQLException;
import org.sonar.db.Database;
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/AddProductionScopeToScaDependenciesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/AddProductionScopeToScaDependenciesTable.java
index 4764e60d61b..bf2aab43019 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/AddProductionScopeToScaDependenciesTable.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/AddProductionScopeToScaDependenciesTable.java
@@ -17,7 +17,7 @@
* 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.v202503;
+package org.sonar.server.platform.db.migration.version.v202502;
import java.sql.SQLException;
import org.sonar.db.Database;
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuid.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnScaReleasesComponentUuid.java
index 85dc6395842..848d5925a9e 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/CreateIndexOnScaReleasesComponentUuid.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/CreateIndexOnScaReleasesComponentUuid.java
@@ -17,7 +17,7 @@
* 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.v202503;
+package org.sonar.server.platform.db.migration.version.v202502;
import java.sql.Connection;
import java.sql.SQLException;
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/CreateUniqueIndexOnArchitectureGraphs.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/CreateUniqueIndexOnArchitectureGraphs.java
new file mode 100644
index 00000000000..802396d18b1
--- /dev/null
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/CreateUniqueIndexOnArchitectureGraphs.java
@@ -0,0 +1,60 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.v202502;
+
+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.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class CreateUniqueIndexOnArchitectureGraphs extends DdlChange {
+
+ static final String TABLE_NAME = "architecture_graphs";
+ static final String INDEX_NAME = "uq_idx_ag_branch_type_source";
+ static final String COLUMN_NAME_BRANCH_UUID = "branch_uuid";
+ static final String COLUMN_NAME_TYPE = "type";
+ static final String COLUMN_NAME_SOURCE = "source";
+
+ public CreateUniqueIndexOnArchitectureGraphs(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ createIndex(context, connection);
+ }
+ }
+
+ private void createIndex(Context context, Connection connection) {
+ if (!DatabaseUtils.indexExistsIgnoreCase(TABLE_NAME, INDEX_NAME, connection)) {
+ context.execute(new CreateIndexBuilder(getDialect())
+ .setTable(TABLE_NAME)
+ .setName(INDEX_NAME)
+ .setUnique(true)
+ .addColumn(COLUMN_NAME_BRANCH_UUID, false)
+ .addColumn(COLUMN_NAME_TYPE, false)
+ .addColumn(COLUMN_NAME_SOURCE, false)
+ .build());
+ }
+ }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/DbVersion202502.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/DbVersion202502.java
index 0db5c95b6f3..8bbbe17ee01 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/DbVersion202502.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/DbVersion202502.java
@@ -54,6 +54,10 @@ public class DbVersion202502 implements DbVersion {
.add(2025_02_015, "Add new_in_pull_request column to SCA dependencies", AddNewInPullRequestToScaDependenciesTable.class)
.add(2025_02_016, "Insert default AI Codefix provider key and modelKey properties", InsertDefaultAiSuggestionProviderKeyAndModelKeyProperties.class)
.add(2025_02_017, "Add table 'architecture_graphs'", CreateArchitectureGraphsTable.class)
- ;
+ .add(2025_02_018, "Drop 'sca_releases_comp_uuid' index", DropIndexOnScaReleasesComponent.class)
+ .add(2025_02_019, "Create 'sca_releases_comp_uuid_uuid' index", CreateIndexOnScaReleasesComponentUuid.class)
+ .add(2025_02_020, "Add 'sca_dependencies.production_scope' column", AddProductionScopeToScaDependenciesTable.class)
+ .add(2025_02_021, "Add declared_license_expression to SCA releases", AddDeclaredLicenseExpressionToScaReleasesTable.class)
+ .add(2025_02_022, "Create 'uq_idx_ag_branch_type_source' for architecture graphs", CreateUniqueIndexOnArchitectureGraphs.class);
}
}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponent.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/DropIndexOnScaReleasesComponent.java
index 8001e821463..5cec4743767 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DropIndexOnScaReleasesComponent.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202502/DropIndexOnScaReleasesComponent.java
@@ -17,7 +17,7 @@
* 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.v202503;
+package org.sonar.server.platform.db.migration.version.v202502;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.step.DropIndexChange;
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503.java
deleted file mode 100644
index c015f4a94ea..00000000000
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2025 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.v202503;
-
-import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
-import org.sonar.server.platform.db.migration.version.DbVersion;
-
-// ignoring bad number formatting, as it's indented that we align the migration numbers to SQ versions
-@SuppressWarnings("java:S3937")
-public class DbVersion202503 implements DbVersion {
-
- /**
- * We use the start of the 10.X cycle as an opportunity to align migration numbers with the SQ version number.
- * Please follow this pattern:
- * 2025_03_000
- * 2025_03_001
- * 2025_03_002
- */
- @Override
- public void addSteps(MigrationStepRegistry registry) {
- registry
- .add(2025_03_000, "Drop 'sca_releases_comp_uuid' index", DropIndexOnScaReleasesComponent.class)
- .add(2025_03_001, "Create 'sca_releases_comp_uuid_uuid' index", CreateIndexOnScaReleasesComponentUuid.class)
- .add(2025_03_002, "Add 'sca_dependencies.production_scope' column", AddProductionScopeToScaDependenciesTable.class)
- .add(2025_03_003, "Add declared_license_expression to SCA releases", AddDeclaredLicenseExpressionToScaReleasesTable.class);
- }
-}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/package-info.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/package-info.java
deleted file mode 100644
index cc36bc37f03..00000000000
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v202503/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2025 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.server.platform.db.migration.version.v202503;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202503/AddDeclaredLicenseExpressionToScaReleasesTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202502/AddDeclaredLicenseExpressionToScaReleasesTableTest.java
index f2ff0411c79..182fcf41ecb 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202503/AddDeclaredLicenseExpressionToScaReleasesTableTest.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202502/AddDeclaredLicenseExpressionToScaReleasesTableTest.java
@@ -17,7 +17,7 @@
* 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.v202503;
+package org.sonar.server.platform.db.migration.version.v202502;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503Test.java
deleted file mode 100644
index e1480dd9844..00000000000
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v202503/DbVersion202503Test.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2025 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.v202503;
-
-import org.junit.jupiter.api.Test;
-
-import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationNotEmpty;
-import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
-
-class DbVersion202503Test {
-
- private final DbVersion202503 underTest = new DbVersion202503();
-
- @Test
- void migrationNumber_starts_at_2025_03_000() {
- verifyMinimumMigrationNumber(underTest, 2025_03_000);
- }
-
- @Test
- void verify_migration_is_not_empty() {
- verifyMigrationNotEmpty(underTest);
- }
-}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java b/server/sonar-server-common/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java
index 92ffa498023..1786a62e90f 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java
@@ -20,13 +20,13 @@
package org.sonar.server.setting;
import com.google.common.annotations.VisibleForTesting;
+import jakarta.inject.Inject;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
-import jakarta.inject.Inject;
import org.apache.ibatis.exceptions.PersistenceException;
import org.sonar.api.CoreProperties;
import org.sonar.api.ce.ComputeEngineSide;
diff --git a/server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/Dimension.java b/server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/Dimension.java
index f3479858bff..4b136272f6c 100644
--- a/server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/Dimension.java
+++ b/server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/Dimension.java
@@ -31,7 +31,8 @@ public enum Dimension {
USER("user"),
PROJECT("project"),
LANGUAGE("language"),
- ANALYSIS("analysis");
+ ANALYSIS("analysis"),
+ FIX_SUGGESTION("fixsuggestion");
private final String value;
diff --git a/server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/schema/FixSuggestionMetric.java b/server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/schema/FixSuggestionMetric.java
new file mode 100644
index 00000000000..e7b079a0b6d
--- /dev/null
+++ b/server/sonar-telemetry-core/src/main/java/org/sonar/telemetry/core/schema/FixSuggestionMetric.java
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.telemetry.core.schema;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.sonar.telemetry.core.TelemetryDataType;
+
+import static org.sonar.telemetry.core.Granularity.ADHOC;
+
+public class FixSuggestionMetric extends InstallationMetric {
+
+ @JsonProperty("fix_suggestion_uuid")
+ private String fixSuggestionUuid;
+
+ @JsonProperty("project_uuid")
+ private String projectUuid;
+
+ public FixSuggestionMetric(String key, Object value, TelemetryDataType type, String projectUuid, String fixSuggestionUuid) {
+ super(key, value, type, ADHOC);
+ this.projectUuid = projectUuid;
+ this.fixSuggestionUuid = fixSuggestionUuid;
+ }
+
+ public String getProjectUuid() {
+ return projectUuid;
+ }
+
+ public void setProjectUuid(String projectUuid) {
+ this.projectUuid = projectUuid;
+ }
+
+ public String getFixSuggestionUuid() {
+ return fixSuggestionUuid;
+ }
+
+ public void setFixSuggestionUuid(String fixSuggestionUuid) {
+ this.fixSuggestionUuid = fixSuggestionUuid;
+ }
+}
diff --git a/server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/DimensionTest.java b/server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/DimensionTest.java
index f80c2a971bb..69d77f3716f 100644
--- a/server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/DimensionTest.java
+++ b/server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/DimensionTest.java
@@ -39,11 +39,13 @@ class DimensionTest {
assertEquals(Dimension.USER, Dimension.fromValue("user"));
assertEquals(Dimension.PROJECT, Dimension.fromValue("project"));
assertEquals(Dimension.LANGUAGE, Dimension.fromValue("language"));
+ assertEquals(Dimension.FIX_SUGGESTION, Dimension.fromValue("fixsuggestion"));
assertEquals(Dimension.INSTALLATION, Dimension.fromValue("INSTALLATION"));
assertEquals(Dimension.USER, Dimension.fromValue("USER"));
assertEquals(Dimension.PROJECT, Dimension.fromValue("PROJECT"));
assertEquals(Dimension.LANGUAGE, Dimension.fromValue("LANGUAGE"));
+ assertEquals(Dimension.FIX_SUGGESTION, Dimension.fromValue("FIXSUGGESTION"));
}
@Test
diff --git a/server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/schema/FixSuggestionMetricTest.java b/server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/schema/FixSuggestionMetricTest.java
new file mode 100644
index 00000000000..4169ca95089
--- /dev/null
+++ b/server/sonar-telemetry-core/src/test/java/org/sonar/telemetry/core/schema/FixSuggestionMetricTest.java
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.telemetry.core.schema;
+
+import org.junit.jupiter.api.Test;
+import org.sonar.telemetry.core.Granularity;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.telemetry.core.TelemetryDataType.STRING;
+
+class FixSuggestionMetricTest {
+
+ @Test
+ void getters() {
+ FixSuggestionMetric metric = new FixSuggestionMetric("ai_codefix.suggestion_rule_key", "rule:key", STRING, "projectUuid", "fixSuggestionUuid");
+
+ assertThat(metric.getKey()).isEqualTo("ai_codefix.suggestion_rule_key");
+ assertThat(metric.getValue()).isEqualTo("rule:key");
+ assertThat(metric.getProjectUuid()).isEqualTo("projectUuid");
+ assertThat(metric.getGranularity()).isEqualTo(Granularity.ADHOC);
+ assertThat(metric.getType()).isEqualTo(STRING);
+ assertThat(metric.getFixSuggestionUuid()).isEqualTo("fixSuggestionUuid");
+ }
+
+ @Test
+ void setters() {
+ FixSuggestionMetric metric = new FixSuggestionMetric("ai_codefix.suggestion_rule_key", "rule:key", STRING, "projectUuid", "fixSuggestionUuid");
+ metric.setProjectUuid("newProjectUuid");
+ metric.setFixSuggestionUuid("newFixSuggestionUuid");
+
+ assertThat(metric.getProjectUuid()).isEqualTo("newProjectUuid");
+ assertThat(metric.getFixSuggestionUuid()).isEqualTo("newFixSuggestionUuid");
+ }
+}
diff --git a/server/sonar-webserver-api/src/it/java/org/sonar/server/plugins/DetectPluginChangeIT.java b/server/sonar-webserver-api/src/it/java/org/sonar/server/plugins/DetectPluginChangeIT.java
index 174537211d5..51745d15781 100644
--- a/server/sonar-webserver-api/src/it/java/org/sonar/server/plugins/DetectPluginChangeIT.java
+++ b/server/sonar-webserver-api/src/it/java/org/sonar/server/plugins/DetectPluginChangeIT.java
@@ -19,6 +19,8 @@
*/
package org.sonar.server.plugins;
+import java.util.List;
+import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.Plugin;
@@ -96,6 +98,35 @@ public class DetectPluginChangeIT {
}
@Test
+ public void detect_changes_when_forced_refresh() {
+ addPluginToDb("plugin1", "hash1", PluginDto.Type.BUNDLED);
+ addPluginToFs("plugin1", "hash1", PluginType.BUNDLED);
+ addPluginToDb("plugin2", "hash2", PluginDto.Type.EXTERNAL);
+ addPluginToFs("plugin2", "hash2", PluginType.EXTERNAL);
+
+ dbTester.executeDdl("insert into internal_properties (kee, is_empty, text_value, created_at) values ('plugin.refresh.forced', false, 'true', 12345)");
+
+ detectPluginChange.start();
+ assertThat(detectPluginChange.anyPluginChanged()).isTrue();
+
+ // Ensure the force refresh flag has been deleted
+ assertThat(getInternalProperty("plugin.refresh.forced")).isEmpty();
+ }
+
+ @Test
+ public void detect_changes_when_internal_propertiy_has_false_value_should_not_refresh() {
+ addPluginToDb("plugin1", "hash1", PluginDto.Type.BUNDLED);
+ addPluginToFs("plugin1", "hash1", PluginType.BUNDLED);
+ addPluginToDb("plugin2", "hash2", PluginDto.Type.EXTERNAL);
+ addPluginToFs("plugin2", "hash2", PluginType.EXTERNAL);
+
+ dbTester.executeDdl("insert into internal_properties (kee, is_empty, text_value, created_at) values ('plugin.refresh.forced', false, 'false', 12345)");
+
+ detectPluginChange.start();
+ assertThat(detectPluginChange.anyPluginChanged()).isFalse();
+ }
+
+ @Test
public void fail_if_start_twice() {
detectPluginChange.start();
assertThrows(IllegalStateException.class, detectPluginChange::start);
@@ -123,4 +154,7 @@ public class DetectPluginChangeIT {
pluginRepository.addPlugin(serverPlugin);
}
+ private List<Map<String, Object>> getInternalProperty(String key) {
+ return dbTester.select("select * from internal_properties where kee='" + key + "'");
+ }
}
diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/DetectPluginChange.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/DetectPluginChange.java
index 40f8f8036d7..af1972430f9 100644
--- a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/DetectPluginChange.java
+++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/DetectPluginChange.java
@@ -34,6 +34,7 @@ import org.sonar.db.plugin.PluginDto;
import static java.util.function.Function.identity;
public class DetectPluginChange implements Startable {
+ public static final String FORCE_PLUGIN_RELOAD_PROPERTY = "plugin.refresh.forced";
private static final Logger LOG = Loggers.get(DetectPluginChange.class);
private final ServerPluginRepository serverPluginRepository;
@@ -49,7 +50,7 @@ public class DetectPluginChange implements Startable {
public void start() {
Preconditions.checkState(changesDetected == null, "Can only call #start() once");
Profiler profiler = Profiler.create(LOG).startInfo("Detect plugin changes");
- changesDetected = anyChange();
+ changesDetected = isForcedReload() || anyChange();
if (changesDetected) {
LOG.debug("Plugin changes detected");
} else {
@@ -65,6 +66,17 @@ public class DetectPluginChange implements Startable {
return changesDetected;
}
+ private boolean isForcedReload() {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ boolean forceRefresh = Boolean.parseBoolean(dbClient.internalPropertiesDao().selectByKey(dbSession, FORCE_PLUGIN_RELOAD_PROPERTY).orElse("false"));
+ if (forceRefresh) {
+ dbClient.internalPropertiesDao().delete(dbSession, FORCE_PLUGIN_RELOAD_PROPERTY);
+ dbSession.commit();
+ }
+ return forceRefresh;
+ }
+ }
+
private boolean anyChange() {
try (DbSession dbSession = dbClient.openSession(false)) {
Map<String, PluginDto> dbPluginsByKey = dbClient.pluginDao().selectAll(dbSession).stream()
diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/PropertiesDBCleaner.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/PropertiesDBCleaner.java
new file mode 100644
index 00000000000..d4f87c46ce4
--- /dev/null
+++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/PropertiesDBCleaner.java
@@ -0,0 +1,62 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.startup;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.SonarEdition;
+import org.sonar.api.SonarRuntime;
+import org.sonar.api.Startable;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+
+import static java.util.Arrays.asList;
+
+public class PropertiesDBCleaner implements Startable {
+ private static final Logger LOG = LoggerFactory.getLogger(PropertiesDBCleaner.class);
+ private final SonarRuntime runtime;
+ private final DbClient dbClient;
+
+ public PropertiesDBCleaner(DbClient dbClient, SonarRuntime runtime) {
+ this.dbClient = dbClient;
+ this.runtime = runtime;
+ }
+
+ @Override
+ public void start() {
+ LOG.info("Clean up properties from db");
+ deleteMisraPropertyIfRequired();
+ }
+
+ private void deleteMisraPropertyIfRequired() {
+ String misraProperty = "sonar.earlyAccess.misra.enabled";
+ SonarEdition edition = runtime.getEdition();
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ if (asList(SonarEdition.COMMUNITY, SonarEdition.DEVELOPER).contains(edition)) {
+ dbClient.propertiesDao().deleteGlobalProperty(misraProperty, dbSession);
+ dbSession.commit();
+ }
+ }
+ }
+
+ @Override
+ public void stop() {
+ // Nothing to do
+ }
+}
diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/PropertiesDBCleanerTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/PropertiesDBCleanerTest.java
new file mode 100644
index 00000000000..15c9955f853
--- /dev/null
+++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/PropertiesDBCleanerTest.java
@@ -0,0 +1,78 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2025 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.startup;
+
+import java.util.Objects;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.sonar.api.SonarEdition;
+import org.sonar.api.SonarRuntime;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.property.PropertyDto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+
+class PropertiesDBCleanerTest {
+ @RegisterExtension
+ public DbTester db = DbTester.create();
+ private final DbClient dbClient = db.getDbClient();
+ private final DbSession dbSession = db.getSession();
+ private final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
+ private static final String MISRA_SETTING = "sonar.earlyAccess.misra.enabled";
+
+ @ParameterizedTest
+ @ValueSource(strings = { "COMMUNITY", "DEVELOPER" })
+ void should_clean_up_misra_prop_when_dev_or_community_edition(String edition) {
+ when(sonarRuntime.getEdition()).thenReturn(SonarEdition.valueOf(edition));
+
+ dbClient
+ .propertiesDao()
+ .saveProperty(dbSession, new PropertyDto()
+ .setKey(MISRA_SETTING)
+ .setValue("true"), null, null, null, null);
+ dbSession.commit();
+
+ new PropertiesDBCleaner(dbClient, sonarRuntime).start();
+ assertThat(dbClient.propertiesDao().selectGlobalProperty(MISRA_SETTING)).isNull();
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = { "ENTERPRISE", "DATACENTER" })
+ void should_not_clean_up_misra_prop_when_enterprise_or_above(String edition) {
+ when(sonarRuntime.getEdition()).thenReturn(SonarEdition.valueOf(edition));
+
+ PropertyDto prop = new PropertyDto()
+ .setKey(MISRA_SETTING)
+ .setValue("true");
+ dbClient
+ .propertiesDao()
+ .saveProperty(dbSession, prop, null, null, null, null);
+ dbSession.commit();
+
+ new PropertiesDBCleaner(dbClient, sonarRuntime).start();
+ assertThat(Objects.requireNonNull(dbClient.propertiesDao().selectGlobalProperty(MISRA_SETTING)).getValue()).isEqualTo(prop.getValue());
+ }
+}
diff --git a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java
index e9162a0c1f3..f8c11a99d6e 100644
--- a/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java
+++ b/server/sonar-webserver-webapi-v2/src/main/java/org/sonar/server/v2/WebApiEndpoints.java
@@ -21,7 +21,7 @@ package org.sonar.server.v2;
public class WebApiEndpoints {
public static final String JSON_MERGE_PATCH_CONTENT_TYPE = "application/merge-patch+json";
- public static final String INTERNAL = "internal";
+ public static final String INTERNAL = "x-sonar-internal";
public static final String SYSTEM_DOMAIN = "/system";
public static final String LIVENESS_ENDPOINT = SYSTEM_DOMAIN + "/liveness";
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java
index 95a2e80093a..0c1e7a36271 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/measure/ws/ComponentActionIT.java
@@ -33,6 +33,7 @@ import org.sonar.db.component.ProjectData;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.measure.MeasureDto;
import org.sonar.db.metric.MetricDto;
+import org.sonar.db.permission.GlobalPermission;
import org.sonar.server.component.TestComponentFinder;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
@@ -50,6 +51,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple;
import static org.sonar.api.measures.CoreMetrics.RELIABILITY_ISSUES;
import static org.sonar.api.utils.DateUtils.parseDateTime;
+import static org.sonar.api.web.UserRole.SCAN;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME;
import static org.sonar.db.component.BranchType.PULL_REQUEST;
@@ -107,6 +109,32 @@ public class ComponentActionIT {
}
@Test
+ public void user_with_project_scan_permission_is_allowed_to_get_project_measures() {
+ ProjectData projectData = db.components().insertPrivateProject();
+ ComponentDto mainBranch = projectData.getMainBranchComponent();
+ userSession.addProjectPermission(SCAN, projectData.getProjectDto())
+ .registerBranches(projectData.getMainBranchDto());
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType("INT"));
+
+ ComponentWsResponse response = newRequest(mainBranch.getKey(), metric.getKey());
+
+ assertThat(response.getMetrics().getMetricsCount()).isOne();
+ }
+
+ @Test
+ public void user_with_global_scan_permission_is_allowed_to_get_project_status() {
+ ProjectData projectData = db.components().insertPrivateProject();
+ ComponentDto mainBranch = projectData.getMainBranchComponent();
+ userSession.addPermission(GlobalPermission.SCAN);
+
+ MetricDto metric = db.measures().insertMetric(m -> m.setValueType("INT"));
+
+ ComponentWsResponse response = newRequest(mainBranch.getKey(), metric.getKey());
+
+ assertThat(response.getMetrics().getMetricsCount()).isOne();
+ }
+
+ @Test
public void without_additional_fields() {
ProjectData projectData = db.components().insertPrivateProject();
ComponentDto mainBranch = projectData.getMainBranchComponent();
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java
index 8206511d176..af594642a2e 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualityprofile/ws/CreateActionIT.java
@@ -21,30 +21,18 @@ package org.sonar.server.qualityprofile.ws;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
-import org.sonar.api.config.Configuration;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.System2;
-import org.sonar.api.utils.Version;
-import org.sonar.core.platform.SonarQubeVersion;
import org.sonar.core.util.UuidFactoryFast;
-import org.sonar.core.util.UuidFactoryImpl;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.qualityprofile.QProfileDto;
-import org.sonar.db.rule.RuleDto;
-import org.sonar.db.rule.RuleTesting;
import org.sonar.server.es.EsTester;
import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.pushapi.qualityprofile.QualityProfileChangeEventService;
import org.sonar.server.qualityprofile.QProfileFactoryImpl;
-import org.sonar.server.qualityprofile.QProfileRules;
-import org.sonar.server.qualityprofile.QProfileRulesImpl;
-import org.sonar.server.qualityprofile.builtin.RuleActivator;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
-import org.sonar.server.rule.index.RuleIndex;
-import org.sonar.server.rule.index.RuleIndexer;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
@@ -56,7 +44,6 @@ import org.sonarqube.ws.Qualityprofiles.CreateWsResponse.QualityProfile;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.mockito.Mockito.mock;
import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES;
import static org.sonar.db.permission.GlobalPermission.SCAN;
import static org.sonar.server.language.LanguageTesting.newLanguages;
@@ -64,9 +51,6 @@ import static org.sonar.server.language.LanguageTesting.newLanguages;
class CreateActionIT {
private static final String XOO_LANGUAGE = "xoo";
- private static final RuleDto RULE = RuleTesting.newXooX1()
- .setSeverity("MINOR")
- .setLanguage(XOO_LANGUAGE);
@RegisterExtension
private final DbTester db = DbTester.create();
@@ -75,20 +59,12 @@ class CreateActionIT {
@RegisterExtension
private final UserSessionRule userSession = UserSessionRule.standalone();
- private final Configuration config = mock(Configuration.class);
private final DbClient dbClient = db.getDbClient();
private final DbSession dbSession = db.getSession();
- private final RuleIndex ruleIndex = new RuleIndex(es.client(), System2.INSTANCE, config);
- private final RuleIndexer ruleIndexer = new RuleIndexer(es.client(), dbClient);
private final ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(dbClient, es.client());
- private final QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
- private final SonarQubeVersion sonarQubeVersion = new SonarQubeVersion(Version.create(10, 3));
- private final RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, UuidFactoryImpl.INSTANCE, null, userSession, mock(Configuration.class),
- sonarQubeVersion);
- private final QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);
private final CreateAction underTest = new CreateAction(dbClient, new QProfileFactoryImpl(dbClient, UuidFactoryFast.getInstance(), System2.INSTANCE, activeRuleIndexer),
- newLanguages(XOO_LANGUAGE), userSession, activeRuleIndexer);
+ newLanguages(XOO_LANGUAGE), userSession);
private WsActionTester ws = new WsActionTester(underTest);
@@ -153,12 +129,6 @@ class CreateActionIT {
assertThat(response.getMediaType()).isEqualTo(MediaTypes.JSON);
}
- private void insertRule(RuleDto ruleDto) {
- dbClient.ruleDao().insert(dbSession, ruleDto);
- dbSession.commit();
- ruleIndexer.commitAndIndex(dbSession, ruleDto.getUuid());
- }
-
private CreateWsResponse executeRequest(String name, String language) {
TestRequest request = ws.newRequest()
.setParam("name", name)
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
index 0f52c689e69..f57d384d416 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/ws/ComponentAction.java
@@ -42,6 +42,7 @@ import org.sonar.db.component.SnapshotDto;
import org.sonar.db.measure.MeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.db.metric.MetricDtoFunctions;
+import org.sonar.db.permission.GlobalPermission;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.UserSession;
@@ -66,6 +67,7 @@ import static org.sonar.server.measure.ws.ComponentResponseCommon.addMetricToRes
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createAdditionalFieldsParameter;
import static org.sonar.server.measure.ws.MeasuresWsParametersBuilder.createMetricKeysParameter;
import static org.sonar.server.measure.ws.SnapshotDtoToWsPeriod.snapshotToWsPeriods;
+import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.KEY_PULL_REQUEST_EXAMPLE_001;
@@ -88,10 +90,15 @@ public class ComponentAction implements MeasuresWsAction {
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction(ACTION_COMPONENT)
.setDescription("Return component with specified measures.<br>" +
- "Requires the following permission: 'Browse' on the project of specified component.")
+ "Requires one of the following permissions:" +
+ "<ul>" +
+ "<li>'Browse' on the project of the specified component</li>" +
+ "<li>'Execute Analysis' on the project of the specified component</li>" +
+ "</ul>")
.setResponseExample(getClass().getResource("component-example.json"))
.setSince("5.4")
.setChangelog(
+ new Change("2025.2", "The 'Execute Analysis' permission also allows to access the endpoint"),
new Change("10.8", format("The following metrics are not deprecated anymore: %s",
MeasuresWsModule.getUndeprecatedMetricsinSonarQube108())),
new Change("10.8", String.format("Added new accepted values for the 'metricKeys' param: %s",
@@ -282,7 +289,11 @@ public class ComponentAction implements MeasuresWsAction {
}
private void checkPermissions(ComponentDto baseComponent) {
- userSession.checkComponentPermission(UserRole.USER, baseComponent);
+ if (!userSession.hasComponentPermission(UserRole.USER, baseComponent) &&
+ !userSession.hasComponentPermission(UserRole.SCAN, baseComponent) &&
+ !userSession.hasPermission(GlobalPermission.SCAN)) {
+ throw insufficientPrivilegesException();
+ }
}
private static class ComponentRequest {
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java
deleted file mode 100644
index 2dadd2d8015..00000000000
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/QProfileResult.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2025 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.qualityprofile;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.sonar.db.qualityprofile.QProfileDto;
-
-public class QProfileResult {
-
- private List<String> warnings;
- private List<String> infos;
-
- private QProfileDto profile;
-
- private List<ActiveRuleChange> changes;
-
- public QProfileResult() {
- warnings = new ArrayList<>();
- infos = new ArrayList<>();
- changes = new ArrayList<>();
- }
-
- public List<String> warnings() {
- return warnings;
- }
-
- public QProfileResult addWarnings(List<String> warnings) {
- this.warnings.addAll(warnings);
- return this;
- }
-
- public List<String> infos() {
- return infos;
- }
-
- public QProfileResult addInfos(List<String> infos) {
- this.infos.addAll(infos);
- return this;
- }
-
- public QProfileDto profile() {
- return profile;
- }
-
- public QProfileResult setProfile(QProfileDto profile) {
- this.profile = profile;
- return this;
- }
-
- public List<ActiveRuleChange> getChanges() {
- return changes;
- }
-
- public QProfileResult addChanges(List<ActiveRuleChange> changes) {
- this.changes.addAll(changes);
- return this;
- }
-
- public QProfileResult add(QProfileResult result) {
- warnings.addAll(result.warnings());
- infos.addAll(result.infos());
- changes.addAll(result.getChanges());
- return this;
- }
-
-}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java
index cc833d15e83..2c391027a21 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/CreateAction.java
@@ -29,9 +29,7 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.QProfileDto;
import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileResult;
import org.sonar.server.qualityprofile.builtin.QProfileName;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.Qualityprofiles.CreateWsResponse;
@@ -51,15 +49,13 @@ public class CreateAction implements QProfileWsAction {
private final QProfileFactory profileFactory;
private final Languages languages;
private final UserSession userSession;
- private final ActiveRuleIndexer activeRuleIndexer;
public CreateAction(DbClient dbClient, QProfileFactory profileFactory, Languages languages,
- UserSession userSession, ActiveRuleIndexer activeRuleIndexer) {
+ UserSession userSession) {
this.dbClient = dbClient;
this.profileFactory = profileFactory;
this.languages = languages;
this.userSession = userSession;
- this.activeRuleIndexer = activeRuleIndexer;
}
@Override
@@ -88,19 +84,17 @@ public class CreateAction implements QProfileWsAction {
@Override
public void handle(Request request, Response response) throws Exception {
userSession.checkLoggedIn();
+ userSession.checkPermission(ADMINISTER_QUALITY_PROFILES);
try (DbSession dbSession = dbClient.openSession(false)) {
- userSession.checkPermission(ADMINISTER_QUALITY_PROFILES);
CreateRequest createRequest = toRequest(request);
writeProtobuf(doHandle(dbSession, createRequest), request, response);
}
}
private CreateWsResponse doHandle(DbSession dbSession, CreateRequest createRequest) {
- QProfileResult result = new QProfileResult();
QProfileDto profile = profileFactory.checkAndCreateCustom(dbSession, QProfileName.createFor(createRequest.getLanguage(), createRequest.getName()));
- result.setProfile(profile);
- activeRuleIndexer.commitAndIndex(dbSession, result.getChanges());
- return buildResponse(result);
+ dbSession.commit();
+ return buildResponse(profile);
}
private static CreateRequest toRequest(Request request) {
@@ -110,21 +104,15 @@ public class CreateAction implements QProfileWsAction {
return builder.build();
}
- private CreateWsResponse buildResponse(QProfileResult result) {
- String language = result.profile().getLanguage();
+ private CreateWsResponse buildResponse(QProfileDto profile) {
+ String language = profile.getLanguage();
CreateWsResponse.QualityProfile.Builder builder = CreateWsResponse.QualityProfile.newBuilder()
- .setKey(result.profile().getKee())
- .setName(result.profile().getName())
+ .setKey(profile.getKee())
+ .setName(profile.getName())
.setLanguage(language)
- .setLanguageName(languages.get(result.profile().getLanguage()).getName())
+ .setLanguageName(languages.get(profile.getLanguage()).getName())
.setIsDefault(false)
.setIsInherited(false);
- if (!result.infos().isEmpty()) {
- builder.getInfosBuilder().addAllInfos(result.infos());
- }
- if (!result.warnings().isEmpty()) {
- builder.getWarningsBuilder().addAllWarnings(result.warnings());
- }
return CreateWsResponse.newBuilder().setProfile(builder.build()).build();
}
diff --git a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/qualityprofile/ws/create-example.json b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/qualityprofile/ws/create-example.json
index b154d6233ae..a1f54c5aa82 100644
--- a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/qualityprofile/ws/create-example.json
+++ b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/qualityprofile/ws/create-example.json
@@ -6,11 +6,5 @@
"languageName" : "Java",
"name" : "My New Profile",
"key" : "AU-TpxcA-iU5OvuD2FL1"
- },
- "warnings" : [
- "Unable to import unknown PMD rule 'rulesets/java/strings.xml'",
- "Unable to import unknown PMD rule 'rulesets/java/basic.xml/UnnecessaryConversionTemporary'",
- "Unable to import unknown PMD rule 'rulesets/java/basic.xml/EmptyCatchBlock'",
- "Unable to import unknown PMD rule 'rulesets/java/braces.xml'"
- ]
+ }
}
diff --git a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel3.java b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel3.java
index 6d29800e273..8d6253b5e58 100644
--- a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel3.java
+++ b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel3.java
@@ -31,6 +31,7 @@ import org.sonar.server.platform.serverid.ServerIdModule;
import org.sonar.server.plugins.DetectPluginChange;
import org.sonar.server.setting.DatabaseSettingLoader;
import org.sonar.server.setting.DatabaseSettingsEnabler;
+import org.sonar.server.startup.PropertiesDBCleaner;
import static org.sonar.core.extension.CoreExtensionsInstaller.noAdditionalSideFilter;
import static org.sonar.core.extension.PlatformLevelPredicates.hasPlatformLevel;
@@ -49,6 +50,7 @@ public class PlatformLevel3 extends PlatformLevel {
NoopDatabaseMigrationImpl.class,
new ServerIdModule(),
ServerImpl.class,
+ PropertiesDBCleaner.class,
DatabaseSettingLoader.class,
DatabaseSettingsEnabler.class,
UriReader.class,