Skip to content

Commit

Permalink
SONAR-10593 SONAR-10315 support plugin uninstall before CE processing
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon Brandhof authored and SonarTech committed May 10, 2018
1 parent efdcb66 commit 5684413
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 59 deletions.
Expand Up @@ -29,7 +29,6 @@
import org.sonar.api.utils.MessageException;
import org.sonar.ce.queue.CeTask;
import org.sonar.core.component.ComponentKeys;
import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginRepository;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
Expand All @@ -42,13 +41,13 @@
import org.sonar.scanner.protocol.output.ScannerReport.Metadata.QProfile;
import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.analysis.Organization;
import org.sonar.server.project.Project;
import org.sonar.server.computation.task.projectanalysis.analysis.ScannerPlugin;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
import org.sonar.server.computation.task.projectanalysis.component.BranchLoader;
import org.sonar.server.computation.task.step.ComputationStep;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.OrganizationFlags;
import org.sonar.server.project.Project;
import org.sonar.server.qualityprofile.QualityProfile;

import static com.google.common.base.Preconditions.checkState;
Expand Down Expand Up @@ -153,13 +152,12 @@ private void loadQualityProfiles(ScannerReport.Metadata reportMetadata, Organiza

@CheckForNull
private String getBasePluginKey(Plugin p) {
PluginInfo pluginInfo = pluginRepository.getPluginInfo(p.getKey());
if (pluginInfo == null) {
if (!pluginRepository.hasPlugin(p.getKey())) {
// May happen if plugin was uninstalled between start of scanner analysis and now.
// But it doesn't matter since all active rules are removed anyway, so no issues will be reported
return null;
}
return pluginInfo.getBasePlugin();
return pluginRepository.getPluginInfo(p.getKey()).getBasePlugin();
}

/**
Expand Down
Expand Up @@ -22,11 +22,15 @@
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.sonar.api.Plugin;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.System2;
import org.sonar.ce.queue.CeTask;
Expand All @@ -39,15 +43,16 @@
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.analysis.Organization;
import org.sonar.server.project.Project;
import org.sonar.server.computation.task.projectanalysis.analysis.ScannerPlugin;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
import org.sonar.server.computation.task.projectanalysis.component.BranchLoader;
import org.sonar.server.computation.task.step.ComputationStep;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.OrganizationFlags;
import org.sonar.server.organization.TestDefaultOrganizationProvider;
import org.sonar.server.project.Project;

import static java.util.Arrays.stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.ArgumentMatchers.any;
Expand All @@ -71,7 +76,7 @@ public class LoadReportAnalysisMetadataHolderStepTest {

private DbClient dbClient = db.getDbClient();
private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
private PluginRepository pluginRepository = mock(PluginRepository.class);
private TestPluginRepository pluginRepository = new TestPluginRepository();
private OrganizationFlags organizationFlags = mock(OrganizationFlags.class);
private ComponentDto project;
private ComputationStep underTest;
Expand Down Expand Up @@ -330,8 +335,8 @@ public void execute_fails_with_MessageException_when_report_has_quality_profiles
metadataBuilder
.setOrganizationKey(organization1.getKey())
.setProjectKey(projectInOrg1.getDbKey());
metadataBuilder.getMutableQprofilesPerLanguage().put("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("jsInOrg1").setName("Sonar way").setLanguage("js").build());
metadataBuilder.getMutableQprofilesPerLanguage().put("php", ScannerReport.Metadata.QProfile.newBuilder().setKey("phpInOrg2").setName("PHP way").setLanguage("php").build());
metadataBuilder.putQprofilesPerLanguage("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("jsInOrg1").setName("Sonar way").setLanguage("js").build());
metadataBuilder.putQprofilesPerLanguage("php", ScannerReport.Metadata.QProfile.newBuilder().setKey("phpInOrg2").setName("PHP way").setLanguage("php").build());
reportReader.setMetadata(metadataBuilder.build());

db.qualityProfiles().insert(organization1, p -> p.setLanguage("js").setKee("jsInOrg1"));
Expand All @@ -353,7 +358,7 @@ public void execute_does_not_fail_when_report_has_a_quality_profile_that_does_no
metadataBuilder
.setOrganizationKey(organization.getKey())
.setProjectKey(project.getDbKey());
metadataBuilder.getMutableQprofilesPerLanguage().put("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("p1").setName("Sonar way").setLanguage("js").build());
metadataBuilder.putQprofilesPerLanguage("js", ScannerReport.Metadata.QProfile.newBuilder().setKey("p1").setName("Sonar way").setLanguage("js").build());
reportReader.setMetadata(metadataBuilder.build());

ComputationStep underTest = createStep(createCeTask(project.getDbKey(), organization.getUuid()));
Expand All @@ -363,22 +368,28 @@ public void execute_does_not_fail_when_report_has_a_quality_profile_that_does_no

@Test
public void execute_read_plugins_from_report() {
ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder();
metadataBuilder.getMutablePluginsByKey().put("java", ScannerReport.Metadata.Plugin.newBuilder().setKey("java").setUpdatedAt(12345L).build());
metadataBuilder.getMutablePluginsByKey().put("php", ScannerReport.Metadata.Plugin.newBuilder().setKey("php").setUpdatedAt(678910L).build());
metadataBuilder.getMutablePluginsByKey().put("customjava", ScannerReport.Metadata.Plugin.newBuilder().setKey("customjava").setUpdatedAt(111111L).build());
when(pluginRepository.getPluginInfo("customjava")).thenReturn(new PluginInfo("customjava").setBasePlugin("java"));
// the installed plugins
pluginRepository.add(
new PluginInfo("java"),
new PluginInfo("customjava").setBasePlugin("java"),
new PluginInfo("php"));

// the plugins sent by scanner
ScannerReport.Metadata.Builder metadataBuilder = newBatchReportBuilder();
metadataBuilder.putPluginsByKey("java", ScannerReport.Metadata.Plugin.newBuilder().setKey("java").setUpdatedAt(10L).build());
metadataBuilder.putPluginsByKey("php", ScannerReport.Metadata.Plugin.newBuilder().setKey("php").setUpdatedAt(20L).build());
metadataBuilder.putPluginsByKey("customjava", ScannerReport.Metadata.Plugin.newBuilder().setKey("customjava").setUpdatedAt(30L).build());
metadataBuilder.putPluginsByKey("uninstalled", ScannerReport.Metadata.Plugin.newBuilder().setKey("uninstalled").setUpdatedAt(40L).build());
reportReader.setMetadata(metadataBuilder.build());

underTest.execute();

assertThat(analysisMetadataHolder.getScannerPluginsByKey()).containsOnlyKeys("java", "php", "customjava");
assertThat(analysisMetadataHolder.getScannerPluginsByKey().values()).extracting(ScannerPlugin::getKey, ScannerPlugin::getBasePluginKey, ScannerPlugin::getUpdatedAt)
.containsOnly(
tuple("java", null, 12345L),
tuple("customjava", "java", 111111L),
tuple("php", null, 678910L));
.containsExactlyInAnyOrder(
tuple("java", null, 10L),
tuple("php", null, 20L),
tuple("customjava", "java", 30L),
tuple("uninstalled", null, 40L));
}

private LoadReportAnalysisMetadataHolderStep createStep(CeTask ceTask) {
Expand All @@ -398,4 +409,34 @@ private CeTask createCeTask(String projectKey, String organizationUuid) {
return res;
}

private static class TestPluginRepository implements PluginRepository {
private final Map<String, PluginInfo> pluginsMap = new HashMap<>();

void add(PluginInfo... plugins) {
stream(plugins).forEach(p -> pluginsMap.put(p.getKey(), p));
}

@Override
public Collection<PluginInfo> getPluginInfos() {
return pluginsMap.values();
}

@Override
public PluginInfo getPluginInfo(String key) {
if (!pluginsMap.containsKey(key)) {
throw new IllegalArgumentException();
}
return pluginsMap.get(key);
}

@Override
public Plugin getPluginInstance(String key) {
throw new UnsupportedOperationException();
}

@Override
public boolean hasPlugin(String key) {
return pluginsMap.containsKey(key);
}
}
}
Expand Up @@ -27,9 +27,10 @@ public class BlueGreenPlugin implements Plugin {
public void define(Context context) {
context.addExtensions(
BuiltInProfilesV1.class,
MetricsDefinitionV1.class,
PageDefinitionV1.class,
RulesDefinitionV1.class,
RuleSensorV1.class);
SensorV1.class);
}

}
Expand Up @@ -25,8 +25,12 @@ public class BuiltInProfilesV1 implements BuiltInQualityProfilesDefinition {
@Override
public void define(Context context) {
NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile("Blue Profile", "xoo");
profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "a").overrideSeverity("BLOCKER");
profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "b").overrideSeverity("CRITICAL");
profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "a")
.overrideSeverity("BLOCKER");
NewBuiltInActiveRule activeB = profile.activateRule(RulesDefinitionV1.REPOSITORY_KEY, "b")
.overrideSeverity("CRITICAL");
activeB.overrideParam("p1", "one");
activeB.overrideParam("p2", "two");
profile.done();
}
}
Expand Down
@@ -0,0 +1,34 @@
/*
* 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.sonarqube.qa.bluegreen;

import java.util.Arrays;
import java.util.List;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metrics;

public class MetricsDefinitionV1 implements Metrics {
@Override
public List<Metric> getMetrics() {
return Arrays.asList(
new Metric.Builder("blue", "Blue", Metric.ValueType.INT).create(),
new Metric.Builder("bluegreen", "BlueGreen", Metric.ValueType.INT).create());
}
}
Expand Up @@ -19,6 +19,7 @@
*/
package org.sonarqube.qa.bluegreen;

import org.sonar.api.rules.RuleType;
import org.sonar.api.server.rule.RulesDefinition;

public class RulesDefinitionV1 implements RulesDefinition {
Expand All @@ -28,8 +29,16 @@ public class RulesDefinitionV1 implements RulesDefinition {
@Override
public void define(Context context) {
NewRepository repo = context.createRepository(REPOSITORY_KEY, "xoo").setName("BlueGreen");
repo.createRule("a").setName("Rule A").setHtmlDescription("Rule A");
repo.createRule("b").setName("Rule B").setHtmlDescription("Rule B");
repo.createRule("a")
.setName("Rule A")
.setHtmlDescription("Rule A")
.setType(RuleType.VULNERABILITY);
NewRule ruleB = repo.createRule("b")
.setName("Rule B")
.setHtmlDescription("Rule B")
.setType(RuleType.VULNERABILITY);
ruleB.createParam("p1").setName("Param One");
ruleB.createParam("p2").setName("Param Two");
repo.done();
}
}
Expand Up @@ -20,6 +20,7 @@
package org.sonarqube.qa.bluegreen;

import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.measure.MetricFinder;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
Expand All @@ -28,7 +29,13 @@

import static org.sonarqube.qa.bluegreen.RulesDefinitionV1.REPOSITORY_KEY;

public class RuleSensorV1 implements Sensor {
public class SensorV1 implements Sensor {

private final MetricFinder metricFinder;

public SensorV1(MetricFinder metricFinder) {
this.metricFinder = metricFinder;
}

@Override
public void describe(SensorDescriptor descriptor) {
Expand All @@ -43,6 +50,17 @@ public void execute(SensorContext context) {
saveIssue(context, inputFile, "a");
saveIssue(context, inputFile, "b");
}

context.newMeasure()
.forMetric(metricFinder.findByKey("blue"))
.on(context.module())
.withValue(10)
.save();
context.newMeasure()
.forMetric(metricFinder.findByKey("bluegreen"))
.on(context.module())
.withValue(20)
.save();
}

private void saveIssue(SensorContext context, InputFile inputFile, String ruleKey) {
Expand Down
Expand Up @@ -27,9 +27,10 @@ public class BlueGreenPlugin implements Plugin {
public void define(Context context) {
context.addExtensions(
BuiltInProfilesV2.class,
MetricsDefinitionV2.class,
PageDefinitionV2.class,
RulesDefinitionV2.class,
RuleSensorV2.class);
SensorV2.class);
}

}
Expand Up @@ -25,7 +25,10 @@ public class BuiltInProfilesV2 implements BuiltInQualityProfilesDefinition {
@Override
public void define(Context context) {
NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile("Green Profile", "xoo");
profile.activateRule(RulesDefinitionV2.REPOSITORY_KEY, "b").overrideSeverity("MINOR");
NewBuiltInActiveRule activeB = profile.activateRule(RulesDefinitionV2.REPOSITORY_KEY, "b")
.overrideSeverity("MINOR");
activeB.overrideParam("p2", "two");
activeB.overrideParam("p3", "three");
profile.activateRule(RulesDefinitionV2.REPOSITORY_KEY, "c").overrideSeverity("INFO");
profile.done();
}
Expand Down
@@ -0,0 +1,35 @@
/*
* 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.sonarqube.qa.bluegreen;

import java.util.Arrays;
import java.util.List;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metrics;

public class MetricsDefinitionV2 implements Metrics {
@Override
public List<Metric> getMetrics() {
return Arrays.asList(
// the metric "blue" has been dropped
new Metric.Builder("bluegreen", "BlueGreen", Metric.ValueType.INT).create(),
new Metric.Builder("green", "Green", Metric.ValueType.INT).create());
}
}
Expand Up @@ -19,6 +19,7 @@
*/
package org.sonarqube.qa.bluegreen;

import org.sonar.api.rules.RuleType;
import org.sonar.api.server.rule.RulesDefinition;

public class RulesDefinitionV2 implements RulesDefinition {
Expand All @@ -28,8 +29,17 @@ public class RulesDefinitionV2 implements RulesDefinition {
@Override
public void define(Context context) {
NewRepository repo = context.createRepository(REPOSITORY_KEY, "xoo").setName("BlueGreen");
repo.createRule("b").setName("Rule B").setHtmlDescription("Rule B");
repo.createRule("c").setName("Rule C").setHtmlDescription("Rule C");
NewRule ruleB = repo.createRule("b")
.setName("Rule B")
.setHtmlDescription("Rule B")
.setType(RuleType.VULNERABILITY);
ruleB.createParam("p2").setName("Param Two");
ruleB.createParam("p3").setName("Param Three");

repo.createRule("c")
.setName("Rule C")
.setHtmlDescription("Rule C")
.setType(RuleType.VULNERABILITY);
repo.done();
}
}

0 comments on commit 5684413

Please sign in to comment.