Skip to content

Releases

code-association 0.10.0

Choose a tag to compare

@geek-xin geek-xin released this 30 Oct 05:55

code-association 0.10.0

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

这一版有两件新东西:设置页可以把设置项 + 全部代码源导出成一个文件,搬到另一台机器上导入回来;
证据面板不再只贴引用行上下 3 行,而是把引用行所在的整个方法 / 类型 / XML 元素 / SQL 语句展开。
同时修好两处「读不到、读不全」的问题:大变更上影响清单过多会让整次分析在最后一步失败,
历史报告的证据链则整段显示「源码不可用」。

新增:配置导入导出

换机器以前要分两步:先用「代码源导入导出」搬代码源,再手工重配 AI 接口与 GitLab 令牌——
只带走代码源的话,另一半配置没人记得,新机器上第一件事就是「AI 审核怎么不生效」。
现在设置页的「配置导入导出」卡片把 AI 审核设置、GitLab 令牌与全部代码源装进同一个文件
(kind=code-association.config、version=1),导出与导入各一个接口。

  • 密钥默认不进文件。 「包含密钥」默认不勾,此时文件里没有 ai.apiKey 与 gitlab.token;
    只有显式勾选或 ?secrets=1 才写入,导出响应带 Cache-Control: no-store。
  • 导入不会清空本机密钥。 文件里没写的字段保持本机现值——一份不含密钥的备份被导回来,
    不该顺手把令牌清空。
  • 部分成功是常态,仍是 HTTP 200。 设置项按 ai / gitlab 分组独立校验、独立应用,
    失败的一组记入 settings.errors(带 section 与中文 reason),其余分组与代码源照常生效;
    只有 kind 不认识、version 比 1 新才回 400。
  • 也接受 5.9 的代码源导出文件(kind=code-association.sources),此时只处理代码源。

新增:证据链展开引用行所在的整段代码

证据行与路径跳点下方原来固定贴引用行上下各 3 行:够看清一个条件,却常常把方法签名和结尾切在
窗口外,读者仍然要回仓库确认「这是哪个方法」。现在 GET /api/analyses/{id}/code 支持
mode=block(界面固定传),片段按代码块边界取整块:

  • Java / JS / TS 等花括号语言取最近的方法体 / 类型体 / 初始化块;if / for / try 这类
    控制块继续向外扩,lambda 与匿名类也继续向外;字符串、注释、文本块里的花括号不参与配对。
  • MyBatis mapper / XML 取包含引用行的元素(通常是一整条 <select>),根元素不选。
  • .sql 按分号切语句,字符串与注释里的分号不算。
  • 没有块边界的 .properties / .yml 退化为上下各 10 行。
  • 超过 160 行的块只展示引用行附近,并注明「共 N 行,展示第 a–b 行」。

片段上方新增一行小字说明范围(「方法 · 第 27–30 行」「元素 select · 第 5–20 行」);
原来的 note 继续只承担「分析版本不在本地仓库」「文件只到第 N 行」这类异常说明。

修复:跨程序影响过多时,分析不再在最后一步失败

一次 2880 个文件、20052 项变更的分析产出 67 万条跨程序影响,report_json 序列化成单个字符串时
撞上 Jackson 的 2 GiB 文本缓冲上限,整次分析在跑完 107 秒后被标记失败、报告全丢。现在影响清单
按风险保留前 N 条(code-association.max-report-impacts,默认 5000,名额按对比程序公平分配),
计数仍按全量;报告新增 impactsTotal / impactsShown / impactsTruncated / impactsNote,
审核页明确写出「共多少处、列表保留多少处」。同一批影响不再序列化两遍(peers[].impacts 不再进
JSON),契约地图的模块关系边也按程序去重。

修复:历史报告的证据链不再整段显示「源码不可用」

报告里的 peerSourceId 是 long,本程序内部影响落库后是 0 而不是 null;前端把 0 当成
对比程序 id 传给源码接口,服务端按「这次分析里没有该对比程序」拒绝。现在 0 与空值同义
(读本程序源码),历史报告里也能直接展开方法。

下载

文件 说明
code-association-0.10.0.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.10.0.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.10.0.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.10.0.tar.gz   # 或 unzip code-association-0.10.0.zip
cd code-association-0.10.0
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。

本版新增一个配置项 code-association.max-report-impacts(默认 5000,0 或负数表示不截断),
其余配置与历史报告不受影响;被旧缺陷挡住的分析重新发起一次即可。

code-association 0.9.2

Choose a tag to compare

@geek-xin geek-xin released this 30 Oct 02:58

code-association 0.9.2

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

这一版修好「勾选仓库首次提交就分析失败」:选中的最旧提交没有父提交时,基线按空树处理,
首次提交照常进入评审,不再整次分析报错。

修复:勾选仓库首次提交不再导致分析失败

「提交范围」模式勾选提交时,基线固定取「最旧那个选中提交的父提交」。仓库的首次提交没有父提交,
于是整次分析直接报「选中的提交 xxx 是仓库的第一个提交,没有可比对的父提交」,首次提交因此
完全无法评审——而 GIT_DIFF 把首次提交当作目标时一直是按空树处理的。

现在勾选路径与 GIT_DIFF 一致:基线为空树,首次提交里的内容相对空树都是新增,rangeNote
会注明「最早提交没有父提交,基线为空树」。同时勾选首次提交与其后的提交时,diff 仍只包含
这些提交碰过的文件,中间提交不会混进来。

下载

文件 说明
code-association-0.9.2.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.9.2.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.9.2.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.9.2.tar.gz   # 或 unzip code-association-0.9.2.zip
cd code-association-0.9.2
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。

本版只有分析行为修复,没有新增配置项;已有配置与历史报告不受影响。被这个缺陷挡住的分析
(勾选了仓库首次提交的那次)重新发起一次即可。

code-association 0.9.1

Choose a tag to compare

