From ea7bcaff2f20257d080420d535dbedca8eea233a Mon Sep 17 00:00:00 2001 From: dongzi Date: Tue, 14 Jul 2026 10:23:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E4=BB=8Egitea?= =?UTF-8?q?=E4=B8=8A=E8=8E=B7=E5=8F=96=E9=85=8D=E7=BD=AE=E7=9A=84=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/config/redis-schema-check-config.yaml | 2 +- .../redis/report/ReportBuilder.java | 56 ++++++++++++++----- .../redis/report/ReportBuilderTest.java | 43 ++++++++++++++ 3 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 src/test/java/com/codechecker/redis/report/ReportBuilderTest.java diff --git a/.gitea/config/redis-schema-check-config.yaml b/.gitea/config/redis-schema-check-config.yaml index d35a666..78d2382 100644 --- a/.gitea/config/redis-schema-check-config.yaml +++ b/.gitea/config/redis-schema-check-config.yaml @@ -19,7 +19,7 @@ notify: enabled: true webhook_url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=fa14f0b3-e01a-40f6-96bd-e18beb94e85e notify_on_clean: false - title_prefix: "[Redis数据结构变更]" + title_prefix: "【Redis数据结构变更】" # 观察期:先只扫描 jnpf-tenant 模块,稳定后改为 include_modules: [] include_modules: diff --git a/src/main/java/com/codechecker/redis/report/ReportBuilder.java b/src/main/java/com/codechecker/redis/report/ReportBuilder.java index 6cab34c..9ef39f6 100644 --- a/src/main/java/com/codechecker/redis/report/ReportBuilder.java +++ b/src/main/java/com/codechecker/redis/report/ReportBuilder.java @@ -22,20 +22,12 @@ public class ReportBuilder { public String toMarkdown(CheckReport report) { StringBuilder sb = new StringBuilder(); sb.append("## ").append(titlePrefix).append(' ') - .append(nvl(report.getRepository())).append('\n'); - sb.append("> 分支: ").append(nvl(report.getBranch())).append('\n'); - sb.append("> 提交: ").append(shortSha(report.getOldSha())) + .append(nvl(report.getRepository())).append("\n\n"); + sb.append("> **分支**: ").append(nvl(report.getBranch())).append('\n'); + sb.append("> **提交**: ").append(shortSha(report.getOldSha())) .append(" → ").append(shortSha(report.getNewSha())).append('\n'); - sb.append("> 提交人: ").append(nvl(report.getModifier())).append('\n'); - sb.append("> 时间: ").append(nvl(report.getModifyTime())).append('\n'); - sb.append("> 模式: ").append(nvl(report.getMode())); - if (report.isBlocked()) { - sb.append("(已阻断)"); - } - sb.append('\n'); - sb.append("> 汇总: P0=").append(report.count(Severity.P0)) - .append(" P1=").append(report.count(Severity.P1)) - .append(" P2=").append(report.count(Severity.P2)).append("\n\n"); + sb.append("> **提交人**: ").append(nvl(report.getModifier())).append('\n'); + sb.append("> **时间**: ").append(nvl(report.getModifyTime())).append("\n\n"); Map> grouped = new EnumMap<>(Severity.class); for (SchemaChange c : report.getChanges()) { @@ -55,10 +47,10 @@ public class ReportBuilder { } sb.append('\n'); if (c.getWriteLocation() != null) { - sb.append(" - 位置: ").append(c.getWriteLocation()).append('\n'); + sb.append(" - **位置**: ").append(c.getWriteLocation()).append('\n'); } if (c.getMessage() != null) { - sb.append(" - ").append(c.getMessage()).append('\n'); + sb.append(" - ").append(formatDetailMessage(c.getMessage())).append('\n'); } } sb.append('\n'); @@ -66,6 +58,40 @@ public class ReportBuilder { return sb.toString(); } + /** + * 将详情文案中的 key 加粗,如「删除字段 lastError」→「**删除字段**: lastError」。 + */ + private String formatDetailMessage(String message) { + String trimmed = message.trim(); + int colonCn = trimmed.indexOf(':'); + if (colonCn > 0 && colonCn <= 24) { + return "**" + trimmed.substring(0, colonCn) + "**: " + + trimmed.substring(colonCn + 1).trim(); + } + int colonEn = trimmed.indexOf(':'); + if (colonEn > 0 && colonEn <= 24 && !trimmed.substring(0, colonEn).contains(" ")) { + return "**" + trimmed.substring(0, colonEn) + "**: " + + trimmed.substring(colonEn + 1).trim(); + } + String[] knownPrefixes = { + "删除字段 ", "新增字段 ", "字段路径迁移 ", "新增包装层 ", "新增 Redis 写入点,", + "删除 Redis 写入点,原 value 类型: " + }; + for (String prefix : knownPrefixes) { + if (trimmed.startsWith(prefix)) { + String key = prefix.trim(); + if (key.endsWith(",") || key.endsWith(",")) { + key = key.substring(0, key.length() - 1); + } + return "**" + key + "**: " + trimmed.substring(prefix.length()).trim(); + } + } + if (trimmed.startsWith("字段 ") && trimmed.contains(" 类型由 ")) { + return "**字段类型变更**: " + trimmed.substring("字段 ".length()).trim(); + } + return trimmed; + } + public String toConsole(CheckReport report) { if (!report.hasChanges()) { return "未检测到 Redis 序列化结构变更。"; diff --git a/src/test/java/com/codechecker/redis/report/ReportBuilderTest.java b/src/test/java/com/codechecker/redis/report/ReportBuilderTest.java new file mode 100644 index 0000000..6bbedd5 --- /dev/null +++ b/src/test/java/com/codechecker/redis/report/ReportBuilderTest.java @@ -0,0 +1,43 @@ +package com.codechecker.redis.report; + +import com.codechecker.redis.diff.ChangeType; +import com.codechecker.redis.diff.SchemaChange; +import com.codechecker.redis.diff.Severity; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ReportBuilderTest { + + @Test + void markdownTemplateWithoutModeAndSummary() { + CheckReport report = new CheckReport(); + report.setRepository("jnpf-java-cloud"); + report.setBranch("code/redis_change_detection_v1.0"); + report.setOldSha("cedd161c"); + report.setNewSha("67c8a6eb"); + report.setModifier("dongzi"); + report.setModifyTime("2026-07-13 16:54:17"); + report.setMode("notify"); + + SchemaChange change = new SchemaChange(ChangeType.FIELD_REMOVED); + change.setSeverity(Severity.P0); + change.setKeyPattern("saas:period-config:migration:current"); + change.setWriteLocation("SaasPeriodConfigMigrationRedisSupport#putCurrent:41"); + change.setMessage("删除字段 lastError1"); + report.getChanges().add(change); + + String md = new ReportBuilder("[Redis数据结构变更]").toMarkdown(report); + + assertTrue(md.startsWith("## [Redis数据结构变更] jnpf-java-cloud")); + assertTrue(md.contains("> **分支**: code/redis_change_detection_v1.0")); + assertTrue(md.contains("> **提交**: cedd161c → 67c8a6eb")); + assertTrue(md.contains("> **提交人**: dongzi")); + assertTrue(md.contains("> **时间**: 2026-07-13 16:54:17")); + assertTrue(md.contains(" - **位置**: SaasPeriodConfigMigrationRedisSupport#putCurrent:41")); + assertTrue(md.contains(" - **删除字段**: lastError1")); + assertFalse(md.contains("模式")); + assertFalse(md.contains("汇总")); + } +}