由于 JCenter 即将关停,前段时间把几个活跃开源项目的发布流程迁移到了 MavenCentral 上去。参考的两篇文章在各个步骤细节上已经讲解的比较详细了:
然而这个过程我还是踩了些坑,以及有一些摸不着头脑的操作,让我决定写篇文章分享下。
在申请 OSSRH Ticket 时,其实我们在申请的是 Group ID,关键的参数是 Group Id,标题其实都不需要提及具体的 Artifact。
一般 Group ID 即域名倒置,会要求验证域名所有权、Github 仓库所有权、JCenter Group 所有权等,根据对应的回复提示操作即可。一次申请,后续所有的新包发布都不需要再申请,例如:我申请了 me.2bab
的 group,那么未来所有 me.2bab.*
的发布都将支持。
为了校验上传的合法性,我们会对待上传的包做 GPG 签名,用的 Gradle 官方的 The Signing Plugin。刚开始集成时,我按照上述两篇教程的步骤做完,总感觉不对:因为并没有发现我把 signing plugin 所需要的密钥信息传入插件中。
// 插件 DSL 配置最基本的情况就只要这一行
signing {
sign(publishing.publications)
}
简单浏览下文档,然后你就会发现他竟然约定了一些 Keys,插件配置时直接从 Project 的 Properties 读取了。
// 所以你可以看到参考教程的写法都是如下
ext["signing.keyId"] = ...
ext["signing.password"] = ...
ext["signing.secretKeyRingFile"] = ...
以及这个我以前一直不知道能这样干的约定,参考 Build Environment:
//. Using the following setup, you can pass the secret key (in ascii-
// armored format) and the password using the
// ORG_GRADLE_PROJECT_signingKey and ORG_GRADLE_PROJECT_signingPassword
// environment variables, respectively:
signing {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
sign(tasks["stuffZip"])
}
我挺不喜欢这种过于“隐式”的规定,不仔细看文档根本不能知道我到底写了啥。好在它还有提供显示配置的办法:
signing {
val signingKeyId: String? by project // 放在哪里是可选项,不一定要用 Project Properties
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword) // 这行才是关键
sign(tasks["stuffZip"])
}
类似做法的还有 Android Gradle Plugin 的一些 experimental config,那个由于存在和运用的广泛度太高,可能也懒得吐槽了(不过大部分的开关还是可以从 DSL 里直接配置)。如果你看到这不觉得它有问题,那么可以考虑这样的场景:
下次更新插件的时候我就打算改成 useInMemoryPgpKeys(...)
,不然过一年又不记得这个坑,或者任何接手你项目而不了解 Signing 插件的人都会再迷惑一回。
如果采用了 signing.secretKeyRingFile
配置,那么就得考虑本地和 CI 环境下的不同配置:
../local/secret.gpg
,建议放项目根目录或建立一个 local
文件夹并整个文件夹加入 gitignore,原因是一台机器上可能用不止一份的 secret.gpg,密钥随项目走其实比较好找,对其他合作者来说 setup 也方便;/secret.gpg
,直接放虚拟环境根目录,方便配合 RingFile 生成脚本;前不久在掘金看到有人写的 MavenCentral 发布教程,提到不要多个包上传后再一起 Close。事实上这是支持并且推荐的,同一 Group ID 的 Package 会放到一个 staging repo,然后就可以一起 close & release。如果引用了自动处理 close & release 流程的插件,聚合上传(batch upload)反倒能提升后续操作的成功率(SonaType 的 API 和网页都不太稳定)。比如我的这个项目有六个模块,其实就使用了 Batch Upload 策略。
欢迎关注我的公众号和微博。