返回

Gitlab CI 中 Maven Publish 任务依赖错误怎么办?

Android

解决 Gitlab CI 中出现的 Maven Publish 任务依赖错误

在使用 Gitlab CI 进行 Android 项目持续集成时,我们常常借助 maven-publish 插件将构建产物发布到 Maven 仓库。然而,CI 环境下执行 maven-publish 任务时,有时会遭遇 Task Dependency Issue 错误,即使本地构建一切正常。本文将深入分析该错误的根源,并提供解决方案和代码示例,助你轻松解决这个棘手问题。

错误根源解析

你遇到的错误信息 Task ':core:common:publishMyPublishPublicationToMavenLocalRepository' uses this output of task ':core:common:bundleProdReleaseAar' without declaring an explicit or implicit dependency 清晰地表明:publishMyPublishPublicationToMavenLocalRepository 任务依赖于 bundleProdReleaseAar 任务的输出,但并未显式或隐式地声明这种依赖关系。

为何会出现这种状况?

本地构建时,Gradle 能够根据项目结构和插件配置自动推断任务之间的依赖关系。然而,CI 环境通常是干净的构建环境,Gradle 可能无法准确推断出所有任务的依赖关系,进而导致上述错误。

解决方案探究

要解决这个问题,我们需要明确地声明 publishMyPublishPublicationToMavenLocalRepository 任务对 bundleProdReleaseAar 任务的依赖。

打开你的 build.gradle 文件,在 afterEvaluate 代码块中添加如下内容:

tasks.named("publishMyPublishPublicationToMavenLocalRepository") {
    dependsOn(":core:common:bundleProdReleaseAar")
}

这段代码明确告知 Gradle,publishMyPublishPublicationToMavenLocalRepository 任务依赖于 :core:common:bundleProdReleaseAar 任务。如此一来,Gradle 就会先执行 bundleProdReleaseAar 任务,生成 aar 文件,然后执行 publishMyPublishPublicationToMavenLocalRepository 任务进行发布。

代码优化实践

除了解决上述错误,我们还可以对代码进行优化,使其更简洁易懂:

  1. 依赖声明简化: 使用 implementation 替代 configurations.implementation.allDependencies.each,更简洁地声明依赖。

  2. group 属性的应用:MavenPublication 中设置 group 属性,避免在每个依赖中重复指定 group

以下是优化后的代码:

apply plugin: 'maven-publish'

group = 'com.yourcompany' // 设置项目组

afterEvaluate {
    if (!plugins.hasPlugin("android")) {
        publishing {
            publications {
                myPublish(MavenPublication) {
                    version releaseVersion
                    if (plugins.hasPlugin("java")) {
                        from components.java
                    } else if (plugins.hasPlugin("android-library")) {
                        artifactId = project.name
                        artifact("$buildDir/outputs/aar/${project.name}-prod-release.aar")
                        pom.withXml {
                            def dependenciesNode = asNode().appendNode('dependencies')
                            def dependenciesManagementNode = asNode().appendNode('dependencyManagement').appendNode('dependencies')

                            // 简化依赖声明
                            implementation.each { dep ->
                                if (dep.group.contains("mflota-android")) {
                                    dependenciesNode.appendNode('dependency')
                                            .appendNode('groupId', dep.group)
                                            .appendNode('artifactId', dep.name)
                                            .appendNode('version', releaseVersion)
                                } else {
                                    dependenciesNode.appendNode('dependency')
                                            .appendNode('groupId', dep.group)
                                            .appendNode('artifactId', dep.name)
                                            .appendNode('version', dep.version)
                                }
                            }
                        }
                    }
                }
            }
            repositories {
                mavenLocal()
                maven {
                    url "https://gitlab.com/api/v4/projects/...."
                    credentials(HttpHeaderCredentials) {
                        name = "Private-Token"
                        value = TOKEN
                    }
                    authentication {
                        header(HttpHeaderAuthentication)
                    }
                }
            }
        }

        // 声明任务依赖
        tasks.named("publishMyPublishPublicationToMavenLocalRepository") {
            dependsOn(":core:common:bundleProdReleaseAar")
        }
    }
}

通过上述修改,你就能解决 Gitlab CI 中出现的 Maven Publish 任务依赖错误,同时使你的构建脚本更加清晰简洁。

常见问题解答

1. 为什么本地构建没有问题,但在 CI 环境下就会出现 Task Dependency Issue 错误?

本地构建时,Gradle 会缓存项目结构和依赖关系信息,因此能够自动推断任务之间的依赖。而在 CI 环境中,每次构建都是一个全新的环境,Gradle 无法获取缓存信息,需要明确声明任务依赖关系。

2. 如何确定哪些任务之间存在依赖关系?

仔细阅读 Gradle 的报错信息,它会明确指出哪些任务之间存在未声明的依赖关系。

3. 除了 dependsOn 方法,还有哪些方式可以声明任务依赖?

还可以使用 mustRunAftershouldRunAfter 方法声明任务的执行顺序,但 dependsOn 方法更加直接和明确。

4. 为什么优化后的代码中使用了 implementation 替代了 configurations.implementation.allDependencies.each

implementation 是 Gradle 提供的简化语法,可以更简洁地声明依赖关系。

5. group 属性的作用是什么?

group 属性用于标识项目的所属组织或公司,通常与项目的包名相对应。在 MavenPublication 中设置 group 属性可以避免在每个依赖中重复指定 group,使代码更简洁。