ARTICLE DETAIL

资讯详情

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

Java组件发布到Maven中央仓库完整实战指南

Java组件发布到Maven中央仓库完整实战指南 Maven 中央仓库用 Java 的人几乎每天都在跟它打交道。你项目里依赖的每一个 jar 包Spring Boot、MyBatis、Hutool最终都能在 Maven 中央仓库里找到对应文件反过来想如果你自己封装了一个通用组件也希望别人通过一行dependency直接引入那你迟早要面对同一个问题怎么把它发布到 Maven 中央仓库。我最早接触这套发布流程时以为把 jar 传上去就完事结果被 GPG 签名、命名空间验证、POM 合法性校验这些概念轮流教育了一把。实际上这一整套门槛都是为了发布物的可靠性和可追踪性而设计的每个环节都有它存在的道理。这篇指南就是我实测过很多遍之后的完整路径整理从注册账号到组件真正能被全世界开发者用依赖语句拉下来一次讲清楚。适合谁看如果你在做开源组件、在公司里沉淀公共 jar 包或者单纯想搞懂 Maven 依赖背后的流通机制这篇文章都适用。下面先从最核心的三个概念开始。1. 发布前的核心认知账号、坐标与签名1.1 Maven 中央仓库到底在解决什么问题Maven 是一个构建工具但真正让整个 Java 生态跑起来的是它背后的仓库体系。所谓仓库本质上就是一堆 jar 包、pom 文件、校验和文件、签名文件按固定目录结构存放的地方。Maven 构建时按依赖坐标去仓库里下载把下载到的 jar 放到本地~/.m2/repository里复用。中央仓库就是这套体系里最权威、最上游的公共仓库。它的核心价值不是能下载而是可信。你从中央仓库拿到的 jar 都有校验和和签名理论上可以验证文件是否被篡改过。正因为有了这层保障全球开发者才敢默认相信别人的依赖。你要发布组件实际上就是把自己的产物挂到这个可信体系里接受同样的校验规则。这里顺便说一句和私有 Nexus 仓库的区别。公司内部用 Nexus 传包不需要 GPG 签名也不需要验证命名空间因为使用者是自己人信任关系靠内网和账号体系建立。但中央仓库面向全世界它不信任你这个人只信任一套公开可验证的规则。所以你在内网几分钟搞定的事到中央仓库就得按规矩一步步来。1.2 你得先有一个被认可的坐标Maven 坐标由三部分组成groupId:artifactId:version。groupId一般对应组织或个人的命名空间artifactId是组件名version是版本号。比如 Hutool 的坐标就是cn.hutool:hutool-all:5.8.25其中cn.hutool就对应它的域名命名空间。中央仓库对groupId有验证要求不是随便写一个就能发布。常见的合规格式有两种基于自有域名比如com.example.component前提是你真的拥有example.com这个域名并能通过 DNS 记录证明基于 GitHub 账号的io.github.用户名格式比如io.github.zhangsan前提是你得拥有对应的 GitHub 账号并能按要求建一个公开仓库。artifactId相对自由用一个你能长期维护、不容易和现有组件撞名的名字即可version推荐语义化版本比如1.0.0、2.3.1。发布成功之后任何人都能通过下面的方式引用你的组件dependency groupIdio.github.zhangsan/groupId artifactIdmy-component/artifactId version1.0.0/version /dependency这个坐标一旦发布就会像所有主流依赖一样被全球的 Maven 项目直接享用。所以第一步不是写代码而是先把命名空间这个门牌号定下来。1.3 为什么一定要 GPG 签名发布到 Maven 中央仓库的每个文件都必须附带一个.asc后缀的 PGP 签名文件。GPG 是一种非对称加密工具你用私钥对文件签名别人用你的公钥验证签名是否有效。中央仓库要求这个环节核心目的是防篡改和确认发布者身份。理解起来其实很生活化你在快递单上盖了私章收件人拿着你的印鉴样本来比对确认包裹确实是你发出的、中途没被人拆开过。Git 提交的 GPG 签名、软件发布时提供的 SHA256 校验本质都是同一件事的变体。早期发布必须要到 Sonatype 的工单系统提交申请等管理员人工审核并开通权限流程很重。现在官方已经把入口收敛到了 Central Portal注册后自助验证命名空间、上传公钥指纹就能发布。不过旧教程里很多概念在今天是通用的比如 GPG 签名、POM 校验要求这些都没有变。下面进入实际准备阶段。2. 发布前的环境准备与账号配置2.1 注册 Central Portal 并生成用户令牌新流程的主入口是 Central Portal地址是central.sonatype.com不需要再去老旧的 OSSRH 页面提交工单。打开后用邮箱注册或者直接用 GitHub 账号登录。登录后的第一件事不是急着写代码而是生成用户令牌User Token。这个令牌是一对随机生成的用户名和密码专门给 Maven 构建时的 settings.xml 配置使用不是你的账号登录密码。生成位置一般在账号设置或个人资料相关的菜单里portal 会明确给出 token 的 username 和 password把它复制保存好。为什么要用令牌而不是账号密码因为发布组件通常是自动化脚本或者 CI 在跑直接用登录密码既不安全也不好撤销。令牌可以单独重置泄露了也不会影响账号本身的登录安全。这一步对应很多教程里说settings.xml 里的用户名密码哪里来的答案就是这里来的。2.2 验证命名空间的两种方式有了账号接下来要在 Portal 里录入你要使用的命名空间也就是groupId并完成验证。Portal 通常提供两种验证方式按你的groupId格式来选择。第一种是 DNS TXT 记录验证适合com.xxx、org.xxx这种基于自有域名的命名空间。Portal 会生成一条 TXT 记录的内容你在域名服务商的管理后台添加对应解析比如给二级域或根域名加一条TXT记录内容填 Portal 给的随机校验字符串。DNS 生效后回到 Portal 点验证系统会去查这条记录匹配上了命名空间就算归你了。第二种是 GitHub 仓库验证适合io.github.你的用户名这种格式。Portal 会要求用一个公开命名的仓库配合校验通常是建一个与命名空间同名的公开仓库然后在 Portal 指定的位置填入校验内容或创建指定文件。验证原理很简单io.github.zhangsan这个命名空间只有 GitHub 用户zhangsan理论上才有权创建对应仓库别人抢注不了这样就形成了所有权证明。验证完成后这个命名空间下发布的组件才会被中央仓库接受。常见的坑是随便编一个com.公司名.xxx当 groupId结果自己没有对应域名验证怎么都过不去。2.3 生成并上传 GPG 密钥GPG 密钥是发布流程里最容易卡住新人的环节但步骤其实固定。先在本地生成一对密钥gpg --full-generate-key交互过程中选择默认的 RSA 算法密钥长度建议选 4096 位有效期我建议不设过期时间。生成时要填写姓名和邮箱这个邮箱最好和你在 Central Portal 注册时使用的邮箱一致后续对得上号。完成后查看密钥列表找到你的密钥 IDgpg --list-keys输出里类似[SC]后面那串十六进制指纹取后 16 位或全指纹都行。接着把公钥上传到公共密钥服务器让中央仓库验证签名时能找到公钥gpg --keyserver keyserver.ubuntu.com --send-keys 你的密钥ID同时把公钥的文本内容导出出来备用Portal 的账号设置里一般会要求填写公钥指纹或粘贴公钥内容gpg --armor --export 你的密钥ID这一步对应很多人问的为什么发布时说找不到公钥签名是用你的私钥做的但中央仓库验证时要去公钥服务器上找对应公钥你不上传它就验证不了。整个发布链路里私钥留在自己手里公钥公开这一对关系贯穿始终。2.4 settings.xml 的正确姿势Maven 的全局配置文件在~/.m2/settings.xml发布相关的认证和签名参数都放这里。下面是一个最小可用的配置模板settings xmlnshttp://maven.apache.org/SETTINGS/1.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd servers server idcentral/id username这里填User Token的用户名/username password这里填User Token的密码/password /server /servers profiles profile idsonatype/id properties gpg.keyname这里填密钥ID/gpg.keyname gpg.passphrase这里填密钥的passphrase/gpg.passphrase /properties /profile /profiles activeProfiles activeProfilesonatype/activeProfile /activeProfiles /settingsserver里的id必须和后面 POM 里发布仓库的id严格一致否则 Maven 匹配不上认证信息会直接报 401。gpg.keyname告诉 Maven 用哪把私钥签名gpg.passphrase是生成密钥时设置的口令Maven 在非交互环境下想自动完成签名就得靠它。这里必须强调一个安全习惯不要把真实 token 和 passphrase 提交到 Git 仓库。本地开发可以放 settings.xmlCI 环境应该用环境变量占位符比如${env.CENTRAL_USERNAME}。另外gpg.passphrase这种配置放进版本库等同于把私钥密码告诉所有人踩过一次坑就长记性了。顺带提一下国内环境常见的诉求依赖下载慢可以配阿里云等公共 Maven 镜像来加速这没问题但千万不要在 settings.xml 里把mirrorOf配成*。我见过有项目因为全量镜像配置导致执行mvn deploy时把产物传到了镜像源而不是中央仓库。稳妥做法是日常下载用一份带镜像的 settings发布时单独用-s publish-settings.xml指定一份不含镜像的配置文件。3. POM 配置与构建插件编排3.1 一份能通过校验的 POM 必须包含什么POM 是 Maven 项目的说明书中央仓库对这份说明书有硬性校验。project 的基础坐标groupId、artifactId、version谁都会写但很多第一次发布的人会忽略下面这些必须出现的元数据name、description、url、licenses、developers、scm。我整理了一份可以直接套用的 POM 骨架你只需要把里面的值替换成自己的信息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 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdio.github.zhangsan/groupId artifactIdmy-component/artifactId version1.0.0/version packagingjar/packaging namemy-component/name descriptionA concise and clear description of my component for Maven Central./description urlhttps://github.com/zhangsan/my-component/url licenses license nameApache License, Version 2.0/name urlhttps://www.apache.org/licenses/LICENSE-2.0.txt/url distributionrepo/distribution /license /licenses developers developer idzhangsan/id nameZhang San/name emailzhangsanexample.com/email roles roleDeveloper/role /roles timezoneAsia/Shanghai/timezone /developer /developers scm connectionscm:git:https://github.com/zhangsan/my-component.git/connection developerConnectionscm:git:ssh://gitgithub.com/zhangsan/my-component.git/developerConnection urlhttps://github.com/zhangsan/my-component/url /scm properties project.build.sourceEncodingUTF-8/project.build.sourceEncoding maven.compiler.release17/maven.compiler.release /properties /project这里有几个容易忽略的细节description不要写得太短中央仓库校验要求描述性文本足够明确只写一两个词会直接被拒url和scm不要用example.com占位licenses用 SPDX 里的标准许可证名称更规范。这些字段不是摆设它们会直接展示在 Maven 中央仓库的组件详情页里是使用者判断能不能信你的第一印象。3.2 sources 与 javadoc 插件配置中央仓库有一条硬性要求除了主 jar还必须有-sources.jar和-javadoc.jar。这背后其实是在为使用者着想——IDE 里点开依赖方法能直接跳源码、看注释靠的就是源码包和文档包。没有这两个附件的组件发布校验会直接失败。在build节点里配置对应的 Maven 插件build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-source-plugin/artifactId version3.3.0/version executions execution idattach-sources/id goals goaljar-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 goals goaljar/goal /goals /execution /executions configuration doclintnone/doclint /configuration /plugin /plugins /buildJDK 17 以上对 javadoc 的注释规范校验很严格代码里注释格式稍微不规范javadoc:jar就会报错中断构建。加了doclintnone/doclint之后可以跳过这些审计只保证文档能生成。如果你的项目用很旧的 JDK 或者注释风格比较随意这个配置几乎是必备的。3.3 签名与发布插件怎么配合签名插件和发布插件是发布链路里真正干活的角色。签名用maven-gpg-plugin发布到中央仓库推荐用 Sonatype 官方维护的central-publishing-maven-plugin这是新 Portal 流程下的推荐方式不再需要老式 Nginx Staging 那套繁琐的 staging 仓库 close/release 操作。配置形式如下plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-gpg-plugin/artifactId version3.2.2/version executions execution idsign-artifacts/id phaseverify/phase goals goalsign/goal /goals configuration gpgArguments arg--pinentry-mode/arg argloopback/arg /gpgArguments /configuration /execution /executions /plugin plugin groupIdorg.sonatype.central/groupId artifactIdcentral-publishing-maven-plugin/artifactId version0.5.0/version extensionstrue/extensions configuration publishingTypeAUTO/publishingType /configuration /plugin--pinentry-mode loopback这个参数很关键。GPG 在普通终端里会弹图形窗口或命令行窗口让你输 passphrase但在 CI 这种无交互环境里根本弹不出来构建就挂在那里。加了 loopback 之后Maven 会直接读取 settings.xml 里的gpg.passphrase完成签名。没有这个参数你本地签得好好的一上 CI 就失败基本都是这个原因。central-publishing-maven-plugin设置了extensionstrue/extensions之后会在构建时接管部署环节自动把产物送到 Central Portal旧式的distributionManagement地址可以省略。publishingType有两种AUTO表示产物上传完成后 portal 自动发布USER_MANAGED表示上传到 staging 区后需要你到 Portal 界面手动点发布按钮。个人建议选AUTO少一步人工操作。3.4 版本号与 SNAPSHOT 的处理版本号规则看起来基础但很多人栽在这里。中央仓库发布的是正式版本版本号不能带-SNAPSHOT后缀。SNAPSHOT表示的是开发快照Maven 仓库对它的处理是每次构建覆盖更新随时可变。正式发布版本则要求不可变同一个版本号发布一次之后就不应该再动。如果项目还在快速迭代阶段你可以把版本号写成1.0.0-SNAPSHOT上传到中央仓库的快照仓库snapshotRepository供内部或早期用户试用。发布正式版时去掉-SNAPSHOT比如1.0.0、1.1.0传到 releases 仓库。语义化版本号建议遵循主版本.次版本.修订版的约定不兼容的 API 改动升主版本向后兼容的新功能升次版本bug 修复和细微调整升修订版。发布前给 Git 打个 tag比如v1.0.0让版本号、POM 里的 version 和 tag 三者对应起来这是团队协作里非常必要的纪律。4. 首次发布全流程实操4.1 本地先过一遍完整构建发布前先在本地把完整构建跑一遍不要一上来就 deploy。先确认代码能编译、测试能过、附件能正常生成mvn clean verify -DskipTests注意这里的 lifecycle 是verify它会在install之前把source、javadoc、gpg这些插件绑定的目标依次执行掉。构建成功后去target目录看一眼应该能看到这几个文件my-component-1.0.0.jarmy-component-1.0.0-sources.jarmy-component-1.0.0-javadoc.jar每个 jar 对应的.asc签名文件如果发现缺了某个文件不要急着继续。缺 sources 或 javadoc一定是对应的插件没有绑定到正确的生命周期 phase缺.asc说明 gpg 插件没生效或签名失败。本地验证的目标就是把这些低级问题全部暴露出来而不是留到发布时被远程仓库拒绝。另外建议在正式发布前把代码推送到 Git 仓库并且打好 tag。很多自动构建脚本默认从 Git tag 触发就算这次手动发布不需要为 CI 铺路也值得。4.2 执行 deploy 发布本地构建验证通过后执行发布命令mvn clean deploy -DskipTests这行命令会把整个构建流程走完最后调用发布插件把产物上传到 Central Portal 的部署区。执行过程中留意控制台输出正常情况下会看到类似下面这样的日志片段[INFO] Uploading to central: https://central.sonatype.com/repository/maven-releases/io/github/zhangsan/my-component/1.0.0/my-component-1.0.0.jar [INFO] Uploaded to central: ... ... [INFO] BUILD SUCCESS看到BUILD SUCCESS只是完成了上传不意味着已经对外可见。因为publishingType配的是AUTOPortal 会在上传完成后自动做校验并发布如果配的是USER_MANAGED那组件会先停留在 staging 状态等你手动发布。这里补充一个我在实际操作中很在意的点发布命令里clean一定不要省。旧的target目录里如果残留着上一次构建的产物尤其是 SNAPSHOT 版本的 class 文件很可能你改了源码但发布出去的还是老东西。clean一下成本很低收益是确定性。4.3 在 Central Portal 查看并确认发布发布构建完成后打开 Central Portal 的部署管理页面一般叫 Deployments 或 Publishing 相关菜单。你能看到刚才上传的这条部署记录状态有这几种常见情况DeployingPortal 还在处理上传内容Staged已上传并校验通过等待手动发布Published已发布正在等待同步到 Maven 中央仓库Publish Failed校验没过需要点击查看具体失败原因。如果你是AUTO模式看到Published就说明中央仓库那边已经在走同步流程。如果是USER_MANAGED模式看到Staged后需要点一下Publish按钮确认跳出的提示才真正进入发布队列。Portal 界面里往往会给出校验报告比如某个字段不合法、某个插件产物缺失。所有校验都应该在这里得到绿色通过。如果出现红色失败项排查思路和我们后面讲的常见问题模块是一致的。4.4 验证 Maven Central 同步结果状态变成Published之后还需要等待中央仓库的同步完成。同步时间一般从几分钟到一两个小时不等这和当天仓库的处理负载有关。最直接的验证方式不是去搜索页刷新而是直接访问 repo1 上的目录结构curl -I https://repo1.maven.org/maven2/io/github/zhangsan/my-component/1.0.0/返回 HTTP 200 说明文件已经落盘。也可以打开这个 URL 在浏览器里看目录列表确认 jar、sources、javadoc、pom、asc、校验和文件都在。再进一步可以在本地新建一个临时 Maven 项目pom 里加上你刚发布组件的依赖然后执行mvn dependency:get或者直接编译一下看能不能从中央仓库拉取成功。这样才算真正闭环验证。要注意的是~/.m2/repository里可能已经有本地构建的缓存验证前可以先确认 Maven 用的是远程下载的还是本地已有的避免误判。5. 常见问题与排查技巧实录5.1 认证与权限类问题发布过程中遇到最多的是鉴权失败。现象通常是401 Unauthorized或Failed to transfer file返回码在 HTTP 层就断了。最常见的原因有三类User Token 复制错了settings.xml 里的 serverid和 POM 发布仓库的id不一致环境变量占位符在 CI 里没有正确注入。排查思路是先确认 settings.xml 里server的id再确认 POM 里distributionManagement或发布插件的目标仓库id两者必须完全一致。Maven 校验的是字符串匹配差一个字符都对不上。然后是 token 本身重新到 Portal 生成一份新的把 settings.xml 里的值换掉排除 token 过期或复制遗漏的可能。5.2 签名与 GPG 类问题GPG 相关的报错信息很多整理成一条规律只要是gpg: signing failed、secret key not available、no passphrase given这类问题基本出在密钥本身或签名环境上。secret key not available最常见的原因是本机确实没有对应私钥。很多人拿着同事的公钥或者公司统一密钥在跑构建公钥只能验证签名没法做签名。用gpg --list-secret-keys确认你要用的密钥 ID 存在并且 settings.xml 里的gpg.keyname填的是这个私钥的 ID。no passphrase given则多半是 CI 环境问题。本地终端因为可以交互输 passphrase构建看起来是好的但 CI 里没有输入机会。解决办法就是我们前面配置的 loopback 模式加gpg.passphrase属性两个条件缺一不可。如果还不行可以把签名相关配置单独放到一个 profile 里避免其他 profile 干扰。5.3 构建与 POM 校验类问题中央仓库的校验器非常严格常见拒绝原因很固定我把高频问题整理成了一个速查表现象常见原因解决办法Invalid POM 中描述缺失或过短description用了一两个词写一段完整的组件功能描述Invalid POM 中许可证缺失没有配置licenses补全标准许可证信息Missing sources jarmaven-source-plugin未绑定按 3.2 节的配置补齐Missing javadoc jarmaven-javadoc-plugin未绑定或生成失败补齐插件配置加doclintnone/doclintjavadoc 生成报错JDK 17 对注释规范要求严格加 doclint 跳过配置或统一注释风格Deploy 时提示 repository 元素未指定未配置发布目标和仓库改走 central-publishing 插件或补 distributionManagement这组问题的共同特征是本地mvn package能过但远程校验失败。原因在于打包和发布是两个层面的事情package只关心能不能产出 jar中央仓库校验器还会核对附件是否齐全、POM 字段是否合规。建议把 source、javadoc、gpg、central-publishing 这些插件绑定好之后用 4.1 节的验证流程在本地提前暴露问题。5.4 发布成功后的几个注意点很多人在发布成功后就松懈了其实后面还有几条行为准则值得记住。第一正式版本发布成功后尽量不要再覆盖同一个版本号。中央仓库已经同步过的文件是公开不可撤销的即使你技术上能重新部署使用者拉到的可能是混合状态这在依赖供应链上是非常危险的行为。需要修复就发修订版比如1.0.1。第二SNAPSHOT 和正式版要严格区分仓库。把1.0.0-SNAPSHOT传到 releases 仓库会被拒把正式版传到快照仓库则会造成混乱。配置里snapshotRepository和repository各归各位。第三Portal 里的 Drop 操作只能作用于尚未完全发布的部署记录。如果状态还是Staged发现有误可以 Drop 掉重新上传一旦Published并同步完成这条路就走不通了。所以手动发布模式下点 Publish 之前务必再检查一遍版本号和附件列表。6. 进阶把发布流程交给自动化6.1 为什么值得上 CI手动发布一次不难但团队协作时就会发现每次都要有人记得带正确的 settings.xml、确认密钥、跑特定命令过程很容易出错。更重要的是手动发布不可审计——谁发的、什么时候发的、发的是哪个版本全都依赖个人自觉。把发布流程交给 CI 后每次触发都有记录失败有日志回滚有 tag整体风险会小很多。GitHub Actions 是覆盖面最广的选择原因是很多开源组件的源码就在 GitHub 上。上传组件代码打 tag 自动出发发布这个流程在社区里已经非常成熟。下面给一份可以直接改改就用的配置。6.2 一个可用的 GitHub Actions 配置在仓库根目录创建.github/workflows/publish.yml内容大致如下name: Deploy to Maven Central on: push: tags: - v* jobs: publish: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-javav4 with: distribution: temurin java-version: 17 server-id: central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} gpg-passphrase: GPG_PASSPHRASE - name: Publish run: mvn -B clean deploy -DskipTests env: MAVEN_USERNAME: ${{ secrets.CENTRAL_USERNAME }} MAVEN_PASSWORD: ${{ secrets.CENTRAL_PASSWORD }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}这里有几个操作细节要和前面的 settings.xml 对应上。setup-java里的server-id: central会自动生成一个临时 settings.xml并把CENTRAL_USERNAME和CENTRAL_PASSWORD注入成对应 server 的用户名密码。GPG 私钥通过gpg-private-key导入GPG_PASSPHRASE作为环境变量存在POM 里 gpg 插件会自动读取。对应的 Secrets 需要在 GitHub 仓库的 Settings 里配置包括CENTRAL_USERNAME、CENTRAL_PASSWORD、GPG_PRIVATE_KEY、GPG_PASSPHRASE。导出私钥用这个命令gpg --export-secret-key --armor 你的密钥ID把输出内容整体复制到 Secret 里。注意私钥导出会包含 passphrase 保护的 armor 文本和我们平时导出的公钥文本完全不同不要搞混。6.3 自动化发布的关键细节自动化发布踩过的坑我总结成几条实用经验。第一触发条件用 tag 而不是 main 分支 push。仓库每天可能有几十次提交每次提交都触发发布既浪费又危险。规定只有v*格式的 tag 才触发发布等于强制了发布前先打 tag的流程纪律。第二私钥导入和 passphrase 解耦。很多 CI 报错都是因为setup-java导入了密钥但 passphrase 没对上。gpg-passphrase参数配好后Maven 构建里还要保证 gpg 插件启用了 loopback 模式否则 CI 里照样弹不了 passphrase。第三发布失败不要直接重跑同一版本。如果 job 是因为网络超时失败的可以直接重跑如果是产物问题导致的比如 sources 缺失必须改代码重新打 tag。因为 source 和 tag 的版本版本要一致否则发布出去的包和源码对不上以后排查问题会非常痛苦。如果你平时不用 GitHubTeamCity、Jenkins、GitLab CI 的思路完全一致把密钥放密件库构建时注入环境变量只在特定分支或 tag 上触发deploy。我个人实际操作中的体会是发布到 Maven 中央仓库这件事真正难的从来不是某个单独步骤而是第一次把整个链路串起来时那种到处是必须条件的挫败感。如果你把账号令牌、命名空间、GPG 密钥、POM 元数据这四件事在动手前都准备妥当剩下的就是几个插件的配置和一条发布命令的事。最后再分享一个小技巧发布完先别急着刷新搜索页直接打开 repo1.maven.org 上的目录路径看到文件列表出现的那一刻比搜索页显示结果要早也比搜索不到是不是失败的焦虑来得踏实。
返回列表