import org.sonar.server.rule.CommonRuleDefinitionsImpl;
import org.sonar.server.rule.DefaultRuleFinder;
import org.sonar.server.rule.DeprecatedRulesDefinitionLoader;
+import org.sonar.server.rule.ExternalRuleCreator;
import org.sonar.server.rule.RuleDefinitionsLoader;
import org.sonar.server.rule.index.RuleIndex;
+import org.sonar.server.rule.index.RuleIndexer;
import org.sonar.server.setting.DatabaseSettingLoader;
import org.sonar.server.setting.DatabaseSettingsEnabler;
import org.sonar.server.setting.ThreadLocalSettings;
CommonRuleDefinitionsImpl.class,
RuleDefinitionsLoader.class,
RulesDefinitionXmlLoader.class,
+ ExternalRuleCreator.class,
+ RuleIndexer.class,
// languages
Languages.class, // used by CommonRuleDefinitionsImpl
assertThat(picoContainer.getComponentAdapters())
.hasSize(
CONTAINER_ITSELF
- + 81 // level 4
+ + 83 // level 4
+ 21 // content of QualityGateModule
+ 6 // content of CeConfigurationModule
+ 4 // content of CeQueueModule
return definition.isExternal();
}
+ public RuleDto setIsExternal(boolean isExternal) {
+ definition.setIsExternal(isExternal);
+ return this;
+ }
+
public boolean isTemplate() {
return definition.isTemplate();
}
private String templateRepository;
private String internalKey;
private String language;
+ private boolean isExternal;
private int type;
private long createdAt;
private long updatedAt;
public int getType() {
return type;
}
+
+ public boolean isExternal() {
+ return isExternal;
+ }
public long getCreatedAt() {
return createdAt;
r.priority as "severity",
r.status as "status",
r.is_template as "isTemplate",
+ r.is_external as "isExternal",
r.system_tags as "systemTags",
t.plugin_rule_key as "templateRuleKey",
t.plugin_name as "templateRepository",
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
assertThat(actual.getConfigKey()).isEqualTo(expected.getConfigKey());
assertThat(actual.getSeverity()).isEqualTo(expected.getSeverity());
assertThat(actual.getSeverityString()).isEqualTo(expected.getSeverityString());
+ assertThat(actual.isExternal()).isEqualTo(expected.isExternal());
assertThat(actual.isTemplate()).isEqualTo(expected.isTemplate());
assertThat(actual.getLanguage()).isEqualTo(expected.getLanguage());
assertThat(actual.getTemplateId()).isEqualTo(expected.getTemplateId());
public void scrollIndexingRules() {
Accumulator<RuleForIndexingDto> accumulator = new Accumulator<>();
RuleDefinitionDto r1 = db.rules().insert();
- RuleDefinitionDto r2 = db.rules().insert();
+ RuleDefinitionDto r2 = db.rules().insert(r -> r.setIsExternal(true));
underTest.scrollIndexingRules(db.getSession(), accumulator);
assertThat(accumulator.list)
.extracting(RuleForIndexingDto::getId, RuleForIndexingDto::getRuleKey)
.containsExactlyInAnyOrder(tuple(r1.getId(), r1.getKey()), tuple(r2.getId(), r2.getKey()));
- RuleForIndexingDto firstRule = accumulator.list.iterator().next();
+ Iterator<RuleForIndexingDto> it = accumulator.list.iterator();
+ RuleForIndexingDto firstRule = it.next();
assertThat(firstRule.getRepository()).isEqualTo(r1.getRepositoryKey());
assertThat(firstRule.getPluginRuleKey()).isEqualTo(r1.getRuleKey());
assertThat(firstRule.getDescriptionFormat()).isEqualTo(r1.getDescriptionFormat());
assertThat(firstRule.getSeverity()).isEqualTo(r1.getSeverity());
assertThat(firstRule.getStatus()).isEqualTo(r1.getStatus());
+ assertThat(firstRule.isExternal()).isFalse();
assertThat(firstRule.isTemplate()).isEqualTo(r1.isTemplate());
assertThat(firstRule.getSystemTagsAsSet()).isEqualTo(r1.getSystemTags());
assertThat(firstRule.getTemplateRuleKey()).isNull();
assertThat(firstRule.getType()).isEqualTo(r1.getType());
assertThat(firstRule.getCreatedAt()).isEqualTo(r1.getCreatedAt());
assertThat(firstRule.getUpdatedAt()).isEqualTo(r1.getUpdatedAt());
+
+ RuleForIndexingDto secondRule = it.next();
+ assertThat(secondRule.isExternal()).isTrue();
+
}
@Test
public static Consumer<RuleDefinitionDto> setType(RuleType type) {
return rule -> rule.setType(type);
}
+
+ public static Consumer<RuleDefinitionDto> setIsExternal(boolean isExternal) {
+ return rule -> rule.setIsExternal(isExternal);
+ }
public static Consumer<RuleDefinitionDto> setIsTemplate(boolean isTemplate) {
return rule -> rule.setIsTemplate(isTemplate);
import org.sonar.server.computation.task.step.ComputationStepExecutor;
import org.sonar.server.computation.task.step.ComputationSteps;
import org.sonar.server.computation.taskprocessor.MutableTaskResultHolderImpl;
-import org.sonar.server.rule.ExternalRuleCreator;
import org.sonar.server.view.index.ViewIndex;
public final class ProjectAnalysisTaskContainerPopulator implements ContainerPopulator<TaskContainer> {
DuplicationRepositoryImpl.class,
// issues
- ExternalRuleCreator.class,
RuleRepositoryImpl.class,
ScmAccountToUserLoader.class,
ScmAccountToUser.class,
}
private void persistAndIndex(DbSession dbSession, NewExternalRule external) {
- Rule rule = creator.create(dbSession, external);
+ Rule rule = creator.persistAndIndex(dbSession, external);
rulesById.put(rule.getId(), rule);
rulesByKey.put(external.getKey(), rule);
}
*/
package org.sonar.server.rule;
-import org.sonar.api.server.ServerSide;
+import org.sonar.api.rule.RuleStatus;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
import org.sonar.server.computation.task.projectanalysis.issue.Rule;
import org.sonar.server.computation.task.projectanalysis.issue.RuleImpl;
+import org.sonar.server.rule.index.RuleIndexer;
import static org.sonar.db.rule.RuleDto.Scope.ALL;
-@ServerSide
public class ExternalRuleCreator {
private final DbClient dbClient;
private final System2 system2;
+ private final RuleIndexer ruleIndexer;
- public ExternalRuleCreator(DbClient dbClient, System2 system2) {
+ public ExternalRuleCreator(DbClient dbClient, System2 system2, RuleIndexer ruleIndexer) {
this.dbClient = dbClient;
this.system2 = system2;
+ this.ruleIndexer = ruleIndexer;
}
- public Rule create(DbSession dbSession, NewExternalRule external) {
+ /**
+ * Persists a rule in the DB and indexes it.
+ * @return the rule that was inserted in the DB, which <b>includes the generated ID</b>.
+ */
+ public Rule persistAndIndex(DbSession dbSession, NewExternalRule external) {
RuleDao dao = dbClient.ruleDao();
dao.insert(dbSession, new RuleDefinitionDto()
.setRuleKey(external.getKey())
.setPluginKey(external.getPluginKey())
- .setIsExternal(true)
+ .setIsExternal(external.isExternal())
.setName(external.getName())
.setDescriptionURL(external.getDescriptionUrl())
.setType(external.getType())
.setScope(ALL)
+ .setStatus(RuleStatus.READY)
.setSeverity(external.getSeverity())
.setCreatedAt(system2.now())
.setUpdatedAt(system2.now()));
- return new RuleImpl(dao.selectOrFailByKey(dbSession, external.getKey()));
+
+ Rule newRule = new RuleImpl(dao.selectOrFailByKey(dbSession, external.getKey()));
+ // TODO write rule repository if needed
+ ruleIndexer.commitAndIndex(dbSession, newRule.getId());
+ return newRule;
}
}
.setSystemTags(ruleDef.tags())
.setType(RuleType.valueOf(ruleDef.type().name()))
.setScope(toDtoScope(ruleDef.scope()))
+ .setIsExternal(false)
.setCreatedAt(system2.now())
.setUpdatedAt(system2.now());
if (ruleDef.htmlDescription() != null) {
recorder.getRemaining().forEach(rule -> {
if (rule.isCustomRule()) {
customRules.add(rule);
- } else if (rule.getStatus() != RuleStatus.REMOVED) {
+ } else if (!rule.isExternal() && rule.getStatus() != RuleStatus.REMOVED) {
removeRule(dbSession, recorder, rule);
}
});
return this;
}
+ public boolean isExternal() {
+ return getField(RuleIndexDefinition.FIELD_RULE_IS_EXTERNAL);
+ }
+
+ public RuleDoc setIsExternal(boolean b) {
+ setField(RuleIndexDefinition.FIELD_RULE_IS_EXTERNAL, b);
+ return this;
+ }
+
public RuleType type() {
return RuleType.valueOf(getField(RuleIndexDefinition.FIELD_RULE_TYPE));
}
.setRepository(dto.getRepository())
.setInternalKey(dto.getInternalKey())
.setIsTemplate(dto.isTemplate())
+ .setIsExternal(dto.isExternal())
.setLanguage(dto.getLanguage())
.setName(dto.getName())
.setRuleKey(dto.getPluginRuleKey())
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_EXTENSION_TAGS;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_HTML_DESCRIPTION;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_INTERNAL_KEY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_IS_EXTERNAL;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_IS_TEMPLATE;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_KEY;
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_LANGUAGE;
.stream().map(token -> boolQuery().should(
matchQuery(
SEARCH_GRAMS_ANALYZER.subField(FIELD_RULE_NAME),
- StringUtils.left(token, DefaultIndexSettings.MAXIMUM_NGRAM_LENGTH)
- ).boost(20f)).should(
- matchPhraseQuery(
- ENGLISH_HTML_ANALYZER.subField(FIELD_RULE_HTML_DESCRIPTION),
- token
- ).boost(3f))
- ).forEach(textQuery::must);
+ StringUtils.left(token, DefaultIndexSettings.MAXIMUM_NGRAM_LENGTH)).boost(20f))
+ .should(
+ matchPhraseQuery(
+ ENGLISH_HTML_ANALYZER.subField(FIELD_RULE_HTML_DESCRIPTION),
+ token).boost(3f)))
+ .forEach(textQuery::must);
qb.should(textQuery.boost(20f));
}
QueryBuilders.termQuery(FIELD_RULE_IS_TEMPLATE, Boolean.toString(isTemplate)));
}
+ Boolean isExternal = query.isExternal();
+ if (isExternal != null) {
+ filters.put(FIELD_RULE_IS_EXTERNAL,
+ QueryBuilders.termQuery(FIELD_RULE_IS_EXTERNAL, Boolean.toString(isExternal)));
+ }
+
String template = query.templateKey();
if (template != null) {
filters.put(FIELD_RULE_TEMPLATE_KEY,
public static final String FIELD_RULE_STATUS = "status";
public static final String FIELD_RULE_LANGUAGE = "lang";
public static final String FIELD_RULE_IS_TEMPLATE = "isTemplate";
+ public static final String FIELD_RULE_IS_EXTERNAL = "isExternal";
public static final String FIELD_RULE_TEMPLATE_KEY = "templateKey";
public static final String FIELD_RULE_TYPE = "type";
public static final String FIELD_RULE_CREATED_AT = "createdAt";
ruleMapping.keywordFieldBuilder(FIELD_RULE_LANGUAGE).disableNorms().build();
ruleMapping.createBooleanField(FIELD_RULE_IS_TEMPLATE);
+ ruleMapping.createBooleanField(FIELD_RULE_IS_EXTERNAL);
ruleMapping.keywordFieldBuilder(FIELD_RULE_TEMPLATE_KEY).disableNorms().build();
ruleMapping.keywordFieldBuilder(FIELD_RULE_TYPE).disableNorms().build();
private String internalKey;
private String ruleKey;
private OrganizationDto organization;
+ private Boolean isExternal;
@CheckForNull
public QProfileDto getQProfile() {
return this;
}
+ @CheckForNull
+ public Boolean isExternal() {
+ return isExternal;
+ }
+
+ public RuleQuery setIsExternal(@Nullable Boolean b) {
+ this.isExternal = b;
+ return this;
+ }
+
@CheckForNull
public String templateKey() {
return templateKey;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_GAP_DESCRIPTION;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_HTML_DESCRIPTION;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_INTERNAL_KEY;
+import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_IS_TEMPLATE;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_LANGUAGE;
import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_LANGUAGE_NAME;
setLanguage(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setLanguageName(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setIsTemplate(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+ setIsExternal(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setTemplateKey(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
setDefaultDebtRemediationFunctionFields(ruleResponse, ruleDefinitionDto, fieldsToReturn);
setEffortToFixDescription(ruleResponse, ruleDefinitionDto, fieldsToReturn);
ruleResponse.setIsTemplate(ruleDto.isTemplate());
}
}
+
+ private static void setIsExternal(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn) {
+ if (shouldReturnField(fieldsToReturn, FIELD_IS_EXTERNAL)) {
+ ruleResponse.setIsExternal(ruleDto.isExternal());
+ }
+ }
private static void setTemplateKey(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, SearchResult result, Set<String> fieldsToReturn) {
if (shouldReturnField(fieldsToReturn, FIELD_TEMPLATE_KEY) && ruleDto.isCustomRule()) {
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_COMPARE_TO_PROFILE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INHERITANCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ORGANIZATION;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE;
query.setInheritance(request.paramAsStrings(PARAM_INHERITANCE));
query.setActiveSeverities(request.paramAsStrings(PARAM_ACTIVE_SEVERITIES));
query.setIsTemplate(request.paramAsBoolean(PARAM_IS_TEMPLATE));
+ query.setIsExternal(request.paramAsBoolean(PARAM_IS_EXTERNAL));
query.setTemplateKey(request.param(PARAM_TEMPLATE_KEY));
query.setTypes(toEnums(request.paramAsStrings(PARAM_TYPES), RuleType.class));
query.setKey(request.param(PARAM_RULE_KEY));
public static final String PARAM_INHERITANCE = "inheritance";
public static final String PARAM_ACTIVE_SEVERITIES = "active_severities";
public static final String PARAM_IS_TEMPLATE = "is_template";
+ public static final String PARAM_IS_EXTERNAL = "is_external";
public static final String PARAM_TEMPLATE_KEY = "template_key";
public static final String PARAM_ORGANIZATION = "organization";
public static final String PARAM_COMPARE_TO_PROFILE = "compareToProfile";
public static final String FIELD_SEVERITY = "severity";
public static final String FIELD_STATUS = "status";
public static final String FIELD_INTERNAL_KEY = "internalKey";
+ public static final String FIELD_IS_EXTERNAL = "isExternal";
public static final String FIELD_IS_TEMPLATE = "isTemplate";
public static final String FIELD_TEMPLATE_KEY = "templateKey";
public static final String FIELD_TAGS = "tags";
* @since 7.1
*/
public static final String FIELD_SCOPE = "scope";
-
+
public static final String FIELD_PARAMS = "params";
public static final String FIELD_ACTIVES = "actives";
- public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_REPO, FIELD_NAME, FIELD_CREATED_AT, FIELD_SEVERITY, FIELD_STATUS, FIELD_INTERNAL_KEY, FIELD_IS_TEMPLATE,
+ public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_REPO, FIELD_NAME, FIELD_CREATED_AT, FIELD_SEVERITY, FIELD_STATUS, FIELD_INTERNAL_KEY, FIELD_IS_EXTERNAL, FIELD_IS_TEMPLATE,
FIELD_TEMPLATE_KEY, FIELD_TAGS, FIELD_SYSTEM_TAGS, FIELD_LANGUAGE, FIELD_LANGUAGE_NAME, FIELD_HTML_DESCRIPTION, FIELD_MARKDOWN_DESCRIPTION, FIELD_NOTE_LOGIN,
FIELD_MARKDOWN_NOTE, FIELD_HTML_NOTE,
FIELD_DEFAULT_DEBT_REM_FUNCTION, FIELD_EFFORT_TO_FIX_DESCRIPTION, FIELD_DEBT_OVERLOADED, FIELD_DEBT_REM_FUNCTION,
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_COMPARE_TO_PROFILE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INHERITANCE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ORGANIZATION;
.addPagingParams(100, MAX_LIMIT)
.setHandler(this)
.setChangelog(new Change("7.1", "The field 'scope' has been added to the response"))
- .setChangelog(new Change("7.1", "The field 'scope' has been added to the 'f' parameter"));
+ .setChangelog(new Change("7.1", "The field 'scope' has been added to the 'f' parameter"))
+ .setChangelog(new Change("7.2", "The field 'isExternal' has been added to the response"))
+ .setChangelog(new Change("7.2", "The field 'isExternal' has been added to the 'f' parameter"));;
action.createParam(FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
.setDescription("Filter template rules")
.setBooleanPossibleValues();
+ action
+ .createParam(PARAM_IS_EXTERNAL)
+ .setDescription("Filter external engine rules")
+ .setBooleanPossibleValues()
+ .setSince("7.2");
+
action
.createParam(PARAM_TEMPLATE_KEY)
.setDescription("Key of the template rule to filter on. Used to search for the custom rules based on this template.")
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "CODE_SMELL",
"params": [
{
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "CODE_SMELL",
"params": [
{
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "BUG",
"params": [
{
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "VULNERABILITY",
"params": [
{
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "CODE_SMELL",
"params": [
{
"lang": "java",
"langName": "Java",
"scope": "MAIN",
+ "isExternal": false,
"type": "CODE_SMELL",
"params": [
{
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.sonar.server.es.EsTester;
import org.sonar.server.rule.ExternalRuleCreator;
import org.sonar.server.rule.index.RuleIndexDefinition;
+import org.sonar.server.rule.index.RuleIndexer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
@org.junit.Rule
public DbTester db = DbTester.create(System2.INSTANCE);
- @org.junit.Rule
- public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
private DbClient dbClient = mock(DbClient.class);
private DbSession dbSession = mock(DbSession.class);
private RuleDao ruleDao = mock(RuleDao.class);
- private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+ private RuleIndexer ruleIndexer = mock(RuleIndexer.class);
+ private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(db.getDbClient(), System2.INSTANCE, ruleIndexer);
private RuleRepositoryImpl underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
@Before
@Test
public void accept_new_externally_defined_Rules() {
- DbClient dbClient = db.getDbClient();
- externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
- underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
-
RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
underTest.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
@Test
public void persist_new_externally_defined_Rules() {
- DbClient dbClient = db.getDbClient();
- DbSession dbSession = dbClient.openSession(false);
- externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
- underTest = new RuleRepositoryImpl(externalRuleCreator, dbClient, analysisMetadataHolder);
+ underTest = new RuleRepositoryImpl(externalRuleCreator, db.getDbClient(), analysisMetadataHolder);
RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
underTest.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
.setType(BUG)
.build());
- underTest.persistNewExternalRules(dbSession);
-
- dbSession.commit();
+ underTest.persistNewExternalRules(db.getSession());
+ db.commit();
- RuleDao ruleDao = dbClient.ruleDao();
- Optional<RuleDefinitionDto> ruleDefinitionDto = ruleDao.selectDefinitionByKey(dbClient.openSession(false), ruleKey);
+ Optional<RuleDefinitionDto> ruleDefinitionDto = db.getDbClient().ruleDao().selectDefinitionByKey(db.getSession(), ruleKey);
assertThat(ruleDefinitionDto).isPresent();
Rule rule = underTest.getByKey(ruleKey);
assertThat(rule).isNotNull();
assertThat(underTest.getById(ruleDefinitionDto.get().getId())).isNotNull();
+ verify(ruleIndexer).commitAndIndex(db.getSession(), ruleDefinitionDto.get().getId());
}
private void expectNullRuleKeyNPE() {
*/
package org.sonar.server.computation.task.projectanalysis.step;
+import java.util.Optional;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.server.es.EsTester;
import org.sonar.server.rule.ExternalRuleCreator;
import org.sonar.server.rule.index.RuleIndexDefinition;
-
-import java.util.Optional;
+import org.sonar.server.rule.index.RuleIndexer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.rule.Severity.BLOCKER;
@org.junit.Rule
public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
- private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+ private RuleIndexer indexer = new RuleIndexer(es.client(), dbClient);
+ private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE, indexer);
@Override
protected ComputationStep step() {
}
@Test
- public void persist_new_external_rules() {
+ public void persist_and_index_new_external_rules() {
RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
ruleRepository.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
assertThat(reloaded.getName()).isEqualTo("disallow assignment operators in conditional statements (no-cond-assign)");
assertThat(reloaded.getPluginKey()).isEqualTo("eslint");
+ assertThat(es.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isEqualTo(1l);
+ assertThat(es.getDocuments(RuleIndexDefinition.INDEX_TYPE_RULE).iterator().next().getId()).isEqualTo(Integer.toString(reloaded.getId()));
+ }
+
+ @Test
+ public void do_not_persist_existing_external_rules() {
+ RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
+ db.rules().insert(ruleKey, r -> r.setIsExternal(true));
+ ruleRepository.insertNewExternalRuleIfAbsent(ruleKey, () -> new NewExternalRule.Builder()
+ .setKey(ruleKey)
+ .setPluginKey("eslint")
+ .setName("disallow assignment operators in conditional statements (no-cond-assign)")
+ .setDescriptionUrl("https://eslint.org/docs/rules/no-cond-assign")
+ .setSeverity(BLOCKER)
+ .setType(BUG)
+ .build());
+
+ underTest.execute();
+ RuleDao ruleDao = dbClient.ruleDao();
+ assertThat(ruleDao.selectAllDefinitions(dbClient.openSession(false))).hasSize(1);
+ assertThat(es.countDocuments(RuleIndexDefinition.INDEX_TYPE_RULE)).isZero();
}
}
@org.junit.Rule
public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
- private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE);
+ private ExternalRuleCreator externalRuleCreator = mock(ExternalRuleCreator.class);
@Override
protected ComputationStep step() {
package org.sonar.server.rule;
import org.junit.Test;
+import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.System2;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
import org.sonar.server.computation.task.projectanalysis.issue.Rule;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.rule.index.RuleIndexDefinition;
+import org.sonar.server.rule.index.RuleIndexer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.rule.Severity.BLOCKER;
@org.junit.Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- private ExternalRuleCreator underTest = new ExternalRuleCreator(dbTester.getDbClient(), System2.INSTANCE);
+ @org.junit.Rule
+ public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
+
+ private RuleIndexer indexer = new RuleIndexer(es.client(), dbTester.getDbClient());
+ private ExternalRuleCreator underTest = new ExternalRuleCreator(dbTester.getDbClient(), System2.INSTANCE, indexer);
private DbSession dbSession = dbTester.getSession();
@Test
public void create_external_rule() {
-
RuleKey ruleKey = RuleKey.of("eslint", "no-cond-assign");
NewExternalRule externalRule = new NewExternalRule.Builder()
.setKey(ruleKey)
.setType(BUG)
.build();
- Rule rule1 = underTest.create(dbSession, externalRule);
+ Rule rule1 = underTest.persistAndIndex(dbSession, externalRule);
assertThat(rule1).isNotNull();
assertThat(rule1.isExternal()).isTrue();
import static org.sonar.api.rules.RuleType.VULNERABILITY;
import static org.sonar.db.rule.RuleTesting.setCreatedAt;
import static org.sonar.db.rule.RuleTesting.setIsTemplate;
+import static org.sonar.db.rule.RuleTesting.setIsExternal;
import static org.sonar.db.rule.RuleTesting.setLanguage;
import static org.sonar.db.rule.RuleTesting.setName;
import static org.sonar.db.rule.RuleTesting.setOrganization;
// find all
RuleQuery query = new RuleQuery();
- SearchIdResult results = underTest.search(query, new SearchOptions());
+ SearchIdResult<Integer> results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).hasSize(2);
// Only template
results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(ruleIsTemplate.getId(), ruleNoTemplate.getId());
}
+
+ @Test
+ public void search_by_is_external() {
+ RuleDefinitionDto ruleIsNotExternal = createRule(setIsExternal(false));
+ RuleDefinitionDto ruleIsExternal = createRule(setIsExternal(true));
+ index();
+
+ // find all
+ RuleQuery query = new RuleQuery();
+ SearchIdResult<Integer> results = underTest.search(query, new SearchOptions());
+ assertThat(results.getIds()).hasSize(2);
+
+ // Only template
+ query = new RuleQuery().setIsTemplate(true);
+ results = underTest.search(query, new SearchOptions());
+ assertThat(results.getIds()).containsOnly(ruleIsExternal.getId());
+
+ // Only not template
+ query = new RuleQuery().setIsTemplate(false);
+ results = underTest.search(query, new SearchOptions());
+ assertThat(results.getIds()).containsOnly(ruleIsNotExternal.getId());
+
+ // null => no filter
+ query = new RuleQuery().setIsTemplate(null);
+ results = underTest.search(query, new SearchOptions());
+ assertThat(results.getIds()).containsOnly(ruleIsExternal.getId(), ruleIsNotExternal.getId());
+ }
@Test
public void search_by_template_key() {
import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
import static org.sonar.db.qualityprofile.ActiveRuleDto.INHERITED;
import static org.sonar.db.qualityprofile.ActiveRuleDto.OVERRIDES;
-import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;
+import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_COMPARE_TO_PROFILE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_INHERITANCE;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_TEMPLATE;
+import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_IS_EXTERNAL;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ORGANIZATION;
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE;
assertThat(result.isAscendingSort()).isTrue();
assertThat(result.getAvailableSinceLong()).isNull();
assertThat(result.getInheritance()).isNull();
+ assertThat(result.isExternal()).isNull();
assertThat(result.isTemplate()).isNull();
assertThat(result.getLanguages()).isNull();
assertThat(result.getQueryText()).isNull();
PARAM_ACTIVE_SEVERITIES, "MINOR,MAJOR",
PARAM_AVAILABLE_SINCE, "2016-01-01",
PARAM_INHERITANCE, "INHERITED,OVERRIDES",
- PARAM_IS_TEMPLATE, "true",
+ PARAM_IS_TEMPLATE, "true",
+ PARAM_IS_EXTERNAL, "true",
PARAM_LANGUAGES, "java,js",
TEXT_QUERY, "S001",
PARAM_ORGANIZATION, organization.getKey(),
assertThat(result.isAscendingSort()).isFalse();
assertThat(result.getAvailableSinceLong()).isNotNull();
assertThat(result.getInheritance()).containsOnly(INHERITED, OVERRIDES);
+ assertThat(result.isExternal()).isTrue();
assertThat(result.isTemplate()).isTrue();
assertThat(result.getLanguages()).containsOnly(qualityProfile.getLanguage());
assertThat(result.getQueryText()).isEqualTo("S001");
public void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction("fake")
.setHandler(this);
- defineRuleSearchParameters(action);
+ defineGenericRuleSearchParameters(action);
}
@Override
optional bool remFnOverloaded = 45;
optional string gapDescription = 44;
optional sonarqube.ws.commons.RuleScope scope = 46;
+ optional bool isExternal = 47;
optional sonarqube.ws.commons.RuleType type = 37;