Dagger TypeScript SDK DirectoryWithFileOpts 详解:向目录写入文件并精确控制权限与属主

Dagger TypeScript SDK DirectoryWithFileOpts 详解:向目录写入文件并精确控制权限与属主 Dagger TypeScript SDK DirectoryWithFileOpts 详解向目录写入文件并精确控制权限与属主【免费下载链接】daggerAutomation engine to build, test and ship any codebase. Runs locally, in CI, or directly in the cloud项目地址: https://gitcode.com/GitHub_Trending/da/daggerDagger 的 TypeScript SDK 通过Directory.withFile可以将任意File拷贝进一个不可变目录快照而DirectoryWithFileOpts则是该操作的可选参数类型别名用于控制拷贝结果的文件权限permissions与属主owner。本文以version-0.20参考文档为核心结合 SDK 生成的客户端代码与 Dagger 引擎层实现完整解析该类型别名的定义、字段语义、底层解析逻辑与实战用法。从 API 参考文档说起类型别名的定位在 version-0.20 TypeScript API 参考 中DirectoryWithFileOpts被定义为一个object类型的 Type Alias它专门服务于Directory.withFile方法——Retrieves this directory plus the contents of the given file copied to the given path获取当前目录并把给定文件的内容拷贝到给定路径后的结果。其完整签名可以概括为type DirectoryWithFileOpts { owner?: string // 可选拷贝文件及目录内容的属主格式 user:group permissions?: number // 可选拷贝文件的权限例如 0600 }该类型在生成的客户端代码 sdk/typescript/src/api/client.gen.ts 中有完整的 JSDoc 注释是 Dagger GraphQL API 通过 codegen 自动生成的类型之一因此它与 Go、Python、Rust 等 SDK 中对应的WithFileOpts结构在语义上保持一致仓库各语言 SDK 的dagger.gen.go/gen.rs中均有同名定义。字段逐一拆解owner 与 permissionsowner?: string参考文档对该字段的描述为A user:group to set for the copied directory and its contents. The user and group must be an ID (1000:1000), not a name (foo:bar). If the group is omitted, it defaults to the same as the user.即以user:group的形式指定拷贝后文件以及其所在目录内容的属主version-0.20文档要求使用数字 ID如1000:1000不能使用名称如foo:bar若省略:group组默认为与用户相同的值例如只传1000则 UID 与 GID 都是1000。值得注意的是当前仓库主干上生成的 TypeScript 类型注释已放宽为 The user and group can either be an ID (1000:1000) or a name (foo:bar)见 client.gen.ts说明新版引擎同时支持名称解析。这一点在引擎实现中可以得到印证见下文属主解析小节。permissions?: number参考文档对该字段的描述为Permission given to the copied file (e.g., 0600).即给被拷贝文件设置的权限位示例值0600表示仅属主可读写rw-------。该参数是 JavaScript/TypeScript 的number类型实际使用八进制字面量如0o600最为直观。与相邻类型别名的对比在 client.gen.ts 中可以看到一组语义相近的兄弟类型便于理解DirectoryWithFileOpts的边界DirectoryWithFilesOpts用于withFiles批量拷贝多个文件只有permissions没有ownerDirectoryWithDirectoryOpts用于withDirectory拷贝整个目录同时具有owner与permissions其中权限描述为 Permission given to the copied directory and contents (e.g., 0755)DirectoryWithNewFileOpts/DirectoryWithNewDirectoryOpts用于新建文件/目录同样包含permissions。也就是说单文件拷贝场景的权限语义是作用于该文件本身而目录拷贝场景的权限语义是作用于目录及其全部内容。引擎层实现原理permissions 与 owner 如何生效DirectoryWithFileOpts最终通过 GraphQL 参数permissions与owner传递到 Dagger 引擎的目录服务核心实现在 core/directory.go 的Directory.WithFile方法中其签名直接对应这两个参数func (dir *Directory) WithFile( ctx context.Context, parent dagql.ObjectResult[*Directory], destPath string, src dagql.ObjectResult[*File], permissions *int, owner string, ... ) error权限位的转换layercopyMode引擎将permissions *int交给 layercopyMode 转换为os.FileMode空值未传permissions直接返回nil表示沿用拷贝源的默认权限常规的 rwx 位通过os.FileMode(raw) os.ModePerm提取额外支持特殊权限位S_ISUIDsetuid、S_ISGIDsetgid与S_ISVTXsticky bit分别映射为os.ModeSetuid、os.ModeSetgid、os.ModeSticky。转换后的模式连同属主一起被传入layercopy.CopyOptionsChown、Mode在copier.CopyFile中完成最终的拷贝与元数据写入。属主解析resolveDirectoryOwner引擎通过 resolveDirectoryOwner 解析owner字符串使用strings.Cut(owner, :)切分用户与组两部分若传入部分是纯数字直接按 UID/GID 解析若传入的是名称如foo则到目标根文件系统中的/etc/passwd与/etc/group中查找对应 ID若省略组gid uid——与文档描述一致即组默认等于用户。目标路径语义实现中还有一个与选项本身无关但直接影响使用方式的行为当destPath以/或/.结尾时引擎判定目标为目录会保留源文件的文件名进行拷贝destPathHintIsDirectory逻辑见 core/directory.go这在实际使用中十分常见。实战示例在 TypeScript 中使用 DirectoryWithFileOpts以下示例演示了如何在 Dagger TypeScript 模块中组合使用withFile与这两个选项import { dag, Directory, File } from dagger.io/dagger // 准备一个源文件运行时生成的内容 const source: File dag.directory() .withNewFile(app-config.json, JSON.stringify({ mode: prod })) .file(app-config.json) // 1) 基础用法不传任何选项直接拷贝 const basic: Directory dag.directory().withFile(/opt/app/config.json, source) // 2) 显式设置权限 0600属主可读写其余无权限 const locked: Directory dag.directory().withFile( /opt/app/config.json, source, { permissions: 0o600 }, ) // 3) 同时设置属主省略组时组默认为用户即 UID1000、GID1000 const owned: Directory dag.directory().withFile( /opt/app/config.json, source, { permissions: 0o600, owner: 1000:1000 }, ) // 4) 目标路径以 / 结尾自动使用源文件原名 const byName: Directory dag.directory().withFile(/opt/app/, source)关键点path既可以是完整的目标文件名也可以是以/结尾的目录路径此时采用源文件名permissions建议使用八进制字面量0o600/0o755等与文档示例0600语义一致owner在version-0.20下请优先使用数字 ID 形式1000:1000并记得省略组则组等于用户的默认规则。行为细节与测试佐证仓库的集成测试 core/integration/directory_test.goTestWithFile覆盖了与上述选项相关的大量边界行为内容与路径正确性将文件拷贝到目标路径后File(target-file).Contents()返回源内容而未拷贝的兄弟文件访问报错子目录路径WithFile(sub-dir/target-file, file)可自动在子目录中落位权限生效验证DirectoryWithNewFileOpts{Permissions: 0o777}后挂载进容器执行ls -l可见rwxrwxrwx默认权限则是rw-r--r--即0644证明权限位确实写入最终产物目录引用语义Directory(...).WithNewDirectory(some-dir).Directory(/some-dir).WithFile(f, f)之后原目录内容不再可见说明withFile返回的是以目标目录为根的新快照目标路径为.、、/时均使用源文件名作为落位名称。这些测试与上文destPathHintIsDirectory的实现相互印证可作为编写 CI 流水线或构建产物组织时的行为参考。注意事项与版本差异文档版本口径本文依据的是version-0.20的参考文档其中明确要求owner使用数字 ID。若你使用更新的 Dagger 版本请以当前 SDK 生成的类型注释为准——主干 SDK 已支持名称形式foo:bar引擎底层也具备/etc/passwd、/etc/group的名称解析能力。权限位范围permissions除常规 9 位权限外还支持 setuid / setgid / sticky 位未设置时保持源文件默认模式。适用场景DirectoryWithFileOpts适合在构建阶段注入单文件如写入.env、公钥、配置文件、证书配合Container.withDirectory即可将带权限与属主约束的文件送入最终镜像从而在不依赖exec脚本的情况下精确控制产物元数据。参考文件索引类型定义与 JSDocsdk/typescript/src/api/client.gen.tswithFile客户端方法sdk/typescript/src/api/client.gen.ts引擎实现拷贝与选项应用core/directory.go权限位转换core/directory.go属主解析core/directory.go集成测试core/integration/directory_test.go【免费下载链接】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),仅供参考