Skip to content

Embed the Dang runtime into generated modules - #24

Open
eunomie wants to merge 4 commits into
dagger:mainfrom
eunomie:embed-dang-runtime
Open

Embed the Dang runtime into generated modules#24
eunomie wants to merge 4 commits into
dagger:mainfrom
eunomie:embed-dang-runtime

Conversation

@eunomie

@eunomie eunomie commented Sep 1, 2026

Copy link
Copy Markdown
Member

Modules created by this SDK no longer point at a separate runtime module: dagger generate now emits a self-contained runtime.dang next to dagger-module.toml, and new modules record [runtime] source = "embed:runtime.dang". An embed-aware engine reads that file straight from the module's own directory and evaluates it in-process with its native Dang interpreter — no runtime module is resolved, fetched, or loaded. This is the fastest runtime-loading path available, and it removes the unpinned-git-ref exposure that pointing modules at this repository's runtime module would have carried (see future/done/self-contained-python-sdk.md, which this supersedes as "PR 2").

How it works

  • runtime/main.dang stays the single source of truth. Its only reads of its own module source — the two Dockerfile image pins and the runtime.py entrypoint script — are now fenced between #<externals> / #</externals> markers (first commit, behavior-neutral: the module-ref runtime path still passes its e2e checks).
  • At generation time, Mod.generate assembles runtime.dang by splicing that block with literals: the image refs extracted from the Dockerfiles, and the entrypoint script inlined as a string. Assembly raises if the result still contains currentModule, so the emitted file is self-contained by construction — if the runtime ever grows a module-source read outside the fence, generation fails loudly instead of emitting a broken file.
  • The file rides the module's changeset like the vendored sdk/, for every dagger-module.toml module. Legacy dagger.json modules are untouched.
  • targetRuntime flips from "python" to "embed:runtime.dang" in an isolated commit, so it can be reverted independently if sequencing requires.

Tests

  • toml-generate-check now asserts the emitted file: placed next to dagger-module.toml, carries the generated-file marker, declares pub moduleRuntime(, contains the image pins and the inlined entrypoint, and contains no currentModule.
  • New embed-runtime-call-check grafts a freshly generated runtime.dang plus the embed-form config onto the runtime fixture and drives dagger call through a released CLI.
  • Cross-verified against a development engine with embed support: module init writes the embed source, the generated runtime.dang loads, and dagger call succeeds through the embed path with no external runtime-module resolution in the trace.

⚠️ Known-red CI until an engine release ships embed support

Depends on engine PR: dagger/dagger#14018

Released engines (≤ v1.0.0-beta.11) reject the new runtime source with invalid SDK: "embed:runtime.dang". Until an engine release understands the embed form, 18 checks are red, all with exactly that root cause:

  • e-2-e:embed-runtime-call-check (fails at the released engine's SDK loader, proving the plumbing up to it)
  • 17 sdk-sdk checks that init or load a scaffolded module through the released CLI: chain:* (3), generation:succeeds, generation:respects-cwd, init:* (4), module:loads, module:deps-list-succeeds, module:engine-required-reports-version, monorepo:* (5)

The remaining 31 checks are green, including the full e2e suite and the legacy-path regression net (generate-check, generate-all-check, runtime-call-check, runtime-requires-generated-files-check, sdk-test-check).

The runtime reads its own module source in exactly three places: the two
Dockerfile image pins and the runtime.py entrypoint script. Gather them,
plus the imageFrom helper they use, into one marker-delimited block, and
write the entrypoint from its contents instead of mounting the source
file. The SDK's generator can then embed this runtime into a generated
module by replacing the block with literals, leaving a fully
self-contained file.

Signed-off-by: Yves Brissaud <yves@dagger.io>
…toml

Generation now assembles the module runtime into a single file and adds
it to every dagger-module.toml module's changeset: runtime/main.dang
with its externals block replaced by literals — the image pins extracted
from the runtime's Dockerfiles and the entrypoint script inlined as a
string. Assembly fails loudly when the runtime source grows a
module-source read outside the fenced block, so the emitted file stays
self-contained by construction.

The engine reads the file straight from the module root and evaluates it
in-process, without resolving a runtime module.

The authoring module's source needs runtime/ back in its include list;
the exclusion predates the vendored library's move to sdk/, and the
runtime directory is five small files today.

Signed-off-by: Yves Brissaud <yves@dagger.io>
dagger module init now records embed:runtime.dang as the module's
runtime source. The engine reads the named file from the directory
holding dagger-module.toml — where generate emits it — and evaluates it
in-process with its native Dang interpreter, the fastest runtime-loading
path there is: no runtime module is resolved, fetched or loaded, and the
unpinned git-ref exposure that pointing at this repository's runtime
module would have carried never materializes.

Engines that predate the embed runtime source reject it, so this flip
must not ship before an engine release understands the form.

Signed-off-by: Yves Brissaud <yves@dagger.io>
tomlGenerateCheck asserts what generation emits: runtime.dang lands next
to dagger-module.toml, declares moduleRuntime, carries the generated
marker, the pinned images and the inlined entrypoint script, and reads
no module source. embedRuntimeCallCheck rebases the runtime fixture onto
the embed form with a freshly generated runtime.dang and drives a call
through a released CLI; it stays red until a released engine understands
the embed runtime source, and its docstring says so.

Signed-off-by: Yves Brissaud <yves@dagger.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant