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/"
}
复制代码

便可进行发布。

相关文章
相关标签/搜索