如何让依赖的Gradle任务脱离配置阶段,仅在执行阶段运行
解决Gradle任务在配置阶段提前运行的问题
首先得明确Gradle的配置阶段和执行阶段的核心区别:配置阶段会处理所有任务的配置逻辑(不管你有没有指定要执行这个任务),而执行阶段只运行你指定的任务及其依赖的执行逻辑。你的问题就出在这两个任务的核心逻辑都跑到配置阶段执行了,而且依赖关系没处理对。
问题拆解
getCoverageReport任务的代码直接写在任务块里,没有用doFirst/doLast包裹,所以Gradle在配置阶段就会执行这段代码,哪怕你只跑build任务也会触发它。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
相关产品推荐
相关产品推荐

