Chainguard Checks:CI结果何时可复用

黎 浩然/ 16 10 月, 2026/ 大语言模型/LARGELANGUAGEMODEL/LLM, 教程/TUTORIAL, 计算机/COMPUTER/ 0 comments

AI写完代码后,一份“测试通过”的结果可以复用,但前提是它验证的代码、检查集合和运行环境,仍然对应准备合并的对象。签名只能解决其中一部分问题:结果有没有被篡改、是否来自认可的执行者。它不能替你判断测试是否足够,也不能把旧代码的绿灯搬到新代码上。

文章目录
  1. 这次发布改变了哪一段反馈循环
  2. 绿灯最容易丢失的是“测了谁”
  3. 三个层次,三个不同的问题
  4. 用五个本地断言看清结果复用
  5. “同一个环境”不能只写Python版本
  6. 真正接入前,先决定拒绝哪些结果
  7. 资料与补发说明

Chainguard Checks把CI检查前移到开发循环,这个变化值得关注。下面从一次修改后的结果复用讲起,拆开“签名有效”和“允许合并”之间的距离。Read in English。

这次发布改变了哪一段反馈循环

Google News收录了10月15日的Trend Hunter报道。追溯Chainguard在10月14日的原始公告,Checks当时发布为Beta:开发者或Agent可以在提交前调用CI检查,运行侧使用预热、隔离的microVM,并返回签名判定。

这让“修改—检查—修复”的反馈有机会更早发生。它与仅让模型阅读代码不同:结果应来自执行检查的系统。公告也提到后续可配置合并门禁来复用通过结果;不能据此认为所有仓库已经自动免除重复CI,更不能把Beta公告当成经过独立测评的延迟或成本承诺。

1
冻结待测源码
包括实际改动
2
执行指定检查
记录环境与结果
3
执行者签名
保护结果完整性
4
合并端核对对象
再执行门禁策略
原创流程图:一次检查的结果只有在对象和策略仍匹配时,才可能被合并端复用。

绿灯最容易丢失的是“测了谁”

设Agent对工作区A运行测试,结果为通过。随后它又改了一个边界分支,工作区成为B。如果界面只保存“最后一次成功”,B就可能继承A的绿灯。即使A的结果签名完全有效,这次复用仍然错了。

因此结果必须绑定被测对象。只记录Git提交号可能不够:提交前检查面对的是尚未提交的改动,也可能包括测试配置、生成文件或依赖锁文件。工程上要定义输入快照的边界:哪些路径进入摘要、如何处理文件模式与符号链接、外部依赖如何固定。例如只给已提交的文件做摘要,却实际测试了工作区里的未提交补丁,报告就没有绑定真正被执行的版本。这个边界如果模糊,摘要再长也无济于事。

下面的教学模型把源码、检查集合、环境分别做摘要,并把它们放进受认证的报告。它是本文提出的简化协议,不是Chainguard实际证明文件的字段说明;公告不足以确认其完整负载格式。

三个层次,三个不同的问题

第一层是完整性:报告是否由可信执行侧产生、内容是否变化。第二层是对象匹配:报告中的源码、检查集合、环境是否与门禁要求一致。第三层是接受策略:哪些检查必须成功,跳过、超时、零测试分别怎样处理。

Sigstore验证文档把签名验证与负载声明检查区分开,并展示身份和签发者约束。这是理解门禁的一个参照,不意味着Checks采用本文的协议,或接入Sigstore后便自动完成测试策略。签名来自谁、签了什么、这些事实足不足够,必须分别回答。

可写成一个判断式:接受 = 来源可信 ∧ 内容完整 ∧ 对象匹配 ∧ 检查满足策略。任意一项缺失,都不应只凭一个绿色图标放行。

1
有效认证 + 同一对象
继续检查策略
2
有效认证 + 源码已变
拒绝复用
3
有效认证 + 零测试
示例策略拒绝
4
报告被改写
完整性检查拒绝
原创判定图:认证有效是必要条件之一;对象或测试策略不匹配,仍然不能接受。

用五个本地断言看清结果复用

这段Python只使用标准库。HMAC让示例无需外部签名库,但它是共享密钥消息认证,不是公钥数字签名;拥有验证密钥的一方也能生成认证码。因此它只用于说明绑定关系,不能直接充当面向Agent分发的生产签名方案。示例密钥每次运行临时生成,不输出。

# Teaching protocol only: not a Chainguard attestation format.
import hashlib, hmac, json, secrets

