v19.5.0
v19.5.0 — 脱敏闸门 · 把铁律变成不可绕过的程序
定性:纪律版。 不改任何运行时行为,改的是「什么情况下才允许发布」。
为什么有这一版
前两轮连续栽在同一件事上:脱敏做了,但做没做到位,全靠人的记性和自觉。写在文档里的铁律,人会漏;漏了以后没有任何东西会红。
更麻烦的是,这类工具的失败是沉默的——词表少配一个词,扫描照跑、报告全绿、脏包上了公开索引,事后才发现。它不报错、不崩溃,只是安静地发放一张「已经检查过了」的凭证。
一个坏掉的扫描器和一个干净的项目,报出来的东西一模一样:都是「0」。
所以这一版真正要解决的问题不是「能不能扫出来」,而是 「当扫描器坏掉时,它会不会老老实实地失败」。
做了什么
| 变更 | 说明 |
|---|---|
新增 scripts/release_scan.py |
七面敏感内容扫描器。词表外置于仓库之外,模块内无任何内置词表兜底;词表为空或缺失一律拒绝运行(退出码 2) |
新增 tests/test_release_hygiene.py |
20 条守卫盯着闸门本身。核心是把扫描逻辑打坏成瞎子(什么都不报)、疯子(什么都报)、漏勺(豁免溢出全文件),自检必须每种都抓到 |
| 负向对照焊进代码 | 每次真扫前先在合成样本上三向验证;任一不符即退出码 3,整轮结果作废 |
| 公开面六面升七面 | 新增「⑥ 包索引渲染面」——元数据渲染出的项目网页,不下载就能看见 |
| 豁免机制收窄 | 只认命中所在的那一行,无文件级、更无目录级豁免;且豁免仍逐条出现在报告里:从失败计数里消失,不从视野里消失 |
scripts/backup_gate.sh |
备份根默认值不再写死任何部署环境绝对路径,改为相对仓库根目录 |
闸门第一次真扫,就抓到了它自己
首版 main() 用「不以 - 开头就是目录」挑扫描目标,于是 --name X 的选项名被丢掉、值 X 被当成目录——而 X 并不存在,扫出 0 个文件,报告照样打印 ✅ 无硬敏感命中。
一个手滑的参数换来一行绿色,正是本版立意要消灭的那类静默失败,首轮真扫时当场踩到。
已修:未知选项拒绝运行、扫描目标不存在拒绝运行(均退出码 2),并各补一条带正向对照的守卫——证明拒绝来自参数本身,而不是那个目录有问题。
这次打脸的完整经过写进了 CHANGELOG.md 与 ducky/version.py。藏起来没有意义。
兼容性
与 v19.4.3 运行时行为完全等价。 无 API 变更、无数据迁移、无配置变更。升级即替换。
测试
423 用例 · 独立开发机 411 passed / 12 skipped · 完整环境 423 全绿
Full Changelog: v19.4.3...v19.5.0