Search code examples
gradlesonarqubebuild.gradlesonarqube-scan

Cannot have different system properties values for different tasks


I am trying to create 2 tasks to execute the sonarcube task. I want to be able to specify different properties depending on the task

   task sonarqubePullRequest(type: Test){

        System.setProperty( "sonar.projectName", "sonarqubePullRequest")
        System.setProperty("sonar.projectKey", "sonarqubePullRequest")
        System.setProperty("sonar.projectVersion", serviceVersion)
        System.setProperty("sonar.jacoco.reportPath", 
        "${project.buildDir}/jacoco/test.exec")

        tasks.sonarqube.execute()
    }


task sonarqubeFullScan(type: Test){
    System.setProperty("sonar.projectName", "sonarqubeFullScan")
    System.setProperty("sonar.projectKey", "sonarqubeFullScan")
    System.setProperty("sonar.projectVersion", serviceVersion)
    System.setProperty("sonar.jacoco.reportPath", 
    "${project.buildDir}/jacoco/test.exec")
    tasks.sonarqube.execute()
}

The tasks work but there seems to be an issue with the properties I am setting

if I run the first task which is sonarqubePullRequest then everything is fine, but if run sonarqubeFullScan then if uses the values specified in the sonarqubePullRequest. so the project name is set sonarqubePullRequest

it is as if those properties are set at run time and cannot be updated. I feel like I am missing something obvious any suggestions greatly received.


Solution

  • First of all: NEVER use execute() on tasks. The method is not part of the public Gradle API and therefor, its behaviour can change or be undefined. Gradle will execute the tasks on its own, either because you specified them (command line or settings.gradle) or as task dependencies.

    The reason, why your code does not work, is the difference between the configuration phase and the execution phase. In the configuration phase, all the (configuration) code in your task closures is executed, but not the tasks. So, you'll always overwrite the system properties. Only (internal) task actions, doFirst and doLast closures are executed in the execution phase. Please note, that every task is only executed ONCE in a build, so your approach to parametrize a task twice will never work.

    Also, I do not understand why you are using system properties to configure your sonarqube task. You can simply configure the task directly via:

    sonarqube {
        properties {
            property 'sonar.projectName', 'sonarqubePullRequest'
            // ...
        }
    }
    

    Now you can configure the sonarqube task. To distinguish between your two cases, you can add a condition for different property values. The next example makes use of a project property as condition:

    sonarqube {
        properties {
            // Same value for both cases
            property 'sonar.projectVersion', serviceVersion
            // Value based on condition
            if (project.findProperty('fullScan') {
                property 'sonar.projectName', 'sonarqubeFullScan'
            } else {
                property 'sonar.projectName', 'sonarqubePullRequest'
            }
        }
    }
    

    Alternatively, you can add another task of the type SonarQubeTask. This way, you could parametrize both tasks differently and call them (via command line or dependency) whenever you need them:

    sonarqube {
        // Generated by the plugin, parametrize like described above
    }
    
    task sonarqubeFull(type: org.sonarqube.gradle.SonarQubeTask) {
        // Generated by your build script, parametrize in the same way
    }