Dev 日誌 | 如何將 jar 包發佈到 Maven 中央倉庫

摘要

Maven 中央倉庫並不支持直接上傳 jar 包,所以須要將 jar 包發佈到一些指定的第三方 Maven 倉庫,好比:Sonatype OSSRH 倉庫,而後該倉庫再將 jar 包同步到 Maven ,本文詳細記錄整個發佈、同步過程。html

註冊一個 Sonatype 用戶

進入地址:https://issues.sonatype.org/secure/Signup!default.jspa 註冊 Sonatype 用戶,Sonatype 經過 JIRA(JIRA 是 Atlassian 公司出品的項目與事務跟蹤工具)來管理 OSSRH 倉庫。<br />java

建立一個發佈構件的 issue

提交「構件發佈申請」的第一步是在 JIRA Dashborad 上建立一個 issue。以下所示,點擊 Create 按鈕:git

image

會彈出一個對話框讓你填寫 issue 的詳細信息,這裏最重要的就是 Group Id,通常會帶上域名,千萬別弄錯了,這關係到之後發佈其它的構件。咱們這裏是com.vesoftgithub

Sonatype 有域名驗證,驗證方式:數據庫

  • 往你的 DNS 中添加 JIRA 編號記錄
  • 重定向到你的 Github 主頁

若是你沒有域名,可參考這個連接:http://central.sonatype.org/pages/choosing-your-coordinates.html 的方法進行操做apache

  • 選擇一個帶有項目託管信息的 GroupId,例如 io.github.facebook 或 com.github.facebook
  • 另一種推薦的方式是使用免費的 free managed security reporting service 

等待 issue 審覈經過

審覈由於時差緣由須要必定時間,審覈經過後會收到郵件通知,同時在對應 issue 下會看到 Sonatype 工做人員的回覆,通常是添加一個 comment,內容大體以下:安全

Configuration has been prepared, now you can: Deploy snapshot artifacts into repository https://oss.sonatype.org/content/repositories/snapshots Deploy release artifacts into the staging repository https://oss.sonatype.org/service/local/staging/ deploy/maven2 Promote staged artifacts into repository 'Releases' Download snapshot and release artifacts from group https://oss.sonatype.org/content/groups/public Download snapshot, release and staged artifacts from staging group https://oss.sonatype.org/content/groups/staging please comment on this ticket when you promoted your first release, thanks服務器

使用 GPG 生成密鑰對

生成密鑰對

> gpg --gen-key

會讓選擇加密方式:微信

  • RSA and RSA (default)
  • DSA and Elgamal
  • DSA (sign only)
  • RSA (sign only)

默認選第一個,選擇以後,需輸入用戶名和郵箱,和 Passphase——至關於密鑰庫密碼。jsp

查看公鑰

> gpg --list-keys