def encode(value):
    return json.dumps(value,sort_keys=True,separators=(",",":"),
                      ensure_ascii=True).encode("ascii")

def digest(value):
    return hashlib.sha256(encode(value)).hexdigest()

key = secrets.token_bytes(32)  # ephemeral demo key; never printed
expected = {"source": digest({"main.py": "print(1)\n"}),
            "suite": digest(["unit-v3", "integration-v2"]),
            "environment": digest({"image": "fictional-image-v1"})}
report = dict(expected, passed=True, tests=12)
def tag(report):
    return hmac.new(key,encode(report),hashlib.sha256).hexdigest()

def accept(report, signature, expected):
    if not hmac.compare_digest(tag(report),signature):
        return False
    if any(report.get(k)!=v for k,v in expected.items()):
        return False
    return report.get("passed") is True and type(report.get("tests")) is int \
        and report["tests"]>0

signature = tag(report)
assert accept(report,signature,expected)
changed = dict(expected,source=digest({"main.py": "print(2)\n"}))
assert not accept(report,signature,changed) # authentic, wrong source
assert not accept(dict(report,tests=120),signature,expected) # tampered
empty = dict(report,tests=0)
assert not accept(empty,tag(empty),expected) # authentic, inadequate
wrong_suite = dict(expected,suite=digest(["unit-v3"]))
assert not accept(report,signature,wrong_suite)
print("5 receipt checks passed")

代码已在本地执行,五个检查全部通过:正确报告被接受;源码变化、报告篡改、零测试、检查集合变化分别被拒绝。这个结果验证的是示例函数,不是Checks产品,也不是项目测试覆盖率。

“同一个环境”不能只写Python版本

环境摘要应该对应能够被执行侧重建或定位的实际环境描述。仅写“Python 3”没有表达补丁版本、系统库、架构和依赖集合;仅写一个可变镜像标签,也不保证下次解析到同一内容。教学代码里的fictional-image-v1只是占位符,真实门禁应使用不可变的内容标识和明确的配置版本。

检查集合也需要固定。若Agent把单元测试入口改成永远返回成功的脚本,同时生成新的“通过”结果,内容认证仍可能完全成立。门禁要判断测试配置变更由谁批准、哪些必需检查不能被候选代码自行移除,而不能让待验证的一方同时定义通过标准。

预热解决重复准备环境的开销,不会自动证明输入完整。此前站内Bazel缓存命中文章讨论的是缓存键漏掉输入;这里的问题发生在消费检查结果的门禁,两者都要求先把依赖边界写清。

真正接入前,先决定拒绝哪些结果

可以先把现有CI当作基线,记录源码快照、必需检查版本、执行环境、执行身份与结果状态。尝试复用时,先以观察模式比较旧流水线与新判定的差异;只有理解差异来源后,才考虑取消重复任务。观察期还应故意改动一个未提交文件、替换检查配置、切换运行环境,确认旧结果会被拒绝。暂时多跑一次比错误复用更容易定位。

时间同样是策略问题。测试报告针对的外部服务、漏洞规则或合并基线可能已经变化;源码没变并不总意味着结果永远可用。是否过期、是否需要重新测试合并后的树、哪些动态依赖禁止复用,应由仓库风险和测试设计决定,不能从“有签名”推导出来。

零测试检查也只是示例底线。跑过12个测试不代表覆盖12类需求;一个重要回归可能完全没有断言。对读者最实用的动作,是拿一份真实绿灯问:它绑定了哪些输入,谁可以改变检查,门禁具体接受了什么?答不出来时,先补证据,再谈省掉CI。

资料与补发说明

消息线索为Google News收录的10月15日报道,产品事实依据10月14日官方公告;验证语义参考Sigstore文档。两幅图与协议示例为原创教学内容。本文于10月16日补发,文章日期保留原计划16:00;所有新闻来源早于该时段。

如果这套核对方法帮助你识别了一个“签名正确、复用错误”的CI结果,欢迎通过文末支持区自愿打赏。

支持

如果文中的解释或示例帮你解决了问题、节省了时间,欢迎自愿打赏支持本站。

微信支持二维码,点击查看大图
微信
支付宝支持二维码,点击查看大图
支付宝
Buy Me a Coffee,点击支持本站
Buy Me a Coffee

二维码可点击放大。更多支持方式见支持页面。

Share this Post

Leave a Comment

您的邮箱地址不会被公开。 必填项已用 * 标注

*
*