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}") } } }
关键修改点说明
- 过滤可解析配置:不是所有配置都能被解析(比如
apiElements是用于发布的输出配置),通过it.canBeResolved过滤出可以解析的配置,同时只保留我们关心的类路径配置,避免做无用功。 - 强制解析配置:调用
configuration.resolvedConfiguration会触发Gradle解析该配置,这一步会处理依赖下载、冲突解决等操作,之后我们才能拿到真实的依赖列表。 - 显式检查依赖:直接遍历已解析的依赖(
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
相关产品推荐
相关产品推荐