@geek-xin geek-xin released this 29 Oct 11:04

code-association 0.9.1

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

这一版修好「分析卡在 96%」:AI 评审段有了总时间预算并按阶段推进进度;「影响审核」页
合并成一处影响清单,每条证据直接贴出引用行上下 3 行源码;远程代码源名称统一为程序名。

修复:分析不再「卡在 96%」

96% 是 AI 评审段的进度。以前整段只写一次 96%,之后最多十几次串行模型调用没有任何更新,
看起来和卡死一样。现在 AI 段按阶段上报:生成评审要点 → 逐条评审意见 → 分块 i/n →
重定位意见 i/n → 反思意见 → 整理意见,百分比在 96..99 之间推进;100% 仍只由报告落库写入。

新增:AI 段总时间预算

code-association.ai.total-budget-seconds(只写在 application.yml)限制摘要 + 最多十几次评论
调用的总耗时;不写时按 timeout-seconds × 3 推导并夹在 90..900 秒。每次调用把单次超时收缩到
剩余预算内,耗尽后停止剩余调用并保留已生成部分。传输层同时限制整次交换(含 body 读取):
上游发完响应头再停写 body 时,不再能永久挂住一次分析。

预算耗尽只影响这次解释,影响清单、路径与风险结论不变;reviewError 与 reviewStats.notes
会说明「超出时间预算,已保留已生成的部分」。

改进:影响审核页只剩一处影响清单

「对其他程序的影响」不再单独占一张全宽卡:发现列表标题下用一行汇总 pill(每个程序:契约数 /
影响处数),逐条影响只在列表里出现一次;右侧证据面板在未选中发现时展示完整契约命中与对方使用点,
选中后切换为逐跳证据链,并保留「契约命中」按钮回到默认态。两栏在 ≤1180px 折成单列。

新增:证据直接贴出引用行源码

复核页与影响详情页的每条证据、每一跳下方,内联引用行上下各 3 行源码(引用行高亮、超长行截断)。
本程序按报告记录的 head commit 读取,对比程序按分析时记录的 peer commit;纯目录或旧提交已丢失时
退回当前工作区并在片段下注明。GET /api/analyses/{id}/code 只允许读取报告引用过的文件。

改进:远程代码源名称统一为程序名

远程仓库名称取 URL 最后一段(程序名),与本地目录名一致;owner / group 仍在位置里显示。
升级后首次启动只改写「仍等于旧 owner/repo 推导值」的记录,手工命名与本地代码源保持不变。
两个 group 下的同名程序会显示同一个名称,用位置区分。

修复:侧栏选中代码源的图标不再消失

active 行只把条目主图标染成白色;代码源那枚 22px 品牌磁贴固定用 --primary-700,
浅色与深色主题下都可见。

下载

文件 说明
code-association-0.9.1.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.9.1.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.9.1.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.9.1.tar.gz   # 或 unzip code-association-0.9.1.zip
cd code-association-0.9.1
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。

本版新增可选的 code-association.ai.total-budget-seconds;已有配置与报告不受影响。
远程代码源的名称会在启动时自动收敛为程序名(只改仍等于旧推导值的记录,手工命名不动)。
历史报告不会重写——要看到新的复核页与证据源码,请重新分析一次;旧报告仍可打开,
源码片段会退回当前工作区并在片段下方注明。

code-association 0.9.0

Choose a tag to compare

@geek-xin geek-xin released this 29 Oct 08:10

code-association 0.9.0

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

这一版新增 GitLab 私有仓库令牌设置,并重做左侧导航与总览影响卡;接口向后兼容。

新增:设置页配置 GitLab 个人访问令牌

私有 GitLab 仓库不再必须先导出 GITLAB_TOKEN 再重启。设置页新增「GitLab 私有仓库」卡片:
粘贴个人访问令牌(PAT,scope 至少 read_repository)保存即生效,克隆、fetch、列分支都使用它;
只对来源类型 GITLAB 生效,GITHUB / GIT / LOCAL_* 不会附加。

令牌存 {data-dir}/gitlab-settings.json(原子写、POSIX 600),GET/PUT /api/gitlab 只回显掩码;
代码源「凭据环境变量」有值时优先,否则回退到设置页令牌或 yml 的 code-association.gitlab.token
(默认读 GITLAB_TOKEN)。自建 GitLab 的 http:// 与 https:// 地址都支持。

改进:单侧栏,默认收起

原来 68px 图标栏 + 268px 文字菜单合成一条 288px 紫色侧栏:展开显示图标 + 标签 + 搜索 +
代码源/状态/最近分析,收起只剩 72px 图标列。默认收起;展开后写入 localStorage 的
ca.nav,下次保持。折叠/展开按钮都在侧栏顶部,状态与 aria-expanded 同步。

改进:总览影响卡合并

「其他程序的待处理影响」与「对其他程序的影响」合并为一张卡:先给每个对比程序一枚
契约数 / 影响处数汇总 pill,再按风险列出前 6 条影响并标注待复核 / 已确认 / 已忽略;
完整的契约命中、使用点与逐跳传播仍在「影响审核」页。

改进:只保留一个添加入口

去掉「代码源」分组标题里重复的加号,只保留侧栏顶部页面标题旁的添加按钮。

下载

文件 说明
code-association-0.9.0.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.9.0.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.9.0.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.9.0.tar.gz   # 或 unzip code-association-0.9.0.zip
cd code-association-0.9.0
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。

本版新增 code-association.gitlab.token 配置(默认读 GITLAB_TOKEN),已有配置不受影响;
设置页令牌保存在数据目录的 gitlab-settings.json,删除该文件重启即可回退到 yml / 环境变量。
历史报告不会重写——请重新分析一次,新的侧栏、总览与 GitLab 令牌才会生效。

code-association 0.8.0

Choose a tag to compare

@geek-xin geek-xin released this 29 Oct 02:09

