news 2026/9/28 2:59:25

release-please 的 Java Yoshi 发布策略:注解标记、BOM 依赖推理与 LTS 版本方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
release-please 的 Java Yoshi 发布策略:注解标记、BOM 依赖推理与 LTS 版本方案
  • 开发工具
  • CI/CD
  • DevOps

【免费下载链接】release-please

generate release PRs based on the conventionalcommits.org spec

项目地址:https://gitcode.com/gh_mirrors/re/release-please
点击查看免费下载

本篇技术指南围绕 release-please 仓库中的 docs/java-releases.md 展开,深入讲解面向 Google Cloud Java 客户端库团队设计的java-yoshi/java-yoshi-mono-repo策略族:如何通过versions.txt清单统一管理制品版本,如何使用内联与块状注解驱动代码中的版本替换,以及 Java BOM 与 Java LTS 两套特殊场景下的版本决策逻辑。读完本文,你将掌握这些策略的配置入口、版本占位符的书写规范、deps:提交到 BOM 版本提升的映射规则,以及 LTS 分支-sp.N/-lts.N版本演进与SNAPSHOT快照的完整机制。

背景:Yoshi 策略面向谁

文档开宗明义:当前实现的 Java 发布策略是专门为 Google Cloud 的 Java 客户端库团队(Yoshi)量身定制的,并非通用 Maven 项目的开箱即用方案。这一点在 src/strategies/java-yoshi.ts 中得到印证:JavaYoshi直接继承自通用 Java 策略基类Java,其核心假设是仓库中存在versions.txt清单文件。

因此,若你的仓库是典型的单体 Maven 项目,官方建议优先使用maven策略(递归更新所有pom.xml,见 docs/java.md);只有当仓库组织方式与 Google Cloud Java 库一致(多制品、单一versions.txt主清单)时,才选择 Yoshi 策略族。策略的注册入口分别在 src/factory.ts(java-yoshi、java-yoshi-mono-repo)与 src/factories/versioning-strategy-factory.ts(service-pack)。

版本管理的主清单:versions.txt

Yoshi 策略依赖一个名为versions.txt的清单文件来跟踪所有制品的版本。其行格式为module:released-version:current-version,真实样例见 test/fixtures/strategies/java-yoshi/versions.txt:

# Format: # module:released-version:current-version google-cloud-trace:0.108.0-beta:0.108.1-beta-SNAPSHOT grpc-google-cloud-trace-v1:0.73.0:0.73.1-SNAPSHOT
  • 第一列是制品(artifact)名称,如grpc-google-cloud-trace-v1;
  • 第二列是released版本,即该分支上最近一次正式发布的版本;
  • 第三列是current版本,即 HEAD 上当前的版本(通常带-SNAPSHOT后缀)。

解析与写回逻辑

VersionsManifestupdater(src/updaters/java/versions-manifest.ts)实现了三个关键静态方法:

  • parseVersions:按^([\w\-_]+):([^:]+):([^:]+)逐行解析,将每行第一列映射为Version(取第二列);
  • updateSingleVersion:写回时,若新版本含SNAPSHOT,仅更新current列(module:released:current),否则将两列都更新为同一正式版本(module:version:version);
  • needsSnapshot:若没有任何一行的current版本带-SNAPSHOT后缀,则返回true,触发快照发布。

文件缺失时,JavaYoshi.getVersionsContent会抛出MissingRequiredFileError(src/strategies/java-yoshi.ts),可见versions.txt是该策略的硬性前置条件。

用注解标记需要替换版本的代码行

有了主清单,接下来要解决"仓库中哪些位置需要被替换"的问题。Yoshi 策略采用在代码行末尾追加特殊注解的方式声明版本占位,由JavaUpdateupdater(src/updaters/java/java-update.ts)负责扫描与替换。

内联注解(Inline Annotation)

在希望被替换的 semver 版本所在行的行尾注释中追加:

{x-version-update:<artifact-name>:current} {x-version-update:<artifact-name>:released}
  • current:使用versions.txt中该制品的当前(HEAD)版本;
  • released:使用该制品在当前分支上最近一次已发布的版本。

对应正则INLINE_UPDATE_REGEX = /{x-version-update:([\w\-_]+):(current|released)}/,匹配后用VERSION_REGEX(\d+\.\d+\.\d+(-\w+(\.\d+)?)?(-SNAPSHOT)?)定位行内版本号并替换为新值(src/updaters/java/java-update.ts)。

一个典型用法是把版本写进代码注释中并随时保持同步:

// 每次发布时,release-please 会把 1.2.2 替换为最新版本 String version = "1.2.2"; // {x-version-update:google-cloud-trace:current}

