使用Gradle上传jar/aar至Maven
- 注册Sonatype帐号
- 创建一个JIRA ticket
打开Sonatype JIRA注册帐号,注册好之后打开Create Issue创建一个JIRA ticket,一个JIRA ticket对应一个项目。
其中Summary填写项目名,例如android dev tips;Description填写项目描述;Group Id必须是项目包名的父级,比如我的包名是cn.mindstack.utils,那么为了我所有的项目都可以发布,Group Id填写为cn.mindstack。
其它按照提示填写,完成后大概两个工作日左右,有时候RP爆发的话第二天就可以了,该issue会变成RESOLVED状态,表示可用,在可用前除了最后一步正式发布之外,其它都可以正常进行。
下载地址 GPG
$gpg --version
gpg (GnuPG/MacGPG2) 2.0.28
libgcrypt 1.6.3
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ gpg --gen-key
填写相关信息,最后需要输入一个passphrase,妥善保管这个口令,后面配置Gradle脚本时需要用到
$ gpg --list-keys
/Users/tony/.gnupg/pubring.gpg
------------------------------
....
pub 4096R/DAE9AF00 2016-03-30 [expires: 2020-03-30]
uid [ultimate] wuhaiyang <wuhaiyang1213@gmail.com>
uid [ultimate] [jpeg image of size 8453]
sub 4096R/BF816FAC 2016-03-30 [expires: 2020-03-30]
输出的路径为公钥文件,DAE9AF00为keyId,需要上传给服务器
gpg --list-secret-keys
Users/tony/.gnupg/secring.gpg
------------------------------
sec 4096R/DAE9AF00 2016-03-30 [expires: 2020-03-30]
uid wuhaiyang <wuhaiyang1213@gmail.com>
uid [jpeg image of size 8453]
ssb 4096R/BF816FAC 2016-03-30
私钥文件路径在配置Gradle脚本时需要用到
$ gpg --keyserver hkp://pool.sks-keyservers.net --send-keys DAE9AF00
可用GPGKeychain,如图,然后生成的公钥上传至服务器
Gradle脚本使用了开源项目gradle-mvn-push,Thx Chris大神!
把下面的脚本复制到工程目录,新建文件maven-push-jar.gradle
/*
* Copyright 2013 Chris Banes
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
apply plugin: 'maven'
apply plugin: 'signing'
def isReleaseBuild() {
return VERSION_NAME.contains("SNAPSHOT") == false
}
def getReleaseRepositoryUrl() {
return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
: "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
}
def getSnapshotRepositoryUrl() {
return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
: "https://oss.sonatype.org/content/repositories/snapshots/"
}
def getRepositoryUsername() {
return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
}
def getRepositoryPassword() {
return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
}
afterEvaluate { project ->
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
pom.groupId = GROUP
pom.artifactId = POM_ARTIFACT_ID
pom.version = VERSION_NAME
repository(url: getReleaseRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
snapshotRepository(url: getSnapshotRepositoryUrl()) {
authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
}
pom.project {
name POM_NAME
packaging POM_PACKAGING
description POM_DESCRIPTION
url POM_URL
scm {
url POM_SCM_URL
connection POM_SCM_CONNECTION
developerConnection POM_SCM_DEV_CONNECTION
}
licenses {
license {
name POM_LICENCE_NAME
url POM_LICENCE_URL
distribution POM_LICENCE_DIST
}
}
developers {
developer {
id POM_DEVELOPER_ID
name POM_DEVELOPER_NAME
email POM_DEVELOPER_EMAIL
}
}
}
}
}
}
signing {
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from tasks.javadoc.destinationDir
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}
artifacts {
archives jar
archives javadocJar
archives sourcesJar
}
}
maven-push-aar.gradle跟maven-push-jar.gradle大同小异
// new task apklib
task apklib(type: Zip){
appendix = extension = 'apklib'
from 'AndroidManifest.xml'
into('res') {
from 'res'
}
into('src') {
from 'src'
}
}
artifacts {
archives androidSourcesJar
archives androidJavadocsJar
archives apklib
}
在工程目录下的gradle.properties文件中设置属性
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
VERSION_NAME=1.0
VERSION_CODE=1
GROUP=cn.mindstack
POM_DESCRIPTION=sonatype
POM_URL=https://github.com/haiyangwu/sonatype
POM_SCM_URL=https://github.com/haiyangwu/sonatype
POM_SCM_CONNECTION=scm:https://github.com/haiyangwu/sonatype.git
POM_SCM_DEV_CONNECTION=scm:https://github.com/haiyangwu/sonatype.git
POM_LICENCE_NAME=The MIT License
POM_LICENCE_URL=http://mit-license.org
POM_LICENCE_DIST=repo
POM_DEVELOPER_ID=haiyangwu
POM_DEVELOPER_NAME=haiyangwu
POM_DEVELOPER_EMAIL=wuhaiyang1213@gmail.com
SNAPSHOT_REPOSITORY_URL=https://oss.sonatype.org/content/repositories/snapshots
RELEASE_REPOSITORY_URL=https://oss.sonatype.org/service/local/staging/deploy/maven2
注意:VERSION_NAME后面加-SNAPSHOT表示发布的是版本快照。
GROUP设置成项目包名,注意,父级要和之前创建JIRA ticket时的Group Id一致。
我们需要给上传的Module配置(我们的工程中可能有多个Module需要上传到仓库中,要给每个Module添加配置)
给需要上传到Maven仓库的Module提供一个gradle.properties文件:
POM_NAME=Mindstack Cn Library
POM_ARTIFACT_ID=utils
POM_PACKAGING=jar
这个组件对应的依赖已经浮出水面了:GROUP:POMARTIFACTID:VERSION_NAME即 cn.mindstack:utils:1.0
修改Module目录的build.gradle,在最后加上:
apply from: '../gradle-publish/maven-push-jar.gradle'
这个全局的Gradle配置文件默认在USER_HOME/.gradle/gradle.properties,没有的话可以新建一个
在这里配置Maven服务器的用户名和密码,还需要配置之前生成的keyId, password和一个secretKeyRingFile,这个文件用来在上传release版本时对文件进行签名。
signing.keyId=#yourkeyid#
signing.password=#yourpassword#
signing.secretKeyRingFile=#yourkeylocation#/secring.gpg
NEXUS_USERNAME=#yourusername#
NEXUS_PASSWORD=#yourpassword#
所有的配置已经完成,现在可以上传了,在Terminal输入命令:
gradle uploadArchives
xecuting task ':lib:uploadArchives' (up-to-date check took 0.001 secs) due to:
Task has not declared any outputs.
Publishing configuration: configuration ':lib:archives'
Publishing to org.gradle.api.publication.maven.internal.deployer.DefaultGroovyMavenDeployer@1d3fb2c1
Deploying to https://oss.sonatype.org/service/local/staging/deploy/maven2
Uploading: cn/mindstack/utils/1.0/utils-1.0.jar to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 1K from remote
Uploaded 1K
Uploading: cn/mindstack/utils/1.0/utils-1.0.pom to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 1K from remote
Uploaded 1K
Uploading: cn/mindstack/utils/1.0/utils-1.0.jar.asc to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 1K from remote
Uploaded 1K
Uploading: cn/mindstack/utils/1.0/utils-1.0-javadoc.jar to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 20K from remote
Uploaded 20K
Uploading: cn/mindstack/utils/1.0/utils-1.0-sources.jar to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 1K from remote
Uploaded 1K
Uploading: cn/mindstack/utils/1.0/utils-1.0-javadoc.jar.asc to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 1K from remote
Uploaded 1K
Uploading: cn/mindstack/utils/1.0/utils-1.0-sources.jar.asc to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 1K from remote
Uploaded 1K
Uploading: cn/mindstack/utils/1.0/utils-1.0.pom.asc to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 1K from remote
Uploaded 1K
Downloading: cn/mindstack/utils/maven-metadata.xml from repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Could not find metadata cn.mindstack:utils/maven-metadata.xml in remote (https://oss.sonatype.org/service/local/staging/deploy/maven2)
Uploading: cn/mindstack/utils/maven-metadata.xml to repository remote at https://oss.sonatype.org/service/local/staging/deploy/maven2/
Transferring 0K from remote
Uploaded 0K
:lib:uploadArchives (Thread[Daemon worker,5,main]) completed. Took 1 mins 27.062 secs.
上传成功后,打开Sonatype Nexus Professional登录,选择左侧Build Promotion菜单中的Staging Repositories选项,在出现的选项卡右上角的搜索框输入关键字,筛选出你上传的组件所在的repository。
部署完成之后,上传的组件会存储在一个独立的临时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。