欢迎你来读这篇博客,这篇博客主要是关于 Renovate + OpenRewrite 的整合实践。
如果只用 Renovate,我们可以自动发现依赖新版本,并创建升级 MR;如果只用 OpenRewrite,我们可以自动重构代码、迁移 API、替换配置。但真正的企业项目里,最麻烦的往往不是“有没有新版本”,而是:
依赖升级之后,代码、配置、测试、构建脚本也要跟着改。
所以这篇文章要讲的是一个更完整的工程化方案:
Renovate 负责发现依赖升级机会并创建 MR,OpenRewrite 负责把项目代码自动迁移到适配新版本,CI 负责验证,人工 Review 负责最后兜底。
序言 在 Java 后端项目中,依赖升级是一件长期被低估的事情。
很多团队的 pom.xml 一开始看起来还挺清爽:
1 2 3 4 <spring-boot.version > 2.7.18</spring-boot.version > <spring-cloud.version > 2021.0.9</spring-cloud.version > <mybatis-plus.version > 3.5.5</mybatis-plus.version > <fastjson.version > 1.2.83</fastjson.version >
几年之后,它可能就变成了“版本考古现场”:
1 2 3 4 5 6 7 Spring Boot 还是 2.x; JDK 还是 8 或 11; javax 还没迁到 jakarta; JUnit 4 和 JUnit 5 混着用; 某些老依赖带着漏洞; Maven 插件版本多年没动; Dockerfile 里的基础镜像也很久没升级。
这时如果只靠人工升级,就会非常痛苦。因为依赖升级不是简单改一个版本号,它经常会牵出一串连锁反应:
1 2 3 4 5 6 7 依赖版本变了 -> API 变了 -> import 变了 -> 配置项变了 -> 测试框架变了 -> 构建插件也要变 -> CI 开始爆红
于是我们需要两类工具:
工具
核心职责
Renovate
发现依赖新版本,自动创建升级分支和 MR/PR
OpenRewrite
自动修改源码、配置、构建文件,让代码适配新依赖
这两者不是替代关系,而是互补关系。
一句话概括:
Renovate 管“依赖要不要升”,OpenRewrite 管“升完之后代码怎么改”。
正文 一、Renovate 和 OpenRewrite 分别解决什么问题 1.1 Renovate 的定位 Renovate 是一个依赖自动升级机器人。它会扫描仓库里的依赖声明文件,例如:
1 2 3 4 5 6 7 pom.xml build.gradle package.json Dockerfile docker-compose.yml .gitlab-ci.yml .github/workflows/*.yml
然后发现新版本,创建升级分支,并提交 MR/PR。
在 Maven 项目里,它可以识别:
1 2 3 4 5 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > <version > 3.4.0</version > </dependency >
发现新版本后,自动提交类似这样的 MR:
1 2 3 chore(deps): update spring boot to 3.5.3 chore(deps): update dependency com.alibaba:fastjson to v2 chore(deps): update docker image eclipse-temurin to 21-jre
Renovate 重点解决的是:
1 2 3 4 5 6 1. 哪些依赖有新版本? 2. 哪些依赖有安全更新? 3. 哪些依赖可以分组升级? 4. 哪些依赖可以自动合并? 5. 哪些依赖需要人工审批? 6. 如何把升级变成可 review 的 MR/PR?
但是 Renovate 通常不负责复杂代码迁移。它可以改版本号,但不会天然理解你的业务代码该如何适配新 API。
比如它可以把 Spring Boot 从 2.7 升到 3.5,但升级之后下面的代码会出问题:
1 import javax.servlet.http.HttpServletRequest;
Spring Boot 3 基于 Jakarta EE,很多 javax.* API 要迁移到 jakarta.*:
1 import jakarta.servlet.http.HttpServletRequest;
这个时候就轮到 OpenRewrite 上场了。
1.2 OpenRewrite 的定位 OpenRewrite 是一个自动化代码重构和迁移工具。它通过预定义的 Recipe 规则,对源码、构建文件、配置文件做自动修改。
它能做的事情包括:
1 2 3 4 5 6 7 8 9 10 Spring Boot 2.x -> Spring Boot 3.x Java 8/11/17 -> Java 21 javax.* -> jakarta.* JUnit 4 -> JUnit 5 老 API -> 新 API 废弃配置项 -> 新配置项 Maven 插件版本升级 依赖坐标迁移 代码风格清理 静态分析修复
例如:
1 import javax.annotation.PostConstruct;
迁移后:
1 import jakarta.annotation.PostConstruct;
再比如 JUnit 4:
1 2 3 4 5 6 7 8 9 import org.junit.Test;import static org.junit.Assert.assertEquals;public class UserServiceTest { @Test public void testCreate () { assertEquals(1 , 1 ); } }
迁移到 JUnit 5:
1 2 3 4 5 6 7 8 9 import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.assertEquals;class UserServiceTest { @Test void testCreate () { assertEquals(1 , 1 ); } }
这类机械迁移,如果靠人工改,很容易改漏;如果靠 OpenRewrite,就可以批量处理。
1.3 两者的边界
对比项
Renovate
OpenRewrite
核心目标
依赖升级自动化
代码迁移自动化
主要输入
依赖文件、镜像版本、CI 配置
源码、POM、Gradle、YAML、Properties
输出结果
升级分支、MR/PR
代码 diff
擅长场景
小版本升级、安全升级、版本治理
大版本迁移、API 替换、框架升级
典型问题
这个依赖有没有新版本?
升级之后代码怎么改?
企业落地方式
GitLab/GitHub Bot、定时 Runner
Maven/Gradle 插件、CI Job、迁移分支
更形象一点:
1 2 3 Renovate 像情报员:告诉你哪里有新版本,并把升级申请递上来。 OpenRewrite 像施工队:根据迁移规则,把代码和配置真正改好。 CI 像验收员:编译、测试、扫描,全过了才允许合并。
单独使用 Renovate,容易出现“版本升了,项目炸了”。
单独使用 OpenRewrite,又缺少持续发现依赖升级机会的能力。
所以最佳实践是把它们整合起来。
二、整体架构设计 2.1 推荐流水线 flowchart LR
A[Renovate 定时运行] --> B[扫描依赖文件]
B --> C[发现可升级依赖]
C --> D[创建升级分支]
D --> E[创建 MR/PR]
E --> F[CI 触发]
F --> G[OpenRewrite 自动迁移]
G --> H[提交迁移代码到同一分支]
H --> I[编译与测试]
I --> J[人工 Review]
J --> K[合并]
这个流程的核心目标是:
1 依赖升级不是孤立动作,而是一个完整的变更流水线。
也就是说,MR 里不应该只有一个版本号变化:
1 2 - <version>2.7.18</version> + <version>3.5.3</version>
更理想的 MR 是:
1 2 3 4 1. Renovate 修改依赖版本; 2. OpenRewrite 自动修改不兼容代码; 3. CI 运行编译和测试; 4. 开发者只需要 Review 剩余不可自动化的部分。
这才是真正能落地的升级自动化。
2.2 三种集成模式 Renovate 和 OpenRewrite 整合,一般有三种模式。
模式一:半自动模式 流程:
1 2 3 4 5 Renovate 创建 MR 开发者 checkout 这个分支 本地运行 OpenRewrite 开发者手工 commit 到同一个 MR CI 验证
适合:
1 2 3 4 1. 刚开始试点; 2. 团队还不敢让 CI 自动改代码; 3. 大版本升级风险较高; 4. 老项目测试覆盖不够。
优点:安全、可控。 缺点:人工参与多。
模式二:CI 自动补丁模式 流程:
1 2 3 4 5 Renovate 创建 MR CI 识别这是 Renovate 分支 CI 自动运行 OpenRewrite 如果有代码变化,CI 自动 commit 回 Renovate 分支 CI 再次编译测试
适合:
1 2 3 4 1. 团队有较好的 CI; 2. 测试覆盖较完整; 3. 想减少重复迁移劳动; 4. 主要处理框架升级、JUnit 迁移、Java 版本迁移。
优点:自动化程度高。 缺点:权限、循环触发、误改风险要控制好。
模式三:专项迁移分支模式 流程:
1 2 3 4 5 手工创建 migration/spring-boot-3.5 分支 OpenRewrite 先批量迁移代码 Renovate 后续持续维护依赖小版本 CI 验证 人工分批合并
适合:
1 2 3 4 5 1. Spring Boot 2 -> 3 这种大迁移; 2. Java 8/11 -> 17/21; 3. javax -> jakarta; 4. 多模块项目; 5. 改动范围很大,不适合由 Renovate 单次 MR 承担。
优点:迁移边界清晰。 缺点:周期更长,需要迁移计划。
三、基础准备 本文以一个企业 GitLab + Maven + Spring Boot 项目为例。
假设仓库是:
项目结构类似:
1 2 3 4 5 6 7 8 9 finance/ ├── renovate.json ├── pom.xml ├── com.amugua.finance.impl/ │ └── pom.xml ├── com.amugua.finance.api/ │ └── pom.xml ├── Dockerfile └── .gitlab-ci.yml
本地环境:
1 2 3 4 5 6 JDK 17 或 JDK 21 Maven 3.8+ Node.js 18+ Git GitLab Token Nexus / Maven 私服账号,可选
版本参考:
组件
示例版本
Renovate
43.x
OpenRewrite Maven Plugin
6.41.0
OpenRewrite Gradle Plugin
7.34.0
rewrite-spring
6.32.1
rewrite-testing-frameworks
3.37.0
rewrite-migrate-java
3.36.0
版本会持续变化,生产中建议在文档和 CI 变量里显式固定版本,不要所有地方都写 latest.release 或 RELEASE。试验阶段可以用 RELEASE,生产流水线最好固定版本,别让迁移工具自己“偷偷升级自己”。
四、Renovate 实战配置 4.1 仓库内配置:renovate.json 先在仓库根目录创建 renovate.json。
如果你只想让 Renovate 管 Maven,并且只扫描 com.amugua.finance.impl/pom.xml,可以这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 { "$schema" : "https://docs.renovatebot.com/renovate-schema.json" , "extends" : [ "config:recommended" ] , "enabledManagers" : [ "maven" ] , "includePaths" : [ "com.amugua.finance.impl/pom.xml" ] , "dependencyDashboard" : true , "packageRules" : [ { "description" : "Only manage Amugua Maven coordinates in the impl project." , "matchManagers" : [ "maven" ] , "matchPackageNames" : [ "!/^com\\.amugua(\\.|:)/" ] , "enabled" : false } ] }
这个配置的含义是:
1 2 3 4 5 1. 只启用 Maven manager; 2. 只扫描 com.amugua.finance.impl/pom.xml; 3. 只管理 com.amugua 开头的 Maven 坐标; 4. 非 com.amugua 依赖全部禁用; 5. 开启 Dependency Dashboard,方便集中查看更新情况。
注意:
1 2 includePaths 是相对仓库根目录的路径。 所以运行 Renovate 时要从仓库根目录看路径,不是从子模块目录看路径。
如果你发现 Renovate 仍然扫描了 Dockerfile,说明这个 renovate.json 很可能没有生效。常见原因是:
1 2 3 4 5 1. renovate.json 没有 push 到默认分支; 2. Renovate 读取的是 master,但你把配置提交到了 develop; 3. 你用了远程模式,但本地文件还没提交; 4. 运行配置里覆盖了仓库配置; 5. 配置文件不在 Renovate 支持的位置。
可以用:
1 2 git fetch origin master git show origin/master:renovate.json
确认远程默认分支上到底有没有这份配置。
4.2 Spring Boot 升级专用配置 如果你的目标是让 Renovate 专门处理 Spring Boot / Spring Cloud 升级,可以这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 { "$schema" : "https://docs.renovatebot.com/renovate-schema.json" , "extends" : [ "config:recommended" ] , "enabledManagers" : [ "maven" ] , "dependencyDashboard" : true , "prConcurrentLimit" : 5 , "prHourlyLimit" : 2 , "packageRules" : [ { "description" : "Spring Boot framework upgrade group." , "matchManagers" : [ "maven" ] , "matchPackageNames" : [ "org.springframework.boot:spring-boot-starter-parent" , "org.springframework.boot:spring-boot-dependencies" , "org.springframework.boot:spring-boot-maven-plugin" , "/^org\\.springframework\\.boot:/" ] , "groupName" : "spring boot framework" } , { "description" : "Major upgrades require dashboard approval." , "matchUpdateTypes" : [ "major" ] , "dependencyDashboardApproval" : true } , { "description" : "Patch upgrades can be automerged after CI passes." , "matchUpdateTypes" : [ "patch" ] , "automerge" : true } ] }
这个配置适合持续治理:
1 2 3 4 小版本升级可以自动化; 大版本升级必须先人工审批; Spring Boot 相关依赖集中到一个 MR; 避免一堆零散 PR 把团队淹没。
4.3 自托管运行配置:config.js 仓库里的 renovate.json 只放仓库级配置,不要放 token、endpoint、repositories 这类运行级配置。
本地或 CI 运行 Renovate 时,可以单独创建一个 config.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 module .exports = { platform : 'gitlab' , endpoint : 'https://git.dianplus.cn/api/v4' , token : process.env .RENOVATE_TOKEN , repositories : [ 'background/finance' ], gitAuthor : 'Renovate Bot <renovate-bot@example.com>' , onboarding : false , requireConfig : 'optional' };
运行:
1 LOG_LEVEL=debug npx --yes --package renovate -- renovate --config-file ./config.js --dry-run=full
确认无误后正式运行:
1 LOG_LEVEL=info npx --yes --package renovate -- renovate --config-file ./config.js
4.4 私服 Maven 仓库配置 如果公司依赖来自 Nexus / Artifactory,建议在 config.js 里配置 hostRules 和 registryUrls:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 module .exports = { platform : 'gitlab' , endpoint : 'https://git.dianplus.cn/api/v4' , token : process.env .RENOVATE_TOKEN , repositories : [ 'background/finance' ], gitAuthor : 'Renovate Bot <renovate-bot@example.com>' , hostRules : [ { hostType : 'maven' , matchHost : 'https://nexus.example.com/repository/maven-public/' , username : process.env .MAVEN_REPO_USERNAME , password : process.env .MAVEN_REPO_PASSWORD } ], packageRules : [ { matchDatasources : [ 'maven' ], registryUrls : [ 'https://nexus.example.com/repository/maven-public/' ] } ] };
运行前设置环境变量:
1 2 3 export RENOVATE_TOKEN="glpat_xxxxxxxxxxxxxxxxxxxx" export MAVEN_REPO_USERNAME="renovate" export MAVEN_REPO_PASSWORD="your-password"
注意:不要把私服密码写进 renovate.json。仓库配置会被所有人看到,密码一旦提交,故事就从“依赖治理”变成“事故复盘”了。
4.5 本地验证 Renovate 配置 校验配置文件 1 2 cd /your/project/root npx --yes --package renovate -- renovate-config-validator
本地只扫描当前目录 1 2 3 4 5 6 unset RENOVATE_CONFIGunset RENOVATE_REPOSITORIESunset RENOVATE_ENDPOINTcd /your/project/root LOG_LEVEL=debug npx --yes --package renovate -- renovate --platform=local --dry-run=extract 2>&1 | tee renovate-local.log
注意:
1 platform=local 时,不支持 repositories。
如果你看到:
1 Invalid configuration: repositories list not supported when platform=local
说明你把本地扫描模式和远程仓库模式混用了。
正确理解:
1 2 platform=local:只扫描当前本地目录,不创建分支,不创建 MR。 platform=gitlab:连接 GitLab 仓库,可以创建分支和 MR。
远程 dry-run 1 2 3 4 5 6 7 8 9 10 11 12 export RENOVATE_TOKEN="glpat_xxxxxxxxxxxxxxxxxxxx" export RENOVATE_CONFIG='{ "platform": "gitlab", "endpoint": "https://git.dianplus.cn/api/v4", "repositories": [ "background/finance" ], "gitAuthor": "Renovate Bot <renovate-bot@example.com>" }' LOG_LEVEL=debug npx --yes --package renovate -- renovate --dry-run=full 2>&1 | tee renovate-remote.log
如果日志里出现:
1 DRY-RUN: Would commit files to branch renovate/xxx
说明 Renovate 已经发现可升级依赖,并且如果去掉 dry-run,就会创建分支和 MR。
五、OpenRewrite 实战配置 5.1 Maven 插件方式 在根 pom.xml 中配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <build > <plugins > <plugin > <groupId > org.openrewrite.maven</groupId > <artifactId > rewrite-maven-plugin</artifactId > <version > 6.41.0</version > <configuration > <exportDatatables > true</exportDatatables > <activeRecipes > <recipe > org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5</recipe > </activeRecipes > </configuration > <dependencies > <dependency > <groupId > org.openrewrite.recipe</groupId > <artifactId > rewrite-spring</artifactId > <version > 6.32.1</version > </dependency > </dependencies > </plugin > </plugins > </build >
执行 dry-run:
真正修改代码:
查看改动:
5.2 不改 pom 的命令行方式 如果不想把 OpenRewrite 插件长期写进业务项目,可以直接用命令行:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
这种方式适合:
1 2 3 4 1. 临时迁移; 2. CI 自动运行; 3. 不希望业务 pom 增加迁移工具插件; 4. 多项目统一迁移时由脚本控制版本。
5.3 Spring Boot 3.5 迁移 OpenRewrite 的 Spring Boot 3.5 迁移 Recipe 是:
1 org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5
运行:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
它会尝试处理:
1 2 3 4 5 6 7 Spring Boot 版本升级; Spring Boot Maven Plugin 升级; Spring Boot parent/BOM 升级; Spring Cloud 相关迁移; Spring Security 相关迁移; Spring Boot 配置项迁移; 部分 deprecated API 替换。
但是注意:OpenRewrite 不是魔法棒。下面这类问题仍然可能需要人工处理:
1 2 3 4 5 6 7 1. 公司自研框架适配 Spring Boot 3; 2. 老版本第三方库不支持 jakarta; 3. 运行时行为变化; 4. 配置中心中的远程配置; 5. XML 配置或反射字符串; 6. 动态 SQL、脚本、模板中的类名; 7. 测试覆盖不足导致的问题。
5.4 Java 21 迁移 Java 21 迁移 Recipe:
1 org.openrewrite.java.migrate.UpgradeToJava21
运行:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:3.36.0 \ -Drewrite.activeRecipes=org.openrewrite.java.migrate.UpgradeToJava21 \ -Drewrite.exportDatatables=true
它会尝试处理:
1 2 3 4 5 source/target/release 调整到 21; 构建插件升级; 部分废弃 API 替换; 部分语法现代化; Java 17 到 Java 21 的常见迁移动作。
5.5 JUnit 4 迁移 JUnit 5 JUnit 4 到 JUnit 5 的 Recipe:
1 org.openrewrite.java.testing.junit5.JUnit4to5Migration
运行:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-testing-frameworks:3.37.0 \ -Drewrite.activeRecipes=org.openrewrite.java.testing.junit5.JUnit4to5Migration \ -Drewrite.exportDatatables=true
如果是 Spring Boot 2.x 项目,Spring 相关测试迁移也可以考虑:
1 org.openrewrite.java.spring.boot2.SpringBoot2JUnit4to5Migration
它对 Spring Test Runner、Spring Extension、@RunWith 等场景更友好。
六、整合方案一:半自动模式 半自动模式最适合刚落地时使用。它不会让 CI 自动提交代码,风险最低。
6.1 流程 sequenceDiagram
participant R as Renovate
participant G as GitLab
participant D as Developer
participant O as OpenRewrite
participant C as CI
R->>G: 创建依赖升级 MR
D->>G: checkout Renovate 分支
D->>O: 本地运行 OpenRewrite
O->>D: 修改源码、pom、配置
D->>G: commit 到同一 MR
G->>C: 触发 CI
C->>G: 返回编译/测试结果
6.2 操作示例 Renovate 创建了一个 MR,分支名类似:
1 renovate/spring-boot-framework
本地拉取:
1 2 git fetch origin renovate/spring-boot-framework git checkout -b renovate/spring-boot-framework origin/renovate/spring-boot-framework
运行 OpenRewrite:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
查看 diff:
1 2 git diff --stat git diff
跑测试:
提交到同一个分支:
1 2 3 git add . git commit -m "chore: apply OpenRewrite Spring Boot migration" git push origin renovate/spring-boot-framework
这时 MR 中就包含两类改动:
1 2 1. Renovate 的依赖版本升级; 2. OpenRewrite 的代码和配置迁移。
6.3 适用建议 首次在老项目里使用时,建议先半自动。
原因很简单:你需要先观察 OpenRewrite 对你们公司项目的“改代码风格”。工具是好工具,但第一次上来就让它自动 commit,多少有点像刚认识就把家门钥匙给出去,浪漫是浪漫,风险也是真风险。
七、整合方案二:CI 自动补丁模式 CI 自动补丁模式是更高级的玩法。
核心目标:
Renovate 创建 MR 后,CI 自动运行 OpenRewrite,并把代码迁移结果 commit 回 Renovate 分支。
7.1 GitLab CI 示例 .gitlab-ci.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 stages: - rewrite - test variables: MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" REWRITE_MAVEN_PLUGIN_VERSION: "6.41.0" REWRITE_SPRING_VERSION: "6.32.1" cache: key: "${CI_PROJECT_NAME}-maven" paths: - .m2/repository openrewrite:spring-boot: stage: rewrite image: maven:3.9.9-eclipse-temurin-21 rules: - if: '$CI_COMMIT_BRANCH =~ /^renovate\//' when: manual - when: never before_script: - git config user.name "Renovate Bot" - git config user.email "renovate-bot@example.com" script: - | mvn -U org.openrewrite.maven:rewrite-maven-plugin:${REWRITE_MAVEN_PLUGIN_VERSION}:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:${REWRITE_SPRING_VERSION} \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true - | if ! git diff --quiet; then git add . git commit -m "chore: apply OpenRewrite migration [skip ci]" git push "https://oauth2:${RENOVATE_PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" "HEAD:${CI_COMMIT_REF_NAME}" else echo "No OpenRewrite changes detected." fi maven:test: stage: test image: maven:3.9.9-eclipse-temurin-21 script: - mvn clean test
这里我把 openrewrite:spring-boot 设置成了 manual,原因是:
1 不是所有 Renovate 分支都应该自动跑 Spring Boot 迁移。
比如 fastjson 升级、commons-lang3 升级、小版本 patch 升级,通常不需要跑 Spring Boot 大迁移 Recipe。
如果你确认只对特定分支运行,可以进一步限制规则:
1 2 3 4 rules: - if: '$CI_COMMIT_BRANCH =~ /^renovate\/spring-boot/' when: on_success - when: never
7.2 防止 CI 无限循环 CI 自动 commit 回分支时,容易触发新一轮 CI。为了避免循环,可以在 commit message 中加:
例如:
1 git commit -m "chore: apply OpenRewrite migration [skip ci]"
也可以用更精细的规则:
1 2 3 rules: - if: '$CI_COMMIT_BRANCH =~ /^renovate\// && $CI_COMMIT_MESSAGE !~ /apply OpenRewrite migration/' when: on_success
7.3 Token 权限 RENOVATE_PUSH_TOKEN 至少需要能 push 当前 MR 分支。
GitLab 中常见选择:
1 2 3 Project Access Token Group Access Token 专门的 Bot 用户 Personal Access Token
权限建议:
1 2 3 read_repository write_repository api,可选,如果还要操作 MR
如果分支受保护,要确认 Bot 用户有权限 push。别让工具跑到最后一步才发现没有权限,那感觉就像外卖到了小区门口,但骑手进不来。
7.4 自动补丁模式的风险控制 建议做这些限制:
1 2 3 4 5 6 7 1. 默认 manual,稳定后再自动; 2. 只对 renovate/ 特定分支运行; 3. 只对特定依赖组运行,例如 spring boot framework; 4. commit message 加 [skip ci] 防止循环; 5. OpenRewrite job 之后必须跑 mvn clean test; 6. 合并前必须人工 review; 7. 老项目第一次不要开 automerge。
八、整合方案三:专项迁移分支模式 对于 Spring Boot 2 到 3、Java 11 到 21 这种大迁移,我更推荐专项迁移分支。
8.1 创建迁移分支 1 2 3 git checkout master git pull git checkout -b migration/spring-boot-3.5-java-21
8.2 先迁移 Java 21 1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:3.36.0 \ -Drewrite.activeRecipes=org.openrewrite.java.migrate.UpgradeToJava21 \ -Drewrite.exportDatatables=true
提交:
1 2 git add . git commit -m "chore: migrate build to Java 21 with OpenRewrite"
8.3 再迁移 Spring Boot 3.5 1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
提交:
1 2 git add . git commit -m "chore: migrate to Spring Boot 3.5 with OpenRewrite"
8.4 再迁移 JUnit 5 1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-testing-frameworks:3.37.0 \ -Drewrite.activeRecipes=org.openrewrite.java.testing.junit5.JUnit4to5Migration \ -Drewrite.exportDatatables=true
提交:
1 2 git add . git commit -m "test: migrate JUnit 4 tests to JUnit 5 with OpenRewrite"
8.5 最后运行验证 1 2 mvn clean test mvn clean package -DskipTests
如果项目比较大,可以分模块跑:
1 mvn -pl com.amugua.finance.impl -am clean test
8.6 迁移顺序建议 推荐顺序:
1 2 3 4 5 6 1. 先升级 JDK 构建配置; 2. 再升级 Spring Boot; 3. 再处理 javax -> jakarta; 4. 再迁移测试框架; 5. 再清理废弃 API; 6. 最后跑全量测试和人工验收。
不要一口气把所有 Recipe 全扔进去。那样 diff 会非常大,Review 会变成灾难片。
九、完整实战案例:GitLab + Renovate + OpenRewrite + Maven 下面给一套比较完整的企业落地方案。
9.1 目标 我们希望实现:
1 2 3 4 5 6 7 1. Renovate 定时扫描 background/finance 仓库; 2. 只管理 Maven 依赖; 3. Spring Boot 相关升级聚合成一个 MR; 4. 大版本升级需要人工审批; 5. Spring Boot 升级 MR 可触发 OpenRewrite; 6. OpenRewrite 自动提交迁移代码到同一个分支; 7. CI 编译测试通过后人工合并。
9.2 仓库 renovate.json 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 { "$schema" : "https://docs.renovatebot.com/renovate-schema.json" , "extends" : [ "config:recommended" ] , "enabledManagers" : [ "maven" ] , "dependencyDashboard" : true , "labels" : [ "dependencies" , "renovate" ] , "prConcurrentLimit" : 5 , "prHourlyLimit" : 2 , "packageRules" : [ { "description" : "Group Spring Boot framework dependencies." , "matchManagers" : [ "maven" ] , "matchPackageNames" : [ "org.springframework.boot:spring-boot-starter-parent" , "org.springframework.boot:spring-boot-dependencies" , "org.springframework.boot:spring-boot-maven-plugin" , "/^org\\.springframework\\.boot:/" ] , "groupName" : "spring boot framework" , "branchTopic" : "spring-boot-framework" } , { "description" : "Major updates require manual dashboard approval." , "matchUpdateTypes" : [ "major" ] , "dependencyDashboardApproval" : true } , { "description" : "Patch updates are low risk and can be automerged after CI." , "matchUpdateTypes" : [ "patch" ] , "automerge" : false } ] }
这里我把 automerge 设成了 false。老项目刚接入时,不建议一上来就自动合并。等 CI、测试覆盖、回滚策略都稳定后,再逐步打开 patch 自动合并。
9.3 Renovate Runner 配置 本地或 CI 中创建 config.js:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 module .exports = { platform : 'gitlab' , endpoint : 'https://git.dianplus.cn/api/v4' , token : process.env .RENOVATE_TOKEN , repositories : [ 'background/finance' ], gitAuthor : 'Renovate Bot <renovate-bot@example.com>' , onboarding : false , requireConfig : 'required' , hostRules : [ { hostType : 'maven' , matchHost : 'https://nexus.example.com/repository/maven-public/' , username : process.env .MAVEN_REPO_USERNAME , password : process.env .MAVEN_REPO_PASSWORD } ] };
运行 dry-run:
1 LOG_LEVEL=debug npx --yes --package renovate -- renovate --config-file ./config.js --dry-run=full
正式运行:
1 LOG_LEVEL=info npx --yes --package renovate -- renovate --config-file ./config.js
9.4 GitLab 定时任务 如果你把 Renovate 放到单独的 renovate-runner 项目,可以在 .gitlab-ci.yml 中这样写:
1 2 3 4 5 6 7 8 9 10 stages: - renovate renovate: stage: renovate image: renovate/renovate:43 script: - renovate --config-file config.js rules: - if: '$CI_PIPELINE_SOURCE == "schedule"'
然后在 GitLab 里配置 Pipeline Schedule,例如:
不要每几分钟跑一次。依赖升级不是刷短视频,不需要这么频繁。
9.5 业务仓库 OpenRewrite Job 在 background/finance 仓库 .gitlab-ci.yml 里增加:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 stages: - rewrite - build - test variables: MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" REWRITE_MAVEN_PLUGIN_VERSION: "6.41.0" REWRITE_SPRING_VERSION: "6.32.1" cache: key: "${CI_PROJECT_NAME}-maven" paths: - .m2/repository openrewrite:spring-boot: stage: rewrite image: maven:3.9.9-eclipse-temurin-21 rules: - if: '$CI_COMMIT_BRANCH =~ /^renovate\/spring-boot-framework/' when: manual - when: never before_script: - git config user.name "Renovate Bot" - git config user.email "renovate-bot@example.com" script: - | mvn -U org.openrewrite.maven:rewrite-maven-plugin:${REWRITE_MAVEN_PLUGIN_VERSION}:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:${REWRITE_SPRING_VERSION} \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true - | if ! git diff --quiet; then git add . git commit -m "chore: apply OpenRewrite Spring Boot migration [skip ci]" git push "https://oauth2:${RENOVATE_PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" "HEAD:${CI_COMMIT_REF_NAME}" else echo "No OpenRewrite changes detected." fi maven:compile: stage: build image: maven:3.9.9-eclipse-temurin-21 script: - mvn -U clean compile maven:test: stage: test image: maven:3.9.9-eclipse-temurin-21 script: - mvn test
这套流程运行后,会出现这样的效果:
1 2 3 4 Renovate MR:升级 Spring Boot 版本 OpenRewrite Job:点击后自动修改代码 CI:继续编译测试 开发者:Review MR
9.6 分支命名与规则匹配 Renovate 的分支名可能会因为配置不同而变化。
如果你想稳定匹配,可以在 packageRules 里配置:
1 2 3 4 5 6 7 { "matchPackageNames" : [ "/^org\\.springframework\\.boot:/" ] , "groupName" : "spring boot framework" , "branchTopic" : "spring-boot-framework" }
这样分支更容易被 CI 规则识别:
1 2 rules: - if: '$CI_COMMIT_BRANCH =~ /^renovate\/spring-boot-framework/'
你可能有这样的场景:
1 2 3 4 公司内部有很多 com.amugua.* 依赖; 这些依赖经常发布新版本; 但不希望 Renovate 管所有第三方依赖; 只想先让它管理某个 impl 模块里的公司内部包。
可以这样配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 { "$schema" : "https://docs.renovatebot.com/renovate-schema.json" , "extends" : [ "config:recommended" ] , "enabledManagers" : [ "maven" ] , "includePaths" : [ "com.amugua.finance.impl/pom.xml" ] , "dependencyDashboard" : true , "packageRules" : [ { "description" : "Only manage Amugua Maven coordinates in the impl project." , "matchManagers" : [ "maven" ] , "matchPackageNames" : [ "!/^com\\.amugua(\\.|:)/" ] , "enabled" : false } , { "description" : "Group all Amugua internal dependencies." , "matchManagers" : [ "maven" ] , "matchPackageNames" : [ "/^com\\.amugua(\\.|:)/" ] , "groupName" : "amugua internal dependencies" , "branchTopic" : "amugua-internal-dependencies" } ] }
如果跑出来仍然看到:
1 2 dockerfile: fileCount 1 maven: fileCount 2
说明配置没生效。正确情况下应该接近:
排查顺序:
1 2 3 4 5 6 7 8 9 git fetch origin master git show origin/master:renovate.json LOG_LEVEL=debug npx --yes --package renovate -- renovate --dry-run=full --print-config 2>&1 | tee renovate-debug.log grep -n "enabledManagers\|includePaths\|packageRules\|dockerfile" renovate-debug.log
如果你只是本地测试,不要带 repositories:
1 2 3 4 5 unset RENOVATE_CONFIGunset RENOVATE_REPOSITORIESunset RENOVATE_ENDPOINT LOG_LEVEL=debug npx --yes --package renovate -- renovate --platform=local --dry-run=extract
如果要远程创建 MR,不要用 platform=local:
1 2 3 4 5 6 7 8 9 10 export RENOVATE_CONFIG='{ "platform": "gitlab", "endpoint": "https://git.dianplus.cn/api/v4", "repositories": [ "background/finance" ], "gitAuthor": "Renovate Bot <renovate-bot@example.com>" }' LOG_LEVEL=debug npx --yes --package renovate -- renovate --dry-run=full
十一、实战案例三:Spring Boot 2.7 升级到 3.5 这是 Renovate + OpenRewrite 最典型的组合场景。
11.1 初始项目 pom.xml:
1 2 3 4 5 6 7 8 9 10 <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 2.7.18</version > <relativePath /> </parent > <properties > <java.version > 11</java.version > </properties >
代码中存在:
1 2 3 import javax.servlet.http.HttpServletRequest;import javax.validation.Valid;import javax.annotation.PostConstruct;
测试中存在:
1 2 3 import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.junit4.SpringRunner;
11.2 Renovate 先创建升级 MR Renovate 将 Spring Boot 相关依赖升级到 3.5.x。
MR 中可能出现:
1 2 - <version>2.7.18</version> + <version>3.5.3</version>
这一步只是依赖版本升级。此时项目很可能编译失败。
11.3 OpenRewrite 迁移 Spring Boot 运行:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1 \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
可能产生的变化:
1 2 -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest;
1 2 -import javax.validation.Valid; +import jakarta.validation.Valid;
1 2 -import javax.annotation.PostConstruct; +import jakarta.annotation.PostConstruct;
11.4 OpenRewrite 迁移 JUnit 5 运行:
1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-testing-frameworks:3.37.0 \ -Drewrite.activeRecipes=org.openrewrite.java.testing.junit5.JUnit4to5Migration \ -Drewrite.exportDatatables=true
可能产生的变化:
1 2 -import org.junit.Test; +import org.junit.jupiter.api.Test;
1 2 -import org.junit.Assert.assertEquals; +import org.junit.jupiter.api.Assertions.assertEquals;
11.5 编译验证
如果报错,常见原因有:
1 2 3 4 5 6 1. 第三方依赖不兼容 Spring Boot 3; 2. 公司自研 starter 没支持 jakarta; 3. 旧版本 MyBatis、Dubbo、ShardingSphere 等依赖不兼容; 4. Spring Security 配置需要人工处理; 5. 反射字符串中的 javax 没被替换; 6. 配置中心中的配置项没有同步迁移。
11.6 Review 重点 这种 MR Review 时,不要只看能不能编译,还要看:
1 2 3 4 5 6 7 1. Spring Boot 版本是否符合公司统一基线; 2. Spring Cloud 版本是否匹配; 3. Jakarta 迁移是否完整; 4. starter 是否有兼容版本; 5. 测试是否只是“能跑”,还是确实覆盖关键业务; 6. 配置中心、部署脚本、镜像基础版本是否同步调整; 7. 日志、监控、APM、网关、鉴权是否受影响。
十二、实战案例四:Java 11 升级 Java 21 Java 21 是当前很多企业后端项目的目标版本。配合 Spring Boot 3.x,更适合做长期技术基线。
12.1 Renovate 负责依赖基线更新 Renovate 可以持续升级:
1 2 3 4 5 maven-compiler-plugin maven-surefire-plugin maven-failsafe-plugin maven-dependency-plugin spring-boot-maven-plugin
但 Java 源码和构建配置的迁移,更适合 OpenRewrite。
12.2 OpenRewrite 执行 Java 21 迁移 1 2 3 4 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:3.36.0 \ -Drewrite.activeRecipes=org.openrewrite.java.migrate.UpgradeToJava21 \ -Drewrite.exportDatatables=true
可能改动:
1 2 3 <properties > <java.version > 21</java.version > </properties >
或者:
1 <maven.compiler.release > 21</maven.compiler.release >
12.3 CI 镜像同步升级 .gitlab-ci.yml:
1 image: maven:3.9.9-eclipse-temurin-21
Dockerfile:
1 FROM eclipse-temurin:21 -jre
注意:JDK 升级不是只改 pom.xml。你还要同步检查:
1 2 3 4 5 6 7 1. CI 镜像; 2. Docker 基础镜像; 3. 生产环境 JRE; 4. APM Agent 是否支持 Java 21; 5. Lombok、MapStruct、Maven 插件是否兼容; 6. IDE 编译版本; 7. 构建机 Maven/JDK 版本。
十三、企业落地规范 13.1 MR 类型分级 建议把依赖升级分成三类:
类型
示例
处理策略
Patch
3.5.1 -> 3.5.2
CI 通过后可考虑自动合并
Minor
3.4.x -> 3.5.x
需要 Review,必要时跑 OpenRewrite
Major
2.x -> 3.x
必须专项迁移,禁止自动合并
13.2 推荐分支策略 1 2 3 4 renovate/*:Renovate 自动升级分支; migration/*:专项迁移分支; hotfix/*:紧急安全修复; release/*:发布分支。
13.3 推荐流水线门禁 每个依赖升级 MR 至少跑:
1 2 3 4 5 6 7 1. mvn clean compile; 2. mvn test; 3. 单元测试覆盖率检查; 4. 静态扫描; 5. 依赖漏洞扫描; 6. Docker 镜像构建; 7. 必要时跑集成测试。
Spring Boot / JDK 大迁移还应增加:
1 2 3 4 5 6 1. 启动测试; 2. 配置加载测试; 3. 数据源连接测试; 4. Redis/MQ/Nacos/Dubbo 注册测试; 5. 核心接口冒烟测试; 6. 回滚方案检查。
13.4 建议的团队流程 1 2 3 4 5 6 第一阶段:只开启 Renovate dry-run,观察扫描结果。 第二阶段:开启 Renovate MR,但禁止 automerge。 第三阶段:对低风险 patch 开启自动合并。 第四阶段:引入 OpenRewrite 半自动迁移。 第五阶段:对稳定 Recipe 开启 CI 自动补丁。 第六阶段:沉淀公司内部 Recipe 和版本基线。
不要一上来就:
1 全仓库扫描 + 全依赖自动升级 + OpenRewrite 自动 commit + automerge
这不是自动化,这是把方向盘交给工具,然后希望它懂你们业务。工具懂语法,不懂 KPI。
十四、常见问题排查 14.1 Renovate 只创建 onboarding PR 日志:
1 DRY-RUN: Would create onboarding PR
说明 Renovate 认为仓库还没有完成初始化。
处理方式:
1 2 3 4 1. 确认 renovate.json 已经提交到默认分支; 2. 如果想跳过 onboarding,在运行配置中设置 onboarding=false; 3. 如果要求必须有配置,设置 requireConfig=required; 4. 不要把 self-hosted 配置写进 renovate.json。
14.2 Repository is not found 通常是 repositories 写错。
GitLab 中应该写:
不要写:
1 https://git.dianplus.cn/background/finance.git
也不要带 .git。
验证:
1 git remote get-url origin
提取 repository slug:
1 2 git remote get-url origin \ | sed -E 's#https?://[^/]+/##; s#git@[^:]+:##; s#\.git$##'
错误:
1 Invalid configuration: repositories list not supported when platform=local
原因:
1 platform=local 是本地目录扫描,不允许 repositories。
解决:
1 2 3 4 5 unset RENOVATE_CONFIGunset RENOVATE_REPOSITORIESunset RENOVATE_ENDPOINT LOG_LEVEL=debug npx --yes --package renovate -- renovate --platform=local --dry-run=extract
或者改用 GitLab 远程模式:
1 LOG_LEVEL=debug npx --yes --package renovate -- renovate --dry-run=full
14.4 Renovate 没有按 includePaths 生效 先看远程默认分支配置:
1 2 git fetch origin master git show origin/master:renovate.json
再打印最终配置:
1 LOG_LEVEL=debug npx --yes --package renovate -- renovate --dry-run=full --print-config 2>&1 | tee renovate-debug.log
检查:
1 grep -n "enabledManagers\|includePaths\|packageRules" renovate-debug.log
14.5 OpenRewrite 找不到 Recipe 报错可能类似:
常见原因:
1 2 3 4 5 1. 没有配置 recipeArtifactCoordinates; 2. recipe 包版本不对; 3. recipe 名称写错; 4. 私服无法访问 Maven Central; 5. 公司 Maven settings.xml 没有正确配置 mirror。
解决示例:
1 2 mvn -U org.openrewrite.maven:rewrite-maven-plugin:6.41.0:discover \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:6.32.1
14.6 OpenRewrite 改动太大 处理建议:
1 2 3 4 5 6 1. 拆分 Recipe; 2. 每次只跑一个迁移主题; 3. 先 dryRun; 4. 小步 commit; 5. 每一步都跑测试; 6. 不要把 Java 21、Spring Boot 3、JUnit 5、代码格式化全部塞进一个 commit。
十五、推荐项目结构 可以在企业内部建一个专门的治理仓库:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 dependency-governance/ ├── renovate/ │ ├── config.js │ ├── presets/ │ │ ├── java-maven.json │ │ ├── spring-boot.json │ │ └── internal-amugua.json │ └── README.md ├── openrewrite/ │ ├── rewrite-spring-boot-35.sh │ ├── rewrite-java-21.sh │ ├── rewrite-junit5.sh │ └── rewrite.yml ├── ci/ │ ├── gitlab-renovate.yml │ └── gitlab-openrewrite.yml └── docs/ ├── upgrade-policy.md └── rollback-policy.md
这样做的好处:
1 2 3 4 5 1. 依赖治理配置集中管理; 2. OpenRewrite 命令统一维护; 3. CI 模板可以复用; 4. 各业务项目只引用配置,不重复造轮子; 5. 后续可以沉淀公司内部 Recipe。
十六、推荐 Shell 脚本 16.1 run-renovate-local.sh 1 2 3 4 5 6 7 8 9 10 11 #!/usr/bin/env bash set -euo pipefailunset RENOVATE_CONFIG || true unset RENOVATE_REPOSITORIES || true unset RENOVATE_ENDPOINT || true LOG_LEVEL=debug npx --yes --package renovate -- renovate \ --platform=local \ --dry-run=extract \ 2>&1 | tee renovate-local.log
16.2 run-renovate-gitlab-dryrun.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #!/usr/bin/env bash set -euo pipefail : "${RENOVATE_TOKEN:?RENOVATE_TOKEN is required} " export RENOVATE_CONFIG='{ "platform": "gitlab", "endpoint": "https://git.dianplus.cn/api/v4", "repositories": [ "background/finance" ], "gitAuthor": "Renovate Bot <renovate-bot@example.com>" }' LOG_LEVEL=debug npx --yes --package renovate -- renovate \ --dry-run=full \ 2>&1 | tee renovate-remote.log
16.3 run-openrewrite-spring-boot-35.sh 1 2 3 4 5 6 7 8 9 10 #!/usr/bin/env bash set -euo pipefail REWRITE_MAVEN_PLUGIN_VERSION="6.41.0" REWRITE_SPRING_VERSION="6.32.1" mvn -U org.openrewrite.maven:rewrite-maven-plugin:${REWRITE_MAVEN_PLUGIN_VERSION} :run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:${REWRITE_SPRING_VERSION} \ -Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_5 \ -Drewrite.exportDatatables=true
16.4 run-openrewrite-java-21.sh 1 2 3 4 5 6 7 8 9 10 #!/usr/bin/env bash set -euo pipefail REWRITE_MAVEN_PLUGIN_VERSION="6.41.0" REWRITE_MIGRATE_JAVA_VERSION="3.36.0" mvn -U org.openrewrite.maven:rewrite-maven-plugin:${REWRITE_MAVEN_PLUGIN_VERSION} :run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-migrate-java:${REWRITE_MIGRATE_JAVA_VERSION} \ -Drewrite.activeRecipes=org.openrewrite.java.migrate.UpgradeToJava21 \ -Drewrite.exportDatatables=true
16.5 run-openrewrite-junit5.sh 1 2 3 4 5 6 7 8 9 10 #!/usr/bin/env bash set -euo pipefail REWRITE_MAVEN_PLUGIN_VERSION="6.41.0" REWRITE_TESTING_VERSION="3.37.0" mvn -U org.openrewrite.maven:rewrite-maven-plugin:${REWRITE_MAVEN_PLUGIN_VERSION} :run \ -Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-testing-frameworks:${REWRITE_TESTING_VERSION} \ -Drewrite.activeRecipes=org.openrewrite.java.testing.junit5.JUnit4to5Migration \ -Drewrite.exportDatatables=true
十七、最终建议 Renovate 和 OpenRewrite 的整合,不要理解成“两个工具简单串起来”。
更准确地说,它是一套技术债治理机制:
1 2 3 4 5 Renovate 负责持续发现; OpenRewrite 负责自动修复; CI 负责质量验证; Review 负责业务判断; 版本基线负责长期约束。
如果团队没有版本基线,Renovate 会产生很多升级 MR,最后变成噪音。
如果团队没有测试,OpenRewrite 改完代码,你也不知道对不对。
如果团队没有 Review 规范,自动化工具越强,事故传播越快。
所以真正的落地顺序应该是:
1 2 3 4 5 先观测,再限制; 先 dry-run,再创建 MR; 先人工运行 OpenRewrite,再 CI 自动补丁; 先小版本治理,再大版本迁移; 先单仓试点,再多仓推广。
这套组合用好了,依赖升级就不再是“每年一次的大型恐怖片”,而是持续、可控、可回滚的日常工程能力。
参考资料
OpenRewrite 官方文档:https://docs.openrewrite.org/
OpenRewrite Maven Plugin 配置:https://docs.openrewrite.org/reference/rewrite-maven-plugin
OpenRewrite 最新模块版本:https://docs.openrewrite.org/reference/latest-versions-of-every-openrewrite-module
OpenRewrite Spring Boot 3.5 迁移 Recipe:https://docs.openrewrite.org/recipes/java/spring/boot3/upgradespringboot_3_5-community-edition
OpenRewrite Java 21 迁移 Recipe:https://docs.openrewrite.org/recipes/java/migrate/upgradetojava21
OpenRewrite JUnit 4 到 JUnit 5 迁移 Recipe:https://docs.openrewrite.org/recipes/java/testing/junit5/junit4to5migration
Renovate 官方文档:https://docs.renovatebot.com/
Renovate Configuration Options:https://docs.renovatebot.com/configuration-options/
Renovate Self-Hosted Configuration:https://docs.renovatebot.com/self-hosted-configuration/
Renovate GitLab Platform:https://docs.renovatebot.com/modules/platform/gitlab/
Renovate Local Platform:https://docs.renovatebot.com/modules/platform/local/
启示录 依赖升级不是改版本号,而是一次小型系统迁移。
工具能替你搬砖,但不能替你判断业务风险。
自动化的最高境界,不是无人看管,而是让人只看真正值得看的地方。