import org.sonar.server.platform.db.migration.version.v100.DbVersion100;
import org.sonar.server.platform.db.migration.version.v101.DbVersion101;
import org.sonar.server.platform.db.migration.version.v102.DbVersion102;
+import org.sonar.server.platform.db.migration.version.v103.DbVersion103;
public class MigrationConfigurationModule extends Module {
@Override
DbVersion100.class,
DbVersion101.class,
DbVersion102.class,
+ DbVersion103.class,
// migration steps
MigrationStepRegistryImpl.class,
import java.util.Date;
import java.util.List;
import org.sonar.api.utils.System2;
+import org.sonar.core.config.CorePropertyDefinitions;
import org.sonar.core.platform.SonarQubeVersion;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.Database;
.setLong(5, now)
.addBatch();
+ upsert.setString(1, uuidFactory.create())
+ .setString(2, CorePropertyDefinitions.ALLOW_DISABLE_INHERITED_RULES)
+ .setBoolean(3, false)
+ .setString(4, "true")
+ .setLong(5, now)
+ .addBatch();
+
upsert
.setString(1, uuidFactory.create())
.setString(2, "projects.default.visibility")
.setBoolean(3, false)
.setString(4, "public")
- .setLong(5, system2.now())
+ .setLong(5, now)
.addBatch();
upsert
private void insertGroupRoles(Context context, Groups groups) throws SQLException {
truncateTable(context, "group_roles");
- Upsert upsert = context.prepareUpsert(createInsertStatement("group_roles", "uuid","group_uuid", "role"));
+ Upsert upsert = context.prepareUpsert(createInsertStatement("group_roles", "uuid", "group_uuid", "role"));
for (String adminRole : ADMIN_ROLES) {
upsert
.setString(1, uuidFactory.create())
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.v103;
+
+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 DbVersion103 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:
+ * 10_0_000
+ * 10_0_001
+ * 10_0_002
+ * 10_1_000
+ * 10_1_001
+ * 10_1_002
+ * 10_2_000
+ */
+
+ @Override
+ public void addSteps(MigrationStepRegistry registry) {
+ registry
+ .add(10_3_000, "Set 'sonar.qualityProfiles.allowDisableInheritedRules' to false for upgraded instances", SetAllowQualityProfileDisableInheritedRules.class);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.v103;
+
+import java.sql.SQLException;
+import org.sonar.api.utils.System2;
+import org.sonar.core.config.CorePropertyDefinitions;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.Select;
+
+public class SetAllowQualityProfileDisableInheritedRules extends DataChange {
+ private System2 system2;
+ private UuidFactory uuidFactory;
+
+ public SetAllowQualityProfileDisableInheritedRules(Database db, System2 system2, UuidFactory uuidFactory) {
+ super(db);
+ this.system2 = system2;
+ this.uuidFactory = uuidFactory;
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ if (!propertyIsAlreadyDefined(context)) {
+ insertPropertyWithValueAsFalse(context);
+ }
+ }
+
+ private static boolean propertyIsAlreadyDefined(Context context) throws SQLException {
+ Select select = context.prepareSelect("select p.text_value from properties p where p.prop_key = ?")
+ .setString(1, CorePropertyDefinitions.ALLOW_DISABLE_INHERITED_RULES);
+ String value = select.get(row -> row.getString(1));
+ return value != null;
+ }
+
+ private void insertPropertyWithValueAsFalse(Context context) throws SQLException {
+ context.prepareUpsert("INSERT INTO properties"
+ + "(prop_key, is_empty, text_value, created_at, uuid) "
+ + "VALUES(?, ?, ?, ?, ?)")
+ .setString(1, CorePropertyDefinitions.ALLOW_DISABLE_INHERITED_RULES)
+ .setBoolean(2, false)
+ .setString(3, "false")
+ .setLong(4, system2.now())
+ .setString(5, uuidFactory.create())
+ .execute()
+ .commit();
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.v103;
+
+import javax.annotation.ParametersAreNonnullByDefault;
"text_value as \"VAL\"," +
"created_at as \"CREATED_AT\" " +
" from properties");
- assertThat(rows).hasSize(3);
+ assertThat(rows).hasSize(4);
Map<String, Map<String, Object>> rowsByKey = rows.stream().collect(Collectors.toMap(t -> (String) t.get("PROP_KEY"), Function.identity()));
verifyProperty(rowsByKey, "sonar.forceAuthentication", "true");
+ verifyProperty(rowsByKey, "sonar.qualityProfiles.allowDisableInheritedRules", "true");
verifyProperty(rowsByKey, "projects.default.visibility", "public");
verifyProperty(rowsByKey, "qualitygate.default", qualityGateUuid);
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.v103;
+
+import org.junit.Test;
+
+import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMigrationNotEmpty;
+import static org.sonar.server.platform.db.migration.version.DbVersionTestUtils.verifyMinimumMigrationNumber;
+
+public class DbVersion103Test {
+
+ private final DbVersion103 underTest = new DbVersion103();
+
+ @Test
+ public void migrationNumber_starts_at_10_3_000() {
+ verifyMinimumMigrationNumber(underTest, 10_3_000);
+ }
+
+ @Test
+ public void verify_migration_is_not_empty() {
+ verifyMigrationNotEmpty(underTest);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 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.v103;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.impl.utils.TestSystem2;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SetAllowQualityProfileDisableInheritedRulesTest {
+
+ private static final long NOW = 1;
+
+ @Rule
+ public CoreDbTester dbTester = CoreDbTester.createForSchema(SetAllowQualityProfileDisableInheritedRulesTest.class, "schema.sql");
+
+ private final System2 system2 = new TestSystem2().setNow(NOW);
+
+ private final SetAllowQualityProfileDisableInheritedRules script = new SetAllowQualityProfileDisableInheritedRules(dbTester.database(), system2, UuidFactoryFast.getInstance());
+
+ @Test
+ public void execute_shouldInsertPropertyWithFalseValue() throws SQLException {
+ script.execute();
+
+ assertThatForceAuthenticationEquals("false");
+ }
+
+ @Test
+ public void execute_shouldBeReentrant() throws SQLException {
+ script.execute();
+ // re-entrant
+ script.execute();
+
+ assertThatForceAuthenticationEquals("false");
+ }
+
+ @Test
+ public void execute_shouldNotUpdateTheValueThatAlreadyExistsInTheDatabase() throws SQLException {
+ insertPropertyWithValueAsTrue();
+ script.execute();
+
+ assertThatForceAuthenticationEquals("true");
+ }
+
+ private void assertThatForceAuthenticationEquals(String s) {
+ assertThat(dbTester.selectFirst("select p.text_value from properties p where p.prop_key = 'sonar.qualityProfiles.allowDisableInheritedRules'"))
+ .containsEntry("TEXT_VALUE", s);
+ }
+
+ private void insertPropertyWithValueAsTrue() {
+ dbTester.executeInsert("properties",
+ "uuid", "uuid-1",
+ "prop_key", "sonar.qualityProfiles.allowDisableInheritedRules",
+ "is_empty", false,
+ "text_value", "true",
+ "created_at", NOW);
+ }
+}
--- /dev/null
+CREATE TABLE "PROPERTIES"
+(
+ "UUID" CHARACTER VARYING(40) NOT NULL,
+ "PROP_KEY" CHARACTER VARYING(512) NOT NULL,
+ "IS_EMPTY" BOOLEAN NOT NULL,
+ "TEXT_VALUE" CHARACTER VARYING(4000),
+ "CLOB_VALUE" CHARACTER LARGE OBJECT,
+ "CREATED_AT" BIGINT NOT NULL,
+ "ENTITY_UUID" CHARACTER VARYING(40),
+ "USER_UUID" CHARACTER VARYING(255)
+);
+ALTER TABLE "PROPERTIES"
+ ADD CONSTRAINT "PK_PROPERTIES" PRIMARY KEY ("UUID");
+CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY" NULLS FIRST);
\ No newline at end of file
public static final String DISABLE_NOTIFICATION_ON_BUILT_IN_QPROFILES = "sonar.builtInQualityProfiles.disableNotificationOnUpdate";
+ public static final String ALLOW_DISABLE_INHERITED_RULES = "sonar.qualityProfiles.allowDisableInheritedRules";
+
public static final String PLUGINS_RISK_CONSENT = "sonar.plugins.risk.consent";
public static final String DOCUMENTATION_BASE_URL = "sonar.documentation.baseUrl";
public static final String SUBCATEGORY_PROJECT_CREATION = "subProjectCreation";
+ public static final String SUBCATEGORY_QUALITY_PROFILE = "qualityProfile";
private CorePropertyDefinitions() {
// only static stuff
.description("Avoid sending email notification on each update of built-in quality profiles to quality profile administrators.")
.defaultValue(Boolean.toString(false))
.category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(SUBCATEGORY_QUALITY_PROFILE)
+ .type(BOOLEAN)
+ .build(),
+ PropertyDefinition.builder(ALLOW_DISABLE_INHERITED_RULES)
+ .name("Enable deactivation of inherited rules")
+ .description("Set if users with 'Administer Quality Profiles' permission are allowed to deactivate inherited rules in quality profiles.")
+ .defaultValue(Boolean.toString(true))
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(SUBCATEGORY_QUALITY_PROFILE)
.type(BOOLEAN)
.build(),
PropertyDefinition.builder(PLUGINS_RISK_CONSENT)
property.category.general.looknfeel=Look & Feel
property.category.general.issues=Issues
property.category.general.qualityGate=Quality Gate
+property.category.general.qualityProfile=Quality Profile
property.category.general.subProjects=Sub-projects
property.category.general.subProjectCreation=Project Creation
property.category.almintegration=DevOps Platform Integrations