Mavencentral發佈指南--再不行動起來,你的託管的library就沒了

前言

相信很多朋友都有本身進行維護的做品,並託管在三方Library倉庫開放使用。 而距離Jcenter宣佈中止對非付費用戶的各項運營政策已經有一段時間了,再不行動起來,託管在Jcenter和Jfrog的 library就要沒了html

本文帶你走一遍 sonatype帳號註冊申請groupIdMavenCentral發佈 ,並提供一個更加方便的 Gradle插件 用於發佈。java

背景

今年Jfrog宣佈了 這項決定android

UPDATE: To better support the community in this migration, JFrog has extended the JCenter new package versions submission deadline through March 31st 2021.git

To clarify, the JCenter repository will keep serving packages for 12 months until February 1st 2022. Only the JCenter REST API and UI will be sunsetted on May 1st 2021.github

這就很尷尬了,隨着時間的推移,未付費用戶託管的library將沒法再被獲取。shell

扯點題外話,Google也被這一波操做秀到了,按照Google的尿性,可能會在將來支撐這件事業,但畢竟八字沒一撇。apache

因此,咱們剩下的選擇很少了:安全

  • 成爲 尊貴的付費用戶
  • 轉投 sonatype 的懷抱,使用免費的MavenCentral

註冊 sonatype 帳戶

sonatype的玩法很溜,使用了敏捷開發管理的知名工具 JIRA 進行事物管理,因此第一件事情是 註冊sonatype的JIRA帳戶bash

註冊地址服務器

按照信息指導填寫便可。

申請GroupId

一個託管在三方倉庫的Library由三個信息肯定:GroupId,ArtifactId,version

不難理解,咱們須要先申請一個可用的GroupId。開始申請以前,請先閱讀如下內容,避免無用操做:

按照sonatype的運營策略,他們利用了一些巧妙的方式來管理GroupId而且規避搶注風險

首先分爲兩種類型:

  • 你擁有域名
  • 你沒有域名

第一類的驗證方法我沒有測試過,擁有域名的能夠按照官網介紹試一下:

  • Add a TXT record to your DNS referencing this JIRA ticket: (JIRA-TASK-ID) (Fastest)
  • Setup a redirect to your Github page (if it does not already exist) You can find more information here: central.sonatype.org/publish/

第二類須要利用到第三方(如:Github、Gitlab、Gitee 等) 經過第三方 "對於其用戶名的惟一性約束" 和 "Pages服務",能夠獲得一個託管在三方平臺的網站,以github爲例: 開通Pages後,簡單配置能夠獲得網站:leobert-lan.github.io/

建立Pages網站

以github爲例,Gitee等應該相似

官方介紹

建立一個 {github_user_name}.github.io 的倉庫

pages_create.png

若是已經有我的博客,也能夠利用HEXO或者Git-Book等工具,生成相關博客網頁進行託管

下載倉庫並添加一個 不太離譜index.html

注意:

  • sonatype 僅關注這個域名是否存在,按照映射規則,GroupId爲 io.github.{github_user_name},若是這個域名不存在,不會頒發對應的GroupId給你
  • sonatype 並不關注網頁的內容是啥(哪怕和項目無關),但不要弄得太離譜:政治、宗教、不良信息等不要亂來便可

隨後進入項目的設置 pages_setting.png

選定分支和路徑後保存,能夠很快獲得部署結果,部署成功後能夠自行驗證下。

JIRA建立申請task

  • 點擊新建Task後,類型等均爲默認,簡單描述你的意圖;
  • 按照映射規則,填寫GroupId:io.github.{github_user_name} gitlab、gitee同理
  • 填寫你的Github項目的倉庫信息等

提交後等待,通常會先有 機器人 進行答覆,告知你平臺的運營政策、相關注意事項。

注意:不要一直盯着等待,註冊時填寫了郵箱,一旦流程狀態發生了變動,會有郵件通知

收到郵件後,經過備註進行回覆能夠改變流程狀態,隨後等待人工審覈(若是信息均無誤,可能機器直接過審)

隨後進入帳戶歸屬權認證

驗證帳號歸屬權

固然,這裏是Github或者Gitee等帳號的歸屬權。

