如何釋出自己的專案到中央倉庫

菠菜東發表於2020-07-19

1


以前在github發開源專案,都因為懶,從來不構建到中央倉庫。最近因為其他人要用,聯絡我。希望可以發到中央倉庫。我想,不就是mvn deploy嘛,開搞。一圈弄下來,發現真沒那麼簡單。當中遇到了無數的坑,讓我每一次都心裡默默唸到,發個專案,為何如此痛苦。

現將痛苦的過程詳細記錄下來。希望可以幫助到其他小夥伴少踩點坑。

首先,你需要到sonatype這個站點上去註冊一個賬號。這個頁面長這個樣子:

file

我當時以為我進錯地方了,這不是jira嗎。好吧。看url還是提issue的地方,這和釋出專案有毛的關係...

好吧,點新建,專案選Community Support - Open Source,問題型別選New Project

file

填就是了。注意的是Group Id這裡要填你自己的擁有的域名,比如com.xxxx,沒有的話,自己去註冊域名去。填好之後就是等待稽核。我搜了下,網上小夥伴說要等待3,5天。

3個小時後,我上去再去看,管理員給我回復了:

file

大致意思就是要你證明這個域名是屬於你自己的。有2種方法,加一個txt型別的解析到你的域名裡是最快的方法。

我的域名申請在騰訊雲。登陸進去。找到域名解析設定。加進去txt型別的解析。主機記錄填那個jira ticket名字,記錄值是你這個ticket的連結url。

file

設定完了後,去回覆管理員。然後繼續等待。

管理員大概很快就回復了我。並通過了驗證。接下來,就要搗鼓專案了。

2


要上傳中央倉庫,你的專案必須要符合一些規範才行。

首先pom檔案是有要求的,在你的專案頂層pom檔案裡一定要有以下標籤:

  • name
  • description
  • url
  • licenses
  • developers
  • issueManagement
  • scm

照著一個個填,我參考了一個開源專案的pom,例子如下:

<modelVersion>4.0.0</modelVersion>
<groupId>com.yomahub</groupId>
<artifactId>liteflow</artifactId>
<packaging>pom</packaging>
<version>2.2.0</version>
<name>liteflow</name>
<description>a lightweight and practical micro-process framework</description>
<url>https://github.com/bryan31/liteflow</url>
<licenses>
    <license>
        <name>MIT License</name>
        <url>https://opensource.org/licenses/MIT</url>
        <distribution>repo</distribution>
    </license>
</licenses>
<developers>
    <developer>
        <email>weenyc31@163.com</email>
        <name>bryan.zhang</name>
        <url>https://github.com/bryan31</url>
        <id>bryan31</id>
    </developer>
</developers>
<issueManagement>
    <system>Github Issue</system>
    <url>https://github.com/bryan31/liteflow/issues</url>
</issueManagement>
<scm>
    <connection>scm:git@github.com:bryan31/liteflow.git</connection>
    <developerConnection>scm:git@github.com:bryan31/liteflow.git</developerConnection>
    <url>git@github.com:bryan31/liteflow.git</url>
</scm>

補全了pom的資訊後,還需要補全一些maven外掛,主要有:

  • maven-source-plugin
  • maven-site-plugin
  • maven-javadoc-plugin
  • maven-gpg-plugin

例子如下:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <encoding>UTF-8</encoding>
                <source>${java.version}</source>
                <target>${java.version}</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.18.1</version>
            <configuration>
                <skipTests>true</skipTests>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-source-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <attach>true</attach>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>jar-no-fork</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-site-plugin</artifactId>
            <version>3.7.1</version>
        </plugin>
        <!-- Javadoc -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>3.0.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- Gpg Signature -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-gpg-plugin</artifactId>
            <version>1.6</version>
            <executions>
                <execution>
                    <id>sign-artifacts</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>sign</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

當然還需要加上distributionManagement

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

你的sonatype的使用者名稱和密碼當然不能寫在專案pom裡,你得在maven的setting.xml裡新增server

<server>
    <id>sonatype</id>
    <username>your username</username>
    <password>your password</password>
</server>


3


補全了pom的一些規定資訊和外掛後。可以試下是否可以正確無誤的生成javadoc,在專案根目錄下執行

mvn site

接下去就是無盡的等待,等待從中央倉庫下載各種外掛。這裡最好搭個梯子翻牆,速度會快點。我全程用梯子,也等了40分鐘,這時候可以去幹點別的事情。。40分鐘後,終於build成功了:

file

接下去就是簽名了。想要上傳到倉庫,jar包必須被正確簽名。

用gpg來進行簽名,網上搜了下,windows的使用者可下載gpg4win,我這裡用的是mac,不能用這個軟體。只能自己安裝個命令列gpg工具了

brew install gpg

安裝成功後,執行命令生成祕鑰對:

gpg --gen-key

根據提示,填寫使用者名稱和郵件地址。然後確認。

