一、准备

1.1 注册JIRA账号
注册账号地址如下:
https://issues.sonatype.org/secure/Signup!default.jspa

1.2 将项目提交到Git仓库
创建项目之前需要将项目提交到Git仓库,如GitHub、Gitlab等等,本文以GitHub为例。

二、创建issue

创建issue的地址如下:
https://issues.sonatype.org/secure/CreateIssue.jspa?issuetype=21&pid=10134

2.1 按要求填写issue,带*为必填选项,填写示例地址:https://issues.sonatype.org/browse/OSSRH-59684

2.2 认证域名

要求认证域名

JIRA规定GroupId必须为自己的域名,需要进行域名所有权认证。可采用添加DNS的TXT记录,将域名重定向到项目地址两种方式进行认证。

如果没有域名,可采用io.github.*com.github.*等作为GroupId,本文不详细介绍。

DNS中添加记录:
添加TXT记录

创建issue后等待审核,当这个issue的状态为resolved(已解决)时,可以提交jar包。

审核通过截图

提交第一个包之后要求回复该条评论。

上传第一个包之后回复该评论

三、创建GPG秘钥

3.1 准备软件
Windows系统可以下载Gpg4win来生成密钥对。下载地址:https://www.gpg4win.org/download.html

在我准备安装的时候发现,Git内置了GnuPG插件,可以正常使用,接下来的步骤全部采用GnuPG插件在Git的命令行中完成,GunPG生成秘钥的命令和Gpg4win相同。

打开git,输入命令gpg -help查看是否具有GnuPG
gpg -help

3.2 生成和查看秘钥

# 生成秘钥对
gpg --gen-key

Real name: 用户名
Email address:邮箱

Change (N)ame, (E)mail, or (O)kay/(Q)uit? o
之后需要再输两次 Passphase 相当于密码。

生成GPG秘钥

$ gpg --list-keys
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2022-08-04
/c/Users/lswan/.gnupg/pubring.kbx
---------------------------------
pub   rsa2048 2020-08-04 [SC] [expires: 2022-08-04]
      A1D1E1A06F645429C2CXXXXXXXXXC6016F1FB9
uid           [ultimate] nineya <lswang@nineya.com>
sub   rsa2048 2020-08-04 [E] [expires: 2022-08-04]

A1D1E1A06F645429C2CXXXXXXXXXC6016F1FB9为公钥指纹

3.3 发布公钥

特别注意,两个秘钥服务器都要发布

gpg --keyserver hkp://pool.sks-keyservers.net --send-keys 公钥指纹
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys 公钥指纹

查询公钥是否发布成

gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 公钥指纹
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --recv-keys 公钥指纹

gpg: key 2D7B5FC6016F1FB9: "nineya <lswang@nineya.com>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1

可以查询到即为发布成功

四、修改Maven的Settings.xml文件

修改maven全局配置文件settings.xml,在maven安装目录的conf文件夹下。
如果使用的是IntelliJ的Maven,默认在C:\Users\用户名\.m2目录下,如果没有该文件可以手动创建一个settings.xml文件。

修改Maven的Settings.xml文件

settings.xml添加如下内容:

<servers>
    <server>
        <id>oss</id>
        <username>用户名</username>
        <password>密码</password>
    </server>
</servers>

id可以自己定义,在 pom.xml 中进行使用,用户名和密码就是JIRA的帐号密码

五、修改pom.xml文件

pom.xml 中必须包括:name、description、url、licenses、developers、scm 等基本信息,使用了 Maven 的 profile 功能,只有在 release 的时候才创建源码包、文档包、使用 GPG 进行数字签名。

5.1 name、description、url基础信息

<name>snail-log</name>
<description>A lightweight logging framework.</description>
<url>https://github.com/nineya/snail-log/</url>

5.2 licenses许可信息,如下采用Apache 2.0许可,还有其他许可类别,本文不再赘述。

<licenses>
    <license>
        <name>The Apache Software License, Version 2.0</name>
        <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
    </license>
</licenses>

5.3 developers开发者信息