前面咱們利用這些平臺獲得了惟一的域名,可是sonatype須要判斷 這個域名是你的,由於:

  • 帳號和Pages一一對應
  • Pages和GroupId一一對應
  • Task中對GroupId進行了惟一性校驗

因此sonatype要求在對應的Github帳號下建立一個和TaskID一致的倉庫 例如:

Please create a public repo called github.com/leobert-lan… to verify github account ownership.

If you do not own this github account, please read: central.sonatype.org/publish/req…

建立成功後,再回來評論一次推動流程,等審覈經過後,就得到了GroupId


到此爲止咱們就獲取了GroupId。接下來咱們須要 準備簽名工具

Library的信息所有存在pom文件中,若是沒有簽名機制,就有可能出現李代桃僵的事情。

這裏咱們須要用到 GPGgpg官網 ,有興趣的能夠多研究研究。

注意:macOs >= 10.15時,暫沒法安裝gpg,你可能須要尋找一臺window電腦來生成簽名密鑰,不用擔憂,密鑰是能夠導出的

生成GPG簽名密鑰

生成

gpg --full-generate-key
複製代碼

使用命令進入密鑰生成,

  • 選擇 RSA(僅用於簽名)便可
  • 設置密鑰長度,使用密鑰默認長度 2048
  • 設置過時時間,永久有效便可,不必本身折騰本身
  • 確認信息後輸入 "真實姓名","郵箱","密鑰Comment",Comment不參與任何校驗、用於備註他的做用
  • 肯定信息或者再次修改,確認後須要輸入兩次密碼,請不要忘記你的密碼
  • 生成完成後會輸出信息

固然,沒有必要死記這些信息,

利用:

gpg --list-keys
複製代碼

或者

gpg -K
複製代碼

能夠查看全部生成的key,每一個key都有一段很長的ID,這是其公鑰的ID,長41位,固然,它的後八位也能夠做爲其ID,在使用上二者是等價的,通常用 後八位 便可。

上傳公鑰到公共服務器

我選擇了"pool.sks-keyservers.net",固然還有其餘公共服務器能夠託管。

gpg --keyserver hkp://pool.sks-keyservers.net --send-keys 公鑰 ID
複製代碼

檢查是否上傳成功:

gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 公鑰 ID
複製代碼

導出公鑰、密鑰、鑰匙串(KeyRing)

#導出公鑰到 public-file.key 文件:
gpg -a -o public-file.key --export KeyId 
 #導出私鑰到 private-file.key 文件:
gpg -a -o private-file.key --export-secret-keys KeyId
 #導出鑰匙串到 secring.gpg 文件:
gpg --keyring secring.gpg --export-secret-keys
複製代碼

保管好你的鑰匙!!

配置項目

此時,咱們的準備工做已經到位,開始修改你的項目:

更改plugin

考慮到 Gradle 7.0 會棄用 maven插件 ,咱們選用 maven-publish 插件

plugins {
// 其餘必要的插件
    
    id 'signing'
    id 'maven-publish'
}
複製代碼

添加 maven-publish 用於發佈 添加 signing 用於簽名

添加簽名的必要信息

signing.keyId=公鑰ID,後八位便可
signing.password= GPG密鑰的密碼
signing.secretKeyRingFile=/Users/leobert/.gnupg/secring.gpg #鑰匙串地址
複製代碼

比較遺憾的是我沒有找到在local.properties中配置的方法,彷佛signing插件內部直接讀取了屬性。

考慮到密鑰安全性,能夠將gradle.properties 文件從Git中移除並忽略。

配置生成JavaDoc和Sources的Task

task sourcesJar(type: Jar) {
    classifier = 'sources'
    from sourceSets.main.java.srcDirs
}

//android 項目須要額外定義一下task,java-library等項目插件自帶task
//task javadoc(type: Javadoc) {
// source = android.sourceSets.main.java.srcDirs
// classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
//}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}

tasks.withType(Javadoc) {
    options.addStringOption('Xdoclint:none', '-quiet')
    options.addStringOption('encoding', 'UTF-8')
    options.addStringOption('charSet', 'UTF-8')
}
複製代碼

注意:android 項目須要額外定義一下javadoc 的 task,java-library等項目插件自帶task,並注意路徑

配置發佈信息