块状注解(Block Annotation)

当需要替换的版本分散在多行(或单行内容过长不便内联)时,可用成对标记圈定区域:

{x-version-update-start:<artifact-name>:<current|released>} ...需要替换版本的多行代码... {x-version-update-end}

JavaUpdate.updateContent的状态机逻辑(src/updaters/java/java-update.ts)在读到BLOCK_START_REGEX后进入"块内"模式,将块内每一行命中VERSION_REGEX的部分替换为指定制品的目标版本,直到遇见BLOCK_END_REGEX才退出。实测用例可见 test/updaters/fixtures/java-auth-readme.md,其中 README 使用[//]: #形式的 Markdown 注释包裹{x-version-update-start:...}/{x-version-update-end}标记来维护多组版本号。

快照发布时的行为差异

注意updateContent中的一个关键细节:当isSnapshot为真时,只处理标注为current的注解((!this.isSnapshot || match[2] === 'current'))。原因在于快照 PR 只把 HEAD 推向新的-SNAPSHOT版本,不应触碰代表"上次正式发布"的released标记。

Java BOM:从依赖提交推断 BOM 版本提升

文档中的 "Java Bom" 一节描述的是Bill of Materials(物料清单)制品——一类特殊的pom.xml项目,它本身不含业务代码,只声明一组互相兼容的依赖版本。

在该策略下,release-please 会逐个检查仓库中的deps:提交(依赖更新提交),并从依赖更新的语义化版本提升类型反推 BOM 制品自身的版本提升类型:

例如,某个依赖发生 major 版本提升,则 BOM 制品的版本也应随之进行对应的 major 提升。

换句话说,BOM 的版本号是其所辖依赖"最大公约数"的体现:依赖整体发生破坏性升级时,BOM 必须同步 breaking bump,否则消费者按旧 BOM 锁定依赖会出现不兼容组合。这也是为什么 BOM 项目中CHANGELOG_SECTIONS(src/strategies/java.ts)专门为deps类型提交配置了 "Dependencies" 章节——依赖变化在 Java 版本决策中占据独立而重要的位置。

Java LTS:service-pack 版本方案

文档中的 "Java LTS" 是 Yoshi 策略族里最特殊的一类版本方案(versioning strategy):它不遵循常规的 semver 递增,而是面向LTS(长期支持)分支设计。

版本演进规则

假设 LTS 分支是从主线的1.2.3切出,则后续版本依次为:

1.2.3 ← LTS 分支从主线切出的基线 1.2.3-sp.1 ← 第一个 service pack 1.2.3-lts.2 ← 第二个(LTS 后续发布)

即:版本号主体(1.2.3)保持不变,只递增-sp.N/-lts.N后缀序号。实现位于 src/versioning-strategies/service-pack.ts:

  • ServicePackVersionUpdate.bump用SERVICE_PACK_PATTERN = /sp\.(\d+)/匹配预发布后缀,若已存在sp.N则递增为sp.N+1,否则从sp.1起步(src/versioning-strategies/service-pack.ts);
  • ServicePackVersioningStrategy覆盖determineReleaseType,对任何提交都返回该VersionUpdater,从而将整个 LTS 分支的版本决策强制收敛到 service pack 模式。

该策略在 src/factory.ts 中被预置为 LTS 分支的默认版本策略,在配置中通过versioning: "service-pack"或对应 factory 入口启用(src/factories/versioning-strategy-factory.ts)。

lts-snapshot:sp 之后的 SNAPSHOT

文档特别强调:LTS 发布使用一种特殊的"lts-snapshot" bump。以1.2.3-sp.1为例,其后的快照版本将是:

1.2.3-sp.2-SNAPSHOT

即快照不是简单追加-SNAPSHOT,而是先把 service pack 序号推进到下一个(sp.1→sp.2),再挂上-SNAPSHOT后缀。这与通用 Java 策略中JavaAddSnapshot(src/versioning-strategies/java-add-snapshot.ts)的行为一致:先用一个fix: fake fix假提交驱动一次 patch 级别 bump,再在结果上追加-SNAPSHOT后缀(保留已有 preRelease 时拼接为preRelease-SNAPSHOT)。因此1.2.3-sp.1经 fake commit 提升为1.2.3-sp.2,最终得到1.2.3-sp.2-SNAPSHOT。

策略族全景:java-yoshi 与 java-yoshi-mono-repo 的差异

虽然关联文档聚焦于版本管理机制,了解策略族全景有助于正确选型。两个策略共享同一套注解/清单体系,差异在于更新范围:

  • JavaYoshi(src/strategies/java-yoshi.ts):更新versions.txt,并递归查找目标路径下的pom.xml、build.gradle、dependencies.properties及extra-files中配置的文件,全部套用JavaUpdate;
  • JavaYoshiMonoRepo(src/strategies/java-yoshi-mono-repo.ts):面向多制品 monorepo,额外处理README.md、Version.java、librarian.yaml,并在存在根changelog.json时按子目录拆分提交、生成机器可读的ChangelogJson条目(依赖各目录的.repo-metadata.json中的distribution_name)。

两者都实现了"零提交也强制触发 SNAPSHOT 发布"的postProcessCommits:当提交列表为空时注入一个fake类型假提交(src/strategies/java-yoshi.ts),确保合并正式发布后立即产生快照 PR。

1.0.0 晋升(promotion)

两个策略的updateVersionsMap都内置了晋升逻辑:当检测到RELEASE AS: 1.0.0提交注记时(isPromotionCommit,见 src/strategies/java-yoshi.ts),所有"稳定制品"(名称不以-vN[-alpha|beta|rc]结尾,判定见isStableArtifact)直接设为1.0.0,而带 alpha/beta 后缀的制品仍按常规策略 bump。这解释了 Google Java 库常见的"GA 发布"流程:一条release-as: 1.0.0的提交即可把整套稳定制品晋升为 1.0.0。

配置速查与实践要点

在 release-please 配置中启用

在release-please-config.json中,为 Java 库仓库配置策略与版本方案:

{ "packages": { ".": { "release-type": "java-yoshi", "extra-files": [ "README.md", "src/main/java/com/example/Version.java" ] } }, "plugins": [] }
  • release-type:可选java-yoshi(单仓库)或java-yoshi-mono-repo(多制品 monorepo);
  • extra-files:声明除自动发现的pom.xml/build.gradle/dependencies.properties之外、需要用JavaUpdate注解机制更新的文件;
  • LTS 分支场景,将versioning设置为service-pack。

落地清单(checklist)

  1. 仓库根目录必须存在versions.txt(module:released:current格式,缺失会抛MissingRequiredFileError);
  2. 在每个需要同步版本的代码行/代码块上正确书写x-version-update内联或块状注解,制品名须与versions.txt第一列完全一致;
  3. 需要随正式发布推进的版本标current,需要保持"上次已发布版本"语义的标released;
  4. 合并正式发布 PR 后,release-please 会自动创建携带autorelease: snapshot标签的 SNAPSHOT PR(见 docs/java.md 中关于快照 PR 的说明),将versions.txt与注解位置推进到下一个-SNAPSHOT版本;
  5. BOM 仓库中依赖的 breaking change 会传导为 BOM 制品的 major bump;LTS 分支请使用service-pack版本方案并接受-sp.N/-lts.N演进规则。

已知边界

  • Yoshi 策略是 Google Cloud Java 库专用方案,强依赖versions.txt与注解约定;通用 Maven 单体项目请改用maven策略(自动更新所有pom.xml的/project/version,子模块缺省版本时回退更新/project/parent/version,见 docs/java.md 与 src/updaters/java/pom-xml.ts);
  • released注解在快照 PR 中不会被更新(isSnapshot时仅处理current),请勿将需要随快照推进的版本标为released;
  • 该策略族的设计与实现细节可继续阅读 src/updaters/java/versions-manifest.ts、src/updaters/java/java-update.ts 及对应测试 test/strategies/java-yoshi.ts 深入验证。
  • 开发工具
  • CI/CD
  • DevOps

【免费下载链接】release-please

generate release PRs based on the conventionalcommits.org spec

项目地址:https://gitcode.com/gh_mirrors/re/release-please
点击查看免费下载

相关推荐

上一篇:BadgerDB终极指南:高性能Go语言键值数据库的完整教程
下一篇:终极Arachni性能优化指南:7个技巧让Web安全扫描速度提升300%

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 2:52:10

异次元发卡网插件化架构与强制登录实战指南

简介&#xff1a;这是一套基于原生PHP开发的异次元发卡网完整源码&#xff0c;面向中小型数字商品经营者、独立开发者及二次开发需求者&#xff0c;解决在线虚拟商品&#xff08;如账号、卡密、API服务&#xff09;快速上架、安全交付与多渠道收款等核心问题。资源包共2000个文…

作者头像 李华
网站建设 2026/9/28 2:49:53

Woodpecker Workflow 语法完全指南:steps、条件执行与依赖编排实战

CI/CDDevOps 【免费下载链接】woodpecker Woodpecker is a simple, yet powerful CI/CD engine with great extensibility. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/wo/woodpecker 点击查看 免费下载 本篇指南以 Woodpecker CI/CD 引擎的 workflow 配置文件语法…

作者头像 李华