Dagger 项目贡献者开发指南:用 Dagger 自身构建 Dagger 开发环境
2026/9/14 11:21:31 网站建设 项目流程

Dagger 项目贡献者开发指南:用 Dagger 自身构建 Dagger 开发环境

【免费下载链接】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 仓库根目录的 CONTRIBUTING.md,系统讲解如何为 Dagger 贡献代码的完整流程:从初始环境搭建(安装 Dagger 稳定版、Changie、Fork 仓库)到日常开发(playground 联调、集成测试、Lint、本地文档服务),再到 Pull Request 提交与评审的规范。读完本文,你将能够复现 Dagger 维护者的"自举式"开发工作流——用 Dagger 来开发 Dagger,掌握dagger api call engine-dev ...dagger check ...等核心开发命令,并理解这些命令背后对应的仓库源码(engine-devtest-split等开发模块)。

如何找到值得贡献的问题

官方给出的最自然的贡献起点是:先把自己的工作场景放到 Dagger 上跑一遍。你在真实使用中遇到的任何问题都可以成为贡献素材,例如:

  • 一个文档没有回答清楚的问题(文档缺口);
  • 一个工具链里的 bug;
  • 一个缺失的功能或"毛糙的边缘体验"(rough edge)。

选定问题后,按自己的难度承受力挑选合适的条目着手。贡献过程中随时可以提问,维护者明确表示乐于协助;但有一条原则值得记住:贡献体量越大,越应该尽早与维护者沟通,确认方向正确,避免把精力花在最终不会被合并的方案上。如果计划向各语言 SDK(TypeScript、Go、Python、Elixir、Java、PHP、Rust 等)本身提贡献,仓库中另有专门面向 SDK 的贡献说明 sdk/CONTRIBUTING.md,应先阅读该文档。

初始环境搭建

1. 加入社区

Dagger 官方将社区协作视为项目的核心特性之一,强烈建议先加入其 Discord 服务器。持续的反馈和鼓励不仅能帮你节省大量排障时间,也是保持长期贡献动机的关键。

2. 安装 Dagger:Dogfooding

开发 Dagger 所用的工具——"不出所料"——就是 Dagger 本身(官方原话:To develop Dagger, we use - surprise! - Dagger.)。因此第一步是安装最新的稳定版发行,如果你手上有旧版本,务必先升级。安装脚本可直接参考仓库内的 install.sh。之所以必须使用稳定版而非本地开发版来启动开发,是因为本地构建过程需要一个"底座"引擎来执行构建编排,这个底座由--x-release机制固定到一个已知可用的构建(见下文hack/build解析)。

3. 安装 Changie

Changie 是一个简单的 Release Note 管理工具。凡是涉及用户可感知变更(user-facing changes)的贡献,都需要用它生成发布说明条目。请安装最新版 Changie,后续在准备 PR 时使用changie new生成条目文件。仓库根目录 dagger.toml 中登记了 changelog 模块(.dagger/modules/changelog),且 engine-dev 模块的源码 在打包构建源时会专门排除!.changes目录——说明 changie 生成的.changes条目是仓库内被显式管理的一类文件。

4. Git 配置

  1. 在 GitHub 上找到dagger/dagger仓库并点击Fork

  2. 克隆你的 fork:

    git clone git@github.com:$YOUR_GITHUB_USER/dagger.git
  3. 添加上游仓库为新的 remote:

    git remote add upstream git@github.com:dagger/dagger.git

贡献工作流

官方把工作流概括为六个阶段:认领 issue → 沟通 → 开发 → 准备 PR → 提交 PR → 评审。

1. 认领 issue

在 GitHub Issues 中找到(或自行报告)一个 issue,它可能是 bug、缺失功能、缺失文档或体验毛刺。以评论方式声明你打算贡献解决方案;如果已有人在做,务必与其协调,避免重复劳动。

2. 尽早沟通

对于较大的贡献,先公开你的计划与设计方案,主动征求维护者反馈——可以在 issue 里讨论,也可以在 Discord。官方强调 "Communicate early and often":这既节省你的时间,也节省维护者的时间。

3. 本地开发与手动验证

交互式 playground

在本地开发环境里,跑一条命令即可得到一个集成度完整、可交互的"全组件"调试沙箱:

dagger api call engine-dev playground terminal

