使用gradle外掛釋出專案到nexus中央倉庫

flydean發表於2021-04-19

簡介

Sonatype 提供了一個叫做開源軟體資源庫託管Open Source Software Repository Hosting (OSSRH) 的工具,幫助我們來方便的將專案釋出到中心倉庫中。

但是這個工具和我們的專案構建是割裂的,尤其是在CI整合構建中,很難做到自動化。

Gradle是一個很好的構建工具,靈活而又強大,可不可以直接在Gradle中的任務中直接構建和上傳到中央倉庫或者其他自定義的nexus倉庫中呢?答案是肯定的。

Gradle Nexus Publish Plugin歷史

今天要給大家介紹的gradle外掛名字叫做Gradle Nexus Publish Plugin,最近才釋出了1.0.0版本,有小夥伴可能要問了,gradle出來這麼久了,最近才有這樣的外掛嗎?

其實不然,我們來講一下gradle Nexus釋出外掛的歷史。

2015年,Marcin Zajączkowski建立了gradle-nexus-staging-plugin,該外掛可在Nexus儲存庫管理器中關閉和釋放staging儲存庫。使用這個外掛就可以直接從程式碼中將Gradle專案釋出到Maven Central倉庫。多年來,它已經在全球各地被多個專案所採用。

但是這個外掛存在一個小問題: 由於Gradle釋出過程中的技術限制,因此需要使用啟發式技術來跟蹤隱式建立的staging儲存庫,對於給定狀態的多個儲存庫,通常會發布失敗。尤其是在持續整合服務Travis CI在2019年末更改其網路架構之後,這個外掛問題就更多了。

基於這個問題,馬克·菲利普(Marc Philipp)建立了另外一個外掛Nexus Publish Plugin,該外掛豐富了Gradle中的釋出機制,可以顯式建立staging儲存庫並直接向其釋出(上傳)元件。

通常我們需要將這兩個外掛一起使用,但是,一個功能需要使用到兩個外掛還是會讓使用者感到困惑。所以Gradle Nexus Publish Plugin在2020/2021年應運而生了,它的目的就是合併上面兩個外掛的功能。

外掛的使用

在gradle中使用該外掛很簡單,首先需要引入這個外掛:

plugins {
    id("io.github.gradle-nexus.publish-plugin") version "«version»"
}

注意,這個外掛必須在 Gradle 5.0 或者之後的版本使用,並且在根專案中引入。

接下來,我們需要定義要釋出的倉庫,如果是通過Sonatype's OSSRH Nexus釋出到Maven的中央倉庫,那麼需要新增sonatype(),如下所示:

nexusPublishing {
    repositories {
        sonatype()
    }
}

在sonatype()中,實際上定義了nexusUrl 和 snapshotRepositoryUrl。

釋出到中央倉庫是需要使用者名稱密碼的,我們需要設定sonatypeUsername 和 sonatypePassword 這兩個專案的屬性。一種方法是在~/.gradle/gradle.properties 中進行配置,或者設定 ORG_GRADLE_PROJECT_sonatypeUsername 和 ORG_GRADLE_PROJECT_sonatypePassword 這兩個環境變數。

或者,可以直接在sonatype 中進行定義:

nexusPublishing {
    repositories {
        sonatype {
            username = "your-username"
            password = "your-password"
        }
    }
}

最後,呼叫publishToSonatype和 closeAndReleaseSonatypeStagingRepository就可以分別釋出到Sonatype和關閉併發布到中央倉庫了。

注意,上面的closeAndReleaseSonatypeStagingRepository實際上是包含了兩步操作:close和release。我們也可以僅僅呼叫closeSonatypeStagingRepository,然後手動登入Nexus UI,進行release操作。

下面是兩個分別使用groovy和Kotlin的具體的例子:

Groovy DSL

plugins {
    id "java-library"
    id "maven-publish"
    id "io.github.gradle-nexus.publish-plugin" version "«version»"
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from(components.java)
        }
    }
}

nexusPublishing {
    repositories {
        myNexus {
            nexusUrl = uri("https://your-server.com/staging")
            snapshotRepositoryUrl = uri("https://your-server.com/snapshots")
            username = "your-username" // defaults to project.properties["myNexusUsername"]
            password = "your-password" // defaults to project.properties["myNexusPassword"]
        }
    }
}

Kotlin DSL

plugins {
    `java-library`
    `maven-publish`
    id("io.github.gradle-nexus.publish-plugin") version "«version»"
}

publishing {
    publications {
        create<MavenPublication>("mavenJava") {
            from(components["java"])
        }
    }
}

nexusPublishing {
    repositories {
        create("myNexus") {
            nexusUrl.set(uri("https://your-server.com/staging"))
            snapshotRepositoryUrl.set(uri("https://your-server.com/snapshots"))
            username.set("your-username") // defaults to project.properties["myNexusUsername"]
            password.set("your-password") // defaults to project.properties["myNexusPassword"]
        }
    }
}

預設情況下nexusPublishing中的connectTimeout和clientTimeout是5分鐘,可以根據自己的需要進行調整。

外掛背後的故事

我們來看一下這個外掛背後是怎麼工作的。

首先定義的nexusPublishing { repositories { ... } } 會攔截所有子專案的 maven-publish 外掛,用來修改釋出地址。

如果專案的版本號不是以-SNAPSHOT結尾,這說明是釋出版本,那麼會建立一個initialize${repository.name.capitalize()}StagingRepository 任務,開啟一個新的staging倉庫,並且設定好對應的URL。在多專案構建中,所有擁有相同nexusUrl 的子專案,將會使用同樣的staging倉庫。

initialize${repository.name.capitalize()}StagingRepository為每個配置好的倉庫地址,生成釋出任務。

為每個釋出任務生成一個 publishTo${repository.name.capitalize()} 生命週期task。

在釋出任務之後分別建立 close${repository.name.capitalize()}StagingRepositoryrelease${repository.name.capitalize()}StagingRepository 任務。

總結

這麼好用的外掛,趕緊去試試吧。

本文已收錄於 http://www.flydean.com/07-gradle-nexus-publish-plugin/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章