Repository navigation
story(dagger): move both modules to Dagger v1.0.0-beta.15 and the v1 config shape - #430
Conversation
…config shape Migrate the workspace with `dagger workspace migrate`: a root dagger.toml installing the root module as the entrypoint and the Go SDK with one scope per module (the companion a local client of the root), a dagger-module.toml per module declaring engineVersion v1.0.0-beta.15, and a committed dagger.lock. Both devex dependencies move to fa34af9, whose modules declare beta.15, and every generated file is regenerated with `dagger generate -y` — including the two #414 and #425 edited by hand. `ci` gains Generated, which runs the Go SDK's own staleness check (measured catching a stale binding, go.mod, dagger-module.toml and companion client) and proves on every run that a deliberately stale binding turns it red. EngineLock reads both dagger-module.toml files with a TOML parser. Ci is no longer a +check: on v1 `dagger call` exits 0 on a failed check, which would have made the gate unfailable. CI and release install the CLI version the root dagger-module.toml declares, read with tomllib, and every Dagger job fails if it left dagger.lock changed. Closes #429 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
CONTRIBUTING.md contains contradictory guidance about dagger check exit status vs earlier documented behavior and should be corrected to avoid misleading contributors.
1 open issue
7 files not reviewed
.dagger/dagger.gen.go: Generated file.dagger/internal/dagger/companion.gen.go: Generated file.dagger/internal/dagger/cpybkc.gen.go: Generated file.dagger/internal/dagger/go.gen.go: Generated file.dagger/internal/dagger/z-5-labs.gen.go: Generated filedaggerverse/cpybkc/dagger.gen.go: Generated filedaggerverse/cpybkc/internal/dagger/cpybkc.gen.go: Generated file
What changed in this PR
This PR migrates the repository’s two Dagger modules (root pipeline and daggerverse/cpybkc) from Dagger v0.21.8 / dagger.json to Dagger v1 (dagger-module.toml + workspace dagger.toml) pinned at v1.0.0-beta.15, updating generated bindings, lockfile pinning, CI/release install steps, and contributor docs to match the new v1 workflow.
Changes:
- Replace
dagger.jsonconfigs with v1dagger-module.toml+ workspacedagger.toml, and commit the corresponding regenerated Go bindings. - Add/strengthen safeguards for drift: EngineVersion lock check via TOML parsing and a new “generated code is committed” check, plus CI/release enforcement that
dagger.lockremains unchanged after runs. - Update docs and automation (README/CONTRIBUTING/workflows/renovate) to use
dagger generate/dagger checkand to install the CLI version by parsingdagger-module.toml.
| File | Description |
|---|---|
| renovate.json | Updates Renovate rationale to reflect dagger generate + dagger-module.toml v1 shape. |
| README.md | Documents minimum required Dagger CLI (v1.0.0-beta.15) for the companion module. |
| daggerverse/cpybkc/main.go | Updates module commentary to reference dagger-module.toml + EngineLock. |
| daggerverse/cpybkc/internal/dagger/cpybkc.gen.go | Adds v1-generated Go client bindings for the companion module. |
| daggerverse/cpybkc/dagger.json | Removes legacy v0 module config. |
| daggerverse/cpybkc/dagger.gen.go | Updates generated module schema/metadata emitted for v1. |
| daggerverse/cpybkc/dagger-module.toml | Adds v1 module config for the companion (engine pinned to beta.15). |
| daggerverse/cpybkc/.gitattributes | Marks additional codegen-managed files (go.mod/go.sum) as generated. |
| dagger.toml | Adds v1 workspace config (modules + Go SDK scopes/clients). |
| dagger.lock | Adds committed lockfile pinning SDK refs and image digests. |
| dagger.json | Removes legacy root v0 module config. |
| dagger-module.toml | Adds v1 root module config (engine pinned to beta.15 + deps updated to devex fa34af9). |
| CONTRIBUTING.md | Updates contributor workflow to v1 (dagger generate, dagger check, lockfile policy, worktree caveat). |
| .gitignore | Updates guidance about committed codegen + dagger.lock under v1. |
| .github/workflows/release.yaml | Installs Dagger CLI by parsing dagger-module.toml; enforces clean dagger.lock post-run. |
| .github/workflows/ci.yaml | Installs Dagger CLI by parsing dagger-module.toml; enforces clean dagger.lock post-run. |
| .dagger/main.go | Updates pipeline entrypoint to accept workspace arg; adds Generated check; removes +check from Ci. |
| .dagger/internal/enginelock/enginelock.go | New TOML-based engineVersion parsing + comparison helper for EngineLock. |
| .dagger/internal/enginelock/enginelock_test.go | Unit tests pin enginelock parsing/error semantics and mismatch behavior. |
| .dagger/internal/dagger/z-5-labs.gen.go | Regenerated devex z5labs bindings for updated dependency pin/version. |
| .dagger/internal/dagger/go.gen.go | Regenerated devex go bindings for updated dependency pin/version. |
| .dagger/internal/dagger/companion.gen.go | Regenerated companion bindings in root module client. |
| .dagger/go.sum | Adds BurntSushi/toml checksums for new EngineLock TOML parsing. |
| .dagger/go.mod | Adds BurntSushi/toml dependency for internal/enginelock. |
| .dagger/generated.go | Adds a check that committed codegen matches dagger generate output (uses SDK stale check + proof). |
| .dagger/companion.go | Updates EngineLock implementation to use TOML parsing (internal/enginelock) and v1 manifest name. |
| .dagger/.gitattributes | Marks additional codegen-managed files (go.mod/go.sum) as generated. |
Review effort: Lite
| The one-platform form is a `dagger call`, because `dagger check` passes a check | ||
| no arguments — so read its `CHECKS` summary rather than its exit status, which is | ||
| 0 whether the contract held or not (see [Running one stage](#running-one-stage)). |
There was a problem hiding this comment.
Fair — "its" read as dagger check. Reworded in 67cf99e: the exit-0 behaviour is dagger call on a check, which the one-platform form has to use because dagger check cannot pass arguments; dagger check image-contract exits non-zero on a failure as usual.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

Closes #429
Moves both Dagger modules from v0.21.8 to v1.0.0-beta.15 and to the v1 config shape in one change, following upstream's migration path:
dagger workspace migrate -y, thendagger generate -y, then commitdagger.toml, eachdagger-module.toml, the generated code anddagger.lock.Judgment calls
Ciis no longer a+check. On beta.15,dagger call <a +check function>hands back a Check object and exits 0 whether the check passed or failed. I measured it:dagger call engine-lockover two modules that disagree printed the failure and exited 0, anddagger check engine-lockexited 1. Left as a+check,dagger call ci(CI's gate, the contributor's gate, and the backlog verify command) could never fail. As a plain function it returns its error and exits non-zero. I checked that both ways: it exited 1 on a mismatched tree and 0 on a clean one. Every part ofciis still a+check, sodagger checkruns them all, and no longer runs them twice. story(daggerverse): drop the +check annotations on builder objects dagger check cannot reach z5labs/devex#444 dropped the annotation from its builders'Cifor the same reason. CONTRIBUTING now says to narrow down withdagger check <stage>, notdagger call <stage>.Ci(ctx, callingWorkspace *dagger.Workspace). The newgeneratedpart reads the workspace rather thanSource. The CLI fills the argument in, sodagger call cistill takes no arguments (checked)..dagger/go.mod:github.com/BurntSushi/tomlv1.6.0, for EngineLock's TOML parsing. The parsing lives ininternal/enginelockso tests can reach it.dagger generatekeeps the require (checked).Acceptance criteria
The tree
engineVersion = "v1.0.0-beta.15"in adagger-module.toml, and nodagger.jsonremains. The rootdagger.tomlinstallscpybkc(source.) as the entrypoint, installsdagger-go-sdk, and gives.anddaggerverse/cpybkceach a Go SDK scope. The companion is a local client of the root scope (clients = ["./daggerverse/cpybkc", …]), and the rootdagger-module.tomlkeeps thecompaniondependency edge.fa34af9(devex main, 2026-10-18), whosegoandz5labsmodules declare beta.15. The commit appears in each dependency'ssourceand in the matchingclientsentry. API changes betweenc10a120andfa34af9in the two modules: devex#444 removed+checkfromgo'sCi.CheckandCi.Runand fromz5labs'sGoChain.Ci. In the regenerated client they returnerror, not a deferred*dagger.Check..dagger/callsGoChain.Ci(ctx)and uses its error, so no source change was needed.z5labsnow also depends on devex'socimodule, which resolves transitively. Nothing else in either module's non-generated source changed (git diff c10a120 fa34af9 -- daggerverse/go daggerverse/z5labs).dagger.lock:git-latestentries resolvegithub.com/dagger/go-sdktorefs/tags/v1.1.0andsdk-helpersv1 torefs/tags/v1.0.6, andgit-shaentries pin each to a commit.dagger generate -yon the committed tree changes nothing. Every generated file, including.dagger/internal/dagger/companion.gen.goanddaggerverse/cpybkc/dagger.gen.gofrom story(container): below 1.0.0 any release may break a covered thing, and the covered tables say what 1.0.0 will promise #414/story(cli):cpybkc initwrites each copybook as a definitions file beside the layout, so a project regenerates with no copybook #425, is what beta.15 writes. Deleting the generated files and regenerating also reproduces the tree exactly.No workspace config found, inferring from dagger.json. I grepped every run log from this work.dagger -m github.com/Zaba505/cpybkc/daggerverse/cpybkc@issue-429 functionslists the companion's eight functions.Checks
EngineLockreadsengineVersionfrom bothdagger-module.tomlfiles with a TOML parser (internal/enginelock, BurntSushi/toml). It fails on a bump made in one module but not the other, in both directions (unit tests, plusdagger check engine-lockexited 1 on a real one-sided bump), and its message and tests namedagger-module.toml.cifails when committed codegen is stale. Measured on beta.15: upstream'sdagger-go-sdkstalecheck (dagger check --generated) catches all of these: a binding with a line appended, ago.modwith arequireremoved, adagger-module.tomlwith apinkey restored that codegen drops, and a companion function added without regenerating the root's client. Sociruns it, through the newGeneratedcheck. It runs the SDK module's checks viaWorkspace.artifactsand finds the module by the SDK's ref rather than by a hard-coded name.Generatedalso makes.dagger/internal/dagger/companion.gen.gostale in a copy of the workspace (never written back) and fails unless that copy fails. That is why a passing run reportschecks: 2/2 done (1 failed). A real stale tree failsciwith the files regeneration would change and the fix. It happened during this work, when codegen turned out to own each module's.gitattributes:dagger.lockis committed, and the reason sits beside the regeneration instructions in CONTRIBUTING's After changing the module. Thecijob and both Dagger jobs inrelease.yamlend with anif: always()step that runsgit diff --exit-code dagger.lockand names the fix in an::error. Note that acirun resolves golang image digests thatdagger generatenever pins, so those entries are committed here too.dagger call cipasses on beta.15 locally (exit 0, the tree anddagger.lockunchanged afterwards). CI is below.CI and release
ci.yamland both Dagger install steps inrelease.yamlinstall the version declared in the rootdagger-module.toml, read with Python'stomllib(standard library, on every hosted runner) rather thanjqoverdagger.json.dagger call … exportartifact builds succeeded;dagger call release --tag irpb/v0.0.0 …(dummy credentials) passed the credential gate and the release plan, and returnedirpb/v0.0.0 is not a release of the image …; nothing published;dagger call release-notesrefusedv0.0.0because it does not point at HEAD, which is correct. With a local-only tagv99.0.0on HEAD (never pushed, deleted afterwards) it spliced the image block. With anirpb/tag it left the notes unchanged;git diff --exit-code dagger.lockwas clean afterwards.Docs
dagger-module.tomlviatomllib.dagger generate -yand commitsdagger.lock, with the reason.engineVersion… is re-measured on beta.15. The edge now refuses only a companion a whole release ahead (module requires dagger v1.1.0, but you have v1.0.0-beta.15), because beta.15 ignores the prerelease: a companion atv1.0.0-beta.99, or atv1.0.0, loads.dagger developline is updated.DAGGER_LEAVE_OLD_ENGINE=1is explained in a new Running another Dagger version beside this one.dagger checkand explains why.dagger develop/dagger.jsonwording is updated in.dagger/companion.go,daggerverse/cpybkc/main.go,.gitignoreand renovate.json's go.mod rule. In.gitattributes, codegen writes/dagger.gen.go,/internal/dagger/**and/internal/telemetry/**itself (it appends any that are missing). Each module's file now keeps those and addsgo.mod/go.sum, which codegen also rewrites.v1.0.0-beta.15, for driving the companion module.dagger call cidoes not run inside a git worktree on beta.15. It fails in 4s atload contextual arg "gitDir" … stat …/.git: not a directory, anddagger checkfails the same way.dagger generatedoes run in a worktree and is a no-op there. CONTRIBUTING records this, so the backlog cycle's "verify from an ordinary clone" step is confirmed.How it was verified
From an ordinary clone of this branch (
/var/tmp), on a beta.15 engine:dagger generate -ywas a no-op,dagger call ciexited 0,dagger.lockand the tree were unchanged,go test ./internal/enginelock/passed, and the release dry run above succeeded. Separately,dagger call ciexited 1 on a tree with a one-sided engine bump, andGeneratedfailed on a stale companion source.🤖 Generated with Claude Code