序言

将一个普通的 Java 项目上传至 Maven 中央仓库并不是一件很困难的事情。按照官方提供的配置即可。但如果想上传一个 Kotlin 多平台项目,就没那么方便了。网上关于 Kotlin 多平台项目的资料很少,如何上传至中央仓库更是几乎没有。
本篇文章将介绍将 Kotlin 多平台项目上传至 Maven 中央仓库的方法、流程、配置、坑和其处理方式。

一、准备工作

先了解一下概念,OSSRH - Sonatype OSSRH 是为开源软件提供 Maven 仓库托管的服务。要在 Maven 中央仓库( Maven Central )中发布,需要先注册账号。

1.1 注册 Sonatype JIRA 账号

注册链接:https://issues.sonatype.org/secure/Signup!default.jspa

注册成功后会进入如下界面:




鸿蒙 java js 鸿蒙 java kotlin_javad


英语不够好的请选择「中文(中国)」


鸿蒙 java js 鸿蒙 java kotlin_github_02


选择「下一步」

1.2 提交发布项目申请


鸿蒙 java js 鸿蒙 java kotlin_git 上传项目到linux仓库_03


选择「创建一个问题」

注:如果已经注册,则在主页上点击「新建」也可以进入到创建 issue 的页面。


鸿蒙 java js 鸿蒙 java kotlin_javad_04


「项目」一栏选择 Community Support - Open Source Project Repository Hosting (OSSRH) ,选择这一项代表我们是要发布一个开源项目。

「问题类型」一栏选择 New Project,然后「下一步」


鸿蒙 java js 鸿蒙 java kotlin_git 上传项目到linux仓库_05


「概要」和「描述」填写关于项目的简单概要和详细介绍,如果不知道填啥可以填项目名和简介。


鸿蒙 java js 鸿蒙 java kotlin_javad_06


「GroupId」为 Maven 坐标的 GroupId,不能随便填写。需要持有该域名才能使用该 GroupId。 例如我的域名为 jcr.pub 那么我的 GroupId 可以填写 pub.jcr.* 这种格式。
如果没有自己的域名,那么可以使用 Github 的其用户名作为 GroupId 。我的 Github 用户名为 csgajcr 那么我可以填写 com.github.csgajcr 作为我的 GroupId。

「Project URL」填写项目的链接地址。https://github.com/csgajcr/unity-bridge-android

「SCM URL」填写项目的版本管理地址。https://github.com/csgajcr/unity-bridge-android.git

填写完成后,点击「新建」

至此,就已经成功提交一个申请了。

注:提交之后需要等待 10 分钟左右,工作人员会给我们提交的 issue 一个回复,让你验证域名。(因为我之前选择的域名作为 GroupId)

1.3 配置域名通过认证

大约 10 分钟后,工作人员会给你一个回复,并且会把 issue 的状态修改为 「wait for response」


鸿蒙 java js 鸿蒙 java kotlin_上传_07


根据回复的内容,可以通过两种方式证明你拥有这个域名:

  1. 为域名添加 TXT 记录
  2. 为域名设置重定向到 Github page

我选择的「为域名添加 TXT 记录」

注:我的域名在阿里云购买,所以进入阿里云控制台配置即可,其他域名服务商也有对应的设置位置。


鸿蒙 java js 鸿蒙 java kotlin_git 上传项目到linux仓库_08


添加之后,点击前面 issue 页面上方的按钮「Response」,问题会变成 「open」状态。继续等待 10 分钟左右。如果验证成功就会看到成功的评论,如果失败,请参考在 issue 中的回复内容,进行修改即可。


鸿蒙 java js 鸿蒙 java kotlin_github_09


上图为认证成功的评论。

二、项目配置

本节主要介绍在跨平台项目中 Gradle 脚本应该如何配置上传功能。

2.1 引入插件

在项目根目录的 build.gradle 中加入如下代码:


