最近我做了一个开源项目 Disconf:Distributed Configuration Management Platform(分布式配置管理平台) ,简单来说,就是为所有业务平台系统管理配置文件的平台系统。更详细的介绍,请看项目主页。
项目是用Java写的,Maven管理的,那么,自然而然,整个项目应该以Maven仓库POM方式暴露给用户来使用。因此,这两天我一直在折腾Maven Central Repository。
本文使用Sonatype Nexus作为代理仓库。也就是说先要把软件发布到这里,然后他们会帮同步到Maven的Central Repository上,这貌似是目前最简单有效的办法。 Sonatype使用Nexus为开源项目提供托管服务。你可以通过它发布快照(snapshot)或是稳定版(release)到Maven中央仓库。 我们只要注册一个Sonatype的JIRA账号、创建一个JIRA ticket,然后对POM文件稍作配置即可。
Disconf的项目结构介绍
disconf
- disconf-client
- disconf-core
- disconf-web
- disconf-demos
我将会把 disconf-core和disconf-client 推送到Maven的Central Repository上,因为这两个包是编程用户需要的。disconf-web 的编译结果是一个war包,因此不会推送到Maven的Central Repository上。
下面将仔细的介绍 disconf-core 包的推送过程。
第零步:将你的电脑与Github打通
用ssh-key生成的id_rsa.pub的内容放到 https://github.com/settings/ssh 中。
第一步:修改 disconf-core 的 POM文件
它至少应该包括以下标签:
具体可参见:https://github.com/knightliao/disconf/blob/master/disconf-core/pom.xml
<modelVersion>4.0.0</modelVersion>
<artifactId>disconf-core</artifactId>
<packaging>jar</packaging>
<version>2.3-SNAPSHOT</version>
<name>disconf-core</name>
<parent>
<groupId>com.baidu.disconf</groupId>
<artifactId>disconf-base</artifactId>
<version>2.1</version>
<relativePath>../</relativePath>
</parent>
<url>https://github.com/knightliao/disconf/tree/master/disconf-core</url>
<description>https://github.com/knightliao/disconf/tree/master/disconf-core</description>
<organization>
<name>Baidu</name>
<url>http://www.baidu.com</url>
</organization>
<scm>
<url>scm:git:[email protected]:knightliao/disconf</url>
<connection>scm:git:[email protected]:knightliao/disconf</connection>
<tag>disconf-core</tag>
</scm>
下面为它设置一个profile, 命名为release,意思就是发布到中央库。这里设置了两个库,一个snapshots,一个是正式的发布库。
另外,中央库需要source和doc,所以增加两个plugin.
<profiles>
<profile>
<id>release</id>
<distributionManagement>
<snapshotRepository>
<id>nexus-release</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>nexus-release</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
第二步:修改 disconf 的 POM文件
disconf的Pom是disconf-core的parent pom。
具体可参见:https://github.com/knightliao/disconf/blob/master/pom.xml
它至少应该包括以下标签:
<developers>
<developer>
<name>Liao Qiqi</name>
<id>knightliao</id>
<email>liaoqiqi (AT) baidu.com</email>
<roles>
<role>Developer</role>
</roles>
<timezone>+8</timezone>
</developer>
<developer>
<name>Wu Ning</name>
<id>wuning</id>
<email>wuning01 (AT) baidu.com</email>
<roles>
<role>Developer</role>
</roles>
<timezone>+8</timezone>
</developer>
</developers>
第三步:准备好GPG工具
我们在本地生成好jar包后,要上传到中央库,为了保证上传过程的数据校验是对的,Sonatype要求我们使用GPG来进行数据校验。
gpg --gen-key
出现如下提示后输入1:
在如下提示后输入想要的KEY的位数,没有特别需要的话直接回车也可以:
接着会出现询问KEY的有效期,默认这是0,也就是说永远不过期:
接着输入y并回车确认永久有效。然后会出现下面的提示,要求输入你的真实姓名:
根据提示输入姓名,邮箱和备注后,然后会提示输入用来保护密钥的密码(passphrase),如果不需要密码的话直接回车,如果输入了密码那么一定要记住,这个密码在后面会用到。接下来系统会要求你输入一些随机字符,在键盘的字母和符号上乱按就可以了,不过别按回车。
注意,这里的姓名和邮箱、密码 三个东西都要记住。!!
生成成功以后会出现信息:
public and secret key created and signed
要查看现有的公钥,输入:
gpg --list-keys
输出的格式是这个样子的:
[email protected]:~$ gpg --list-keys
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
/home/knightliao/.gnupg/pubring.gpg
-----------------------------------
pub 2048R/XX 2014-07-08
uid 用户名 <邮箱>
sub 2048R/YY 2014-07-08
这里顺便说一下,如果你有多个KEY,想删除其中的某个KEY,方法是:
gpg --delete-keys XX
生成了key以后,按照Sonatype的要求,我们需要把公钥上传到服务器上。输入:
gpg --keyserver <a href="http://hkp://pool.sks-keyservers.net">hkp://pool.sks-keyservers.net</a> --send-keys XX
这个服务器地址是Sonatype规定的,因此不需要修改。
验证一下:
gpg --keyserver <a href="http://hkp://pool.sks-keyservers.net">hkp://pool.sks-keyservers.net</a> --recv-keys C67A5D26
如果打印以下,则说明上传成功:
gpg: requesting key C67A5D26 from hkp server <a href="http://pool.sks-keyservers.net">pool.sks-keyservers.net</a>
gpg: key C67A5D26: "用户名 <邮箱>" not changed
gpg: Total number processed: 1
gpg: unchanged: 1
第四步:注册Sonatype
就要像Sonatype提出申请了。首先,要到这里申请他们的Jira帐号。获得帐号以后,到这里提 交一个申请ticket。点击Create issue, Project要选Support - Open Source Project Repository Hosting,Issue Type选New Project。 再次提醒:groupId的写法非常重要,要么使用自己拥有的域名。要么使用项目托管的子域名,例如com.github.username。为了节省时 间,如果使用的是自己拥有的域名,那么可以在description里写清楚,否则客服有可能会问,这样就一个来回就需要一个工作日了。
一个例子就是:https://issues.sonatype.org/browse/OSSRH-10550
注意,注册时用户名和邮箱必须是 第三步里的 用户名和邮箱。
注册成功后,他们就会给你发送邮件,然后就可 登录这里 进行查看: https://oss.sonatype.org/
第五步:修改本地maven的 settings.xml
用上一步注册时的用户名和密码填充这里:
nexus-release 用户名 密码
这里的id要和pom.xml文件里面的repository id对应,用户名和密码则是Sonatype的Jira帐号和密码。
第六步:编译本地代码
进到 disconf 根目录下,执行 mvn clean install
然后
cd disconf-core
mvn clean install
如果没有问题,说明可以准备上传了。
第七步之一:上传SNAPSHOT版本代码
如果你的项目是 SNAPSHOT的,那么 就可以使用本步方法进行上传,它会上传到 https://oss.sonatype.org/content/repositories/snapshots
首先,为了后续的操作顺利执行,我们要确保项目的整个目录没有本地未提交的修改,最好先pull一遍确保后续的步骤里没有冲突。然后运行:
mvn release:prepare
mvn release:prepare does the following:
- Checks that your local source code does not have any modifications
- Writes a release.properties file with details of what it is doing
- Modifies the pom.xml to the release versions
- Does a build as far as "package" in order to assure itself that it‘s changes have not broken the build
- Commits the modified pom.xml files to SCM
- Tags the trunk
- Modifies the pom.xml to the next snapshot version
- Commits the modified pom.xml files to SCM
如果命令顺利运行结束,那么这个步骤就算完成了。如果中间出现了什么问题,可以在修复问题后再次运行这条命令,如果想要获得更详细的信息,可以运行:
mvn release:prepare -X
如果不希望从终止的地方开始,而是想从头再来的话可以输入:
mvn release:prepare -Dresume=false
如果想回滚,则
mvn release:rollback
如果这步成功了,则上传到 https://oss.sonatype.org/content/repositories/snapshots 这里了。
第七步之二:上传非SNAPSHOT版本代码
SNAPSHOT一般代表着有Bug版本,线上代码一般不会使用,因此,非SNAPSHOT版本的包才是我们真正需要的。
不要执行"第七步之一”,执行:
mvn clean deploy -P release -Dgpg.passphrase=第三步中的密码
mvn release:perform does the following
- Checks out the tagged release into target/checkout
- Forks a "mvn deploy site-deploy"
- Removes the release.properties file
注:mvn clean deploy -P release -Dgpg.passphrase=第三步中的密码 这句话执行时,如果你的版本是快照的,则上传快照,如果是非快照的则上传非快照的,Maven会根据模块的版本号(pom文件中的version)中是否 带有-SNAPSHOT来判断是快照版本还是正式版本。
发布构建
进入https://oss.sonatype.org并登陆,会在左侧有个staging Repositories点击进入,在右侧面板找到你的构件,状态应该是open,你要将其置为closed,点击上方的close按钮即可
接下来系统会自动验证有效性,如果你的Group Id和pom.xml没有错误,状态会自动变成closed,如果有问题,会在下面提示你那里有问题,加入有问题你可以点击drop按钮删掉这个构件,修改后重新执行步骤7。
接下来你需要点击release按钮发布你的构件。
在Issue中通知工作人员
然后回到JIRA中你的Issue,写个comment,我写的是Component has been successfully issued.告诉工作人员我发布完成了,等待他们审核。审核通过后我们就可以在中央库搜索到我们的构件了!搜索的地址 是:http://search.maven.org/
上传的最佳实践
- 先让你的电脑与Github建立连接
- git clone 代码下下载下来
- 对本地代码执行 mvn clean install , 解决代码本身的编译问题
- 准备好GPG工具
- 申请注册Sonatype
- 对于SNAPSHOT版本,则执行 mvn release:prepare , 一旦发现有错误,需要执行 mvn release:rollback,项目做完后,执行 mvn release:clean
- 对于release版本,则执行 mvn clean deploy -P release -Dgpg.passphrase=第三步中的密码 。
遇到的一些问题
Return code is: 401, ReasonPhrase: Unauthorized. release:perform
这个是因为你在Maven的settings.xml里的配置与disconf-core的pom.xml配置对应不上来。很可能就是 id没有匹配。
Maven error: “You don‘t have a SNAPSHOT project in the reactor projects list.”
如果的项目的版本不是SNAPSHOT,而你却要用“第七步之一”进行上传,则会报此错误。
i am getting permgen size error in jenkins how to increase
在Sonatype的界面进行上传
我试过在本地编译成jar包,然后再在界面上传。实践证明这种方法不可取。因为签名验证通不过。