首页 > 解决方案 > 使用 Grade、Jacoco 和 Sonarqube 处理多项目构建

问题描述

到目前为止这是有效的(至少看起来它有效),但我不觉得它是惯用的,或者即使几个月也能经受住时间的考验。有什么办法可以做得更好或更“按书”?

我们在 Gradle 中有一些多项目构建,其中一个项目的测试可能会触及另一个项目的代码,因此即使它不在同一个项目中,但它在同一个多项目中,查看覆盖率也很重要。我可能正在解决不存在的问题,但在早期的 SonarQube 版本中,我必须“jacocoMerge”覆盖结果。

jacocoTestReport {
    reports {
        executionData (tasks.withType(Test).findAll { it.state.upToDate || it.state.executed })
        xml.enabled true
    }
}

if(!project.ext.has('jacocoXmlReportPathsForSonar')) {
    project.ext.set('jacocoXmlReportPathsForSonar', [] as Set<File>)
}

task setJacocoXmlReportPaths {
    dependsOn('jacocoTestReport')
    doLast {
        project.sonarqube {
            properties {
                property 'sonar.coverage.jacoco.xmlReportPaths', project.
                    ext.
                    jacocoXmlReportPathsForSonar.
                    findAll { d -> d.exists() }.
                    collect{ f -> f.path}.
                    join(',')
            }
        }
    }
}
project.rootProject.tasks.getByName('sonarqube').dependsOn(setJacocoXmlReportPaths)

sonarqube {
    properties {
        property "sonar.java.coveragePlugin", "jacoco"
        property "sonar.tests", []
        property "sonar.junit.reportPaths", []
    }
}

afterEvaluate { Project evaldProject ->
    JacocoReport jacocoTestReportTask = (JacocoReport) evaldProject.tasks.getByName('jacocoTestReport')

    evaldProject.ext.jacocoXmlReportPathsForSonar += jacocoTestReportTask.reports.xml.destination

    Set<Project> dependentProjects = [] as Set<Project>

    List<String> configsToCheck = [
        'Runtime',
        'RuntimeOnly',
        'RuntimeClasspath',
        'Compile',
        'CompileClasspath',
        'CompileOnly',
        'Implementation'
    ]

    evaldProject.tasks.withType(Test).findAll{ it.state.upToDate || it.state.executed }.each { Test task ->
        logger.debug "JACOCO ${evaldProject.path} test task: ${task.path}"

        sonarqube {
            properties {
                properties["sonar.junit.reportPaths"] += task.reports.junitXml.destination.path
                properties["sonar.tests"] += task.testClassesDirs.findAll { d -> d.exists() }
            }
        }

        configsToCheck.each { c ->
            try {
                Configuration cfg = evaldProject.configurations.getByName("${task.name}${c}")
                logger.debug "JACOCO ${evaldProject.path} process config: ${cfg.name}"

                def projectDependencies = cfg.getAllDependencies().withType(ProjectDependency.class)

                projectDependencies.each { projectDependency ->
                    Project depProj = projectDependency.dependencyProject
                    dependentProjects.add(depProj)
                }
            } catch (UnknownConfigurationException uc) {
                logger.debug("JACOCO ${evaldProject.path} unknown configuration: ${task.name}Runtime", uc)
            }
        }
    }

    dependentProjects.each { p ->
        p.plugins.withType(JacocoPlugin) {
            if (!p.ext.has('jacocoXmlReportPathsForSonar')) {
                p.ext.set('jacocoXmlReportPathsForSonar', [] as Set<File>)
            }
            p.ext.jacocoXmlReportPathsForSonar += jacocoTestReportTask.reports.xml.destination

            JacocoReport dependentJacocoTestReportTask = (JacocoReport) p.tasks.getByName('jacocoTestReport')
            dependentJacocoTestReportTask.dependsOn(jacocoTestReportTask)
            setJacocoXmlReportPaths.dependsOn(dependentJacocoTestReportTask)
        }
    }
}

标签: gradlesonarqubejacoco

解决方案


推荐阅读