Skip to content

Commit

Permalink
Add sonar scanning (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
jskov authored Jan 21, 2024
1 parent 0c4c1cd commit 4d50620
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 27 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ dependencies {
// null-checker
implementation "net.ltgt.gradle:gradle-errorprone-plugin:3.1.0"

// sonar
implementation "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:4.4.1.3373"

// dependencies added by the plugin
// not used in the plugin code, but here Dependabot will keep them up to date
addedDependencies "com.uber.nullaway:nullaway:0.10.21@jar"
Expand Down
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
org.gradle.caching=true

version = 0.0.0-SNAPSHOT

dk.mada.style.sonar.projectKey = jskov_mada-style-gradle
dk.mada.style.sonar.organization = jskov-github
30 changes: 29 additions & 1 deletion src/main/java/dk/mada/style/MadaStylePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.quality.CheckstyleExtension;
import org.gradle.api.plugins.quality.CheckstylePlugin;
import org.sonarqube.gradle.SonarExtension;
import org.sonarqube.gradle.SonarQubePlugin;

import com.diffplug.gradle.spotless.SpotlessExtension;
import com.diffplug.gradle.spotless.SpotlessPlugin;
Expand All @@ -13,6 +16,7 @@
import dk.mada.style.config.PluginConfiguration;
import dk.mada.style.configurators.CheckstyleConfigurator;
import dk.mada.style.configurators.ErrorProneConfigurator;
import dk.mada.style.configurators.SonarConfigurator;
import dk.mada.style.configurators.SpotlessConfigurator;
import net.ltgt.gradle.errorprone.ErrorPronePlugin;

Expand All @@ -26,8 +30,11 @@ public void apply(Project project) {
}

private void applyPlugins(Project project) {
Logger logger = project.getLogger();
logger.info("Applying mada.style plugin");

var configuration = new PluginConfiguration(project);
var configExtractor = new ConfigFileExtractor(project.getLogger(), project.getGradle().getGradleHomeDir().toPath());
var configExtractor = new ConfigFileExtractor(logger, project.getGradle().getGradleHomeDir().toPath());

if (configuration.isCheckstyleActive()) {
project.getPluginManager().apply("checkstyle");
Expand All @@ -47,6 +54,16 @@ private void applyPlugins(Project project) {
project.getPlugins().withType(ErrorPronePlugin.class,
ep -> new ErrorProneConfigurator(project, configuration.errorProne(), configuration.nullchecker()).configure());
}

if (configuration.isSonarActive()) {
// This should be a Gradle property, but is a system property
// https://sonarsource.atlassian.net/browse/SONARGRADL-134
System.setProperty("sonar.gradle.skipCompile", "true");

project.getPluginManager().apply("org.sonarqube");

project.getPlugins().withType(SonarQubePlugin.class, sp -> lazyConfigureSonar(project, configuration));
}
}

/**
Expand All @@ -72,4 +89,15 @@ private void lazyConfigureFormatter(Project project, PluginConfiguration configu
project.getExtensions().configure(SpotlessExtension.class,
se -> new SpotlessConfigurator(project.getLogger(), configuration.formatter(), configExtractor).configure(se));
}

/**
* Lazy configure sonar extension.
*
* @param project the project
* @param configuration the plugin configuration
*/
private void lazyConfigureSonar(Project project, PluginConfiguration configuration) {
project.getExtensions().configure(SonarExtension.class,
se -> new SonarConfigurator(project, configuration.sonar()).configure(se));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public Path getLocalConfigFile(String path) {
throw new IllegalStateException("Failed to read " + path + " from data checksums: " + dataChecksums);
}

String suffix = "." + path.replaceAll(".*[.]", "");
String suffix = path.substring(path.lastIndexOf('.'));
String filename = path.replace('/', ':').replace(suffix, "") + "-" + value + suffix;

Path targetFile = madaConfigDir.resolve(filename);
Expand Down
62 changes: 46 additions & 16 deletions src/main/java/dk/mada/style/config/PluginConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dk.mada.style.config;

import java.util.Map;

import org.gradle.api.Project;
import org.jspecify.annotations.Nullable;

Expand All @@ -21,7 +23,9 @@ public class PluginConfiguration {
/** The parsed formatter configuration. */
private final FormatterConfiguration formatterConf;
/** The parsed null-checker configuration. */
private final NullcheckerConfiguration nullcheckerProps;
private final NullcheckerConfiguration nullcheckerConf;
/** The parsed sonar configuration. */
private final SonarConfiguration sonarConf;

/**
* Checkstyle configuration.
Expand All @@ -38,6 +42,19 @@ public record CheckstyleConfiguration(boolean enabled, boolean ignoreFailures, b
@Nullable String configPath) {
}

/**
* ErrorProne configuration.
*
* @param enabled flag to activate error prone
* @param ignoreTestSource flag to ignore test source files
* @param ignoreGeneratedSource flag to ignore generated source files
* @param excludePathsRegexp a regular expression of source paths to ignore
* @param disabledRules a comma-separated list of rule names to disable
*/
public record ErrorProneConfiguration(boolean enabled, boolean ignoreTestSource, boolean ignoreGeneratedSource,
String excludePathsRegexp, String disabledRules) {
}

/**
* Formatter configuration.
*
Expand All @@ -60,16 +77,12 @@ public record NullcheckerConfiguration(boolean enabled, String includePackages,
}

/**
* ErrorProne configuration.
* SonarSource sonar configuration.
*
* @param enabled flag to activate error prone
* @param ignoreTestSource flag to ignore test source files
* @param ignoreGeneratedSource flag to ignore generated source files
* @param excludePathsRegexp a regular expression of source paths to ignore
* @param disabledRules a comma-separated list of rule names to disable
* @param enabled flag to activate sonar
* @param madaConventionProperties convention properties for sonar
*/
public record ErrorProneConfiguration(boolean enabled, boolean ignoreTestSource, boolean ignoreGeneratedSource,
String excludePathsRegexp, String disabledRules) {
public record SonarConfiguration(boolean enabled, Map<String, String> madaConventionProperties) {
}

/**
Expand Down Expand Up @@ -105,10 +118,17 @@ public PluginConfiguration(Project project) {
getProperty("formatter.exclude", ""),
getNullableProperty("formatter.eclipse-config-path", null));

nullcheckerProps = new NullcheckerConfiguration(
nullcheckerConf = new NullcheckerConfiguration(
getBoolProperty("null-checker.enabled", true),
getProperty("null-checker.include-packages", "dk"),
getProperty("null-checker.exclude-packages", ""));

sonarConf = new SonarConfiguration(
getBoolProperty("sonar.enabled", true),
Map.of(
"sonar.host.url", "https://sonarcloud.io",
"sonar.inclusions", "**/src/main/**",
"sonar.sourceEncoding", "UTF-8"));
}

/** {@return the CheckStyle configuration} */
Expand All @@ -131,24 +151,34 @@ public boolean isErrorProneActive() {
return errorProne().enabled();
}

/** {@return the formatter configuration} */
public FormatterConfiguration formatter() {
return formatterConf;
}

/** {@return true if the formatter is active} */
public boolean isFormatterActive() {
return formatter().enabled();
}

/** {@return the formatter configuration} */
public FormatterConfiguration formatter() {
return formatterConf;
/** {@return the null-checker configuration} */
public NullcheckerConfiguration nullchecker() {
return nullcheckerConf;
}

/** {@return true if the null-checker is active} */
public boolean isNullcheckerActive() {
return nullchecker().enabled();
}

/** {@return the null-checker configuration} */
public NullcheckerConfiguration nullchecker() {
return nullcheckerProps;
/** {@return the sonar configuration} */
public SonarConfiguration sonar() {
return sonarConf;
}

/** {@return true if sonar is active} */
public boolean isSonarActive() {
return sonar().enabled();
}

private boolean getBoolProperty(String name, boolean defaultValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.quality.Checkstyle;
import org.gradle.api.plugins.quality.CheckstyleExtension;
import org.gradle.api.tasks.TaskContainer;

import dk.mada.style.config.ConfigFileExtractor;
import dk.mada.style.config.PluginConfiguration.CheckstyleConfiguration;
Expand Down Expand Up @@ -56,17 +57,16 @@ public void configure(CheckstyleExtension ce) {
if (toolVersion != null) {
ce.setToolVersion(toolVersion);
}
TaskContainer taskContainer = project.getTasks();
if (checkstyleConfig.ignoreTestSource()) {
project.getTasks().named("checkstyleTest", this::disableTask);
taskContainer.named("checkstyleTest", this::disableTask);
}

if (checkstyleConfig.ignoreGeneratedSource()) {
project.getTasks().withType(Checkstyle.class, t -> {
if (t.getName().endsWith("Apt")) {
disableTask(t);
}
});
}
taskContainer.withType(Checkstyle.class, t -> {
if (checkstyleConfig.ignoreGeneratedSource() && t.getName().endsWith("Apt")) {
disableTask(t);
}
});
}

private void disableTask(Task t) {
Expand Down
66 changes: 66 additions & 0 deletions src/main/java/dk/mada/style/configurators/SonarConfigurator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package dk.mada.style.configurators;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.quality.Checkstyle;
import org.gradle.api.tasks.TaskContainer;
import org.sonarqube.gradle.SonarExtension;
import org.sonarqube.gradle.SonarTask;

import dk.mada.style.config.PluginConfiguration.SonarConfiguration;

/**
* Configures Sonar.
*/
public class SonarConfigurator {
/** The gradle project. */
private final Project project;
/** The gradle logger. */
private final Logger logger;
/** The sonarqube configuration. */
private final SonarConfiguration sonarConfig;

/**
* Creates new instance.
*
* @param project the gradle project
* @param sonarConfig the sonarqube configuration
*/
public SonarConfigurator(Project project, SonarConfiguration sonarConfig) {
this.project = project;
this.logger = project.getLogger();
this.sonarConfig = sonarConfig;
}

/**
* Configures the sonarqube extension.
*
* @param se the spotless extension
*/
public void configure(SonarExtension se) {
logger.info("dk.mada.style configure sonar");

TaskContainer taskContainer = project.getTasks();

// Make sonar depend on checkstyle tasks (we want sonar to run last)
taskContainer.withType(SonarTask.class, sonar -> taskContainer.withType(Checkstyle.class, sonar::dependsOn));

Map<String, String> inputProps = project.getProperties().entrySet().stream()
.filter(e -> !e.getKey().equals("dk.mada.style.sonar.enabled"))
.filter(e -> e.getKey().startsWith("dk.mada.style.sonar."))
.collect(Collectors.toMap(e -> e.getKey().replace("dk.mada.style.", ""), e -> Objects.toString(e.getValue())));

Map<String, String> combinedMadaSonarProps = new HashMap<>();
combinedMadaSonarProps.putAll(sonarConfig.madaConventionProperties());
combinedMadaSonarProps.putAll(inputProps);

logger.info("Set sonar properties: {}", combinedMadaSonarProps);

se.properties(sp -> combinedMadaSonarProps.forEach(sp::property));
}
}
2 changes: 1 addition & 1 deletion src/main/resources/config/checkstyle/checkstyle-mada.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@

<!-- Checks for Headers -->
<!-- See https://checkstyle.org/config_header.html -->
<!-- <module name="Header"> -->
<!-- <module name="Header"> --> <!-- NOSONAR -->
<!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
<!-- <property name="fileExtensions" value="java"/> -->
<!-- </module> -->
Expand Down

0 comments on commit 4d50620

Please sign in to comment.