likes
comments
collection
share

发布 jar 包到 Maven 中央仓库

作者站长头像
站长
· 阅读数 13

记录一下我将项目发布到 Maven 中央仓库的过程。我会给出尽可能地给出所有的官方文档。

前置准备

申请 groupId

我们的 jar 包要想发布到 Maven 中央仓库,需要部署到 Sonatype(很想吐槽一下这个网站,乱七八糟的)。 我们需要先拿 groupId 向 Sonatype 进行申请,groupId 通常是项目网站的域名的反写,比如如果我的网站是xezzon.xyz,那么 groupId 就是xyz.xezzon。如果没有网站也没关系,可以白嫖 GitHub Page,这样的话, groupId 就是 io.github.xezzon。 定好 groupId 后,在 Sonatype 的 JIRA 上新建一个工单(注册登录的事情就不细讲了)。内容模板可以照着这个模板去填。 工单创建之后,会有人进行跟进。会被要求在 GitHub 上建一个仓库以验明正身。建好之后重新打开工单,很快就能审核通过了。

部署

修改 Maven 文件

~/.m2/settings.xml

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <servers>
    <server>
      <id>ossrh</id>
      <username>${env.OSSRH_ID}</username>
      <password>${env.OSSRH_PWD}</password>
    </server>
  </servers>
</settings>

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">
  <modelVersion>4.0.0</modelVersion>
  <!-- 需要与 Sonatype 申请时使用的 groupId 一致 -->
  <groupId>io.github.xezzon</groupId>
  <artifactId>tao</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>

  <!-- Sonatype 要求填写以下信息 -->
  <name>${project.groupId}:${project.artifactId}</name>
  <description>后端开发中的一些常用组件与抽象定义</description>
  <url>https://github.com/xezzon/tao.git</url>
  <licenses>
    <license>
      <name>GNU Lesser General Public License v3.0</name>
      <url>https://www.gnu.org/licenses/lgpl-3.0.html</url>
      <distribution>repo</distribution>
    </license>
  </licenses>
  <developers>
    <developer>
      <name>xezzon</name>
      <email>xezzon@outlook.com</email>
    </developer>
  </developers>
  <scm>
    <connection>scm:git:git://github.com/xezzon/tao.git</connection>
    <developerConnection>scm:git:ssh://github.com:xezzon/tao.git</developerConnection>
    <url>http://github.com/xezzon/tao/tree/master</url>
  </scm>

  <modules>
  </modules>

  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencyManagement>
  </dependencyManagement>

  <dependencies>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
        <version>3.2.1</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>jar-no-fork</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
        <version>3.4.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>3.0.1</version>
        <executions>
          <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
              <goal>sign</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <profiles>
    <profile>
      <id>release</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <distributionManagement>
        <snapshotRepository>
          <!-- 这里的 id 要和 settings.xml 中的 servers.server.id 一致 -->
          <id>ossrh</id>
          <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
        </snapshotRepository>
      </distributionManagement>
      <build>
        <plugins>
          <!-- 这里使用了 nexus-staging-maven-plugin 插件,部署后可以自动发布 -->
          <plugin>
            <groupId>org.sonatype.plugins</groupId>
            <artifactId>nexus-staging-maven-plugin</artifactId>
            <!-- 这里的版本最好选 1.6.13 以上的,否则不支持 Java 17 -->
            <version>1.6.13</version>
            <extensions>true</extensions>
            <configuration>
              <!-- 这里的 serverId 要和 settings.xml 中的 servers.server.id 一致 -->
              <serverId>ossrh</serverId>
              <nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
              <autoReleaseAfterClose>true</autoReleaseAfterClose>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>

签名

Sonatype 要求发布时文件都要用私钥签名,在上述的配置文件中,使用了 maven-gpg-plugin 就是做这件事的。不过除了配置 maven-gpg-plugin 以外,还需要先自己生成一对密钥,并且把公钥发送给公钥服务器。

gpg --gen-key

按照 prompt 输入一些信息,最后需要填写口令。 生成完后查看一下:

gpg --list-keys

将公钥上传到公钥服务器(将以下的$UID替换成上一步中需要导出的key的ID):

gpg --send-keys $UID

发布

mvn package deploy -P release

查看结果

发布成功之后会收到一封来自 Sonatype 的邮件。稍微等一段时间,上 Maven Central 查看结果。也可以上 Nexus Repository ManagerCentral Repository 查看。

持续集成

GitHub Actions

给出以下 GitHub Actions 配置仅供参考。

# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path

name: Maven Package

on:
  release:
    types: [created]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'
          cache: 'maven'
      - name: Build with Maven
        run: mvn -B package --file pom.xml

      - name: Set up Apache Maven Central
        uses: actions/setup-java@v3
        with: # running setup-java again overwrites the settings.xml
          distribution: 'temurin'
          java-version: '17'
          cache: 'maven'
          server-id: ossrh # Value of the distributionManagement/repository/id field of the pom.xml
          server-username: MAVEN_USERNAME # env variable for username in deploy
          server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
          gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
          gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
      - name: Publish to Apache Maven Central
        run: mvn deploy
        env:
          MAVEN_USERNAME: ${{ vars.MAVEN_USERNAME }}
          MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
          MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

导出密钥

使用以下命令将签名章节生成的密钥导出。

gpg --armor --export-secret-keys $UID

设置参数

在代码仓库的 Actions secrets and variables 的设置页面添加以下参数:MAVEN_USERNAME(前置准备时 Sonatype 的注册用户名);添加以下保密参数:MAVEN_CENTRAL_TOKEN(前置准备时 Sonatype 的注册密码)、MAVEN_GPG_PRIVATE_KEY(导出密钥章节的结果)、MAVEN_GPG_PASSPHRASE(签名章节使用的口令)。

参考资料