我mac上用的是iterm2,確認後一直卡著,提示正在生成位元組。然後等了很久也沒有反應。我一直以為這就是正常現象,已經生成祕鑰對了。只不過命令列不友好,沒有告訴我。。。導致了我後面簽名一直籤不成功。

後來我換了一個ssh工具,electerm,才正確生成。最後是要讓你輸入passphase。以下是正確生成祕鑰對的介面

file

接下去就是要利用maven-gpg-plugin對jar包進行簽名了。在進行之前,需要在setting.xml檔案的當前profile里加上

<properties>
    <gpg.executable>gpg</gpg.executable>
    <gpg.passphrase>your passphrase</gpg.passphrase>
</properties>

然後執行mvn install。

我這裡一直簽名不成功,報以下錯:

file

網上搜尋了下,原來是我本地的gpg工具版本太新了,和maven的外掛版本不匹配。需要在~/.gnupg這個目錄下增加2個配置:

gpg.conf

use-agent
pinentry-mode loopback

gpg-agent.conf

allow-loopback-pinentry

折騰了半天,終於可以mvn install正確執行gpg的jar包簽名了。接下去準備進行激動人心的mvn deploy了。

由於之前已經解決了jar包簽名的問題,deploy過程也是相當的順利。deploy過程中,會把你專案的jar包,加簽資訊,javadoc,javasource等包一併上傳到sonatype伺服器。

deploy好,你就可以在sonatype的staging repo裡看到了,staging repo相當於暫存的狀態,還沒有正式釋出到release倉庫,sonatype需要校驗你上傳jar包的規範性,合法性。

選中你提交的暫存資訊,點close,等一段時間,refresh之後底下會有校驗結果。全部通過後才能點release。底下是我第一次校驗的結果:

file

可以看到,有2項沒通過,第1項是我pom不規範,原因是我第一次pom提交的時候少了<name>標籤。關鍵是第2項簽名校驗失敗,從右邊的詳細資訊裡可以看到,sonatype在校驗我的jar包簽名時找不到我的public key。

gpg生成的是RSA的key,有公鑰和私鑰。我本地加簽之後,應該把公鑰給到sonatype,否則sonatype無法驗證我的jar包的加簽資訊是否有效。所以我之前流程應該缺少了這一步!

看詳細資訊,sonatype應該是到以下3個地方去拿key,發現都沒有,所以才報了錯。

http://pgp.mit.edu:11371
http://keyserver.ubuntu.com:11371
http://pool.sks-keyservers.net:11371

所以我們只需要上傳key到任意一個key server就可以了。

gpg上傳公鑰的命令是

gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys yourkeyid

這裡我踩了2個坑,第一個是上傳的協議是hkp,不是http,網上一搜才知道。sonatype報錯的地方都是http。

第二個是gpg在傳送公鑰的時候並不是直接指定公鑰發上去,而是需要你的keyid,個人推測可能是根據這個keyid再在檔案系統中找到公鑰進行傳送吧。它需要什麼,我們只能給什麼。問題是這個keyId是什麼呢,從哪來呢

在生成祕鑰對的時候,我注意到給了一個fingerprint,也能用gpg --list-keys 這個命令進行檢視:

file

難道這個就是keyId?我嘗試著用這個作為keyId,進行傳送,也能成功。但是在sonatype上進行檢測卻過不了。

這個keyId卡了我很久,最後還是依靠萬能的谷歌查到了。原來所謂的KeyId就是fingerprint的後16個字元。我Fxx...(省略N個讚美的詞語)。

拿到了正確的KeyId,繼續執行gpg的上傳命令,上傳好,然後執行檢視key的命令:

gpg --keyserver hkp://keyserver.ubuntu.com:11371 --recv-keys yourkeyid

也能在key server上找到

file

4


我們繼續在sonatype的staging repo進行close操作校驗,這個操作其實我已經做了n遍了,各種坑,所以見到以下這個畫面的時候有點激動:

file

可以看到,所有的校驗都通過了,沒有報錯了。Release的按鈕也已經點亮。通往中央倉庫的大門已經敞開!

堅定的點下release按鈕。輸入備註後,成功提交。

在sonatype進行Release後 ,要真正在中央倉庫看到,可能要等上個5到6小時。

最後。終於,在中央倉庫的地址我看到了提交的包,大功告成

file

原本以為提交中央倉庫可能不是那麼困難,實際操作一遍,發現需要注意的細節有很多。而專案本身也有很多需要規範的地方。整個過程花了一天時間,碰了無數的坑,我工位旁邊的小夥伴之前操作過,但是時間久遠,細節又很多。所以對很多坑印象比較模糊了。所以記錄下來。

個人開發的專案被其他人所使用,是一件很有成就感的事情。所以提交中央倉庫是必然途徑。雖然我希望整個過程能簡單點,但是中央倉庫就一個,只能按照它的規範來做。希望有人看到這篇記錄,能讓你少走點彎路~

5

微信關注 「jishuyuanren」獲取更多技術乾貨

相關文章