xxx/.gnupg/pubring.gpg
---------------------------------
pub   2048R/xxxx 2019-12-02
uid   $YOUR_UID <$YOUR_EMAIL>
sub   2048R/**** 2019-12-02

這裏的公鑰 ID 是 xxxx,立刻就會用到了。

將公鑰上傳到 PGP 密鑰服務器

gpg --keyserver hkp://keys.gnupg.net:11371 --send-keys xxxx

查看公鑰是否上傳成功

> gpg --keyserver hkp://keys.gnupg.net:11371 --recv-keys xxxx

gpg: 下載密鑰‘xxxx’,從 hkp 服務器 keys.gnupg.net
gpg: 密鑰 xxxx:「$YOUR_UID <$YOUR_EMAIL>」未改變
gpg: 合計被處理的數量:1
gpg: 未改變:1

NOTE: 

  • 根據實際填寫此處的公鑰 ID
  • 不少網上教程給的是  pool.sks-keyservers.net,我的感受 pool.sks-keyservers.net 這個 keyserver 很差用,上傳了 key,常常會驗證失敗,也獲取失敗,maven 支持兩個 key servers http://keys.gnupg.net:11371http://pool.sks-keyservers.net:11371
  • 此處採用 hkp 協議而不是 http 協議
  • 不少教程沒有給端口,經試驗,需加上端口號

本地的私鑰用來對上傳的構件進行數字簽名,而下載該構件的用戶可經過上傳的公鑰來驗證簽名--需驗證這個構件是否由本人上傳的,由於存在構件被篡改的可能。

修改 Maven 配置文件

修改 Maven 配置文件主要是須要修改 setting.xml 和項目的 pom.xml 文件

配置 Maven 的 setting.xml

修改 ~/.m2/setting.xml 文件

<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>snapshots</id>
            <username>$USER_NAME</username>
            <password>$YOUR_PASSWORD</password>
        </server>
        <server>
            <id>release</id>
            <username>$USER_NAME</username>
            <password>$YOUR_PASSWORD</password>
        </server>
    </servers>

</settings>

替換 USER_NAME , YOUR_PASSWORD 爲 Sonatype 上面註冊的用戶名和密碼, 這裏的 ID 會在 pom.xml 裏面使用到。

配置 Maven 的 pom.xml

<project>
    ...

    <!-- More Project Information -->
    <name>nebula-java</name>
    <description>Nebula Java Client</description>
    <url>https://github.com/vesoft-inc/nebula-java</url>
    <scm>
        <connection>scm:git:https://github.com/vesoft-inc/nebula</connection>
        <url>https://github.com/vesoft-inc/nebula</url>
        <developerConnection>scm:git:https://github.com/vesoft-inc/nebula</developerConnection>
    </scm>
    <licenses>
        <license>
            <name>Apache License, Version 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
            <distribution>repo</distribution>
            <comments>license</comments>
        </license>
    </licenses>

    ...
    <profiles>
        <profile>
            <id>release</id>
            <build>
                <plugins>
                    <!-- Source -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-source-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>attach-sources</id>
                                <goals>
                                    <goal>jar</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <!-- Javadoc -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-javadoc-plugin</artifactId>
                        <version>3.1.1</version>
                        <configuration>
                            <excludePackageNames>com.facebook.thrift:com.facebook.thrift.*</excludePackageNames>
                        </configuration>
                        <executions>
                            <execution>
                                <id>attach-javadocs</id>
                                <phase>package</phase>
                                <goals>
                                    <goal>jar</goal>
                                </goals>
                                <configuration>
                                    <doclint>none</doclint>
                                </configuration>
                            </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>
                <repository>
                    <id>release</id>
                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
                </repository>
                <snapshotRepository>
                    <id>snapshots</id>
                    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
                </snapshotRepository>
            </distributionManagement>
        </profile>
    </profiles>
    ...
</project>
  • pom.xml 中必須包括: name 、 description 、 url 、 licenses 、 developers 、 scm 等基本信息 (血淚史之踩過的坑
  • 發佈 maven 除了 jar 必須還有文檔包和源碼包。所以 pom 需添加 maven-javadoc-plugin  和  maven-source-plugin 。 參考示例:
com-vesoft-client
|-- pom.xml
|-- src\
`-- target
    `-- attach-source-javadoc-1.0-SNAPSHOT.jar
    `-- attach-source-javadoc-1.0-SNAPSHOT-javadoc.jar
    `-- attach-source-javadoc-1.0-SNAPSHOT-sources.jar
  • 發佈構建須要祕鑰加密,所以 pom 需添加 maven-gpg-plugin  (血淚史之踩過的坑

多模塊項目配置

nebula-java 是多模塊項目

<modules>
    <module>client</module>
    <module>examples</module>
</modules>

爲了上傳 Client,須要上傳 parent 的 pom.xml,不然 Client 會找不到依賴(血淚史之踩過的坑),但咱們又不但願上傳 examples 模塊,故作了以下改動: 

  • 項目信息 namedescriptionurllicensesdevelopersscm 等信息和 maven-gpg-plugin 放在 parent 的 pom.xml 文件中
<project>
  ...
    <name>nebula-java</name>
    <description>Nebula Java Client</description>
    <url>https://github.com/vesoft-inc/nebula-java</url>
    <scm>
        <connection>scm:git:https://github.com/vesoft-inc/nebula</connection>
        <url>https://github.com/vesoft-inc/nebula</url>
        <developerConnection>scm:git:https://github.com/vesoft-inc/nebula</developerConnection>
    </scm>
    <licenses>
        <license>
            <name>Apache License, Version 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
            <distribution>repo</distribution>
            <comments>license</comments>
        </license>
    </licenses>

    <developers>
        <developer>
            <id>$ID</id>
            <name>$NAME</name>
            <email>$EMAIL</email>
            <organization>vesoft</organization>
            <roles>
                <role>architect</role>
                <role>developer</role>
            </roles>
        </developer>
    </developers>

    <distributionManagement>
        <repository>
            <id>release</id>
            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
        </repository>
        <snapshotRepository>
            <id>snapshots</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

    <build>
        <plugins>
            <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>
  </project>
  • 在 Java Client 的 pom.xml 中添加 maven-javadoc-plugin  、  maven-source-plugin 和 maven-deploy-plugin
<plugins>
  ......
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
        <executions>
            <execution>
                <id>attach-sources</id>
                <goals>
                    <goal>jar</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
        <version>3.1.1</version>
        <configuration>
            <excludePackageNames>com.facebook.thrift:com.facebook.thrift.*</excludePackageNames>
        </configuration>
        <executions>
            <execution>
                <id>attach-javadocs</id>
                <phase>package</phase>
                <goals>
                    <goal>jar</goal>
                </goals>
                <configuration>
                    <doclint>none</doclint>
                </configuration>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-deploy-plugin</artifactId>
        <executions>
            <execution>
                <id>default-deploy</id>
                <phase>deploy</phase>
            </execution>
        </executions>
    </plugin>
</plugins>

在 example 模塊的 pom.xml 中聲明 skip deploy

<plugins>
  ......
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-deploy-plugin</artifactId>
        <configuration>
            <skip>true</skip>
        </configuration>
    </plugin>
</plugins>

Q: 爲何 maven-gpg-plugin 放在 parent 的 pom.xm l中,而 maven-javadoc-pluginmaven-source-plugin 插件放在 Client 的 pom.xml 中

A: 由於上傳的全部構件都須要加密,包括 parent 的 pom.xml,所以放在 parent 中; 而只有 Client 須要上傳 javadoc,source,所以 maven-javadoc-pluginmaven-source-plugin 插件放在 Client 中。

上傳構件到 OSS 中

在 nebula-java/ 目錄下運行:

> mvn clean deploy -DpomFile=pom.xml

NOTE:不加 -DpomFile ,上傳的文件中會沒有 parent 的 pom.xml (又是一部血淚史)

在 OSS 中發佈構件

使用 Sonatype 帳號登陸 https://oss.sonatype.org/#stagingRepositories,可在 Staging Repositories  中查看已上傳的構件,這些構件目前是放在 Staging 倉庫中,可進行模糊查詢,定位到剛上傳的構件。

此時,該構件的狀態爲 Open ,勾選它,而後點擊 Close  按鈕。系統會自動驗證該構件是否知足指定要求 (幸福的人只有一種,不幸的人各有各的不幸,可能會遇到各類各樣的不符合要求,Good luck!ヾ(◍°∇°◍)ノ゙)

當驗證完畢後,狀態會變爲 Closed

image

最後,點擊 Release 按鈕來發布該構件

image

頁面可能要刷新一下才能看到最新的狀態。

通知 Sonatype 構件已成功發佈

在前面 JIRA 的 issue 下面回覆一條「構件已成功發佈」的評論,通知 Sonatype 的工做人員爲要發佈的構件作審批,發佈後會關閉該 issue。

等待構件審批經過

而後,等待。。。

從中央倉庫中搜索構件

大概十多分鐘後,能夠在這裏 https://repo1.maven.org/maven2 找到剛剛發佈的構件,能夠直接在 pom.xml 中使用啦~~ 👏👏

等同步完成大約 2 個小時,中央倉庫(鏈接:http://search.maven.org/)就能夠搜到啦。

國內不少使用的是阿里雲的鏡像,鏡像同步不是實時同步。爲了及時使用,能夠添加中央倉庫鏡像源,在 ~/.m2/setting.xml 文件添加,以下:

<mirrors>
......
    <mirror>
        <id>nexus-mvn</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus Central</name>
        <url>http://repo1.maven.org/maven2</url>
    </mirror>
</mirrors>

第一次成功發佈以後,之後就不用這麼麻煩了,能夠直接使用 Group Id 發佈構件。

後續操做

以後同一個 Group Id 的發佈流程

最後舒適提示:發佈的版本不支持修改,或者刪除

星雲·小劇場

爲何給圖數據庫取名 Nebula ? Nebula 是星雲的意思,很大嘛,也是漫威宇宙裏面漂亮的星雲小姐姐。對了,Nebula的發音是:[ˈnɛbjələ]

本文星雲圖講解--《阿爾普 188 和蝌蚪的尾巴》

image

爲何這個星系有這麼長的尾巴?

在這張使人驚歎的遠景圖中,根據哈勃遺留檔案的圖像數據,遙遠的星系造成了一個引人注目的背景,這是被破壞的螺旋星系 Arp188,蝌蚪星系。

宇宙蝌蚪距離北方的龍星座(天龍座)只有 4.2 億光年。它引人注目的尾巴大約有 28 萬光年長,以巨大、明亮的藍色星團爲特徵。有一個故事是這樣說的:一個更緻密的闖入星系從 Arp 188 前穿過——從右到左——被它們的引力甩在蝌蚪後面。在此次近距離接觸中,潮汐力將螺旋星系的恆星、氣體和塵埃拉出,造成了壯觀的尾巴。闖入者星系自己,估計位於蝌蚪後面 30 萬光年處,能夠經過右上角的前景螺旋臂看到。與地球同名的蝌蚪星系極可能會隨着年齡的增加而失去尾巴,尾巴上的星團造成了大螺旋星系的小衛星。

資料來源 | Hubble Legacy Archive, ESA, NASA;

圖片來源 | Astronomy Picture of the Day | 2018 December 11

附錄

最後,附上 Nebula Graph GitHub 地址:https://github.com/vesoft-inc/nebula,若是你在使用 Nebula Graph 過程當中遇到任何問題,歡迎 GitHub 聯繫咱們或者加入微信交流羣,請聯繫微信號:NebulaGraphbot

關注公衆號

相關文章
相關標籤/搜索