apply plugin: 'maven-publish'
apply plugin: 'signing'


  • maven-publish 是将项目发布到 Maven 仓库的插件。
  • signing 是签名插件,为发布生成的文件进行签名。

2.2 GPG 密钥设置

Maven Central 会对我们上传的包进行签名。这里使用的签名采用的是公私钥(RSA)的模式,即私钥签名,公钥验证。所以我们需要先为项目生成一份公私钥对,并将公钥上传至公钥中心,再把私钥配置到项目中,为生成的包签名。

这里涉及的概念 「公钥」、「私钥」、「签名」如果不太清楚可以自行查阅相关资料。

1. GPG 安装
GPG 在 Max OSX 环境下可以直接通过命令行安装。


brew install -v gpg


Windows 下可以使用 gpg4win

以下将以 Mac OSX 为基准演示操作流程。Windows 用户可以使用可视化 GPG 管理工具,或者 Windows 下的 bash ,具体请自行查阅相关资料,这里不做太多详述。

2. 新建密钥 执行如下命令


gpg --generate-key


执行后会让你输入密钥的相关信息,根据你的信息输入即可。执行结果:


pub   rsa2048 2020-07-27 [SC] [有效至:2022-07-27]
      BB53A3118459F41C4E355D31E90A28513D397F2F
uid                      Jcr <i@jcr.pub>
sub   rsa2048 2020-07-27 [E] [有效至:2022-07-27]


查看已经生成的密钥,可以看到刚才生成的密钥。


gpg -k


其中 BB53A3118459F41C4E355D31E90A28513D397F2F 为密钥指纹,指纹的后 8 位 「3D397F2F」为密钥的 KeyId,后续在 Gradle 配置中将会使用到。

3. 导出刚创建的私钥
执行命令


gpg --export-secret-keys [密钥指纹] > private-key.gpg


将导出之后的 private-key.gpg 放置到项目目录,方便下一步的配置使用。

4. 上传公钥到公钥服务器
执行命令


gpg --keyserver keyserver.ubuntu.com --send-keys [密钥指纹]


注意: http:// keyserver.ubuntu.com 为公钥服务器的地址,Maven Central 在校验签名是会从公钥服务器拉取。Maven Central 支持的公钥服务器地址有三个 pool.sks-keyservers.netkeyserver.ubuntu.comkeys.gnupg.net。如果一个地址访问失败,替换成换成其中任意一个都是可以的。

2.3 配置发布参数

build.gradle 中设置项目的 groupId 和 version,actifactId 会自动获取你的项目名称。


group 'pub.jcr.android' //这里的 groupId 需要和 OSSRH 中申请的保持一致
version '0.0.0.9'


添加 Maven 发布相关代码


def javadocTask = task javadocJar(type: Jar) {
    archiveClassifier.set("javadoc")
    classifier = "javadoc"
}

publishing {
    publications.configureEach {
        // 添加生成 javadoc 的任务
        artifact javadocTask

        setArtifactId("card-message-core") //设置 artifactId

        //配置上传源码
        pom {
            // 构件名称
            // 区别于artifactId,可以理解为artifactName
            name = 'card-message-core'
            // 构件描述
            description = 'A qingtui card message component'
            // 构件主页
            url = 'https://github.com/im-qingtui/card-message-core'
            // 许可证名称和地址
            licenses {
                license {
                    name = 'The Apache License, Version 2.0'
                    url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                }
            }
            // 开发者信息
            developers {
                developer {
                    name = 'Jcr'
                    email = 'i@jcr.pub'
                }
            }
            // 版本控制仓库地址
            scm {
                url = 'https://github.com/im-qingtui/card-message-core'
                connection = 'scm:git:git://github.com/im-qingtui/card-message-core.git'
                developerConnection = 'scm:git:ssh://git@github.com:im-qingtui/card-message-core.git'
            }
        }

    }
    repositories {
        maven {
            //指定要上传的maven私服仓库,这里只设置了 release 仓库地址。
            url = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
            //认证用户和密码,配置到 gradle.properties 中
            credentials {
                username sonatypeUsername
                password sonatypePassword
            }
        }
    }

    signing {
        // 设置对生成文件进行签名
        sign publishing.publications
    }
}