code-association 0.8.0

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

这一版新增两个能力并修掉一类数据库误报。接口向后兼容,AI 相关新增配置项默认开启。

新增:AI 逐条评审意见(行号由本机算)

AI 审核在整段摘要之外新增逐条意见:每条带严重级、类别、标题、正文、建议、代码引用与
文件:行。模型只逐字引用代码,行号由三层定位在本机算出——hunk 文本匹配 → 整文件扫描
→ 模型重定位;三层都失败就丢弃并计数,不猜位置。

误报由两层过滤控制:确定性过滤(送审文件、证据编号、行号范围、白名单、相似评论合并、
上限截断)之后,可选的反思模型只删除与代码事实矛盾的评论;反思失败或解析失败时保留全部。
每一步都有 token 预算:最多 20 个文件、单文件约 4000 tokens、单 chunk 约 8000 tokens、
每 chunk 最多 10 条评论、反思输入约 12000 tokens。

设置页新增「生成逐条评审意见」「每条分析最多评论」「用反思模型过滤误报」三项;
报告新增 ai.comments / ai.reviewStats / ai.reviewError,分析页与 Markdown 导出同步展示。

新增:提交范围改为勾选要分析的提交

「提交范围」不再要求先填一对起止提交:选择分支,可用 since / until 日期缩小范围,
从最新的 100 个提交里勾选本次要分析的那些。接口 GET /api/sources/{id}/commits 新增
since / until 可选参数,响应带 more;换分支或改日期后,不在新列表里的勾选会自动取消。

修复:删除写语句不再被当成「删除数据库字段」

删掉一条 mapper 写语句(或从 SET / INSERT 列清单里去掉某列)时,本程序只是停止写入
该列,列本身仍在数据库里,对方的 SELECT 不会失败。此前它被当成列删除,命中了所有读该列
的对方程序(例如 AuthMapper.getRightLogList 读 igm_card_right_log.error_reason),
是明确误报。现在停止写入某列只计入「对对方不可观察的变更」,不生成跨程序影响。

字段删除只认迁移脚本里显式的 ALTER TABLE ... DROP COLUMN(或列重命名的旧列名);
只是 CREATE TABLE 快照里不再列出该列(改列清单、删建表脚本)不再按删除传播,只计数。
真正的列删除仍会命中对方读方、写方与映射方。

下载

文件 说明
code-association-0.8.0.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.8.0.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.8.0.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.8.0.tar.gz   # 或 unzip code-association-0.8.0.zip
cd code-association-0.8.0
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。

本版 AI 相关新增 comments / max-comments / reflection 三个配置项,默认开启;
关闭「生成逐条评审意见」即回到只发送分析摘要的模式。历史报告不会重写——请重新分析一次,
逐条评审意见与新的数据库字段删除判定才会出现在报告里。

code-association 0.7.1

Choose a tag to compare

@geek-xin geek-xin released this 28 Oct 15:46

code-association 0.7.1

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

这一版只修一个误报,不改接口、配置与更新机制。

修复:删除实体字段不再被算成数据库列变化

当本程序删除/修改一个 JPA 实体字段,而对比程序也映射同一列时,0.7.0 会把该命中从
共享的列节点继续传播,把对方所有读该列的 SQL(例如 MyBatis 的
ElectricDeviceMapper.getSwitchDevices)报成 HIGH 的 DATA 影响。实体字段删除并不
改变数据库列,对方的 SQL 与自己的映射都不会坏——这是误报。

现在这类命中只保留为低置信度映射提示:

  • 仍然报告「对比程序也映射了同一列」,写入报告说明与计数,避免悄悄丢掉;
  • 不再生成跨程序影响项,也不会把该列的其他读写代码拉进影响路径;
  • 如果双方通过 Maven 依赖共用同一个模型类,字段删除仍可能造成编译失败,
    这种情况请按「Maven 依赖」契约单独确认。

真正的数据库列变化(迁移脚本里的 DROP COLUMN)不受影响:对方读、写、映射该列
的代码仍会正常命中。

下载

文件 说明
code-association-0.7.1.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.7.1.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.7.1.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.7.1.tar.gz   # 或 unzip code-association-0.7.1.zip
cd code-association-0.7.1
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。

本版不改接口、配置与更新机制;历史报告不会重写——请重新分析一次,0.7.0 里那条
「实体字段删除 → 对方 mapper 读列」的误报不会再出现。

code-association 0.7.0

Choose a tag to compare

@geek-xin geek-xin released this 28 Oct 10:58

code-association 0.7.0

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

这一版有两个主题。日志可运维:应用日志按天滚动、保留 7 天,关键节点改成可检索的
结构化事件行,进程原始输出单独收集。数据库影响判断继续收紧:一条 ALTER 的多个
动作分别报告;表重命名按旧表名命中;NOT NULL 且无默认值的列开始命中省略它的
INSERT,不再只算「盲区」。

