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

Gradle插件自定义Snapshot依赖验证任务无法检测到依赖的问题排查

问题分析与解决方案

你的核心问题在于Gradle配置是懒加载的,当前代码只是遍历了配置对象,但这些配置并没有被解析,所以resolutionStrategy.eachDependency这个回调根本不会触发,自然检测不到快照依赖。

为什么当前代码无效?

resolutionStrategy.eachDependency是配置阶段的回调,只有当Gradle需要解析该配置(比如编译、运行任务需要用到依赖)时才会执行。而你的任务只是遍历了配置列表,没有触发任何解析操作,所以这个回调不会被调用,也就找不到那些快照依赖。

修复后的任务实现

我们需要修改任务逻辑,强制解析我们关心的配置,然后遍历已解析的依赖来检查快照版本:

class SnapshotPolicyTask extends DefaultTask {
    @TaskAction
    def snapshotPolicy() {
        println 'SnapshotPolicyTask#snapshotPolicy'
        String version = project.version.toString()
        // 快照版本构建跳过检查
        if (version.endsWith("-SNAPSHOT")) return
        println 'testing dependencies'
        
        // 只检查业务相关的可解析配置,避免检查不需要的配置(比如archives)
        def targetConfigurations = project.configurations.findAll { 
            it.canBeResolved && it.name in [
                'compileClasspath', 'runtimeClasspath', 
                'testCompileClasspath', 'testRuntimeClasspath'
            ]
        }

        targetConfigurations.each { configuration ->
            println "checking configuration: ${configuration.name}"
            try {
                // 强制解析配置,这会触发Gradle下载/计算依赖
                def resolvedConfig = configuration.resolvedConfiguration
                // 检查直接依赖
                resolvedConfig.firstLevelModuleDependencies.each { checkDependency(it) }
                // 如果需要检查传递依赖,可以遍历children
                // resolvedConfig.firstLevelModuleDependencies.each { dep ->
                //     checkDependency(dep)
                //     dep.children.each { checkDependency(it) }
                // }
            } catch (Exception e) {
                throw new GradleException("Failed to resolve configuration ${configuration.name}: ${e.message}", e)
            }
        }
    }

    private void checkDependency(dep) {
        def moduleId = dep.module.id
        println "inspecting dependency: ${moduleId}"
        if (moduleId.version.endsWith("-SNAPSHOT")) {
            throw new GradleException("Found SNAPSHOT dependency: ${moduleId.group}:${moduleId.name}:${moduleId.version}")
        }
    }
}

关键修改点说明

  1. 过滤可解析配置:不是所有配置都能被解析(比如apiElements是用于发布的输出配置),通过it.canBeResolved过滤出可以解析的配置,同时只保留我们关心的类路径配置,避免做无用功。
  2. 强制解析配置:调用configuration.resolvedConfiguration会触发Gradle解析该配置,这一步会处理依赖下载、冲突解决等操作,之后我们才能拿到真实的依赖列表。
  3. 显式检查依赖:直接遍历已解析的依赖(firstLevelModuleDependencies是直接依赖,children是传递依赖),检查版本是否为快照。

任务依赖优化

虽然调用resolvedConfiguration会让Gradle自动处理依赖关系,但显式声明任务依赖会让构建逻辑更清晰:

// 在插件的apply方法中注册任务时
project.tasks.create('snapshotPolicy', SnapshotPolicyTask) {
    // 让任务依赖所有目标配置的解析任务,确保依赖已准备好
    dependsOn project.configurations.compileClasspath, 
              project.configurations.runtimeClasspath,
              project.configurations.testCompileClasspath,
              project.configurations.testRuntimeClasspath
}
// 让check任务依赖该检查任务,这样执行check时会自动运行快照检查
project.tasks.findByName("check")?.dependsOn("snapshotPolicy")

测试代码调整

你的测试需要断言任务失败,而不是只检查输出。修改测试的then块:

then:
// 断言任务抛出了GradleException
thrown(GradleException)
// 或者检查构建结果的任务状态
result.task(":snapshotPolicy").outcome == TaskOutcome.FAILED
// 同时验证错误信息
result.output.contains("Found SNAPSHOT dependency: org.example:example:0.0.1-SNAPSHOT")

这样修改后,你的任务就能正确检测到快照依赖,并且测试也能验证预期的失败场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:29:10