前言
先来闲侃一下,这几天一直在搞这东东,从一点不知道到大体知道,再到知道完整流程,真的看了不是大神的帖子,特别是UK的chrisbanes大神,写了一个标准的gradle脚本,真的很是用,英文不好,所以看起来费了点劲,废话不多说了,下面来讲讲步骤吧。
大概有以下 5 个步骤:
- 到 issues.sonatype.org 注册个帐号,申请发布权限
- 编写 Gradle 自动化发布脚本
- 下载 GPGTools,创建 Signing Key
- 执行 Gradle 发布脚本
- 申请激活 Maven Central Sync 进程
1. 申请 Maven Central 发布权限
第一步就是注册账号,这一步就省略掉吧。
这里需要特别说明的是Group Id,如果你是托管在Github或者Git@OSC 可以使用com.github.XXX或者net.oschina.XXX,我之前注册了个自己的域名com.github.xxl6097,所以在此填写这个group,剩下的可以依照实际情况填写,例如托管的地址等等
- 等待Issue审批
截图为这个Issue的截图,当看到 Configuration has been prepared, now you can: 这句话的时候,说明你已经通过了Issue的审批,可以上传构建了。
2. 编写 Gradle 发布脚本
首先展示一下我的项目目录,方便下面做说明:
library就是我们的库,也就是这边文章的主角色了,sample仅仅是一个使用实例而已。
配置Project属性(library)
在工程目录下的gradle.properties文件中设置属性,把属性修改成自己的。
#版本名称
VERSION_NAME=1.0.0
#版本号
VERSION_CODE=1
#唯一标识
GROUP=com.github.xxl6097
#项目描述信息
POM_DESCRIPTION=this android crash library
#项目托管主页
POM_URL=https://github.com/xxl6097/CustomOnCrash
#项目托管主页
POM_SCM_URL=https://github.com/xxl6097/CustomOnCrash
#项目托管地址
POM_SCM_CONNECTION=scm:git@github.com:xxl6097/CustomOnCrash.git
POM_SCM_DEV_CONNECTION=scm:git@github.com:xxl6097/CustomOnCrash.git
POM_LICENCE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=uuxia
POM_DEVELOPER_NAME=uuxia xxl6097
POM_DEVELOPER_EMAIL=263996097@qq.com
POM_INCEPTION_YEAR=2015
ANDROID_BUILD_TARGET_SDK_VERSION=19
ANDROID_BUILD_TOOLS_VERSION=19.0.3
ANDROID_BUILD_SDK_VERSION=19
注意:VERSION_NAME后面加-SNAPSHOT表示发布的是版本快照。
GROUP设置成项目包名,注意,父级要和之前创建JIRA ticket时的Group Id一致。
配置Module属性(library)
修改项目根目录下的gradle.properties,添加项目的信息:
工程配置好之后,我们还需要给上传的Module配置(我们的工程中可能有多个Module需要上传到仓库中,要给每个Module添加配置)
给需要上传到Maven仓库的Module提供一个gradle.properties文件:
最后到开源库所在的 module 目录,添加编译信息到 library\gradle.properties :
POM_NAME=CustomOnCrash
POM_ARTIFACT_ID=customoncrash
POM_PACKAGING=aar
POMARTIFACTID设置成Module名。
这个组件对应的依赖已经浮出水面了:GROUP:POMARTIFACTID:VERSION_NAME
即:
com.github.xxl6097:customoncrash:1.0.0
配置Module构建脚本(library)
感谢 Chris Banes 大神提供的脚本,稍作修改,弄了一个我自己的版本。
https://github.com/xxl6097/gradle-mvn-push/blob/master/gradle-mvn-push.gradle
将上面的脚本放到项目的根目录下也就是library同级目录,然后到开源库所在的 module 目录(library目录),添加以下代码 library\build.gradle :
apply from: '../gradle-mvn-push.gradle'
配置全局属性
这个全局的Gradle配置文件默认在USER_HOME/.gradle/gradle.properties,没有的话可以新建一个。
在这里配置Maven服务器的用户名和密码,还需要配置之前生成的keyId, password和一个secretKeyRingFile,这个文件用来在上传release版本时对文件进行签名。
#nexus的用户名
NEXUS_USERNAME=xxl6097
#nexus的密码
NEXUS_PASSWORD=*******
#GPG秘钥ID
signing.keyId=FB58CB54
#GPG秘钥密码
signing.password=********
#GPG秘钥文件路径
signing.secretKeyRingFile=C:/Users/uuxia/AppData/Roaming/gnupg/secring.gpg
Windows的secretKeyRingFile路径如上所示,其它系统可以使用gpg –list-secret-keys命令查看。
3. 下载 GPGTools,创建 Signing Key
发布release版本时需要对上传的文件加密和签名,GPG用于生成签名,管理密钥。
上传前我们需要做两件事:
- 生成密钥对
- 上传密钥
安装
- 下载地址:GPG
- 安装之后验证一下:
- 生成密钥
gpg --gen-key
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 8192 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: Special Leung(Testing)
Email address: specialcyci+test@gmail.com
Comment: This is just a testing key.
You selected this USER-ID:
"uuxia (This is just a testing key.) <specialcyci+test@gmail.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.
...
pub 2048R/8C1761A2 2015-01-24
Key fingerprint = xxx
uid [ultimate] uuxia (This is just a testing key.) <specialcyci+test@gmail.com>
sub 2048R/E32D1186 2015-01-24
除了姓名、邮箱、备注外其它都可以使用默认设置,最后需要输入一个passphrase,妥善保管这个口令,后面配置Gradle脚本时需要用到。
- 查看密钥
1.查看公钥:
C:\Users\uuxia\Desktop\CSmtp_v2_4_ssl>gpg –list-keys
C:/Users/uuxia/AppData/Roaming/gnupg\pubring.gpg
———————————————— pub 2048R/FB58CB54 2015-12-15 uid uuxia (This is my personal key)
<263996097@qq.om> sub 2048R/85534FD0 2015-12-15
输出的路径为公钥文件,FB58CB54 为keyId,需要上传给服务器。
2.查看私钥:
C:\Users\uuxia\Desktop\CSmtp_v2_4_ssl>gpg –list-secret-keys
C:/Users/uuxia/AppData/Roaming/gnupg\secring.gpg
———————————————— sec 2048R/FB58CB54 2015-12-15 uid uuxia (This is my personal key)
<263996097@qq.om> ssb 2048R/85534FD0 2015-12-15
私钥文件路径在配置Gradle脚本时需要用到。
3.上传公钥
gpg –keyserver hkp://pool.sks-keyservers.net –send-keys FB58CB54
gpg: sending key FB58CB54 to hkp server pool.sks-keyserver.net
把之前生成的公钥上传至服务器,系统需要你上传的公钥来验证发布时的文件。
FB58CB54 为之前生成的公钥的keyId,一旦提交至一个key server,公钥会自动同步到其它key server。
4. 执行 Gradle 发布脚本
所有的配置已经完成,现在可以上传了,在Android Studio的Terminal输入命令:
gradle uploadArchives
如果上传成功,最后你会看到控制台打印类似的信息:
E:\HeT\maven\CustomOnCrash\library>gradle uploadArchives
2475431305
2475431305
2475431305
:library:androidJavadocs
E:\HeT\maven\CustomOnCrash\library\src\main\java\uuxia\com\library\ui\DefaultErrorActivity.java:36: 错误: 找不到符号
import uuxia.com.library.R;
^
符号: 类 R
位置: 程序包 uuxia.com.library
1 个警告
:library:androidJavadocsJar
:library:androidSourcesJar
:library:compileLint
:library:copyReleaseLint UP-TO-DATE
:library:mergeReleaseProguardFiles UP-TO-DATE
:library:preBuild UP-TO-DATE
:library:preReleaseBuild UP-TO-DATE
:library:checkReleaseManifest
:library:prepareReleaseDependencies
:library:compileReleaseAidl UP-TO-DATE
:library:compileReleaseRenderscript UP-TO-DATE
:library:generateReleaseBuildConfig UP-TO-DATE
:library:generateReleaseAssets UP-TO-DATE
:library:mergeReleaseAssets UP-TO-DATE
:library:generateReleaseResValues UP-TO-DATE
:library:generateReleaseResources UP-TO-DATE
:library:packageReleaseResources UP-TO-DATE
:library:processReleaseManifest UP-TO-DATE
:library:processReleaseResources UP-TO-DATE
:library:generateReleaseSources UP-TO-DATE
:library:processReleaseJavaRes UP-TO-DATE
:library:compileReleaseJavaWithJavac
注: E:\HeT\maven\CustomOnCrash\library\src\main\java\uuxia\com\library\ui\DefaultErrorActivity.java使用或覆盖了已过时的
API。
注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
:library:packageReleaseJar
:library:compileReleaseNdk UP-TO-DATE
:library:packageReleaseJniLibs UP-TO-DATE
:library:packageReleaseLocalJar UP-TO-DATE
:library:packageReleaseRenderscript UP-TO-DATE
:library:bundleRelease
:library:signArchives
:library:uploadArchives
Could not find metadata com.github.xxl6097:customoncrash/maven-metadata.xml in remote (https://oss.sonatype.org/service/
local/staging/deploy/maven2/)
BUILD SUCCESSFUL
Total time: 2 mins 20.451 secs
上传成功后,打开Sonatype Nexus Professional登录,选择左侧Build Promotion菜单中的Staging Repositories选项,在出现的选项卡右上角的搜索框输入关键字,筛选出你上传的组件所在的repository。
部署时创建的repository会根据部署项目的groupId来命名,例如我的groupId为com.github.xxl6097,那么我的repository即为xxl6097-xxxx,后面的xxxx为4个数字,初次部署为1000,后面每次部署这个数字都会+1。选择这个repository,列表下面的面板会显示一些详细信息。
5. 激活 Maven Central Sync 进程
部署完成之后,上传的组件会存储在一个独立的临时staging repository,在正式发布之前如果你在测试时遇到任何问题,都可以删除这个staging repository,在修复之后重新部署。正式发布才会同步到maven central repository。
通常情况下正式发布操作需要手动完成。
首先打开Sonatype Nexus Professional登录,打开Staging Repositories列表,筛选出之前部署的repository。
部署完成之后,这个repository会处于Open状态,你可以切换到Content标签页检查这个repository,如果确信没有问题,可以点击列表上面的Close按钮,这样会触发系统对这个repository进行评估。
如果你的组件不满足评估要求,Close操作会失败。
遇到这种情况,可以切换到Activity标签查看系统评估时出现的具体问题,修复问题,再尝试Close操作;如果需要重新部署,可以点击列表上面的Drop按钮删除这个repository,在本地修改之后,再重新部署。
成功close之后,可以点击Release按钮正式发布repository,组件会被移动到OSSRH的release repository,这个仓库会同步到maven central repository。
Gradle文件的配置可以参考我的项目:CustomOnCrash
我的JIRA ticket:OSSRH-19416
遇到问题
androidJavadocs 错误: 编码GBK的不可映射字符。
解决方法:把中文注释替换成英文注释。
androidJavadocs task 错误:不允许使用自关闭元素。
解决方法:删除注释中
、
之类的标签,把整段注释内容使用
标签包裹起来。Close时评估出现错误:Failed: Signature Validation
解决方法:重试上传GPG生成的keyId
备注
在正式发布时可能会出现403错误:
Release failed
Nexus returned an error: ERROR 403: Forbidden
这是因为之前创建的JIRA ticket的状态还未变成RESOLVED,等待可用既可。
6. 结语
总的来说,发布还是挺方便的,人工审核可能会浪费点时间,偶尔还可能遇到些问题,不过 sonatype 还是很专业的,将你遇到的问题告诉他们之后,都可以得到一个有效的解决办法。
不过最近 Android Studio 把 jCentral 作为默认的节点了,也许下次就得折腾 jCentral 了。
Reference:
- Pushing AARs to Maven Central
- Working with PGP signatures
- Releasing the deployment
- Release the deployment to the central repository