注意,在任務Evaluated以後進行配置,即配置在 afterEvaluate 閉包內

afterEvaluate {
    publishing {
        publications {
            mavenAndroid(MavenPublication) {
                groupId GROUP_ID
                artifactId ARTIFACT_ID
                version VERSION_NAME
                artifact sourcesJar
                artifact javadocJar
                artifact('build/libs/xxx.jar') //
                // 配置 pom 文件格式
                pom {
                    packaging = 'jar'
                    name = ARTIFACT_ID
                    description = ARTIFACT_ID
                    url = siteUrl
                    licenses {
                        license {
                            name = 'The Apache Software License, Version 2.0'
                            url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                        }
                    }
                    developers {
                        developer {
                            id = 'leobert'
                            name = 'leobert'
                            email = 'leobert.l@hotmail.com'
                        }
                    }
                    scm {
                        connection = siteUrl
                        developerConnection = gitUrl
                        url = siteUrl
                    }
                }
            }
        }
        // 配置遠程倉庫
        repositories {
            maven {
                url = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/'
                credentials {
                    username ACCOUNT
                    password PASSWORD
                }
            }
        }
    }

    signing {
        sign publishing.publications.mavenAndroid
    }
}
複製代碼

這是一個簡單的樣板,固然,協議部分、開發者部分、貢獻者部分等還能夠繼續擴展。 ACCOUNTPASSWORD 爲sonatype的帳密,

build以後,執行publish task 便可進行簽名和上傳

最後一步

使用sonatype的帳密 登陸 sonatype 的maven倉庫

左側導航進入:stagingRepositories,找到提交的內容,再次檢查下全部的校驗已經過,close,刷新後進行release。

確認成功後,關閉sonatype-jira的task。

上述操做成功後,提交的Components應當已經進入sonatype的release倉庫,大約1小時內同步到MavenCentral

以後更新版本,理論上會自動同步。

編寫Gradle插件讓配置更加簡單

其實maven-publish插件還支持更加複雜的配置,但我的項目中可能不多用到,挑選了"夠用"的配置項後,咱們編寫一個Gradle插件, 這樣能夠省略重複樣板。

插件源碼倉庫,

  • gradle.properties 中 寫入簽名必要的信息

考慮到本篇的主題是分享MavenCentral發佈的經驗,略去Gradle插件的相關知識,以及本插件的源碼介紹。有興趣的朋友能夠經過倉庫的源碼自行了解

PS:不少時候咱們都是copy了野生配置,並且每每是Groovy代碼,出於Groovy語言的特殊性,這些閉包配置項出現錯誤時,大機率會被兼容,插件使用Kotlin編寫, 閱讀其源碼能夠加深對於maven-publish等插件API的認知

signing.keyId=公鑰ID,後八位便可
signing.password= GPG密鑰的密碼
signing.secretKeyRingFile=/Users/leobert/.gnupg/secring.gpg #鑰匙串地址
複製代碼
  • local.properties 中寫入sonatype 帳密信息:
nexus_user=sonatype帳號
nexus_pwd= sonatype密碼
複製代碼
  • 引入插件後,build.gradle進行必要的配置:
plugins {
    id 'osp.leobert.maven.publish'
}

EasyPublish {
    sourceSet = android.sourceSets.main.java.srcDirs
    docClassPathAppend = project.files(android.getBootClasspath().join(File.pathSeparator)).asPath
    docExcludes = ["a/b/c/*"]
    artifact {
        value = "build/outputs/aar/android-lib-demo-release.aar"
    }

    developer {
        id = 'leobert'
        name = 'leobert'
        email = 'leobert.l@hotmail.com'
    }

    //append developers
// developer {
// id = 'aa'
// name = 'bb'
// email = 'cc'
// }

    groupId = "io.github.leobert-lan"
    artifactId = "android-demo"
    version = "1.0.0"
    packaging = "aar"
    siteUrl = "https://github.com/leobert-lan/EsayPublish"
    gitUrl = "https://github.com/leobert-lan/EsayPublish.git"
    licenseName = 'Apache 2.0'
    licenseUrl = 'https://github.com/leobert-lan/EsayPublish/blob/master/LICENSE'

    mavenRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
}
複製代碼

便可進行發佈。

相關文章
相關標籤/搜索