本次重点:日志可运维

  • 应用日志统一写到 logs/:code-association.log 是 INFO 及以上的完整时间线,
    code-association-error.log 只收 ERROR,archive/*.log.gz 是滚动归档。
    目录由 code-association.log-dir 决定(默认 ./logs,环境变量 LOG_DIR 可覆盖),
    与数据目录 .code-association/ 分开,日志随时可清空。
  • 按天滚动,单文件超过 50MB 再切;只保留 7 天,cleanHistoryOnStart=true 让
    「停了一周再启动」也立刻清掉过期归档。主日志上限 500MB、错误日志 200MB,上限先于时间生效。
  • 写盘走 AsyncAppender:分析线程不为日志 IO 停顿,队列满时阻塞而不是丢日志;
    主日志与错误日志各用一个异步器(AsyncAppender 只接受一个 appender-ref)。
  • 会被反复查询的节点统一写成结构化事件行,例如
    event=analysis.done analysisId=42 source=order-service status=DONE durationMs=8421 high=1 medium=3 low=2:
    事件名小写点分且稳定,字段 camelCase,每条带定位 id 与 durationMs,可直接
    grep 'event=analysis.done' 或按空白切字段。覆盖分析链路、定时扫描、代码源增删改与
    导入导出、版本检查与更新、AI 配置与进程启停。
  • start.sh / start.ps1 的进程原始输出改到 logs/console.log(Windows stderr 为
    logs/console.err.log),每次启动截断,专收 logback 初始化之前的错误与 JVM 崩溃输出。
  • 测试不落盘:logback-test.xml 只写控制台,跑测试不会污染 logs/。

本次重点:数据库跨程序影响

  • 一条 ALTER TABLE 的多个动作按动作报告。 以前每种动作只抓第一个:
    ADD a INT, ADD b INT 只看得到 a,ADD a, DROP b 甚至把 ADD 的类型留在
    DROP 的记录里。现在按顶层逗号拆出全部动作(括号 / 字符串内的逗号不拆),每个动作记
    kind / table / column / type / nullable / default / schema / renamedTo;变更检测按
    kind|table|column 对齐两侧动作,新增、修改、移除各生成一条 DDL_CHANGED,
    因为加列、删列、改类型对读写方的后果不同,不能共用一条结论。语句级旧字段仍保留第一个
    动作,旧索引与旧报告继续可读;ADD INDEX、ADD CONSTRAINT、ENGINE= 等非列动作被忽略。
  • 表重命名按旧表名的表级契约命中。 ALTER TABLE orders RENAME TO orders_archive
    (含顶层 RENAME TABLE ... TO ...)现在生成 RENAME_TABLE 记录:契约写旧表名,
    风险种子 0.90,对方读、写、映射旧表的代码都会命中。新表名刻意不产生候选——它是这次
    改名才出现的,报它等于把同一次改名算两遍。列重命名也不再额外产生一条
    「新列名被当成不可观察加列」的假计数。
  • NOT NULL 且无默认值的列开始命中写入方。 对方一条
    INSERT INTO orders (id) VALUES (?) 省略了新增必填列,MySQL 严格模式、PostgreSQL、
    Oracle 都会拒绝——这是真实不兼容,不该只算盲区。规则只命中完整的 INSERT
    (非动态 SQL)且列清单里没有该列的语句;UPDATE / DELETE 不命中,SELECT * 与
    动态 SQL 仍计入字段盲区且不重复计数。列可空、有默认值,或由数据库自动填充
    (AUTO_INCREMENT / GENERATED / IDENTITY)时都不算必填。
  • 报告口径:新增「必填列变更」计数与后果说明;这类变更不再同时计入
    「对对方不可观察」(否则同一件事既说「对方看不见」又说「对方写入会失败」)。
    「不可观察变更」的措辞同步覆盖「移除 DDL 动作」。
  • 顺手修掉的解析问题:多语句 .sql 中第二条语句的行号曾被算成上一行,导致
    sql:文件#行号 key 撞车、前一条语句被覆盖;现在按第一条非空白字符计算,多语句脚本的
    每个语句都有独立 key。DDL 定义里的 DEFAULT 'a,b' 不再被顶层逗号拆分。

已知边界

数据库侧仍不分析:写入列集合不变但值语义变了(如 status 1 → 2)、事务与锁顺序、
视图 / 触发器 / 存储过程 / 外键级联、真实数据分布、运行时实际 SQL,以及同一程序
多数据源 / 多 schema 下同名表的快照键冲突。自动填充列只识别 ALTER 列定义文本里的
AUTO_INCREMENT / GENERATED / IDENTITY,触发器、序列等其他机制未识别。
报告的「未发现影响」只表示静态契约层没有找到不兼容证据;SELECT * 与动态 SQL
仍以「字段盲区」列出,需要人工确认。

下载

文件 说明
code-association-0.7.0.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.7.0.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.7.0.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.7.0.tar.gz   # 或 unzip code-association-0.7.0.zip
cd code-association-0.7.0
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。
0.3.0 及更早的版本没有应用内更新,请手动下载替换 jar(旧 jar 会被备份为 .bak-<版本>,可回滚)。

本版不改接口与更新机制;新增一个可选的日志目录配置 code-association.log-dir
(默认 ./logs,环境变量 LOG_DIR 可覆盖),不设置也能正常启动。
但日志位置有变化:应用日志改到 logs/,启动脚本的进程输出改到 logs/console.log
(Windows 为 logs/console.err.log),旧版写在根目录的 code-association.log 不再更新。
历史报告不会重写——要看到新的判定,请重新分析一次。

code-association 0.6.1

Choose a tag to compare

@geek-xin geek-xin released this 28 Oct 03:03

code-association 0.6.1

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

这一版没有新功能,全部是 0.6.0「字段级数据库契约」落地之后暴露出来的误报与漏报。
数据库契约的准入条件现在固定为四步:同一数据库对象 → 变更可被观察 → 类型兼容 →
字段级命中
。不满足的不扩散,只计数并在报告里说明,或者进「字段盲区」等人确认。
此前「同名表就命中」「加一列和删一列一样严重」这类结果不会再出现。

本次重点:先确认是同一张表

  • 契约 key 仍是 表.字段,但匹配前先比较两侧的数据源身份:从
    spring.datasource.url / spring.datasource.*.url / spring.datasource.hikari.jdbc-url
    解析数据库名,从 SQL 与 DDL 的 schema.table 读取显式 schema。
  • 两侧都已知且同层级不同 → 排除并计数;一侧未知 → 保留匹配但降低置信度;
    H2 mem / HSQLDB / Derby / SQLite 视为未知,因为进程内数据库不共享数据。
  • 报告会说明有多少候选因数据库不同被排除、多少条因一侧未声明数据库而无法确认同库,
    而不是让它们悄悄消失。

本次重点:DDL 按「变更可被观察」分型

  • 会扩散:DROP COLUMN、收窄类型(VARCHAR(64) → VARCHAR(32)、BIGINT → INT)、
    类型族变化 → 命中读方、写方、映射方。
  • 不扩散只计数:ADD COLUMN、CREATE TABLE、删除迁移脚本、
    类型放宽(VARCHAR(32) → VARCHAR(64)、INT → BIGINT)。加列 / 建表 / 删除迁移脚本
    以前是「悄悄消失」,现在报告给出「对对方不可观察的变更」计数与示例。
  • 新增 ColumnTypeCompatibility:按字符串长度、整数等级、decimal 精度 / scale、
    可空性与安全提升判断兼容性;判断不了就保留命中并降低置信度,不猜。
  • decimal 的整数位补上了:DECIMAL(10,2) → DECIMAL(10,4) 的 scale 变大、precision 不变,
    但整数位从 8 位降到 6 位,12345678.99 放不进去——现在按收窄扩散,不再当成兼容抑制。
  • 加列只对 SELECT * / 无列名 INSERT 形成字段盲区;删除迁移脚本不再被当成 schema 回滚。

本次重点:实体映射与数据库 schema 解耦

  • FIELD_ADDED 不再产生数据库 delta;FIELD_REMOVED / FIELD_TYPE_CHANGED
    只对同样映射该列的对方代码给出低置信度 mapping 提示,不再命中 SQL 读写方。
  • @Transient、static、集合类型不建列映射;显式 @Column / @JoinColumn
    优先于隐式命名;隐式命名按 Hibernate 边界转换(userID → user_id、URLPath → url_path)。

本次重点:解析加固

  • 解析前剥离 SQL 行注释与块注释:注释掉的 ALTER TABLE ... DROP COLUMN 不再生效,
    纯注释改动不再产生 SQL_CHANGED。
  • MySQL 的 # 行注释同样识别:# 注释里的分号不再把一条 DDL 切成两条。
    MyBatis 的 #{id} 占位符与 PostgreSQL 的 #> / #- 运算符不受影响。
  • 单引号内的反斜杠转义被识别:'it\'s' 不再被当成「字符串到此结束」,
    后半句不会被当作 SQL 解析。
  • 同一 SQL 从一个 mapper / 迁移文件移到另一个时,按规范化文本配对
    SQL_REMOVED 与 SQL_ADDED 并抵消——「文件搬家」不会被读成「本程序停止写这一列」。
  • 动态 SQL(<if> / <choose> / <foreach> / <include>、占位符拼接)不再降级为
    表级契约,对方侧改为计入字段盲区。
  • src/test/ 下的 mapper、schema.sql、data.sql 与迁移脚本不参与生产契约。
  • ADD INDEX / ADD CONSTRAINT / DROP INDEX 不再被当成列;INSERT ... SELECT
    读取目标列清单;ON DUPLICATE KEY UPDATE 不再凭空造出名为 status 的表。
  • ALTER / 迁移脚本:识别 PostgreSQL 风格 ALTER COLUMN ... SET/DROP NOT NULL / SET DEFAULT、
    ADD/DROP COLUMN IF [NOT] EXISTS、RENAME COLUMN;多动作 ALTER 的类型不再吞掉后续动作;
    迁移脚本按数值版本排序(V10 在 V2 后);按引号 / 注释外的分号切分语句;
    DDL 只在语句开头识别,字符串字面量里的 CREATE TABLE 不再污染快照。

报告

  • 新增「因数据库不同被排除」「因类型兼容被排除」「对对方不可观察」三组计数与说明。
  • 兼容变更与不可观察变更按变更计:此前按「变更 × 对比程序」累加,对比的程序越多,
    同一个数字越大。
  • 字段盲区口径修正为「读写列都没解析出来或语句不完整」,已作为 writer 命中的纯写语句
    不重复计入。
  • 文档新增 docs/wiki/数据库影响判断.md:四个准入条件、DDL 分型对照表、类型兼容规则、
    字段盲区口径,以及仍然存在的边界(值语义、事务并发、视图 / 触发器 / 存储过程、运行时 SQL)。

下载

文件 说明
code-association-0.6.1.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.6.1.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.6.1.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.6.1.tar.gz   # 或 unzip code-association-0.6.1.zip
cd code-association-0.6.1
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。
0.3.0 及更早的版本没有应用内更新,请手动下载替换 jar(旧 jar 会被备份为 .bak-<版本>,可回滚)。

这一版只改分析结果,不改接口、配置与更新机制:升级后不需要改 application.yml,
历史报告也不会被重写——要看到新的判定,请重新分析一次。

code-association 0.6.0

Choose a tag to compare

@geek-xin geek-xin released this 28 Oct 01:00

code-association 0.6.0

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

本次重点:按提交范围评审

新增分析模式 COMMIT_RANGE:起点「起始提交(不含)」与「结束提交(含)」两端明确指定,
用于「这 12 个提交是我要合进去的」这类以提交为单位、而不是以分支名为单位的评审。

  • 弹窗选到该模式后,两个输入框变成起始 / 结束提交,输入时给出该仓库的提交下拉
    (短 SHA + 提交标题),下方实时预览本次范围包含哪些提交(防抖 300ms,
    读取失败只显示一行提示,不打断表单)。
  • 新增 GET /api/sources/{id}/commits:只带 ref 时返回该分支最新提交,
    带 base + target 时返回该范围内的提交,两种形态同一份响应结构。
  • 报告新增 commits / commitCount / rangeNote,分析页新增「提交范围」卡片,
    PR 评论(--format markdown)在影响明细之前列出本次提交。最多列 200 个
    (按提交时间倒序),超出时注明「只列出最新的 N 个」,而不是把截断列表当作全部。
  • 范围必须是同一条提交线上的祖先关系:起始提交不在结束提交的历史里时直接拒绝,
    并说明是哪一端不成立。否则仍会产出 diff,但那是在比较两个无关快照,
    报告会显得正常而实际答非所问。
  • 只分析选中的几个提交:预览里每一行都能勾选,勾中的提交才进分析。
    基线取最旧那个选中提交的父提交,目标树是选中提交按拓扑从旧到新依次叠加的结果,
    所以 diff 恰好只包含它们碰过的文件;跨分支的选择描述的是一个从未存在过的树,
    直接拒绝并指出哪个提交不在线上。报告新增 selectedCommits。
  • 命令行新增 --range <起始>..<结束>,等价于 --base + --target 并切到
    COMMIT_RANGE;范围解析失败改为退出码 2 + 一句人话,
    此前是未捕获异常,整段堆栈把原因淹没了。

本次重点:数据库契约的单位从「表」改为「字段」

  • 此前只要本程序有一条 SQL 变了,就把这条语句读写的表当成变更契约,对方凡是读写
    同一张表的代码全部命中。「给自己多查一个字段」这种纯内部改动,也会把对方所有碰这张表的
    模块拉进候选队列,噪声盖住了真正需要通知对方的那几条。
  • 现在本程序侧的数据库变更只收三类:表结构变更(DDL)(ALTER TABLE ... ADD / DROP / MODIFY COLUMN 落到具体字段)、写入字段集合变化(INSERT 列清单、UPDATE SET 列
    新增或消失)、实体字段映射变化(@Column 映射的 Java 字段新增 / 删除 / 类型变化)。
    只改 WHERE、JOIN、排序的语句不再产生跨程序数据库影响。
  • 匹配侧改为命中对方 db:column:<table>.<column> 上的使用点(读 / 写 / 实体映射),
    命中条目为 DB_COLUMN。只改读取字段集合不扩散:读多少列是本程序的内部行为,
    对方的查询不会因此失败。写入字段集合变化只命中读方;表结构变更命中读方与写方。
  • 风险种子按操作区分:删字段 / 删表 0.95、改字段类型 0.90、写入字段集合变化 0.85、
    加字段 / 建表 0.60。删比加严重:加一列对方按列名读写通常无害,删一列对方照常运行却读到空值。
  • 对方写 SELECT * 或语句无法解析出列名时不再命中字段级契约,但会计数并在报告里标注
    「字段盲区」
    ——「没读到」不能当成「没影响」。

本次重点:AI 审核从「只能改配置文件」变成可选功能

AiExplainer 早已存在,但只能在 application.yml 里配置,生成的 report.ai 前端从未
渲染,历史报告无法补生成,也没有测试连接。现在:

  • 设置页新增「AI 审核」卡片:启用开关、接口地址、模型、API Key、每条分析最多送审影响、
    请求超时、是否默认生成。「测试连接」发一个只要求模型回 pong 的最小请求并显示实际端点
    与耗时,配置错误的代价从「等一次分析失败」降到一次点击。三个快捷填充
    (DeepSeek / OpenAI / Ollama 本地)只填地址与模型,不动 Key。
  • 新增 GET /api/ai、PUT /api/ai、POST /api/ai/test、
    POST /api/analyses/{id}/ai-review;配置持久化到 {data-dir}/ai-settings.json
    (原子写,POSIX 下尽量 chmod 600)。
  • apiKey 绝不出现在响应、日志与错误信息里,读回的一律是掩码;保存时留空表示不修改,
    只有显式 clearApiKey 才清空。掩码回填的表单若把掩码当明文写回,Key 会在第一次保存后
    悄悄失效,而界面上看不出任何异常。
  • 分析页新增 AI 卡片,按状态给出不同的下一步;正文走既有简易渲染器(模型输出不直接进
    innerHTML),上方是随内容一起存下的 disclaimer,下方是模型、生成时间与送审条数。
  • 失败只影响这张卡:401、超时、响应无法解析都只把原因写进卡片,静态分析结论与 --fail-on
    退出码不受影响。命令行新增 --ai;未配置时打印一行提示并保持原退出码。
  • 关闭(默认)时报告、健康检查与分析流程与改动前完全一致。

本次重点:应用更新后自动重启,失败自动回滚

  • 此前的「应用更新」只把新 jar 覆盖到运行位置,然后提示用户自己执行 stop.sh /
    start.sh。那不算更新,只算通知——对无人值守的机器等于要求人恰好在线。
  • 现在 apply() 换完 jar 后把重启交给 RestartSupervisor:本进程把一个 POSIX 守护脚本
    写到 {data-dir}/restart/restart.sh 并脱离终端启动它,脚本 kill -0 等旧 PID 退出
    (端口因此自然释放)→ 起新 jar → 轮询 GET /api/health → 超时就用备份 jar 覆盖回去
    再拉起一次。
  • 本进程延迟约 1.5 秒才退出:延迟是为了让「更新成功」这个 HTTP 响应先写回浏览器。
    状态写进 {data-dir}/restart-status.json,重启完成后新进程仍能报告
    「上一次是成功了还是回滚了」。
  • 前端在应用更新后轮询轻量端点 GET /api/update/restart,见到 succeeded 自动刷新页面,
    见到 rolled-back 显示红色告警与日志路径。
  • 新增 auto-restart(默认开)、auto-apply(默认关)、
    restart-timeout-seconds(默认 90),以及 PUT /api/update/settings 供运行时切换。
    auto-apply 要求 auto-restart 同时为真:没有热重启的自动应用等于
    「自动把服务停掉等人来开」,那不是更新,是故障。

其他新增

  • 后台自动更新的进度可见:新增 GET /api/update/progress(phase / bytes /
    totalBytes / percent / automatic / message),顶部横幅与设置页各有一条进度条。
    总大小未知时走不确定态、只显示已接收字节数,不编造百分比;运行中最多显示 99%,
    100% 只属于真正结束的那一步。
  • GitHub 网络容错:api-base-urls 多源回退(404 / 401 不降级)、download-mirror、
    只作用于更新流量的 proxy、指数退避重试(5xx / 408 / 429 与传输失败可重试),
    以及全进程共享的 RateLimitGate(额度用尽时所有调用方查同一个截止时间)。
    全部 host 都失败时,每个 host 的失败原因折叠进 warnings 展示。
  • 界面规范落成文档:新增 docs/wiki/界面规范.md 与 docs/wiki/界面实现映射.md,
    把视觉与交互约定从 style.css 的注释里搬进可检索、可引用的文档(含按 WCAG 2.1 实算的
    对比度结论),并新增 UiContractTest 把关键令牌、类名双向契约、断点、焦点与
    reduced-motion、图标 sprite 引用固化为断言。

修复

  • 代码源行的编辑按钮是一块看不见的空白:按钮调 icon('i-edit'),而雪碧图里没有这个
    <symbol>;<use> 命中不到绘制内容时不报错、不占位,按钮还在、还能点,
    只是渲染成什么都没有。改用已有的 i-pencil,并新增 UiContractTest.IconSprite
    逐个核对引用。
  • 代码源列表的操作列偏窄,按钮向左压住「同步时间」列:.tr-sources 最后一轨 58px,
    而内容要 72px;.cell.actions 右对齐,轨道不够时不裁切而是向左溢出。统一改成 76px。
  • 编辑保存后的提示恒为「代码源已添加」:resetSourceModal() 在拼提示之前就把
    state.editingSourceId 清成了 null,判断读到的永远是「没在编辑」。
  • 编辑代码源后「目录缺失」状态不复位:可用性只在导入时判定一次,把位置改到正确目录后
    仍然显示「目录缺失」,还附带一句「导入时目录不存在」。现在编辑保存前显式重判一次。
  • 一次分析跑完会把用户在这期间的编辑整行覆盖掉:收尾时用提交那一刻的 RepoSource
    快照做整行 UPDATE。现在只更新 status / message / last_synced_at 三列——
    这三列是这次分析产出的,其余列归用户所有。
  • 开发模式下「当前运行版本」显示 0.0.0-dev:版本只从运行中的 jar 的 manifest 读,
    而 mvn spring-boot:run 没有 jar。现在构建生成 META-INF/build-info.properties 兜底。
  • 「当前环境不支持自动应用」只写「可能是在 IDE 里启动」:这句话是前端写死的,
    最常撞上它的恰恰是终端里的 mvn spring-boot:run。现在后端判定启动方式并给出具体原因
    与一条可复制的命令,设置页新增「启动方式」一行。
  • .sql 脚本里的 DDL 完全不会产生变更记录:变更识别对 .sql 直接返回,
    用脚本做表结构迁移的项目,加列、删列、删表这些最需要跨程序确认的改动一条都看不到。
    现在 .sql 同样参与比对,产出 DDL_CHANGED。
  • stop.bat 每次都提示「进程无窗口」并白等 3 秒:java.exe 是控制台程序,
    主窗口归 conhost.exe,MainWindowHandle 恒为 0,CloseMainWindow() 永远返回
    False。现在先判断句柄,没有就直接结束;停止只输出一行「已停止 (PID N)」。
    顺带修掉三处会骗人的输出:Stop-Process 权限不足时静默失败却照样打印「已停止」
    (现在复查并以退出码 1 结束)、结束改用句柄上的 Kill()(避免 PID 复用误杀)、
    按端口反查到的 PID 也要过 Test-ServicePid(此前会把恰好占用该端口的任何程序杀掉)。
  • 429 带 x-ratelimit-reset 时重试与多源回退同时失效:先记录限流截止时间再判断是否重试,
    下一轮循环开头的闸门检查立刻把重试打断,连带多源回退也被吃掉,备用源一次都没被请求。
    现在限流后不再对该 host 重试,但仍会去问下一个 host。
  • 重启状态会自相矛盾(「已回滚」同时「仍在重启」):state() 分别读 running 标志与
    phase,终态 phase 先写、标志后清,轮询落在窗口里就会拿到一个自相矛盾的响应。
    现在终态分支先清标志再写状态,running 直接由 phase 推导。

下载

文件 说明
code-association-0.6.0.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.6.0.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.6.0.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.6.0.tar.gz   # 或 unzip code-association-0.6.0.zip
cd code-association-0.6.0
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.6.0 起换完 jar 会自己重启(auto-restart 默认开),失败自动回滚到备份 jar;
更早的版本换完只会提示你自己执行 stop.sh / start.sh。
0.3.0 及更早的版本没有应用内更新,请手动下载替换 jar(旧 jar 会被备份为 .bak-<版本>,可回滚)。

code-association 0.5.0

Choose a tag to compare

@geek-xin geek-xin released this 27 Oct 02:10

code-association 0.5.0

跨程序变更影响扫描工具(Java / Maven 多模块仓库):分析一次提交改动了哪些类、方法、
SQL、MQ 消息结构,并推导出对其他模块 / 服务的连带影响与风险等级。

本次重点:分析过程进度实时可见

分析详情页在运行期间实时显示阶段、百分比、「第 N / 8 步」,以及当前处理的文件与计数
(如 C215.java (1531/2400)),步骤条随阶段点亮。此前大型仓库上进度会长时间停在
同一个数字,看起来像卡死——修掉了三个原因:

  • Progress.file 收下了 to 上界却从未使用,索引阶段始终上报 from(20%)。
    INDEX_HEAD 在大型仓库上占用绝大部分墙钟时间,界面于是一整段时间显示同一个数字。
    现在按已处理文件数在 [from, to) 内插值,阶段结束时仍精确落在边界上。
  • 真正的大头是 CallGraphBuilder.build() 的第二次全量遍历,它此前完全不报进度。
    两趟遍历现在共用一套计数单位(每文件两个单位),百分比单调上升,不会走到 100% 再回退。
  • 从历史记录打开正在运行的分析时只把快照塞进面板、没有订阅它,于是一次渲染后再也不动。
    现在打开运行中的分析会重新开始轮询。

本次重点:代码源标签与导入导出

  • 代码源标签分类:一个代码源可以打多个标签,左侧菜单按标签分组、每组可折叠,
    列表每行显示标签 pill,点一下即按该标签过滤。标签不参与分析,只影响检索与展示。
  • 代码源导入导出:设置页新增卡片,用于换机器迁移、团队共享与备份。
    按 type + location 判定同一代码源,已存在则合并标签(并集),不存在则新建;
    单条非法只记入 errors 并继续处理其余条目。
  • 编辑代码源:列表每行新增编辑按钮,走 PUT /api/sources/{id}。

本次重点:版本检查与自动更新

设置页新增「版本与更新」卡片:当前版本、最新版本、历史版本列表一目了然。
服务会定时向 GitHub 查询 release,不用再手动去发布页翻。

入口 作用
GET /api/update 当前 / 最新 / 历史版本(带缓存,命中不耗 GitHub 额度)
POST /api/update/check 强制重新检查
POST /api/update/download 下载指定版本的 jar 到 {data-dir}/updates/,边下边算 SHA-256
POST /api/update/apply 先备份当前 jar 为 <jar>.bak-<版本>,再替换
POST /api/update/rollback 从最近的备份回滚

检查是自动的,替换 jar 需要你点确认。 让程序重启自己会让前端拿不到响应,
也把「什么时候中断服务」的决定权从运维手里拿走了。替换后界面会提示执行
./stop.sh && ./start.sh(Windows 用 stop.bat 再 start.bat)。

三种情况会明确拒绝替换并说明原因:在 IDE 里跑(没有可替换的 jar)、Windows
(运行中的 jar 被系统锁定)、还没下载(无暂存文件)。

关于 GitHub 限流

未认证调用 api.github.com 每小时只有 60 次。默认 6 小时检查一次,够用;
频繁点「立即检查」会撞 403,此时界面会明确说明是限流并给出额度重置时间。
配置 GITHUB_TOKEN(只读 classic token,无需任何 scope)可提到 5000 次/小时。

左侧菜单栏可收起

文字菜单可以折起来只留图标栏,把宽度让给工作区:

  • 侧栏右上角的折叠按钮,或图标栏底部收起后出现的展开按钮;
  • 快捷键 Ctrl + B / ⌘ + B(在输入框里自动让位);
  • 选择记在浏览器本地,刷新后保持,首帧就按记下的状态渲染。

窄屏(≤860px)默认收起,但仍然可以手动展开——此前该断点把菜单藏死、没有展开入口。

修复

  • 重启提示会误判:apply 后要提示「已替换 jar,请重启服务生效」,原判据是
    「当前版本 == 已应用版本」。但 JVM 一直报告它启动时的版本,所以「重新应用正在跑的
    版本」会被当成「已经重启过」,提示当场消失。改用进程启动时间判断,
    status 返回 startedAt、apply/rollback 返回 swappedAt,只有前者晚于后者才算重启完成。
  • release.sh 的 jar 校验被 SIGPIPE 误判:unzip -Z1 ... | grep -q 在 pipefail 下
    是错的——grep -q 命中后立即退出,unzip 收到 SIGPIPE 被杀,整条管道返回 141,
    于是「校验通过」被当成失败。改为先把清单读进变量再 grep。
  • 分析失败后看不到任何详情:失败的分析没有报告,而详情页在没有报告时会隐藏
    #an-body,进度卡片原先正嵌在这个容器里,于是失败原因被写进一个 display:none
    的区域——点开一条失败记录,页面显示「暂无数据」和「这个代码源还没有分析记录」。
    现在进度/失败卡片移出该容器,失败时单独渲染「失败原因」区块;页面状态改由
    选中的分析记录推导,历史列表与总览时间线也直接显示失败原因。
  • 仓库里有一个超大文件,就导致该程序的每一次分析全部失败:
    GitTreeSource.read 把 20MB 写死在 loader.getBytes(20 * 1024 * 1024) 里,
    而 JGit 超限时抛的是 LargeObjectException(RuntimeException),原有的
    catch (IOException) 拦不住,异常一路冒到 AnalysisService.run,整次分析被标记为 FAILED。
    现在先比 loader.getSize() 再读,超限即跳过并在报告「跨程序分析边界」里列出文件名与大小。
    新增配置 max-file-mb(默认 20MB,设为 0 关闭限制)。

下载

文件 说明
code-association-0.5.0.jar 可执行 jar 单文件,应用内「自动更新」用的就是它
code-association-0.5.0.zip Windows 推荐(自带解压即可,保留 CRLF)
code-association-0.5.0.tar.gz Linux / macOS 推荐

两个压缩包内容完全一致,均包含:可执行 jar、start.sh / stop.sh、
start.bat / stop.bat / start.ps1 / stop.ps1、application.yml 示例配置、
README.md、docs/ 与 INSTALL.md。

运行

Linux / macOS

tar -xzf code-association-0.5.0.tar.gz   # 或 unzip code-association-0.5.0.zip
cd code-association-0.5.0
chmod +x start.sh stop.sh
./start.sh                          # 默认 http://127.0.0.1:9996
./stop.sh

Windows

:: 解压 zip,进入解压目录
start.bat                           :: 默认 http://127.0.0.1:9996
stop.bat

需要 JDK 21+。详见包内 INSTALL.md。

升级说明

从 0.3.0 起可以直接用应用内更新:设置 → 版本与更新 → 应用更新 → 按提示重启。
0.3.0 及更早的版本没有这个功能,请手动下载替换 jar(旧 jar 会被备份为 .bak-<版本>,可回滚)。