<developers>
    <developer>
        <name>nineya</name>
        <email>lswang@nineya.com</email>
        <organization>nineya</organization>
        <organizationUrl>https://blog.nineya.com</organizationUrl>
    </developer>
</developers>

5.4 scm版本控制、变更控制管理

<scm>
    <connection>scm:git:git@github.com:nineya/snail-log.git</connection>
    <developerConnection>scm:git:git@github.com:nineya/snail-log.git</developerConnection>
    <url>git@github.com:nineya/snail-log.git</url>
</scm>

5.5 build配置

使用profiles实现灵活启用和关闭build

<profiles>
        <profile>
            <id>release</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <gpg.executable>E:\Program Files\Git\usr\bin\gpg.exe</gpg.executable>
                <gpg.passphrase>XXXXXX</gpg.passphrase>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.sonatype.plugins</groupId>
                        <artifactId>nexus-staging-maven-plugin</artifactId>
                        <version>1.6.7</version>
                        <extensions>true</extensions>
                        <executions>
                            <execution>
                                <phase>deploy</phase>
                            </execution>
                        </executions>
                        <configuration>
                            <serverId>oss</serverId>
                            <nexusUrl>https://oss.sonatype.org/</nexusUrl>
                            <autoReleaseAfterClose>true</autoReleaseAfterClose>
                        </configuration>
                    </plugin>
                    <!-- 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.10.4</version>
                        <configuration>
                            <show>private</show>
                            <nohelp>true</nohelp>
                            <charset>UTF-8</charset>
                            <encoding>UTF-8</encoding>
                            <docencoding>UTF-8</docencoding>
                            <!-- 防止文档不规范报错 -->
                            <additionalparam>-Xdoclint:none</additionalparam>
                        </configuration>
                        <executions>
                            <execution>
                                <phase>compile</phase>
                                <goals>
                                    <goal>jar</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <!-- GPG -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-gpg-plugin</artifactId>
                        <version>1.6</version>
                        <executions>
                            <execution>
                                <phase>verify</phase>
                                <goals>
                                    <goal>sign</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
            <distributionManagement>
                <!-- snapshotRepository 与 repository 中的 id 必须与 setting.xml 中 server 的 id 一致 -->
                <snapshotRepository>
                    <id>oss</id>
                    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
                </snapshotRepository>
                <repository>
                    <id>oss</id>
                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
                </repository>
            </distributionManagement>
        </profile>
    </profiles>

六、提交release

mvn clean deploy -P release

出现如下提示表示远程部署成功:

[INFO]  * Bulk deploy of locally gathered snapshot artifacts finished.
[INFO] Remote deploy finished with success.
[INFO] -----------------------------------------------
[INFO] Reactor Summary for snail-log 1.0-SNAPSHOT:
[INFO]
[INFO] snail-log .......................................... SUCCESS [  2.411 s]
[INFO] snail-core ......................................... SUCCESS [  3.685 s]
[INFO] demos .............................................. SUCCESS [01:28 min]
[INFO] -----------------------------------------------

提交成功后登陆以下管理系统:

https://oss.sonatype.org/#stagingRepositories

登入后直接看最下面, 找到提交的jar, 选中后左上角close -> 刷新 -> release, 如果没问题到这里就大功告成了。

如果close无法点击,可能提交jar的时候已经自动close

提交release之后还需要等待一段时间才可以在maven上查到,我这里提交等待了将近一天,成功查询到。

maven中央库release查询地址:

https://repo1.maven.org/maven2/你的groupId

# 例如
https://repo1.maven.org/maven2/com/nineya/slog

七、问题解决

7.1 maven-gpg-plugin插件找到

执行以下命令,手动下载插件:

mvn dependency:get -DrepoUrl=http://repo.maven.apache.org/maven2/ -Dartifact=org.apache.maven.plugins:maven-gpg-plugin:1.6

7.2 找不到gpg.exe

检查环境变量,因为本文采用Git内置的GPG,所以采用修改settings.xml的方式解决。

setting.xml中加入:

<profile>
  <id>release</id>
  <properties>
    <gpg.executable>E:\Program Files\Git\usr\bin\gpg</gpg.executable>
    <gpg.passphrase>Passphase</gpg.passphrase>
  </properties>
</profile>

7.3 maven编码gbk的不可映射字符

pom.xml的<project>标签中添加如下内容:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

7.4 on project XXX: Remote staging failed: Staging rules failure!

该异常为服务端审核未通过,具体错误日志需要去服务端查看。

服务端Repository管理地址:http://oss.sonatype.org/

使用JIRA账号登录,登录后选中暂存库中提交失败的记录,便可查看日志。

在实际提交中出现提交失败,失败的暂存库即自动删除。还未知道怎么配置,只能看好时间点,在被删除前查看日志。

错误日志

7.5 Event: Failed: Signature Validation

  • 秘钥验证失败,记得要配置两个秘钥服务器。

7.6 Event: Failed: Sources Validation/Javadoc Validation

已经配置了javadoc和source生成插件?未配置需要先行配置。
已配置了插件,插件生命不可高于或等于nexus-staging-maven-plugin插件。具体原因猜测是因为先执行了nexus-staging-maven-plugin插件提交数据,而javadoc、source还未生成完成。

<executions>
    <execution>
        <phase>package</phase>
    </execution>
</executions>

八、完整的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <name>snail-log</name>
    <description>A lightweight logging framework.</description>
    <url>https://github.com/nineya/snail-log/</url>
    <licenses>
        <license>
            <name>The Apache Software License, Version 2.0</name>
            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <developers>
        <developer>
            <name>nineya</name>
            <email>lswang@nineya.com</email>
            <organization>nineya</organization>
            <organizationUrl>https://blog.nineya.com</organizationUrl>
        </developer>
    </developers>
    <scm>
        <connection>scm:git:git@github.com:nineya/snail-log.git</connection>
        <developerConnection>scm:git:git@github.com:nineya/snail-log.git</developerConnection>
        <url>git@github.com:nineya/snail-log.git</url>
    </scm>

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.nineya.slog</groupId>
    <artifactId>snail-log</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <modules>
        <module>demos</module>
        <module>slog-core</module>
    </modules>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>release</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <gpg.executable>E:\Program Files\Git\usr\bin\gpg.exe</gpg.executable>
                <gpg.passphrase>XXXXXX</gpg.passphrase>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.sonatype.plugins</groupId>
                        <artifactId>nexus-staging-maven-plugin</artifactId>
                        <version>1.6.7</version>
                        <extensions>true</extensions>
                        <executions>
                            <execution>
                                <phase>deploy</phase>
                            </execution>
                        </executions>
                        <configuration>
                            <serverId>oss</serverId>
                            <nexusUrl>https://oss.sonatype.org/</nexusUrl>
                            <autoReleaseAfterClose>true</autoReleaseAfterClose>
                        </configuration>
                    </plugin>
                    <!-- 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.10.4</version>
                        <configuration>
                            <show>private</show>
                            <nohelp>true</nohelp>
                            <charset>UTF-8</charset>
                            <encoding>UTF-8</encoding>
                            <docencoding>UTF-8</docencoding>
                            <!-- 防止文档不规范报错 -->
                            <additionalparam>-Xdoclint:none</additionalparam>
                        </configuration>
                        <executions>
                            <execution>
                                <phase>compile</phase>
                                <goals>
                                    <goal>jar</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <!-- GPG -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-gpg-plugin</artifactId>
                        <version>1.6</version>
                        <executions>
                            <execution>
                                <phase>verify</phase>
                                <goals>
                                    <goal>sign</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
            <distributionManagement>
                <!-- snapshotRepository 与 repository 中的 id 必须与 setting.xml 中 server 的 id 一致 -->
                <snapshotRepository>
                    <id>oss</id>
                    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
                </snapshotRepository>
                <repository>
                    <id>oss</id>
                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
                </repository>
            </distributionManagement>
        </profile>
    </profiles>

</project>