十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Dagger TypeScript SDK 详解:DirectoryWithFilesOpts 与 `Directory.withFiles` 批量复制文件权限控制

Dagger TypeScript SDK 详解:DirectoryWithFilesOpts 与 `Directory.withFiles` 批量复制文件权限控制 Dagger TypeScript SDK 详解DirectoryWithFilesOpts 与Directory.withFiles批量复制文件权限控制【免费下载链接】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 0.21 版 TypeScript SDK 的类型别名DirectoryWithFilesOpts展开深入讲解Directory.withFiles(path, sources, opts)批量复制文件 API 的用法、permissions选项的权限语义以及它在 Dagger 引擎中的底层实现原理。读完本文你将掌握如何把多个File一次性地复制进Directory并精确控制目标文件的权限位也能理解withFiles与withFile、Container.withFiles之间的内在关系从而在实际的构建流水线中正确地组合文件与目录。一、DirectoryWithFilesOpts是什么在 Dagger 0.21 的 TypeScript SDK 参考文档中DirectoryWithFilesOpts被定义为一个object类型的类型别名它是Directory.withFiles()方法的可选参数对象DirectoryWithFilesOptsobjectPropertiespermissions?optionalpermissions?:numberPermission given to the copied files (e.g., 0600).即复制到目标目录中的文件所获得的权限可选类型为number。在 SDK 生成的客户端源码中该类型别名有完整的 JSDoc 注释与参考文档一一对应位于 sdk/typescript/src/api/client.gen.tsexport type DirectoryWithFilesOpts { /** * Permission given to the copied files (e.g., 0600). */ permissions?: number }这是一个只有单一可选属性的精简选项对象用法上与DirectoryWithNewFileOptspermissions、DirectoryWithNewDirectoryOptspermissions等 SDK 中的同类选项保持一致的风格。二、Directory.withFiles方法签名与参数语义DirectoryWithFilesOpts是withFiles方法的第三参可选参完整签名位于 sdk/typescript/src/api/client.gen.ts/** * Retrieves this directory plus the contents of the given files copied to the given path. * param path Location where copied files should be placed (e.g., /src). * param sources Identifiers of the files to copy. * param opts.permissions Permission given to the copied files (e.g., 0600). */ withFiles ( path: string, sources: File[], opts?: DirectoryWithFilesOpts, ): Directory { const ctx this._ctx.select(withFiles, { path, sources, ...opts }) return new Directory(ctx) }三个参数的含义如下参数类型必填说明pathstring是复制文件的目标位置例如/srcsourcesFile[]是待复制的文件数组多个File对象opts.permissionsnumber否复制后文件的权限位例如0600八进制对应的 GraphQL 层定义可以从核心 schema 测试基线 core/schema/testdata/base_schema.graphqls 中看到 Retrieves this directory plus the contents of the given files copied to the given path. withFiles( Location where copied files should be placed (e.g., /src). path: String! Identifiers of the files to copy. sources: [ID!]! expectedType(name: File) Permission given to the copied files (e.g., 0600). permissions: Int ): Directory!可以看到path和sources在 GraphQL 层均为必填String!与[ID!]!permissions为可选的Int并且方法返回一个新的Directory!——这与 Dagger 的不可变immutable语义一致withFiles不会修改原目录而是返回一个在原目录基础上追加了文件的新目录快照。行为语义追加而非覆盖目录本身withFiles返回此目录加上复制到指定路径的文件内容。与withFile的差异withFile每次只复制一个文件而withFiles一次性接收File[]数组适合把多个构建产物、配置或证书文件批量放入同一目录避免多次链式调用。不可变快照调用不改变原有Directory对象返回值可以被继续组合进更大的 DAG有向无环图中。三、permissions选项权限位的精确控制数值含义permissions是一个number含义是标准 Unix 权限位。文档示例中的0600是八进制字面量写法它等价于0o600TypeScript / JavaScript 的现代八进制写法十进制384符号表示rw-------权限位按 owner / group / others 三段排列每段分别是 read4、write2、execute1三个比特位的和权限值八进制含义典型用途0o600仅属主可读写rw-------私钥、凭据、token 等敏感文件0o644属主可读写组与其他仅可读rw-r--r--常规源码、配置文本0o755属主全部权限组与其他可读可执行rwxr-xr-x可执行脚本、二进制什么时候必须用permissions默认情况下不传permissions文件复制后保留什么权限取决于withFile的底层默认行为。而当你复制的是密钥、证书、.env或 CI token这类敏感文件时显式指定0o600可以确保它们在后续容器执行、导出或上传的过程中保持最小权限避免被其他用户读取。TypeScript 写法注意在 TypeScript 源码中0600这种旧式八进制字面量是非法的SyntaxError必须写成{ permissions: 0o600, // 推荐明确的八进制 // 或者 permissions: 384, // 等价十进制 }参考文档中的0600只是权限位的说明性示例而不是可以直接照抄的代码字面量。四、源码级实现withFiles是如何工作的要真正理解permissions的作用需要看 Dagger 引擎侧的实现。核心 schema 中withFiles的实现在 core/schema/directory.go参数结构定义如下type WithFilesArgs struct { Path string Sources []core.FileID Permissions dagql.Optional[dagql.Int] }实现逻辑的核心是一个循环展开withFiles在引擎内部把批量复制转化为对单个文件逐一执行withFileinst parent for _, file : range files { fileID, err : file.ID() if err ! nil { return inst, err } filePath, err : file.Self().File.GetOrEval(ctx, file.Result) if err ! nil { return inst, err } withFileArgs : []dagql.NamedInput{ {Name: path, Value: dagql.String(path.Join(args.Path, path.Base(filePath)))}, {Name: source, Value: dagql.NewID*core.File}, } if args.Permissions.Valid { withFileArgs append(withFileArgs, dagql.NamedInput{ Name: permissions, Value: dagql.Opt(args.Permissions.Value), }) } err srv.Select(ctx, inst, inst, dagql.Selector{ Field: withFile, Args: withFileArgs, }) if err ! nil { return inst, err } }从源码可以提炼出三个关键事实目标路径拼接规则每个源文件被复制到path.Join(args.Path, path.Base(filePath))——即目标目录 源文件的基文件名。这意味着withFiles只能把文件复制到指定目录下保留各自的文件名不能像withFile那样为每个文件单独重命名。权限的透传仅当调用方传入了permissions时args.Permissions.Valid为真该值才会作为permissions参数转发给内部的withFile调用未传时则完全交给withFile的默认行为。这就是为什么DirectoryWithFilesOpts.permissions是可选属性的原因。批量的本质是单文件循环从引擎视角看withFiles是 N 次withFile的组合每次循环都以当前累积结果inst为父节点继续追加最终返回叠加后的Directory快照。因此对每个文件的权限是统一的同一个permissions值无法对数组中的不同文件分别设置不同权限——如果有此需求应改用多次withFile。五、与Container.withFiles的对比withFiles在Container类型上也有对应的变体方法定义于 sdk/typescript/src/api/client.gen.tswithFiles ( path: string, sources: File[], opts?: ContainerWithFilesOpts, ): Container { const ctx this._ctx.select(withFiles, { path, sources, ...opts }) return new Container(ctx) }引擎侧的参数结构core/schema/container.go在WithFilesArgs基础上扩展了更多选项type containerWithFilesArgs struct { WithFilesArgs Owner string default: InheritOwner bool default:false Expand bool default:false }两者的区别值得注意能力Directory.withFilesContainer.withFiles返回类型DirectoryContainerpermissions✅ 支持✅ 支持继承自WithFilesArgsowneruser:group如1000:1000或foo:bar❌✅inheritOwner继承容器当前用户❌✅expand对 path 中的${VAR}/$VAR做环境变量展开❌✅也就是说DirectoryWithFilesOpts是两者中最精简的选项集合只关心文件权限而ContainerWithFilesOpts因为要顾及容器内的属主关系与路径变量展开选项更丰富。如果在目录层面就需要设置属主可以先用Directory.withFiles复制文件并设定权限再通过Container.withDirectory挂载进容器或直接改用Container.withFiles一步到位。六、实战示例批量复制构建产物并收紧权限场景一把多个二进制复制进空目录并设为可执行import { connect } from dagger.io/dagger connect(async (client) { // 从构建上下文取得多个产物文件 const cli client.file(./dist/cli) const server client.file(./dist/server) // 一次性复制到 /usr/local/bin并赋予 0755 执行权限 const release client .directory() .withFiles(/usr/local/bin, [cli, server], { permissions: 0o755 }) await release.export(./release-root) })场景二复制敏感凭据并锁定为仅属主可读写import { connect } from dagger.io/dagger connect(async (client) { const creds client.file(./secrets/credentials.json) const serviceAccount client.file(./secrets/sa-key.json) // 复制进 /app/secrets权限统一设为 0600防止组用户与其他用户读取 const hardened client .directory() .withFiles(/app/secrets, [creds, serviceAccount], { permissions: 0o600 }) // 继续与容器镜像组合 const ctr client .container() .from(node:22-alpine) .withDirectory(/app, hardened) })场景三在 CI 中把多语言产物汇总到同一个目录后打包const bundle client .directory() .withFiles(/dist, [jsBundle, cssBundle, wasmModule], { permissions: 0o644 }) const artifact await bundle .withNewFile(/dist/VERSION, version, { permissions: 0o644 }) .export(./out/artifact)注意事项路径与文件名withFiles的目标路径是目录文件名取自各File的基名若需重命名某个文件先对File使用withName或改用withFile。权限统一性同一次withFiles调用中的所有文件共享同一个permissions需要对不同文件设置不同权限时拆成多次withFile调用。权限影响面permissions影响的是复制后的文件权限位与源文件在宿主上的权限无关如果后续文件会被解压、执行或作为密钥挂载请一并考虑目标容器用户与属主设置Container.withFiles的owner/inheritOwner。七、小结DirectoryWithFilesOpts虽只是一个属性极少的类型别名却是 Dagger TypeScript SDK 目录操作中批量复制文件能力的关键接口它以可选参数permissions?: number提供对复制后文件权限位的统一控制。结合 SDK 生成代码client.gen.ts与引擎实现directory.go可以看出withFiles在底层是对每个文件逐一执行withFile的循环路径规则为目标目录 源文件基名权限仅在显式传入时透传而Container.withFiles则在相同基础上额外支持owner、inheritOwner与expand。理解了这一机制你就能在构建流水线中准确地批量组织目录内容并针对敏感文件实施最小权限策略。【免费下载链接】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),仅供参考
返回列表