gradle.properties 中添加


signing.keyId=[签名 keyId]
signing.password=[签名 password]
signing.secretKeyRingFile=[签名的相对路径 例:publish/secret.gpg]

sonatypeUsername=[OSSRH 用户名]
sonatypePassword=[OSSRH 密码]


  • keyId 为上一步 GPG 密钥所包含的。
  • secretKeyRingFile 为上一步导出的签名路径,

三、发布

完成以上步骤后,执行 Gradle Task - Publishing -> publish 或者 Gradle Task - Publishing -> publishJvmPublicationToMavenRepository,前者是发布整个跨平台项目,后者是发布其中的 JVM 部分。
如果前面配置没有出错,那么这里执行完成之后就上传成功了。但这并没有结束,本地上传成功之后实际会在 Nexus 中生成一个申请,Nexus 会根据校验规则校验我们上传的包,校验通过后,才可以正式发布。所以我们需要登录 Nexus 去查看我们生成的申请。步骤如下:

3.1 登录 Nexus

使用 OSSRH 的账号登录 https://oss.sonatype.org/

3.2 处理申请

点击 「Staging Repositories」


鸿蒙 java js 鸿蒙 java kotlin_github_10


这条记录就是我们刚才创建的申请,当前状态是「Open」,我们需要选择该条申请,点击「Close」。


鸿蒙 java js 鸿蒙 java kotlin_github_11


等待 1 min 后,刷新页面,选择该申请,点击「Activity」-> 「close」 查看审核结果。


鸿蒙 java js 鸿蒙 java kotlin_javad_12


如果没有报错,就说明审核通过了。
点击 「Release」


鸿蒙 java js 鸿蒙 java kotlin_鸿蒙 java js_13


如果是首次发布,请跳到「四、首次发布后续」继续操作,如果不是首次发布,那么到这里,就已经完成发布了,就可以通过你配置的 Maven 坐标下载到对应的包了。

注:项目生成的文件可以 「Activity」右边的「Content」 查看,如果出错可以检查上传的文件是否完整。

3.3 审核步骤详解和排错

在上图中,列出了每一条审核的信息。如果审核失败,会在这里具体标出那一条失败。下面开始说明每一条检验规则。

  1. Javadoc Validation 上传的文件之中必须包含 javadoc,如果没有则报错
  2. Archives must not contain insecure paths 上传的文件包中不能包含不安全的路径。只要我们没有违规配置,这一点一般都没问题
  3. Signature Validation 上传的文件中需要包含 .asc 签名文件,并且会对其进行校验。要和之前密钥配置中匹配
  4. POM Validation 校验 POM 文件中的信息是否完整,除了基本配置之外,还需要包含 「SCM」信息、项目基本信息(名称、详情、URL)、licenses、developers
  5. Profile target matcher 配置是否匹配
  6. Checksum Validation 文件 hash 校验
  7. Sources Validation 上传的文件中必须包含 sources

四、首次发布后续

还记得在前面 OSSRH 认证成功之后工作人员的回复吗?其中有一句「please comment on this ticket when you promoted your first release, thanks」
「三、发布」完成之后,我们需要回到 OSSRH 中对最开始申请的 issue 进行回复。告诉工作人员,我们完成了第一次发布。


鸿蒙 java js 鸿蒙 java kotlin_鸿蒙 java js_14


「I have success to promoted my first release.」

稍等一会儿,管理员回复之后,Maven Central 会开始进行同步,大约 2 小时之后就可以通过 Maven 坐标检索到你的包了。


鸿蒙 java js 鸿蒙 java kotlin_上传_15


至此,首次发布完成。