ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Maven中央仓库发布实战:从GPG签名到Nexus Staging全流程指南

Maven中央仓库发布实战:从GPG签名到Nexus Staging全流程指南 前阵子把自己的一个开源组件正式发布到了 Maven 中央仓库整个过程走下来最大的感受是网上零散教程不少但要么停在“注册账号”这一步要么直接跳到“执行 deploy”中间那些命名空间验证、GPG 签名、staging 校验、中央仓库同步每一步都有不少隐藏细节。这篇文章我把自己从零到一发布的完整路径梳理一遍包括两个可走的发布通道、pom.xml 和 settings.xml 的落地写法、常见的报错与排查手段。如果你是开源作者或者在公司里维护公共组件库、想让同事用一行坐标把包引过去这篇指南应该能帮你节省大量试错时间。1. 发布到 Maven 中央仓库的整体思路怎么设计一条可行路径1.1 Maven 到底在干什么什么才算一个组件很多刚开始接触 Maven 的朋友会问maven 是干嘛的简单说Maven 是一个 Java 项目的构建和依赖管理工具它把项目打包、编译、测试、依赖拉取这些重复劳动接管了。而 Maven 中央仓库相当于 Java 生态的公共制品库全世界开发者的 jar 包都放在那里任何人只需要在项目的 pom.xml 里声明三要素就能把对应的组件拉到本地来用。这三要素就是 groupId、artifactId、version。groupId 标识组织或作者artifactId 标识具体的组件名version 标识版本。生活化类比一下groupId 像快递地址里的城市和街道artifactId 像收件人的名字version 像这个人的第几代手机型号。缺了任何一环Maven 都不知道该从仓库里取哪个包。把自己写的组件发布到中央仓库意味着你的坐标可以在全球范围内的任意 Maven 项目里被引用。别人在自己的 pom.xml 里写一行依赖Maven 就会自动去中央仓库下载连带这个组件依赖的其他第三方库也会一起拉下来。这就是公共组件的威力发布一次全生态受益不用再让使用者手动下载 jar 包丢到 lib 目录也避免了“下载到的 jar 版本和本地不一致”这种传统做法里最令人头疼的问题。我之前在公司里维护过一段时间内部工具库那时候用的都是私有 Nexus 仓库相对简单随便传。但公共组件完全不同中央仓库对内容的审核极其严格这也是本文后面要花大量篇幅讲各种校验规则的原因。1.2 发布的两条通道OSSRH 老流程与 Central Portal 新流程发布到中央仓库现在有两条主流通道。初学者最困惑的就是这里因为网上教程经常各说各话有的让你去 Sonatype JIRA 开工单有的让你去 central.sonatype.com 直接注册其实都对只是时代不同、通道不同。最早也是最经典的通道是 Sonatype 的 OSSRH 服务配合 Nexus Staging 仓库。流程是这样的先去 issues.sonatype.org 提交一个工单申请以某个 groupId 发布组件等管理员审核通过后Maven 会把组件部署到 s01.oss.sonatype.org 对应的 staging 仓库然后你登录网页端执行 Close 校验等校验通过后再执行 Release组件才会自动同步到中央仓库。这套流程运行了十几年大量老项目都在用很多教程讲的也是它。后来 Sonatype 推出了新的 Central Portal也就是 central.sonatype.com。这个门户把发布体验大大简化了注册账号后直接在页面上创建 namespace验证域名所有权之后可以通过网页上传也可以通过 Maven 命令行直接部署。校验和发布的过程也更自动不少环节不需要人工去点 Close、Release系统会直接帮你处理。如果是从没发布过组件的新项目我建议直接走 Central Portal省心很多。老账号继续用 OSSRH 也没有问题两种通道并不冲突。两条通道对比下来大概是这样对比项OSSRH 老通道Central Portal 新通道申请位置issues.sonatype.org 开工单central.sonatype.com 注册后创建命名空间验证提交工单后按提示验证域名自动化域名所有权验证部署地址s01.oss.sonatype.org 的 staging 仓库central.sonatype.com/api/v1/publisher/upload发布操作手动 Close Release页面触发或命令行部署后自动处理适合场景老项目、已有 groupId 的项目新组件、希望流程更简单的开发者我第一次发布时是先接触的老通道等搞完才知道新通道已经很好用了后来第二个组件就全程用 Central Portal。本文后面的配置讲解我会两条路都覆盖到因为老通道的知识点在很多遗留项目里依然会用到。1.3 为什么中央仓库要求这么严源码、javadoc 和 GPG 签名在私有仓库里传 jar 包传上去就能用没人管你。但中央仓库不一样它承载的是全 Java 生态的信任所以对上传物有硬性要求必须提供源码包 sources.jar必须提供 javadoc 包必须用 GPG 对文件做数字签名同时 pom 里必须写清楚 license、developers、scm 这些元数据。很多人不理解为什么非要源码和 javadoc。其实道理很简单公共组件被无数项目引用使用者遇到问题时需要直接看源码定位问题而不是对着反编译代码猜javadoc 则是为了让 IDE 里悬浮提示、自动补全时有完整的 API 文档。如果没有这两个包Central 的规则校验直接就不通过组件根本无法进入发布阶段。GPG 签名更好理解你生成一对公私钥发布时用私钥给 jar 包和 pom 文件都签上名然后把公钥传到公开的 keyserver 上。任何人拿到你的组件都可以用公钥验证文件确实是你发布的、没有被篡改。这就像你在合同上盖了印章而印鉴是在公证处做过备案的。中央仓库在接收组件时也会用你上传的公钥去校验签名。这一环是很多新手最容易卡住的地方因为涉及 GPG 工具、密钥 ID、keyserver 传播细节非常多我在后面单独开一节详细讲。2. 发布前的准备账号、命名空间、GPG 和 Maven 配置2.1 发布前需要准备好的材料清单我整理一下发布前必须准备的东西先列个清单你对照检查缺哪个补哪个免得发布到一半才发现少了东西。材料说明备注JDK 8构建项目的基础环境我习惯用 JDK 17 构建兼容性更好Maven 3.6构建和部署工具老版本也能用但建议新版GnuPG 命令行工具生成密钥和签名macOS/Linux 自带或 brew installWindows 装 Gpg4winSonatype 账号认证身份Central Portal 支持多种登录方式OSSRH 用 JIRA 账号域名或 GitHub 账号验证 groupId 所有权比如 io.github.yourname需要能证明你拥有它待发布的组件源码和 pom你要发布的东西确保本地 mvn clean package 能过私钥备份GPG 私钥要妥善保存CI 自动发布时需要用到这里面最容易忽略的是最后一项。很多人第一遍发布成功后就把 GPG 私钥丢在笔记本里不管了结果换电脑或者配置 CI 自动发布时发现私钥找不回来还得重新生成、重新验证非常被动。2.2 申请命名空间两种通道的具体操作命名空间也就是 groupId 的开发者可控制部分。中央仓库不允许随便使用一个自己没有所有权的 groupId你申请了 io.github.yourname就要证明 yourname 真的归你所有否则任何人都可以冒充一个组织发布恶意组件那生态就乱了。Central Portal 新通道的操作相对轻松。注册并登录 central.sonatype.com进入 Publishing 相关页面点击 Add Namespace输入你想申请的 groupId比如 io.github.yourname。系统会要求验证所有权通常有两种方式如果你填的 groupId 正好对应 GitHub 用户名可以导入 GitHub 仓库列表来自动验证不然就在 DNS 解析里添加一条 TXT 记录验证完成后删除即可。整个流程是自动化的快的话几分钟到几十分钟就通过。OSSRH 老通道则要走人工工单。到 issues.sonatype.org 创建新 issue项目选择 Community Support填写 Summary 和 Description说明你想发布什么组件、期望的 groupId 是什么。机器人会在几分钟内回复告诉你去做域名验证或者其他确认操作。人工审核通常需要一到三个工作日耐心等就行。我当时第一次等了两天每天刷新工单页面后来发现这种等待属于常态不用太焦虑。值得提醒的是groupId 一旦确定并被大家使用了尽量不要再去更换。因为旧坐标会被很多人的 pom.xml、文档、依赖锁定文件引用你改了坐标就等于把以前的使用者全部抛弃了。所以在申请之前想清楚是用个人命名空间 io.github.you还是用公司域名 com.yourcompany还是某个开源组织的专属 groupId。2.3 生成并同步 GPG 密钥这一步最容易踩坑GPG 签名在中央仓库发布里的地位非常高但很多人恰恰在这里被劝退。其实流程本身不复杂生成密钥、导出公钥、上传公钥到 keyserver、发布时配置 Maven 使用私钥签名。生成密钥用命令gpg --full-generate-key交互过程会让你选择密钥类型和长度我选的是 RSA and RSA长度 4096。然后输入姓名和邮箱这里有个小细节邮箱最好和你 Sonatype 账号绑定的邮箱保持一致虽然中央仓库校验时不一定强制邮箱一致但保持一致能避免后续很多身份关联上的疑问。最后设置一个口令这个口令要牢牢记住后面 Maven 签名时要用它不是登录 Sonatype 的密码是私钥的解锁口令。生成后查看密钥 IDgpg --list-secret-keys --keyid-formatlong输出里会有一行类似sec rsa4096/1A2B3C4D5E6F7A8B其中1A2B3C4D5E6F7A8B就是你的密钥 ID。导出公钥gpg --armor --export 1A2B3C4D5E6F7A8B然后把公钥上传到公开 keyservergpg --keyserver keyserver.ubuntu.com --send-keys 1A2B3C4D5E6F7A8B这里有个现象不同 keyserver 之间的公钥同步并不是在瞬间完成的。有时候你刚 send-keys 完中央仓库那边去查询还查不到会报签名验证失败。遇到这种情况基本只能等或者换一个同步更快的 keyserver 再发送一次。我在实际发布时遇到过这个问题当时以为配置错了排查了半天其实只是公钥还没来得及从 keyserver A 传播到 keyserver B睡一觉第二天再试就好了。私钥的导出备份也建议做命令是gpg --export-secret-keys 1A2B3C4D5E6F7A8B private.key文件保存到离线或者加密容器里后面 CI 发布时如果要重新 import就用gpg --batch --import private.key导入。2.4 settings.xml 的正确配置姿势密码别乱塞Maven 的全局配置文件位于~/.m2/settings.xml发布时它负责提供服务器认证信息。最核心的其实是server配置其中id必须和 pom.xml 里 distributionManagement 的 repositoryid完全一致Maven 靠这个 id 去匹配该用哪组用户名密码。老通道 OSSRH 的 settings.xml 可以这样写settings servers server idossrh/id username你的Sonatype账号/username password你的Sonatype密码/password /server /servers profiles profile idossrh/id properties gpg.passphrase你的GPG私钥口令/gpg.passphrase /properties /profile /profiles /settings这里有两个关键点。第一server的 id 不要觉得自己随便定一个就好它是密钥匹配键pom 里写了什么 idsettings.xml 里就要有对应的 id。第二明文密码确实不好Maven 支持 master password 加密机制但配置起来复杂度高于本文范围如果你的电脑是私人机器并且没有把 settings.xml 提交到代码仓库直接使用明文问题不大。真正危险的是把 settings.xml 传到了公开的 GitHub 仓库那密码就相当于裸奔了。Central Portal 新通道的配置思路类似只是部署地址换成了新地址。你可以在 Central Portal 后台生成访问凭据然后在 settings.xml 里配置server idcentral/id username你的用户名或访问令牌名称/username password你的访问令牌/password /serverpom.xml 里镜像仓库 id 也用central这样 Maven 就能匹配上。顺便说一句settings.xml 里配置多套 server 是允许的老通道新通道的 server 可以同时存在互不干扰切换项目时只要 pom 里的 id 不同就能自动匹配到对应配置。3. 核心实操从 pom.xml 配置到命令行成功发布3.1 一份能通过中央仓库校验的 pom.xml 长什么样前面所有准备做好接下来就是把 pom.xml 配置到“中央仓库能接受”的水平。这不是随便一个能构建的 pom 就行中央仓库对元数据有硬性校验缺一项 Close 阶段就过不去。先看一份最小可用的完整配置project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdio.github.yourname/groupId artifactIdyour-component/artifactId version1.0.0/version packagingjar/packaging nameyour-component/name descriptionA brief description of your component/description urlhttps://github.com/yourname/your-component/url licenses license nameApache License, Version 2.0/name urlhttps://www.apache.org/licenses/LICENSE-2.0.txt/url /license /licenses developers developer nameYour Name/name emailyouexample.com/email /developer /developers scm connectionscm:git:git://github.com/yourname/your-component.git/connection developerConnectionscm:git:ssh://gitgithub.com/yourname/your-component.git/developerConnection urlhttps://github.com/yourname/your-component/url /scm distributionManagement repository idossrh/id urlhttps://s01.oss.sonatype.org/service/local/staging/deploy/maven2//url /repository snapshotRepository idossrh/id urlhttps://s01.oss.sonatype.org/content/repositories/snapshots//url /snapshotRepository /distributionManagement build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-source-plugin/artifactId version3.3.1/version executions execution idattach-sources/id goalsgoaljar-no-fork/goal/goals /execution /executions /plugin plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-javadoc-plugin/artifactId version3.6.3/version executions execution idattach-javadocs/id goalsgoaljar/goal/goals /execution /executions /plugin plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-gpg-plugin/artifactId version3.2.4/version executions execution idsign-artifacts/id phaseverify/phase goalsgoalsign/goal/goals /execution /executions /plugin /plugins /build /project老通道的 publicationManagement 指向s01.oss.sonatype.org新通道则是https://central.sonatype.com/api/v1/publisher/upload这个地址会随账号不同而变化建议以 Central Portal 后台显示的为准。licenses、developers、scm 这三项是经常被忽略的。licenses 是必须的没有 license 的组件任何人都不知道你是否允许别人使用、修改中央仓库不可能让这种组件进去developers 记录谁维护这个组件出了问题好找人scm 记录源码仓库地址让使用者能回溯到你的代码。缺任何一项Close 校验都会明确报错。一个非常容易出现的问题如果你用了 Spring Boot 的spring-boot-maven-plugin构建项目默认会生成一个 Fat Jar也就是把依赖都打进去的可执行 jar。中央仓库原则上不接受这种 fat jar因为里面包含了大量第三方类的副本很容易造成类冲突也让源码包和 javadoc 包的规定失去意义。如果你确实要发 Spring Boot 项目一般需要额外保留一个普通 jar或者干脆把组件拆出来单独构建。3.2 发布命令与完整流程deploy 之后的 Close 和 Release配置完成后先在本地执行一次完整构建确认没问题mvn clean package这一步只是打包还不会触发 GPG 签名也不会部署到远端。接下来执行真正的发布命令mvn clean deploy -DskipTests这里让我解释一下-DskipTests的用意。中央仓库并不要求你跳过测试但发布流程中测试增加耗时而且如果你的测试依赖某些环境变量在发布机器上还可能失败导致整个发布中断。我一般发布前先在本地完整跑一遍测试真正执行 deploy 时就跳过组件质量靠发布前的测试保证发布动作本身追求稳定可控。执行过程中Maven 会依次执行 clean、compile、test被 skip、package、sign、deploy。签名阶段会提示输入 GPG 私钥口令如果你在 settings.xml 里通过 profile 配置了gpg.passphrase这里会直接用配置里的口令不会弹交互提示。如果弹出交互输入说明你的配置没生效检查一下 settings.xml 的 profile 是否激活。看到 BUILD SUCCESS 后组件已经上传到远端了。这里我踩过坑一开始以为上传完就结束了其实还差最关键的两步。如果是老通道 OSSRH现在要登录 OSSRH 的网页端在 Staging Repositories 里找到你刚上传的仓库。选择它点击 Close 按钮。Close 的意思是冻结这个 staging 仓库并触发中央仓库的规则校验。校验包括是否含有 source jar、javadoc jar、GPG 签名文件、pom 元数据是否合法。校验一旦失败页面会列出具体错误你得根据错误修复后重新上传和执行 Close。校验通过后再点击 Release组件才会真正同步到中央仓库。新通道 Central Portal 简化了很多你在部署后回到 central.sonatype.com 的发布列表能看到组件状态从 Validating 到 Publishing 再到 Published基本上自动推进不需要手动 Close 和 Release。系统校验失败时也会显示错误信息修复后重新部署即可。关于版本号这里有一个非常关键的概念SNAPSHOT 版本和 Release 版本。带-SNAPSHOT后缀的版本默认发布到快照仓库它不会被同步到中央仓库的正式索引别人也无法通过正式 release 坐标稳定引用。要发布正式版本版本号必须是干净的比如1.0.0、2.3.1不能带-SNAPSHOT。我见过有人用mvn deploy发布1.0.0-SNAPSHOT然后在 Staging 里发现找不到还以为上传失败其实是版本号本身就不对。3.3 发布后如何验证别急着庆祝先检查三件事发布完成后直接去 search.maven.org 搜索你的坐标八成会搜不到。这是因为中央仓库的搜索引擎索引有延迟组件同步到存储节点后建立搜索索引通常需要几分钟到几小时。这时候不要以为自己发布失败先做三层验证。第一层查 Central Portal 或 OSSRH 上的状态。老通道应该能看到 Staging 仓库状态是 Released新通道能看到 Published。第二层直接请求制品库的路径看文件是否真实存在。中央仓库文件地址格式是固定的比如https://repo1.maven.org/maven2/io/github/yourname/your-component/1.0.0/your-component-1.0.0.jar如果能在浏览器直接访问下载说明制品确实已经同步到中央仓库了。第三层是本地依赖验证。在一个全新的空目录里创建测试项目引入你的坐标执行mvn dependency:get -Dartifactio.github.yourname:your-component:1.0.0注意测试项目不要复用你本地的 Maven 仓库缓存。有条件的话可以在 CI 环境或者另一台机器上做一次干净拉取确保没有从本地仓库误读到旧包。这层验证很有价值。我遇到过一种情况自己电脑上测试一切正常后来发现是因为之前mvn install把包装进了本地仓库Maven 优先从本地仓库获取了根本没有触发远端下载。用干净环境验证之后才是真正确认发布成功。4. 发布过程中最常见的坑和排查方法4.1 认证与权限类报错401、403 到底哪里配错了发布过程中遇见的第一类高频问题就是身份认证报错。典型表现是 deploy 执行到最后Maven 提示Return code is: 401, ReasonPhrase: Unauthorized.这类问题的排查思路其实很清晰。401 通常就是用户名密码不对或者 Maven 根本没有找到对应的 server 配置。先检查 settings.xml 里的server id是否和 pom.xml 中 distributionManagement 里 repository 的 id 完全一致。这个 id 匹配是 Maven 的机制pom 里声明部署到哪个仓库Maven 到 settings.xml 里找相同 id 的认证信息。两边不一致Maven 就没有可用的认证信息直接一个 401 甩过来。密码方面如果走老通道用的是 JIRA 账号密码有些人会把 JIRA 密码和登录 Central Portal 的密码混为一谈导致认证失败。新通道的 token 一般是一串长字符串复制的时候注意别把前后空格也带进去了。我遇到过最隐蔽的问题密码里含有或这类 XML 特殊字符直接写进 settings.xml 导致 XML 解析错误或配置被截断后来用 XML 转义或者把特殊字段放到环境变量里引用才解决。403 的情况不太一样通常表示你连到了服务器但权限不足。最常见的原因是命名空间验证还没有通过你用io.github.yourname申请了 namespace但验证流程还没完成或者被拒绝了。这时回到 Central Portal 或工单页面看状态pending 状态就等Rejected 就检查域名所有权证明材料。4.2 签名问题gpg: no secret key 和公钥同步延迟GPG 相关的报错可以排在发布失败原因的前三名。先看一个很常见的gpg: no secret key gpg: signing failed: No secret key出现这个问题的原因很直接Maven 在执行 gpg 签名时找不到你的私钥。首先确认执行命令的当前用户是否是生成密钥的用户如果公司电脑有多个系统账户你的 GPG 密钥在另一个用户下那当然找不到。用gpg --list-secret-keys查看一下私钥是否存在注意sec行代表私钥存在如果只有pub行那只是公钥Maven 签名需要私钥。CI 环境里这个问题更典型。很多人在本地发布了成功然后把代码推给 CI 自动发布结果 CI 机器上没有私钥。正确的做法是先导出私钥再导入 CI 环境gpg --export-secret-keys 1A2B3C4D5E6F7A8B private.key gpg --batch --import private.key导入后还有一个易被忽略的问题GnuPG 2.x 版本和某些 CI 环境没有终端交互运行gpg --sign时会报Inappropriate ioctl for device因为 GPG 默认想弹出终端让用户输入口令。解决办法是确保你在签名时能提供 passphrase可以在 settings.xml 里配置或者在 CI 中设置gpg.passphrase属性。另外GPG 会锁定主目录的某个目录多进程并发签名时可能报“resource temporarily unavailable”CI 里并发构建多个模块时适当控制并发数。至于公钥同步问题前面讲过Keyserver 之间的同步不是实时的。老通道在 Close 阶段中央仓库会验证签名需要去 key server 查你的公钥。如果刚刚发送公钥查不到是很正常的。我的排查方式先用公钥服务器网页端查询看你的密钥 ID 是否已经被收录如果收录了再去新通道或 staging 校验如果没收录换一个 keyserver 重新--send-keys然后再等一段时间。4.3 校验失败缺 sources.jar、javadoc.jar还有 license 的坑Central 的规则校验是出了名的严格。老通道的 Close 阶段如果失败页面上会列出具体错误。排第一的错误基本是Missing: io.github.yourname:your-component:1.0.0 - 缺少 sources.jar - 缺少 javadoc.jar这种情况往往是 pom 里的 source 插件、javadoc 插件没配置或者配置了但没有正确绑定到生命周期。注意maven-source-plugin的 goal 最好用jar-no-fork不要用jar后者在构建某些模块时会因为生命周期 fork 问题导致重复执行或者不执行。javadoc 插件在 Java 17 以上环境有另外一个经典问题javadoc 生成过程中遇到文档语法警告会直接失败报一堆error: unexpected text。解决办法是在插件的configuration里加doclintnone/doclint关闭严格文档检查。还有一种我花了不少时间才定位的问题pom 里写的 license 名称和 URL 与实际使用的许可证不匹配。中央仓库的校验器会检查 license URL 是否指向一个可访问的许可证文本页面填一个https://www.apache.org/licenses/LICENSE-2.0.txt这样真实的地址不要随手填一个空链接。developers 里的 email 格式也必须合法填写xxx这种字符串是无法通过校验的。另外如果你发布的是多模块项目需要在每个子模块里也配置好这些插件或者用 parent pom 统一管理。不然可能会出现主模块全过了某个子模块缺少源码包导致整个 staging 仓库校验失败。这时错误列表会定位到具体模块你去看对应模块的 effective-pom检查插件是否被继承到。4.4 发布成功但中央仓库搜不到索引延迟还是版本号写错这是新手最容易自我怀疑的时刻日志显示 BUILD SUCCESSCentral Portal 状态也是 Published但 search.maven.org 上怎么搜都搜不到。其实大部分原因前面说过就是搜索引擎索引的延迟。补充一个排查技巧如果dependency:get已经能拉到 jar那就是制品确实在仓库里了搜索不到只是索引还没更新。等几个小时再看就行不用重复发布重复发布同一个版本只会徒增烦恼。反过来如果dependency:get报 404那就是制品根本没进仓库这时候要回到状态页面看是否已经正式 Released还是停留在校验失败的边缘。另外检查一下你是不是真的把版本号发布成了正式版而不是 SNAPSHOT。有些人标签写1.0.0但 pom 里 version 写的是1.0.0-SNAPSHOTdeploy 时会进入 snapshot 仓库看着也像发布成功但正式依赖永远拉不到。这种事发生了不止一次检查起来却很简单直接打开仓库文件列表页面看目录名和文件名里的版本号。以下是常见报错与排查的速查表报错信息本质原因建议处理方式401 Unauthorized找不到匹配的认证信息或密码错检查 server id 是否一致、重新生成 token403 Forbidden命名空间验证未完成回到 Central Portal 查看 namespace 状态gpg: no secret key没有私钥或私钥不在当前用户导入私钥使用 gpg --list-secret-keys 确认Missing sources.jar/javadoc.jar构建阶段未生成附件配置 source/javadoc 插件javadoc 加 doclintMissing license / scmpom 元数据缺失补全 licenses、developers、scm 内容FATAL: Not a valid release打包了 Spring Boot fat jar调整构建配置保留普通 jar 再发布5. 一次发布后的经验复盘几个我后来一直在用的习惯走过一遍完整流程后我想分享几个从第二次发布开始就一直遵循的习惯。第一个习惯第一次正式发布前先用一个 dummy 组件把全流程走通。这个 dummy 组件不需要任何真实业务代码就是一个带 main 方法的空 jargroupId 用你申请好的 namespace版本号0.0.1。整个流程走下来确认 GPG、staging、release、索引刷新都正常再回过头发布真正的组件。这样能把签名、校验这些不可控因素提前暴露掉不至于在业务组件的发布窗口期手忙脚乱。第二个习惯把本地手动发布做成 CI 自动发布。发布流程走通后手动重复执行的收益很低还很容易因为某一步忘了点 Release 导致组件永远卡在 staging 仓库。我现在的方式是代码 push 并打上v*格式的 tag 后CI 里自动触发mvn clean deploy并且在 CI 环境里配置好 GPG 私钥和 Sonatype 凭据。这样每次发布都是可重复、可追溯的发布状态也能在 CI 日志里看到。第三个习惯是发布后立刻更新 README把坐标示例放进去并写好版本变更摘要。很多人以为发布的终点是 search.maven.org 能看到组件其实组件被引用了使用者的体验才刚开始。README 里给一个最简依赖示例帮使用者跳过配置学习的成本比任何宣传都有效。我也习惯在 CHANGELOG 里记录每个版本的变化这样即使某次发布不小心引入了破坏性变更使用者也能快速定位并在升级前做好评估。组件发布的整个流程本质上是一次面向公共生态的交付。你不仅是在上传一个 jar更是在建立使用者对这个坐标的信任。把元数据写清楚把签名做好把发布流程自动化后续维护就会变成发布新版本时一个很顺滑的动作。希望这篇文章能帮你少走一些我走过的弯路。
返回列表