首页
/ Halo 的 Gradle 依赖升级实践:版本目录、Versions 插件与项目级约束

Halo 的 Gradle 依赖升级实践:版本目录、Versions 插件与项目级约束

2026-09-05 17:03:43作者:郜逊炳

本文以 Halo 仓库内置的 gradle-dependency-updates 技能文档为主体,系统讲解该项目"检查过期依赖 → 判断可升级范围 → 制定升级计划 → 应用并验证"的完整工作流。读完本文,你将掌握如何基于 Gradle 版本目录(gradle/libs.versions.toml)与 Spring Boot BOM 双轨管理后端依赖、如何用 ben-manes Versions 插件安全地发现过期项,以及 Halo 中几条不可逾越的项目级约束(thymeleaf 平铺 jar、lombok 对齐、插件版本锁定)背后的原因与源码依据。

1. 依赖管理体系:版本目录 + Spring Boot BOM

Halo 的后端依赖由两套机制协同管理:

  • Gradle 版本目录gradle/libs.versions.toml,集中声明 [versions][libraries][bundles][plugins] 四类条目。从当前仓库可以看到,Lucene、Therapi Javadoc、Resilience4j 采用"版本号与库分离"的写法(如 lucene = '10.5.0'version.ref = 'lucene'),而 jsoup、guava、pf4j 等则直接使用内联坐标(如 org.jsoup:jsoup:1.23.1);[bundles] 将同一族的库打包引用(如 lucene bundle 聚合了 core、queryparser、highlighter 等 5 个模块)。
  • Spring Boot BOM:由 platform/application/build.gradle 这个 java-platform 工程承载,其中 api platform(SpringBootPlugin.BOM_COORDINATES) 引入了 Spring Boot 官方 BOM,随后用 constraints 块把版本目录中的 bundle 和第三方库以约束形式注入。:api:application 模块通过 api platform(project(':platform:application')) 消费该平台,因此 Spring Framework、r2dbc 驱动、postgresql、byte-buddy、jspecify、junit-platform-launcher 等大量库的版本不由项目直接控制,而是随 BOM 统一到达。

另外,ben-manes Versions 插件已经应用于 :api:application 两个模块,分别见 api/build.gradleapplication/build.gradle 中的 alias(libs.plugins.versions),插件版本固定为 0.54.0(见 gradle/libs.versions.toml)。多模块结构由 settings.gradle 定义:apiapplicationplatform:applicationplatform:pluginui

注意范围边界:该升级流程仅针对后端(api / application / platform)。前端 ui/ 目录走 pnpm,不在此文档范围内。

2. 第一步:找出过期的依赖

核心命令:

./gradlew dependencyUpdates -DoutputFormatter=plain,json --console=plain

执行后需阅读两份报告并合并去重(两个模块各自输出一份):

  • api/build/dependencyUpdates/report.{txt,json}
  • application/build/dependencyUpdates/report.{txt,json}

一个容易误解的点:插件默认 revision 包含稳定版(stable),所以报告里提示的"later milestone versions"并不等于预发布版——只有带 alpha / beta / rc 限定符的版本才算 pre-release(例如 tika-core 的 4.0.0-beta-1 就应跳过,除非用户明确要求)。

3. 第二步:判断哪些可以升级

拿到过期清单后,按以下四类分别处理:

类别 声明位置 处理方式
Catalog library gradle/libs.versions.toml[libraries] 可直接在目录中升级
Gradle plugin [plugins] 可直接在目录中升级(受约束 3.3 限制)
BOM-managed platform/application 中 Spring Boot BOM 锁定 永远不要单独升级,随下一次 BOM 整体升级
Gradle wrapper gradle/wrapper/gradle-wrapper.properties 单独管理,当前为 gradle-9.7.0-bin.zip

从源码结构看,BOM-managed 的判断依据是:api/build.gradle 中这些依赖只写坐标不写版本号(如 api 'org.jspecify:jspecify'),版本完全来自 platform(project(':platform:application')) 引入的 BOM;而 platform/application/build.gradleconstraints 块才是项目真正能改动的地方。

4. 项目级约束(不可逾越的红线)

技能文档列出了五条硬约束,每一条都有仓库内的具体佐证:

  1. thymeleaf 平铺 jar 不得改动application/build.gradle 中存在如下声明:

    // Build from https://github.com/halo-dev/thymeleaf/commit/d23498ea297059deff04ba8c3578de59c73ccf03
    runtimeOnly ':thymeleaf:3.1.3.RELEASE'
    runtimeOnly ':thymeleaf-spring6:3.1.3.RELEASE'
    

    这是针对 halo-dev/halo#7289 的固定版本 workaround,jar 位于 application/libs/(flat-dir 方式引入),版本号还同时出现在 gradle.properties 中。升级依赖时绝不能触碰它们。

  2. lombok 保持与 io.freefair.lombok 插件对齐。当前 gradle/libs.versions.toml 声明 lombok = 'io.freefair.lombok:9.5.0',不要额外添加 lombok { version = ... } 覆盖。

  3. ben-manes Versions 插件停留在 0.54.0。0.59.0 应用时会因 classloader 错误失败,因此即使报告提示有新版也不升。

  4. 预发布版跳过(如 tika-core 4.0.0-beta-1),除非用户明确要求。

  5. 版本号只允许出现在三处gradle/libs.versions.tomlgradle.propertiesui/package.json,严禁在 build 脚本中硬编码(AGENTS.md 约定)。

5. 第三步:输出升级计划

批准执行之前,先按类别分组展示计划,每个条目需包含:当前版本 → 最新版本、semver 增量级别(major / minor / patch)、落点位置(catalog 的哪个条目、插件段还是 wrapper),并明确列出排除项及原因(例如 BOM-managed 项、锁定在 0.54.0 的 Versions 插件、thymeleaf 平铺 jar)。

6. 第四步:应用修改并验证

只有在用户批准计划之后,才编辑 gradle/libs.versions.toml每次升级只改一行(一个条目一行),然后:

./gradlew build

构建通过后再跑一次 dependencyUpdates,确认:

  • 已升级的条目不再出现在过期清单中;
  • 剩余过期项应当恰好等于第 4 节所列的排除集合(BOM-managed、锁定的插件、平铺 jar、预发布版等),出现"意料之外的残留"说明计划执行不完整。

小结

Halo 的依赖升级并非"见新就升":它通过版本目录 + BOM 双轨制划清权限边界,借助 Versions 插件生成可信的过期报告,再用一组项目级约束(thymeleaf workaround、lombok 对齐、插件版本锁定、预发布过滤、版本号单一来源)防止升级动作破坏构建。按照"发现 → 分类 → 计划 → 批准 → 修改 → 构建 → 复验"这一闭环操作,可以把后端依赖升级控制在一个可审计、可回退的安全范围内。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384