联系
Knight's Tale » 技术

Github开源Java项目(Disconf)上传到Maven Central Repository方法详细介绍

2014-07-09 02:42

最近我做了一个开源项目 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:git@github.com:knightliao/disconf</url>
    <connection>scm:git:git@github.com: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

输出的格式是这个样子的:

knightliao@conan:~$ 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 hkp://pool.sks-keyservers.net --send-keys XX

这个服务器地址是Sonatype规定的,因此不需要修改。

验证一下:

gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys C67A5D26

如果打印以下,则说明上传成功:

gpg: requesting key C67A5D26 from hkp server pool.sks-keyservers.net
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:

  1. Checks that your local source code does not have any modifications
  2. Writes a release.properties file with details of what it is doing
  3. Modifies the pom.xml to the release versions
  4. Does a build as far as "package" in order to assure itself that it's changes have not broken the build
  5. Commits the modified pom.xml files to SCM
  6. Tags the trunk
  7. Modifies the pom.xml to the next snapshot version
  8. 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

  1. Checks out the tagged release into target/checkout
  2. Forks a "mvn deploy site-deploy"
  3. 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/

上传的最佳实践

  1. 先让你的电脑与Github建立连接
  2. git clone 代码下下载下来
  3. 对本地代码执行 mvn clean install , 解决代码本身的编译问题
  4. 准备好GPG工具
  5. 申请注册Sonatype
  6. 对于SNAPSHOT版本,则执行 mvn release:prepare , 一旦发现有错误,需要执行 mvn release:rollback,项目做完后,执行 mvn release:clean
  7. 对于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包,然后再在界面上传。实践证明这种方法不可取。因为签名验证通不过。

参考:

  1. 上传利用GitHub管理的软件到Maven Central Repository之一
  2. 上传利用GitHub管理的软件到Maven Central Repository之二
  3. 上传利用GitHub管理的软件到Maven Central Repository之三
  4. maven deploy到nexus报错:Return code is: 401, ReasonPhrase:Unauthorized
  5. Maven error: “You don't have a SNAPSHOT project in the reactor projects list.”
  6. Maven error: “You don't have a SNAPSHOT project in the reactor projects list.”
  7. Maven Tips and Tricks: Using GitHub
  8. Deploying Maven artefact to multiple repositories with different settings
  9. [i am getting permgen size error in jenkins how to increase](http://stackoverflow.com/questions/12969312/i-am-getting-permgen-size-error-in-jenkins-how-to-increase
  10. Releasing a plugin gives "You don't have a SNAPSHOT project in the reactor projects list."
  11. 将项目发布到Maven中央库
  12. 上传Android或Java库到Maven central repository
  13. 如何上传项目到maven中央库