You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让依赖的Gradle任务脱离配置阶段,仅在执行阶段运行

解决Gradle任务在配置阶段提前运行的问题

首先得明确Gradle的配置阶段和执行阶段的核心区别:配置阶段会处理所有任务的配置逻辑(不管你有没有指定要执行这个任务),而执行阶段只运行你指定的任务及其依赖的执行逻辑。你的问题就出在这两个任务的核心逻辑都跑到配置阶段执行了,而且依赖关系没处理对。

问题拆解

  1. getCoverageReport任务的代码直接写在任务块里,没有用doFirst/doLast包裹,所以Gradle在配置阶段就会执行这段代码,哪怕你只跑build任务也会触发它。
  2. confluence任务的配置块(包括pageVariables的赋值)也是在配置阶段执行的,这时候codeCoverage和testCoverage还没被赋值,而且直接在doFirst里调用getCoverageReport其实是在配置阶段就触发了任务的配置,不是执行。

修复步骤

1. 让getCoverageReport的逻辑只在执行阶段运行

把任务里的核心代码放到doLast(或者doFirst)里,这样只有当任务被执行的时候才会跑这段逻辑:

task getCoverageReport {
    // 提前定义变量并挂载到project属性,避免作用域问题
    project.ext.codeCoverage = null
    project.ext.testCoverage = null

    doLast {
        def headers = [Accept: 'application/json']
        def resourcesId = getProjectResourceId()
        if (resourcesId != null) {
            def jsonText = new URL("(sonar instance)/api/resources?metrics=coverage,test_success_density&resource=" + resourcesId)
                    .getText(requestProperties: headers)
            def parsedJson = new JsonSlurper().parseText(jsonText)
            if (null != parsedJson) {
                project.ext.codeCoverage = parsedJson.msr.get(0).get(0).frmt_val
                project.ext.testCoverage = parsedJson.msr.get(0).get(1).frmt_val
            }
        }
    }
}

这里把变量挂载到project.ext下,是为了让其他任务能在执行阶段顺利获取到这些动态值。

2. 正确建立confluence任务和getCoverageReport的依赖

不要直接在doFirst里调用任务,而是用dependsOn指定依赖,这样Gradle会保证getCoverageReport先执行,再执行confluence。同时,把需要动态获取的pageVariables延迟到执行阶段赋值:

tasks.named('confluence') {
    // 指定依赖,确保getCoverageReport先完成执行
    dependsOn getCoverageReport

    doFirst {
        // 到执行阶段再赋值pageVariables,此时已经能拿到coverage数据
        pageVariables = [
            'project.name' : project.name, 
            'release.version': someversion, 
            'codeCoverage' : project.ext.codeCoverage, 
            'testCoverage' : project.ext.testCoverage 
        ]
    }

    // 固定配置可以保留在外部
    String confluenceUser = XXXXX
    String confluencePassword = XXXXXX
    authentication new String(confluenceUser + ":" + confluencePassword).bytes.encodeBase64().toString()
    restApiUrl 'some uri'
    spaceKey 'XXXX'
    sslTrustAll true

    pages {
        page {
            parentTitle 'page title'
            title "title" + project.getProperties().get('version')
            srcFile file('some file location')
            labels = ['Release Report']
        }
    }
}

3. 验证效果

现在执行./gradlew build的时候,getCoverageReport和confluence都不会运行,因为它们不是build任务的依赖。只有当你执行./gradlew confluence时,Gradle会先执行getCoverageReport的执行逻辑,再执行confluence的任务,完美符合你的需求。

额外提示

  • 永远记住:任务块里的直接代码是配置阶段执行的,只有doFirst/doLast里的代码是执行阶段的。
  • 任务之间的依赖尽量用dependsOn,而不是手动调用任务,这样Gradle能正确处理任务执行顺序和增量构建。

内容的提问来源于stack exchange,提问作者tyro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:36:34