这条命令会依次完成:

  1. 构建 Dagger 引擎,并把核心 SDKs 打包进镜像内部;
  2. 以 Dagger 服务的方式运行开发版引擎(即dagger-in-dagger,用 Dagger 跑 Dagger);
  3. 构建 Dagger CLI;
  4. 启动一个临时容器,容器内安装好 CLI,并把引擎作为 sidecar 提供;
  5. 打开交互式终端。

从源码结构看,这个能力的实现位于 engine-dev 模块。其New构造函数(main.go#L19-L66)会:

  • 通过vcsInfo从工作区 Git 中解析 HEAD commit 与 dirty 状态,并把它们作为标量(而非整个 Workspace 对象)注入构建对象——源码注释解释了原因:避免 Workspace 对象污染内容寻址的缓存键,使构建结果能在引擎重启后存活;
  • 按排除法收集构建所需源码(coreengineutildagqlcmdsdkmodules.dagger.changes等目录),排除sdk/**/examples等无关内容;
  • 支持subnetNumber参数(默认 89),NetworkCidr()据此生成10.<N>.0.0/16网段,IncrementSubnet()则用于"允许嵌套 Dagger 引擎"时错开网络——这正好解释了 playground 中 dagger-in-dagger 能嵌套运行的网络前提。
仓库内置的 dev 脚本链

仓库hack/目录还保留了不依赖工作区新特性的传统脚本入口,可作为开发环境的另一条通路:

  • hack/build:从本地代码构建引擎与 CLI,并在宿主的 Docker 运行时中启动引擎。它通过--x-release固定到一个特定的 main 提交来驱动构建。源码注释说明了两个原因:一是保证宿主机器上装的是什么版本都能跑 v1.0 工作区;二是它会自动 provision 一个dagger-engine-<commit>容器,从而构建不会运行在即将被它替换的那个引擎上(避免自举悖论)。该脚本还会把历史的_EXPERIMENTAL_*环境变量映射为模块参数:容器名(默认dagger-engine.dev)、镜像名(默认localhost/dagger-engine.dev)、宿主平台(按uname解析)、GPU 支持、额外 hosts、Cloud token 等,最终执行dagger --x-release ... api call dev deploy ... --output ./bin
  • hack/dev:先调用hack/build构建并启动开发环境,再通过hack/with-dev在环境中执行指定命令。它会先探测当前 Docker context 的DOCKER_HOST(注释说明原因是dagger shell无法获取该信息),并从仓库根目录执行构建以便发现dagger.toml工作区;
  • hack/with-dev:设置开发环境的关键环境变量后exec目标命令,包括_EXPERIMENTAL_DAGGER_CLI_BIN(指向./bin/dagger)、DAGGER_ENGINE=container://dagger-engine.dev(指定使用本地构建的容器引擎)、_DAGGER_TESTS_ENGINE_TAR(测试用引擎 tar 包),并把./bin加入PATH

也就是说,无论走 playground 还是hack/dev,最终形态都是:本地源码构建的 CLI + 本地源码构建的引擎容器,二者配合完成迭代。

4. 集成测试

开发模块提供了几种不同粒度的测试入口:

  • 跑全部核心测试:

    dagger check test-split:*

    这里test-split对应 dagger.toml 中登记的.dagger/modules/test-split模块,其职责是把核心测试拆分为可并行执行的批次;

  • 跑当前可用的核心测试:

    dagger api call engine-dev tests
  • 跑某个具体的核心测试(例如TestModule套件中的TestNamespacing):

    dagger api call engine-dev test --pkg="./core/integration" --run="^TestNamespacing$"
  • 跑 SDK 测试:

    dagger check *sdk:*test*

从源码看,engine-dev test的完整参数面比文档示例更丰富。test.go 中Test方法(L22-L79)支持:

参数含义
run只运行匹配该正则的测试
skip跳过匹配该正则的测试
pkg包路径,默认./...
failfast首个失败即中止
parallel并行度,默认为 CPU 数
timeout整体超时
race开启竞态检测
count重复次数,默认 1
envFile通过Secret传入的测试环境变量文件
testVerbose详细输出
update更新 golden 文件
ebpfProgs测试期间在引擎中启用的 eBPF 程序列表

另外该方法标注了+cache="session"缓存策略(会话级),而Tests(列出所有核心测试)则委托给 Go 工具链模块执行。pkg="./core/integration"指向的正是仓库中庞大的核心集成测试目录(如 core/integration 下的module_test.go等 515 个 Go 测试文件所在树),TestModule即其中定义的一个测试套件。

5. Lint

运行全部 linter:

dagger check *:lint

这一 glob 语义与 dagger.toml 中modules.golang.settingslint字段呼应——该字段显式列出了需要 lint 的 Go 模块路径(.、engine/distconsts、modules/daggerverse、sdk/go以及各.dagger/modules/*开发模块),并排除了docs-dev/docusaurus等第三方生成目录。也就是说,dagger check *:lint实际执行的是按工作区配置分发到各语言/工具模块的 lint 检查(Go 之外还有 markdownlint、shellcheck、PsScriptAnalyzer 等,均在dagger.toml的模块表中登记)。

6. 本地文档服务器

如需本地预览文档站点:

dagger api call docs server up

docs模块对应 dagger.toml 中的.dagger/modules/docs-dev,其下还包含一个 docusaurus 子模块(.dagger/modules/docs-dev/docusaurus,见as-sdk模块列表),文档源文件位于 docs/ 目录(含current_docsversioned_docs等)。

4. 准备你的 Pull Request

提交 PR 之前,官方给出一份必须逐项完成的 checklist:

  1. 生成产物并提交:运行dagger generate生成 API 文档、客户端绑定(client bindings)及其他生成文件,并把产物一并纳入 git commit。dagger.tomlmodules.golang.settings.generate指明了生成输出路径(如docs/current_docs/reference/cli),这解释了为什么生成文件会出现在仓库中、为何必须随源码一起提交;
  2. 跑全量 linterdagger check *:lint,全部通过;
  3. 用户可感知变更添加 release note:运行changie new并按提示填写,把生成的条目文件加入 commit(对应.changes目录,最终汇入 CHANGELOG.md);
  4. 理解许可协议:所有贡献均以 Apache License 2.0(Apache-2.0)作出,见仓库根目录 LICENSE,确认你愿意并有能力遵守协议条款;
  5. DCO 签署:每个 commit 必须附带 Developer Certificate of Origin,做法是使用git commit -sSigned-off-by行必须与作者的真实姓名一致;
  6. 提交信息规范:commit message 要有用、准确、简洁。

5. 提交 PR 与评审流程

  • 把特性分支推送到你的 GitHub fork;
  • dagger/dagger仓库发起新的 Pull Request;
  • 维护者会评审 PR 并可能建议修改。如需改动,修改后推送到你的分支即可;
  • 若与main分支产生冲突:将你的分支 rebase 到最新的main上,然后 force-push(不熟悉 rebase 可自行查阅任意在线教程);
  • 一切就绪后,由维护者合并你的改动。

小结:Dagger 贡献工作流全景

把上述要素串起来,Dagger 的贡献工作流可以概括为一张命令地图:

阶段命令 / 动作仓库依据
环境底座安装稳定版 Dagger、Changieinstall.sh
本地开发沙箱dagger api call engine-dev playground terminalengine-dev 模块
脚本式开发环境hack/dev/hack/build/hack/with-devhack/build、hack/with-dev
核心测试dagger check test-split:*dagger api call engine-dev test --pkg=... --run=...test.go
SDK 测试dagger check *sdk:*test*dagger.toml
Lintdagger check *:lintdagger.tomlgolang.settings.lint
文档预览dagger api call docs server up.dagger/modules/docs-dev
生成产物dagger generate并纳入 commitgolang.settings.generate
发布说明changie new,产物加入 commit.dagger/modules/changelog
合规Apache-2.0、git commit -s(DCO)LICENSE

值得强调的是整套工作流的"自举"性质:Dagger 用固定版本的稳定引擎(--x-release钉住的构建)作为底座,在 DAG 上构建"引擎 + CLI + 各语言 SDK",再用构建产物反过来替换底座继续开发——构建永远不运行在它即将替换的那个引擎上(见 hack/build 注释)。理解这一点,是理解 Dagger 仓库中大量.dagger/modules/*开发模块(engine-devcli-devdocs-dev、各*-client-dev等)存在意义的关键。

【免费下载链接】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),仅供参考

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

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

立即咨询