Settings set via gradle plugin not reflected in projects

What I expect per the documentation is that I should be able to set a property via a plugin that can be overridden at a project specific level or via command line. It seems like the property set at the plugin level is never used. In this plugin I’m setting properties for pmd, findbugs, etc without issue.

Per documentation:

How I’m setting the properties at the plugin level:

open class JavaAnalysisPlugin : Plugin<Project> {

    companion object {
        private val logger: Logger = Logging.getLogger(JavaAnalysisPlugin::class.java)
        const val PLUGIN_NAME: String = "custom.java-analysis"
        const val TASK_EXTRACT_STATIC_ANALYSIS_CONF_NAME = "extractStaticAnalysisConf"
    }
    private val pluginJarPath = calculatePluginJarPath()
    override fun apply(project: Project) {
        logger.info("Java Analysis Plugin")
        val extractConfTask = createTasks(project)
        configureJava(project)
        configureSonar(project)
    }

    /**
     * Apply the sonarqube plugin to report all results
     */
    private fun configureSonar(project: Project) {
        project.plugins.apply("org.sonarqube")
        val sonarExt: SonarQubeExtension = project.extensions.getByName("sonarqube") as SonarQubeExtension
        sonarExt.properties( Action <SonarQubeProperties>{
            SonarQubeProperties(mapOf(
                "sonar.dependencyCheck.reportPath" to "buildDir/reports/dependency-check/dependency-check-report.xml"
            ))
        })
    }
}

What I expect is that the property being added is used by projects that apply the plugin.

Hi,

To be clear, you’re writing a Gradle plugin that you expect to have an impact on how analysis runs?

 
Ann

Right, so the purpose of the plugin is to set configuration that is used globally across many projects. Any of our projects can use the plugin to apply common tooling and configuration by just including the plugin. At the most basic level, we apply a plugin with project.plugins.apply(“pmd”) then add any additional config, like the common ignore files.

Each of the java project that apply this project are multi-build style projects and most are in the format of
example-project
example-project/example-project-web
example-project/example-project-api

with the owasp report that I’m after stored in example-project/example-project-web/build/reports/dependency-check/dependency-check-report.xml and example-project/example-project-api/build/reports/dependency-check/dependency-check-report.xml

As a work around, running globally with extra command line params may work: ./gradlew build test dependencyCheckAnalyze sonarqube -Dsonar.dependencyCheck.reportPath=build/reports/dependency-check/dependency-check-report.xml -Dsonar.dependencyCheck.htmlReportPath=build/reports/dependency-check/dependency-check-report.html

Although this may work it is not preferred.

Also interestingly when trying the above command line params, I’m able to see the html report in sonar in more-> dependency-check with vulnerabilities, but the vulnerabilities don’t show up in the projects vulnerability count.

edit: just noticed this in the logs when executing using command line params as above: ‘skipping dependency ‘example-project-web.jar’ as no inputFile could established.’ Thinking this is why htmlReportPath works and reportPath does not.

I’ll add as well this is all on Sonar CE 7.4, owasp plugin 1.1.1

Ah, had to add another param on command line to add the additional sources: -Dsonar.sources=build/reports/dependency-check

Hi,

I wonder if this is not the same issue as Allprojects block forces extension addition to be deferred to outside of plugin ? If yes, I would like to keep only this thread to avoid cross-discussion. Can you confirm @cammyjoe and @Tyler_Thrailkill?

Seems like this may be different, I’m able to compile the plugin code and run the plugin during other projects gradle builds, but the property just seems to not be getting picked up. Current code looks like this (to reflect changes that were working on the command line):

    private fun configureSonar(project: Project) {
        project.plugins.apply("org.sonarqube")
        val sonarExt: SonarQubeExtension = project.extensions.getByName("sonarqube") as SonarQubeExtension
        sonarExt.properties( Action <SonarQubeProperties>{
            SonarQubeProperties(mapOf(
                //"sonar.dependencyCheck.reportPath" to "buildDir/reports/dependency-check/dependency-check-report.xml"
                "sonar.dependencyCheck.reportPath" to "build/reports/dependency-check/dependency-check-report.xml",
                "sonar.dependencyCheck.htmlReportPath" to "build/reports/dependency-check/dependency-check-report.html",
                "sonar.sources" to "build/reports/dependency-check"

                ))
        })
    }

I think it is the same issue. The problem isn’t in running the plugin @cammyjoe, but the fact that sonar’s plugin defers to the allprojects block. I didn’t update my post with a working solution, because I’m not looking for a working solution (I have a working solution, it’s just messy), I wanted to ask if sonar could change the design of their plugin to avoid the workaround. Like you, I also had solutions that seemed to do nothing.

For reference, here is the working solution (in kotlin)

class SonarPlugin : Plugin<Project> {
    override fun apply(project: Project): Unit = project.run {
        if (!pluginManager.hasPlugin("org.sonarqube")) {
            pluginManager.apply("org.sonarqube")
        }
        tasks {
            withType<SonarQubeTask> {
                project.allprojects {
                    extensions.configure<SonarQubeExtension>() {
                        if (project.hasProperty("sonar-test")) {
                            properties {
                                property("sonar.sources", "src/test")
                                property("sonar.tests", "")
                                property("sonar.coverage.exclusions", "src/**/*")
                                property("sonar.projectName", "${project.description} Tests")
                                property("sonar.projectKey", "${project.group}.server:${project.name}-tests")
                            }
                        } else {
                            properties {
                                property("sonar.projectName", "${project.description}")
                                property("sonar.projectKey", "${project.group}.server:${project.name}")
                            }
                        }
                    }
                }
            }
        }
    }
}

Note that I have to defer the property setup using the project.allprojects { block, because you are forced to wait until after sonar has configured the allprojects block before you can set the properties.

Do you know by chance if this is a regression of recent version of the plugin? Can you test versions older than 2.7 since some refactoring was made in 2.7, like:

FYI this should be fixed in v2.7.1.

Take a look at your posted code

sonarExt.properties( Action <SonarQubeProperties>{
            SonarQubeProperties(mapOf(
                //"sonar.dependencyCheck.reportPath" to "buildDir/reports/dependency-check/dependency-check-report.xml"
                "sonar.dependencyCheck.reportPath" to "build/reports/dependency-check/dependency-check-report.xml",
                "sonar.dependencyCheck.htmlReportPath" to "build/reports/dependency-check/dependency-check-report.html",
                "sonar.sources" to "build/reports/dependency-check"

                ))
        })

The Action <SonarQubeProperties> is passed in a SonarQubeProperties instance (implicit it), we should put desired properties to this instance. You’re trying to creating a whole new SonarQubeProperties, which might be the problem. Please try adding properties to the passed in instance:

sonarExt.properties( Action <SonarQubeProperties>{
            properties(mapOf(
                //"sonar.dependencyCheck.reportPath" to "buildDir/reports/dependency-check/dependency-check-report.xml"
                "sonar.dependencyCheck.reportPath" to "build/reports/dependency-check/dependency-check-report.xml",
                "sonar.dependencyCheck.htmlReportPath" to "build/reports/dependency-check/dependency-check-report.html",
                "sonar.sources" to "build/reports/dependency-check"

                ))
        })