@@ -186,6 +186,7 @@ CREATE TABLE "RULES" ( | |||
"NAME" VARCHAR(200), | |||
"STATUS" VARCHAR(40), | |||
"LANGUAGE" VARCHAR(20), | |||
"SCOPE" VARCHAR(20) NOT NULL, | |||
"DEF_REMEDIATION_FUNCTION" VARCHAR(20), | |||
"DEF_REMEDIATION_GAP_MULT" VARCHAR(20), | |||
"DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20), |
@@ -31,6 +31,7 @@ import org.apache.commons.lang.builder.HashCodeBuilder; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rules.RuleType; | |||
import org.sonar.db.rule.RuleDto.Scope; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
@@ -54,6 +55,7 @@ public class RuleDefinitionDto { | |||
private String gapDescription; | |||
private String systemTags; | |||
private int type; | |||
private Scope scope; | |||
private RuleKey key; | |||
@@ -295,6 +297,15 @@ public class RuleDefinitionDto { | |||
return this; | |||
} | |||
public Scope getScope() { | |||
return this.scope; | |||
} | |||
public RuleDefinitionDto setScope(Scope scope) { | |||
this.scope = scope; | |||
return this; | |||
} | |||
@CheckForNull | |||
public String getPluginKey() { | |||
return pluginKey; | |||
@@ -358,6 +369,7 @@ public class RuleDefinitionDto { | |||
", key=" + key + | |||
", createdAt=" + createdAt + | |||
", updatedAt=" + updatedAt + | |||
", scope=" + scope + | |||
'}'; | |||
} | |||
} |
@@ -33,6 +33,10 @@ public class RuleDto { | |||
public enum Format { | |||
HTML, MARKDOWN | |||
} | |||
public enum Scope { | |||
MAIN, TEST, ALL; | |||
} | |||
private final RuleDefinitionDto definition; | |||
private final RuleMetadataDto metadata; | |||
@@ -138,11 +142,20 @@ public class RuleDto { | |||
public String getConfigKey() { | |||
return definition.getConfigKey(); | |||
} | |||
public RuleDto setConfigKey(@Nullable String configKey) { | |||
definition.setConfigKey(configKey); | |||
return this; | |||
} | |||
public Scope getScope() { | |||
return definition.getScope(); | |||
} | |||
public RuleDto setScope(Scope scope) { | |||
definition.setScope(scope); | |||
return this; | |||
} | |||
@CheckForNull | |||
public Integer getSeverity() { |
@@ -23,6 +23,7 @@ | |||
r.system_tags as "systemTagsField", | |||
r.rule_type as "type", | |||
r.plugin_key as "pluginKey", | |||
r.scope, | |||
</sql> | |||
<sql id="selectRuleTableColumns"> | |||
@@ -301,6 +302,7 @@ | |||
gap_description, | |||
system_tags, | |||
rule_type, | |||
scope, | |||
created_at, | |||
updated_at | |||
) | |||
@@ -323,6 +325,7 @@ | |||
#{gapDescription,jdbcType=VARCHAR}, | |||
#{systemTagsField,jdbcType=VARCHAR}, | |||
#{type,jdbcType=TINYINT}, | |||
#{scope,jdbcType=VARCHAR}, | |||
#{createdAt,jdbcType=BIGINT}, | |||
#{updatedAt,jdbcType=BIGINT} | |||
) | |||
@@ -347,6 +350,7 @@ | |||
def_remediation_base_effort=#{defRemediationBaseEffort,jdbcType=VARCHAR}, | |||
gap_description=#{gapDescription,jdbcType=VARCHAR}, | |||
system_tags=#{systemTagsField,jdbcType=VARCHAR}, | |||
scope=#{scope,jdbcType=VARCHAR}, | |||
rule_type=#{type,jdbcType=TINYINT}, | |||
updated_at=#{updatedAt,jdbcType=BIGINT} | |||
where |
@@ -44,6 +44,7 @@ import org.sonar.db.RowNotFoundException; | |||
import org.sonar.db.es.RuleExtensionId; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.organization.OrganizationTesting; | |||
import org.sonar.db.rule.RuleDto.Scope; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
import static java.util.Arrays.asList; | |||
@@ -329,6 +330,7 @@ public class RuleDaoTest { | |||
.setGapDescription("squid.S115.effortToFix") | |||
.setSystemTags(newHashSet("systag1", "systag2")) | |||
.setType(RuleType.BUG) | |||
.setScope(Scope.ALL) | |||
.setCreatedAt(1_500_000_000_000L) | |||
.setUpdatedAt(2_000_000_000_000L); | |||
underTest.insert(db.getSession(), newRule); | |||
@@ -352,6 +354,7 @@ public class RuleDaoTest { | |||
assertThat(ruleDto.getDefRemediationBaseEffort()).isEqualTo("10h"); | |||
assertThat(ruleDto.getGapDescription()).isEqualTo("squid.S115.effortToFix"); | |||
assertThat(ruleDto.getSystemTags()).containsOnly("systag1", "systag2"); | |||
assertThat(ruleDto.getScope()).isEqualTo(Scope.ALL); | |||
assertThat(ruleDto.getType()).isEqualTo(RuleType.BUG.getDbConstant()); | |||
assertThat(ruleDto.getCreatedAt()).isEqualTo(1_500_000_000_000L); | |||
assertThat(ruleDto.getUpdatedAt()).isEqualTo(2_000_000_000_000L); | |||
@@ -379,6 +382,7 @@ public class RuleDaoTest { | |||
.setDefRemediationBaseEffort("10h") | |||
.setGapDescription("squid.S115.effortToFix") | |||
.setSystemTags(newHashSet("systag1", "systag2")) | |||
.setScope(Scope.ALL) | |||
.setType(RuleType.BUG) | |||
.setUpdatedAt(2_000_000_000_000L); | |||
@@ -402,6 +406,7 @@ public class RuleDaoTest { | |||
assertThat(ruleDto.getDefRemediationBaseEffort()).isEqualTo("10h"); | |||
assertThat(ruleDto.getGapDescription()).isEqualTo("squid.S115.effortToFix"); | |||
assertThat(ruleDto.getSystemTags()).containsOnly("systag1", "systag2"); | |||
assertThat(ruleDto.getScope()).isEqualTo(Scope.ALL); | |||
assertThat(ruleDto.getType()).isEqualTo(RuleType.BUG.getDbConstant()); | |||
assertThat(ruleDto.getCreatedAt()).isEqualTo(1_500_000_000_000L); | |||
assertThat(ruleDto.getUpdatedAt()).isEqualTo(2_000_000_000_000L); | |||
@@ -783,8 +788,9 @@ public class RuleDaoTest { | |||
tuple(r1.getKey(), organization.getUuid(), r1Extension.getTagsAsString())); | |||
} | |||
private static class Accumulator<T> implements Consumer<T> { | |||
private static class Accumulator<T> implements Consumer<T> { | |||
private final List<T> list = new ArrayList<>(); | |||
@Override | |||
public void accept(T dto) { | |||
list.add(dto); |
@@ -15,6 +15,7 @@ | |||
def_remediation_gap_mult="5d" | |||
def_remediation_base_effort="10h" | |||
gap_description="squid.S115.effortToFix" | |||
scope="MAIN" | |||
created_at="[null]" | |||
updated_at="[null]" | |||
/> |
@@ -12,6 +12,7 @@ | |||
def_remediation_gap_mult="5d" | |||
def_remediation_base_effort="10h" | |||
gap_description="squid.S115.effortToFix" | |||
scope="MAIN" | |||
created_at="1500000000000" | |||
updated_at="1600000000000" | |||
/> | |||
@@ -27,6 +28,7 @@ | |||
def_remediation_function="[null]" | |||
def_remediation_gap_mult="[null]" | |||
def_remediation_base_effort="[null]" | |||
scope="MAIN" | |||
gap_description="[null]" | |||
created_at="1500000000000" | |||
updated_at="1600000000000" |
@@ -8,6 +8,7 @@ | |||
description="Should avoid NULL" | |||
status="READY" | |||
description_format="HTML" | |||
scope="MAIN" | |||
created_at="1500000000000" | |||
updated_at="1600000000000"/> | |||
<rules system_tags="[null]" | |||
@@ -18,6 +19,7 @@ | |||
description="Should not appear" | |||
status="READY" | |||
description_format="HTML" | |||
scope="MAIN" | |||
created_at="1500000000000" | |||
updated_at="1600000000000"/> | |||
@@ -7,6 +7,7 @@ | |||
name="Avoid Null" | |||
description="Should avoid NULL" | |||
status="READY" | |||
scope="MAIN" | |||
created_at="1500000000000" | |||
updated_at="1600000000000"/> | |||
<rules_parameters id="1" | |||
@@ -23,6 +24,7 @@ | |||
name="Unused Rule" | |||
description="Not used" | |||
status="REMOVED" | |||
scope="MAIN" | |||
created_at="1500000000000" | |||
updated_at="1600000000000"/> | |||
<rules_parameters id="2" |
@@ -13,6 +13,7 @@ | |||
system_tags="cwe" | |||
created_at="1500000000000" | |||
updated_at="1600000000000" | |||
scope="ALL" | |||
/> | |||
<rules id="2" | |||
@@ -28,6 +29,7 @@ | |||
system_tags="[null]" | |||
created_at="1500000000000" | |||
updated_at="1600000000000" | |||
scope="ALL" | |||
/> | |||
<rules id="10" | |||
@@ -43,6 +45,7 @@ | |||
system_tags="[null]" | |||
created_at="1500000000000" | |||
updated_at="1600000000000" | |||
scope="ALL" | |||
/> | |||
</dataset> |
@@ -10,6 +10,7 @@ | |||
plugin_config_key="AvoidNull" | |||
priority="2" | |||
is_template="[false]" | |||
scope="MAIN" | |||
language="golo" | |||
created_at="1500000000000" | |||
updated_at="1600000000000"/> |
@@ -6,6 +6,7 @@ | |||
name="Avoid Null" | |||
description="Should avoid NULL" | |||
status="READY" | |||
scope="MAIN" | |||
created_at="1500000000000" | |||
updated_at="1600000000000"/> | |||
@@ -6,6 +6,7 @@ | |||
name="Avoid Null" | |||
description="Should avoid NULL" | |||
status="READY" | |||
scope="MAIN" | |||
created_at="1500000000000" | |||
updated_at="1600000000000"/> | |||
@@ -0,0 +1,26 @@ | |||
package org.sonar.server.platform.db.migration.version.v71; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.def.VarcharColumnDef; | |||
import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
public class AddRuleScope extends DdlChange { | |||
public AddRuleScope(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new AddColumnsBuilder(getDialect(), "rules") | |||
.addColumn(VarcharColumnDef.newVarcharColumnDefBuilder() | |||
.setColumnName("scope") | |||
.setIsNullable(true) | |||
.setLimit(20) | |||
.build()) | |||
.build()); | |||
} | |||
} |
@@ -27,6 +27,9 @@ public class DbVersion71 implements DbVersion { | |||
@Override | |||
public void addSteps(MigrationStepRegistry registry) { | |||
registry | |||
.add(2000, "Delete settings defined in sonar.properties from PROPERTIES table", DeleteSettingsDefinedInSonarDotProperties.class); | |||
.add(2000, "Delete settings defined in sonar.properties from PROPERTIES table", DeleteSettingsDefinedInSonarDotProperties.class) | |||
.add(2001, "Add scope to rules", AddRuleScope.class) | |||
.add(2002, "Set rules scope to MAIN", SetRuleScopeToMain.class) | |||
.add(2003, "Make scope not nullable in rules", MakeScopeNotNullableInRules.class); | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 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.v71; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; | |||
public class MakeScopeNotNullableInRules extends DdlChange { | |||
private static final String TABLE_NAME = "rules"; | |||
public MakeScopeNotNullableInRules(Database db) { | |||
super(db); | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new AlterColumnsBuilder(getDialect(), TABLE_NAME) | |||
.updateColumn(newVarcharColumnDefBuilder() | |||
.setColumnName("scope") | |||
.setLimit(20) | |||
.setIsNullable(false) | |||
.build()) | |||
.build()); | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
package org.sonar.server.platform.db.migration.version.v71; | |||
import java.sql.SQLException; | |||
import org.sonar.api.rule.RuleScope; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.step.DataChange; | |||
import org.sonar.server.platform.db.migration.step.MassUpdate; | |||
public class SetRuleScopeToMain extends DataChange { | |||
private final System2 system2; | |||
public SetRuleScopeToMain(Database db, System2 system2) { | |||
super(db); | |||
this.system2 = system2; | |||
} | |||
@Override | |||
protected void execute(Context context) throws SQLException { | |||
long now = system2.now(); | |||
MassUpdate massUpdate = context.prepareMassUpdate(); | |||
massUpdate.select("select id from rules where scope is NULL"); | |||
massUpdate.rowPluralName("rules"); | |||
massUpdate.update("update rules set scope=?, updated_at=? where scope is NULL"); | |||
massUpdate.execute((row, update) -> { | |||
update.setString(1, RuleScope.MAIN.name()); | |||
update.setLong(2, now); | |||
return true; | |||
}); | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
package org.sonar.server.platform.db.migration.version.v71; | |||
import java.sql.SQLException; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.db.CoreDbTester; | |||
import static java.sql.Types.VARCHAR; | |||
public class AddRuleScopeTest { | |||
@Rule | |||
public final CoreDbTester dbTester = CoreDbTester.createForSchema(AddRuleScopeTest.class, "rules.sql"); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private AddRuleScope underTest = new AddRuleScope(dbTester.database()); | |||
@Test | |||
public void column_is_added_to_table() throws SQLException { | |||
underTest.execute(); | |||
dbTester.assertColumnDefinition("rules", "scope", VARCHAR, null, true); | |||
} | |||
@Test | |||
public void migration_is_not_reentrant() throws SQLException { | |||
underTest.execute(); | |||
expectedException.expect(IllegalStateException.class); | |||
underTest.execute(); | |||
} | |||
} |
@@ -36,7 +36,7 @@ public class DbVersion71Test { | |||
@Test | |||
public void verify_migration_count() { | |||
verifyMigrationCount(underTest, 1); | |||
verifyMigrationCount(underTest, 4); | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2018 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.v71; | |||
import java.sql.SQLException; | |||
import java.sql.Types; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.rule.RuleScope; | |||
import org.sonar.db.CoreDbTester; | |||
public class MakeScopeNotNullableInRulesTest { | |||
@Rule | |||
public CoreDbTester db = CoreDbTester.createForSchema(MakeScopeNotNullableInRulesTest.class, "rules.sql"); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private MakeScopeNotNullableInRules underTest = new MakeScopeNotNullableInRules(db.database()); | |||
@Test | |||
public void execute_makes_column_not_null() throws SQLException { | |||
db.assertColumnDefinition("rules", "scope", Types.VARCHAR, null, true); | |||
insertRow(1); | |||
insertRow(2); | |||
underTest.execute(); | |||
db.assertColumnDefinition("rules", "scope", Types.VARCHAR, null, false); | |||
} | |||
private void insertRow(int id) { | |||
db.executeInsert( | |||
"RULES", | |||
"PLUGIN_RULE_KEY", "key_" + id, | |||
"PLUGIN_NAME", "name_" + id, | |||
"SCOPE", RuleScope.MAIN.name()); | |||
} | |||
} |
@@ -0,0 +1,88 @@ | |||
package org.sonar.server.platform.db.migration.version.v71; | |||
import java.sql.SQLException; | |||
import javax.annotation.Nullable; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.api.rule.RuleScope; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.db.CoreDbTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class SetRuleScopeToMainTest { | |||
@Rule | |||
public final CoreDbTester dbTester = CoreDbTester.createForSchema(SetRuleScopeToMainTest.class, "rules.sql"); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private System2 system = new System2(); | |||
private SetRuleScopeToMain underTest = new SetRuleScopeToMain(dbTester.database(), system); | |||
@Test | |||
public void has_no_effect_if_table_rules_is_empty() throws SQLException { | |||
underTest.execute(); | |||
assertThat(dbTester.countRowsOfTable("rules")).isEqualTo(0); | |||
} | |||
@Test | |||
public void updates_rows_with_null_is_build_in_column_to_false() throws SQLException { | |||
insertRow(1, null); | |||
insertRow(2, null); | |||
assertThat(countRowsWithValue(null)).isEqualTo(2); | |||
assertThat(countRowsWithValue(RuleScope.MAIN)).isEqualTo(0); | |||
underTest.execute(); | |||
assertThat(countRowsWithValue(null)).isEqualTo(0); | |||
assertThat(countRowsWithValue(RuleScope.MAIN)).isEqualTo(2); | |||
} | |||
@Test | |||
public void support_large_number_of_rows() throws SQLException { | |||
for (int i = 0; i < 2_000; i++) { | |||
insertRow(i, null); | |||
} | |||
assertThat(countRowsWithValue(null)).isEqualTo(2000); | |||
assertThat(countRowsWithValue(RuleScope.MAIN)).isZero(); | |||
underTest.execute(); | |||
assertThat(countRowsWithValue(RuleScope.MAIN)).isEqualTo(2_000); | |||
assertThat(countRowsWithValue(null)).isEqualTo(0); | |||
} | |||
@Test | |||
public void execute_is_reentreant() throws SQLException { | |||
insertRow(1, null); | |||
insertRow(2, RuleScope.MAIN); | |||
underTest.execute(); | |||
underTest.execute(); | |||
assertThat(countRowsWithValue(null)).isEqualTo(0); | |||
assertThat(countRowsWithValue(RuleScope.MAIN)).isEqualTo(2); | |||
} | |||
private int countRowsWithValue(@Nullable RuleScope value) { | |||
if (value == null) { | |||
return dbTester.countSql("select count(1) from rules where scope is null"); | |||
} | |||
return dbTester.countSql("select count(1) from rules where scope='" + value + "'"); | |||
} | |||
private void insertRow(int id, @Nullable RuleScope scope) { | |||
dbTester.executeInsert( | |||
"RULES", | |||
"PLUGIN_RULE_KEY", "key_" + id, | |||
"PLUGIN_NAME", "name_" + id, | |||
"SCOPE", scope == null ? null : scope.name()); | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
CREATE TABLE "RULES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"PLUGIN_KEY" VARCHAR(200), | |||
"PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL, | |||
"PLUGIN_NAME" VARCHAR(255) NOT NULL, | |||
"DESCRIPTION" VARCHAR(16777215), | |||
"DESCRIPTION_FORMAT" VARCHAR(20), | |||
"PRIORITY" INTEGER, | |||
"IS_TEMPLATE" BOOLEAN DEFAULT FALSE, | |||
"TEMPLATE_ID" INTEGER, | |||
"PLUGIN_CONFIG_KEY" VARCHAR(200), | |||
"NAME" VARCHAR(200), | |||
"STATUS" VARCHAR(40), | |||
"LANGUAGE" VARCHAR(20), | |||
"DEF_REMEDIATION_FUNCTION" VARCHAR(20), | |||
"DEF_REMEDIATION_GAP_MULT" VARCHAR(20), | |||
"DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20), | |||
"GAP_DESCRIPTION" VARCHAR(4000), | |||
"SYSTEM_TAGS" VARCHAR(4000), | |||
"RULE_TYPE" TINYINT, | |||
"CREATED_AT" BIGINT, | |||
"UPDATED_AT" BIGINT | |||
); | |||
CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); |
@@ -0,0 +1,25 @@ | |||
CREATE TABLE "RULES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"PLUGIN_KEY" VARCHAR(200), | |||
"PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL, | |||
"PLUGIN_NAME" VARCHAR(255) NOT NULL, | |||
"DESCRIPTION" VARCHAR(16777215), | |||
"DESCRIPTION_FORMAT" VARCHAR(20), | |||
"PRIORITY" INTEGER, | |||
"IS_TEMPLATE" BOOLEAN DEFAULT FALSE, | |||
"TEMPLATE_ID" INTEGER, | |||
"PLUGIN_CONFIG_KEY" VARCHAR(200), | |||
"NAME" VARCHAR(200), | |||
"STATUS" VARCHAR(40), | |||
"LANGUAGE" VARCHAR(20), | |||
"SCOPE" VARCHAR(20), | |||
"DEF_REMEDIATION_FUNCTION" VARCHAR(20), | |||
"DEF_REMEDIATION_GAP_MULT" VARCHAR(20), | |||
"DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20), | |||
"GAP_DESCRIPTION" VARCHAR(4000), | |||
"SYSTEM_TAGS" VARCHAR(4000), | |||
"RULE_TYPE" TINYINT, | |||
"CREATED_AT" BIGINT, | |||
"UPDATED_AT" BIGINT | |||
); | |||
CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); |
@@ -0,0 +1,25 @@ | |||
CREATE TABLE "RULES" ( | |||
"ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), | |||
"PLUGIN_KEY" VARCHAR(200), | |||
"PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL, | |||
"PLUGIN_NAME" VARCHAR(255) NOT NULL, | |||
"DESCRIPTION" VARCHAR(16777215), | |||
"DESCRIPTION_FORMAT" VARCHAR(20), | |||
"PRIORITY" INTEGER, | |||
"IS_TEMPLATE" BOOLEAN DEFAULT FALSE, | |||
"TEMPLATE_ID" INTEGER, | |||
"PLUGIN_CONFIG_KEY" VARCHAR(200), | |||
"NAME" VARCHAR(200), | |||
"STATUS" VARCHAR(40), | |||
"LANGUAGE" VARCHAR(20), | |||
"SCOPE" VARCHAR(20), | |||
"DEF_REMEDIATION_FUNCTION" VARCHAR(20), | |||
"DEF_REMEDIATION_GAP_MULT" VARCHAR(20), | |||
"DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20), | |||
"GAP_DESCRIPTION" VARCHAR(4000), | |||
"SYSTEM_TAGS" VARCHAR(4000), | |||
"RULE_TYPE" TINYINT, | |||
"CREATED_AT" BIGINT, | |||
"UPDATED_AT" BIGINT | |||
); | |||
CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); |
@@ -50,6 +50,7 @@ import org.sonar.db.qualityprofile.ActiveRuleDto; | |||
import org.sonar.db.qualityprofile.ActiveRuleParamDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto.Format; | |||
import org.sonar.db.rule.RuleDto.Scope; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.db.rule.RuleRepositoryDto; | |||
import org.sonar.server.organization.OrganizationFlags; | |||
@@ -226,6 +227,7 @@ public class RegisterRules implements Startable { | |||
.setGapDescription(ruleDef.gapDescription()) | |||
.setSystemTags(ruleDef.tags()) | |||
.setType(RuleType.valueOf(ruleDef.type().name())) | |||
.setScope(toDtoScope(ruleDef.scope())) | |||
.setCreatedAt(system2.now()) | |||
.setUpdatedAt(system2.now()); | |||
if (ruleDef.htmlDescription() != null) { | |||
@@ -240,6 +242,19 @@ public class RegisterRules implements Startable { | |||
return ruleDto; | |||
} | |||
private static Scope toDtoScope(RulesDefinition.Scope scope) { | |||
switch (scope) { | |||
case ALL: | |||
return Scope.ALL; | |||
case MAIN: | |||
return Scope.MAIN; | |||
case TEST: | |||
return Scope.TEST; | |||
default: | |||
throw new IllegalArgumentException("Unknown rule scope: " + scope); | |||
} | |||
} | |||
private boolean mergeRule(RulesDefinition.Rule def, RuleDefinitionDto dto) { | |||
boolean changed = false; | |||
if (!StringUtils.equals(dto.getName(), def.name())) { | |||
@@ -271,6 +286,10 @@ public class RegisterRules implements Startable { | |||
dto.setStatus(def.status()); | |||
changed = true; | |||
} | |||
if (!StringUtils.equals(dto.getScope().name(), def.scope().name())) { | |||
dto.setScope(toDtoScope(def.scope())); | |||
changed = true; | |||
} | |||
if (!StringUtils.equals(dto.getLanguage(), def.repository().language())) { | |||
dto.setLanguage(def.repository().language()); | |||
changed = true; |
@@ -40,6 +40,7 @@ import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.db.rule.RuleRepositoryDto; | |||
import org.sonar.db.rule.RuleDto.Scope; | |||
import org.sonar.server.language.LanguageTesting; | |||
import org.sonar.server.qualityprofile.QProfileComparison; | |||
import org.sonar.server.qualityprofile.QProfileName; | |||
@@ -203,6 +204,7 @@ public class CompareActionTest { | |||
.setName(StringUtils.capitalize(id)) | |||
.setLanguage(lang) | |||
.setSeverity(Severity.BLOCKER) | |||
.setScope(Scope.MAIN) | |||
.setStatus(RuleStatus.READY); | |||
RuleDefinitionDto ruleDefinition = rule.getDefinition(); | |||
db.ruleDao().insert(session, ruleDefinition); |
@@ -29,6 +29,7 @@ import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleDto.Scope; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.organization.TestDefaultOrganizationProvider; | |||
@@ -49,6 +50,7 @@ public class DefaultRuleFinderTest { | |||
.setRuleKey("com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck") | |||
.setRepositoryKey("checkstyle") | |||
.setSeverity(4) | |||
.setScope(Scope.MAIN) | |||
.setStatus(RuleStatus.READY); | |||
private RuleDto rule2 = new RuleDto() | |||
@@ -57,6 +59,7 @@ public class DefaultRuleFinderTest { | |||
.setRuleKey("DisabledCheck") | |||
.setRepositoryKey("checkstyle") | |||
.setSeverity(4) | |||
.setScope(Scope.MAIN) | |||
.setStatus(RuleStatus.REMOVED); | |||
private RuleDto rule3 = new RuleDto() | |||
@@ -65,6 +68,7 @@ public class DefaultRuleFinderTest { | |||
.setRuleKey("com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck") | |||
.setRepositoryKey("checkstyle") | |||
.setSeverity(4) | |||
.setScope(Scope.MAIN) | |||
.setStatus(RuleStatus.READY); | |||
private RuleDto rule4 = new RuleDto() | |||
@@ -73,6 +77,7 @@ public class DefaultRuleFinderTest { | |||
.setRuleKey("CallSuperFirst") | |||
.setRepositoryKey("pmd") | |||
.setSeverity(2) | |||
.setScope(Scope.MAIN) | |||
.setStatus(RuleStatus.READY); | |||
private DefaultRuleFinder underTest = new DefaultRuleFinder(dbClient, defaultOrganizationProvider); |
@@ -42,6 +42,7 @@ import org.sonar.db.DbTester; | |||
import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleDto.Scope; | |||
import org.sonar.db.rule.RuleParamDto; | |||
import org.sonar.db.rule.RuleRepositoryDto; | |||
import org.sonar.server.es.EsTester; | |||
@@ -121,6 +122,7 @@ public class RegisterRulesTest { | |||
assertThat(rule1.getConfigKey()).isEqualTo("config1"); | |||
assertThat(rule1.getStatus()).isEqualTo(RuleStatus.BETA); | |||
assertThat(rule1.getCreatedAt()).isEqualTo(DATE1.getTime()); | |||
assertThat(rule1.getScope()).isEqualTo(Scope.ALL); | |||
assertThat(rule1.getUpdatedAt()).isEqualTo(DATE1.getTime()); | |||
assertThat(rule1.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET.name()); | |||
assertThat(rule1.getDefRemediationGapMultiplier()).isEqualTo("5d"); | |||
@@ -494,6 +496,7 @@ public class RegisterRulesTest { | |||
.setRuleKey("rule1") | |||
.setRepositoryKey("findbugs") | |||
.setName("Rule One") | |||
.setScope(Scope.ALL) | |||
.setDescription("Rule one description") | |||
.setDescriptionFormat(RuleDto.Format.HTML) | |||
.setSystemTags(newHashSet("tag1", "tag2"))); | |||
@@ -562,6 +565,7 @@ public class RegisterRulesTest { | |||
.setSeverity(BLOCKER) | |||
.setInternalKey("config1") | |||
.setTags("tag1", "tag2", "tag3") | |||
.setScope(Scope.ALL) | |||
.setType(RuleType.CODE_SMELL) | |||
.setStatus(RuleStatus.BETA) | |||
.setGapDescription("squid.S115.effortToFix"); |
@@ -36,6 +36,7 @@ import org.sonar.db.organization.OrganizationDto; | |||
import org.sonar.db.rule.RuleDefinitionDto; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.db.rule.RuleDto.Scope; | |||
import org.sonar.server.es.EsTester; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
@@ -66,6 +67,7 @@ public class RuleIndexerTest { | |||
.setIsTemplate(true) | |||
.setSystemTags(newHashSet("cwe")) | |||
.setType(RuleType.BUG) | |||
.setScope(Scope.ALL) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1600000000000L); | |||
@@ -4,7 +4,8 @@ | |||
name="Avoid Cycles" | |||
plugin_rule_key="AvoidCycles" | |||
plugin_config_key="[null]" | |||
plugin_name="squid"/> | |||
plugin_name="squid" | |||
scope="MAIN"/> | |||
<projects organization_uuid="org1" | |||
uuid="PROJECT" |
@@ -4,7 +4,8 @@ | |||
name="Avoid Cycles" | |||
plugin_rule_key="AvoidCycles" | |||
plugin_config_key="[null]" | |||
plugin_name="squid"/> | |||
plugin_name="squid" | |||
scope="MAIN"/> | |||
<projects organization_uuid="org1" | |||
uuid="PROJECT" |
@@ -4,7 +4,8 @@ | |||
name="Avoid Cycles" | |||
plugin_rule_key="AvoidCycles" | |||
plugin_config_key="[null]" | |||
plugin_name="squid"/> | |||
plugin_name="squid" | |||
scope="MAIN"/> | |||
<!-- Project 1 --> | |||
<projects organization_uuid="org1" |
@@ -4,7 +4,8 @@ | |||
name="Avoid Cycles" | |||
plugin_rule_key="AvoidCycles" | |||
plugin_config_key="[null]" | |||
plugin_name="squid"/> | |||
plugin_name="squid" | |||
scope="MAIN"/> | |||
<projects organization_uuid="org1" | |||
uuid="PROJECT1" |
@@ -4,7 +4,8 @@ | |||
name="Avoid Cycles" | |||
plugin_rule_key="AvoidCycles" | |||
plugin_config_key="[null]" | |||
plugin_name="squid"/> | |||
plugin_name="squid" | |||
scope="MAIN"/> | |||
<projects organization_uuid="org1" | |||
uuid="PROJECT1" |
@@ -44,6 +44,7 @@ | |||
description_format="MARKDOWN" | |||
created_at="150000" | |||
updated_at="150000" | |||
scope="MAIN" | |||
/> | |||
<properties id="1" |