Dagger v0.18.6 发布解析:Secret 缓存键机制变更、GitRepository.branches 与顶层 File 字段
2026/9/14 11:51:18 网站建设 项目流程

Dagger v0.18.6 发布解析:Secret 缓存键机制变更、GitRepository.branches 与顶层 File 字段

【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger

Dagger v0.18.6(2025-05-06 发布)的核心是一次面向缓存正确性的破坏性变更:URI 形式的 Secret 从此按明文的安全哈希而非 URI 字符串来计算缓存键,并新增可选的cacheKey参数以兼容"明文经常轮换但不应破坏缓存"的场景。围绕这一版本,本篇结合仓库源码讲解 Secret 缓存键的底层实现(argon2 派生、会话资源句柄绑定)、新增的GitRepository.branches与顶层File字段,以及本版本修复的五类缺陷,帮助你在升级 v0.18.6 时理解行为差异并正确使用新 API。

破坏性变更:Secret 缓存键从 URI 改为明文哈希

旧行为为什么会有问题

在 v0.18.6 之前,URI 形式的 Secret(例如env://FOOfile:///some/path)在引擎中的"缓存键"就是 URI 字符串本身。这意味着任何包含该 Secret 的操作(典型如把 Secret 作为环境变量注入Container.withEnvVariable后再withExec)都会按 URI 字符串命中缓存。

问题在于:URI 相同并不意味着明文相同。来自不同客户端的两个 Secret 可能使用完全相同的 URI,但指向完全不同的明文值——此时它们共享同一份缓存,含密操作的输出就会被错误地复用到另一客户端的执行中,产生"意料之外"的结果。这在多客户端并发、跨会话复用引擎缓存等场景下尤为隐蔽。

新行为:按明文的安全哈希做缓存键

v0.18.6 起,URI 形式的 Secret 按其明文值的安全哈希来缓存。两个 URI 相同但明文不同的 Secret 会分别缓存,包含它们的操作不再互相共享缓存。

从源码实现看,这一机制落在 core/secret.go 的两个关键函数上:

  • SecretHandleFromPlaintext(core/secret.go):默认路径下,引擎用 argon2 密钥派生函数(timeCost=10memory=2048threads=1keySize=32)对明文加盐派生出 32 字节密钥,base64 编码后拼成argon2:前缀的 digest,作为 Secret 的会话资源句柄(SessionResourceHandle)。使用 KDF 而非简单哈希,既保证缓存键与明文一一对应,又避免缓存键本身能反推明文,这就是发布说明中"secure hashes"的工程含义。
  • SecretHandleFromCacheKey(core/secret.go):显式提供cacheKey时的路径,直接对自定义字符串做哈希生成句柄。

在 GraphQL 层的 resolver 中(core/schema/secret.go),构造Secret时的选择逻辑非常清晰:

  1. args.CacheKey有值,调用core.SecretHandleFromCacheKey生成句柄;
  2. 否则回落到默认路径——先解析明文,再用core.SecretHandleFromPlaintext(配合父节点的SecretSalt()加盐)生成句柄;若明文解析失败,则记录 warn 日志并回退到 32 字节随机数作为缓存键(保证 Secret 仍然可构造,但不会意外命中任何缓存)。

随后引擎把"具体 Secret 对象"(含 URI 与来源客户端 ID)通过cache.BindSessionResource绑定到该句柄上(core/schema/secret.go),供后续含密操作在需要时按句柄取回真实明文。这也解释了为什么旧行为会跨客户端串缓存:旧版句柄只由 URI 推导,不含客户端维度与明文维度;新版句柄要么内嵌明文派生值,要么内嵌用户显式声明的缓存键,语义都收敛到"明文等价才共享缓存"。

新参数cacheKey:为轮换密文保留共享缓存的通道

发布说明同时指出,有些用户的 Secret 明文会频繁轮换但语义上并不不同(例如定时刷新的 Token),希望它们共享缓存、不因轮换而打破缓存。为此Secret构造新增了一个可选的cacheKey参数。

cacheKey的官方文档描述(定义于 core/schema/secret.go)值得完整引用:

若设置,则给定字符串将作为该 Secret 的缓存键。这意味着任何缓存键相同的 Secret,在缓存查找时将被视为等价,即使它们的 URI 或明文值不同。 例如,两个具有相同缓存键的 Secret 作为环境变量传入两个"其他方面等价"的 Container 时,两者的withExec会互相命中缓存。 若不设置,Secret 的缓存键将在构造 Secret 时按其查得的明文值推导。

各入口的使用方式:

SDK:各语言 SDK 将cacheKey作为Secret构造器的可选参数暴露。

dagger shell

dagger shell -c "some-function --secret-arg $(secret env://FOO --cache-key my-cache-key)"

dagger call(支持通过 URI 查询参数设置缓存键的特殊语法):

dagger call some-function --secret-arg "env://FOO?cacheKey=my-cache-key"

升级提示:如果你升级前依赖的是"同 URI 共享缓存"的行为(例如同一env://FOO在不同流水线中总是相同明文,且你希望复用缓存),升级后行为不变——相同明文仍然命中相同缓存键。真正受影响的是同 URI 但明文不同的场景,它们从"错误地共享缓存"变为"正确地区分开";如果你反而希望它们继续共享,请显式加上cacheKey

新增:GitRepository.branches API

本版本新增GitRepository.branches字段,返回与给定 glob 模式匹配的分支列表,与既有tags字段形成对称。

schema 定义见 core/schema/git.go:

dagql.Func("tags", s.tags). Doc(`tags that match any of the given glob patterns.`). Args( dagql.Arg("patterns").Doc(`Glob patterns (e.g., "refs/tags/v*").`), ), dagql.Func("branches", s.branches). Doc(`branches that match any of the given glob patterns.`). Args( dagql.Arg("patterns").Doc(`Glob patterns (e.g., "refs/tags/v*").`), ),

实现上,branches的 resolver(core/schema/git.go)接受可选的patterns参数(dagql.Optional[dagql.ArrayInput[dagql.String]]),通过parent.LoadRemote(ctx)加载仓库远端引用,再执行remote.Filter(patterns).Branches().ShortNames()返回短名列表。也就是说:

  • patterns是 glob 模式数组,不传则返回全部分支;
  • 返回值是短名(不含refs/heads/前缀),与tags返回的短名风格一致;
  • 典型用法是在模块中枚举符合规则(如release/*)的分支并逐个触发构建。

新增:顶层 File 字段

v0.18.6 在Query上直接暴露了file字段,用于更便捷地创建File对象,无需再经由"空目录 +withNewFile+ 取文件"的绕路方式。

字段定义与参数说明见 core/schema/file.go:

参数说明示例
name新文件名,不允许包含目录部分"foo.txt"
contents文件内容"Hello world!"
permissions文件权限0600

resolver(core/schema/file.go)的校验与实现逻辑:

  • name中包含目录部分,直接报错file name %q must not contain a directory
  • 再经core.ValidateFileName做文件名合法性校验;
  • 内部实现是一个选择链:directory → withNewFile(path, contents, permissions) → file(path),即复用 Directory 的子文件能力构造出目标File。参数默认权限为0644(见newFileArgs,core/schema/file.go)。

这使得"在流水线中临时生成一个配置文件"这类操作变得直接,例如 `query.file(name: "config.toml", contents: ...)。

缺陷修复(Fixed)

本版本还包含五项修复,均对应源码中可定位的行为:

  1. GitRepository.tagspatterns参数现在对本地 git 仓库生效:此前本地仓库场景下 glob 过滤未生效;与新增的branches同属一次 git 引用枚举能力的完善(core/schema/git.go 展示了过滤的统一入口remote.Filter(patterns))。
  2. dagger call中函数参数与持久化(persistent)flag 冲突时返回错误:参数名冲突不再被静默处理,而是在解析阶段显式报错,避免用户误以为参数已生效。
  3. 并发执行同名函数且一个客户端取消请求时的报错修复:修复了"failed to return error"和"failed to emit telemetry"这类二次错误——此前两个相同函数并发执行、其一客户端取消时,错误回传与遥测发射路径会互相干扰并产生误导性的二次错误。
  4. vault Secret provider panic 修复:当 vault 中路径(path)存在但目标 secret 不存在时,旧代码会 panic;现在会返回正常错误。从当前仓库的 provider 实现(如 engine/client/secretprovider/vault.go 中的缓存与字段解析逻辑)可以看到,provider 对"缓存未命中"与"字段缺失"的分支处理正是这类健壮性修复的落点。
  5. Container.build使用FROM scratchDockerfile 时的 panic 修复FROM scratch是最基础的构建场景,修复后该路径不再触发引擎内部 panic,构建会以正常错误流程处理或成功完成。

升级建议小结

  • 检查你的流水线中是否存在同 URI、不同明文的 Secret 跨客户端复用缓存的依赖——升级后这类缓存将被正确隔离,若你希望保持共享,请改用显式cacheKey
  • 对明文频繁轮换但语义恒定的 Secret(轮换 Token、定期重签的凭据),显式传入cacheKey(SDK 构造参数 /dagger shell--cache-key/dagger call?cacheKey=查询参数)可保持缓存稳定性。
  • 新的GitRepository.branches与顶层File字段均为纯增量 API,可直接在模块与 GraphQL 查询中启用。
  • 若你此前遇到过FROM scratch构建 panic 或 vault secret 缺失时的 panic,直接升级到 v0.18.6 即可获得修复。

适用前提:本文所有源码行为描述均基于当前仓库 HEAD 的实现(core/secret.go、core/schema/secret.go、core/schema/git.go、core/schema/file.go),与 v0.18.6 发布说明对应;后续版本的 schema 可能在此基础上继续演进,以实际使用的引擎版本 introspection 结果为准。

【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/dagger

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询