Skip to content

Drop the polyfill for native workspace APIs - #11

Merged
eunomie merged 1 commit into
mainfrom
polyfill-removal-refresh
Aug 25, 2026
Merged

eunomie merged 1 commit into
mainfrom
polyfill-removal-refresh

Conversation

@eunomie

@eunomie eunomie commented Aug 21, 2026 •

Copy link
Copy Markdown
Member

The Dang SDK no longer needs dagger/polyfill.

Supersedes #10, which cannot be updated in place — its head lives on a fork we
cannot push to. Same change, refreshed against the engine as it stands today
and reviewed; @grouville's commit is preserved as the author.

Requires dagger/dagger#13854 and
dagger/dagger#13855, both merged.

What changed

Managed modules come from currentModule.asSDK(workspace: ws).modules, using
the registrations in dagger.toml. Generation keeps the workspace it received
and returns only its own work — Workspace.changes(from:) makes the baseline
explicit, so no workspace fork is needed anywhere. ModuleSource.generate
stages each module's local dependency closure itself, so the SDK no longer does
that by hand.

Config edits go through ModuleSource.withEngineVersion / withDependencies
and updatedConfigDirectory, the same path dagger module engine require takes.

Two knock-on changes worth calling out:

  • The workspace module renames from dagger-dang-sdk to dang-sdk. asSDK
    resolves its entry by the module's own name (resolveCurrentModuleSDKEntry),
    so the dagger.toml key has to match dagger.json's. Check names move with
    it: dagger-dang-sdk:generate is now dang-sdk:generate.
  • engine.require-latest no longer writes the literal string latest. The
    engine resolves that alias as it writes the config
    (moduleSourceWithEngineVersion), so a concrete release lands instead. The
    check and the README follow.

Fixed while refreshing

  • deps update --name <source> silently returned an empty changeset. It matched
    only on module name, while the behaviour it replaced accepted a name, a
    source, or a source at a version — and failed when the target was not there.
    It now mirrors the engine's own matcher, re-pins to an explicitly requested
    version, and distinguishes an unknown target from a local one.
  • mod lookup read the declared runtime by regex-searching dagger.json and
    dagger-module.toml. It now reads ModuleSource.sdk, letting the engine parse
    whichever format the module uses.
  • Mod.path derived the cwd with the polyfill's findUp(".", ".") trick;
    Workspace.cwd is native now.
  • Every config write went through Workspace.withNewDirectory, which replaces
    the directory it writes over — where the polyfill's fork.withDirectory
    layered onto existing content. Three call sites were affected, and two of them
    destroyed data: engine require (and require-current / require-latest /
    deps update) staged the removal of the entire workspace, .git included,
    because updatedConfigDirectory holds only the config file; and initModule
    into a directory that already held files deleted them. All three now layer
    onto what is already there.
  • Dead helpers (isLocalRef, moduleConfigFilenames), a stale generate-all
    in the README, and a README discovery section that still described a
    filesystem scan.

generate reports only what it changed — one edit comes back as one path, not
as the whole generated context re-reported against an empty baseline
(the failure go-sdk#30 hit). This SDK cannot currently reach that: Dang has no
codegen output, so a module's generated context only ever modifies its own
config and never adds files, and the fault is in the added-path direction.
Verified across every module shape here — root, dagger.json,
dagger-module.toml, and one with local dependencies — including regenerating
after denormalizing a config and after denormalizing a dependency's config.
A check now pins it, so the day Dang gains generated output this does not become
a silent regression.

New checks cover the deps update targeting, module lookup against a
dagger.json owned by another runtime or declaring no runtime at all, and
initModule over a non-empty directory. assertOnlyConfigChanged now also
guards the engine-version edits — it asserted removals only on the dependency
paths before, which is why a whole-workspace deletion passed CI.

Note that sdk-sdk's contract:does-not-remove-existing-files does not catch
this class of bug: it only initializes into a fresh path.

deps still reads and writes dagger.json directly for list/add/remove.
withDependencies resolves each dependency, which loses the declared form the
tests pin (a bare-string entry lists as its source, add must not load the
target to learn its name). withUpdateDependencies is also unusable from module
code: a workspace-derived ModuleSource's local dependencies arrive as
DIR_SOURCE with an empty ref, so the engine ends up calling
moduleSource(refString: ""). Worth fixing upstream; not a blocker here.

Test

Run bare — a filtered glob like 'e-2-e:*' silently skips two-level check
names such as sdk-sdk:contract:seeds-files.

dagger check                              # 19 passed
dagger -m github.com/dagger/sdk-sdk check # 28 passed

The cross-repo run is against sdk-sdk main at 3344489, which adds the
monorepo group — a workspace whose dagger.toml sits in a subdirectory of the
git root, driven from that subdirectory
(dagger#13889). Those six checks
pin exactly the property this PR relies on: module paths cross the engine/SDK
boundary workspace-root-relative, and an SDK that rebases them onto the caller's
cwd splits the new module in two. initModule here writes at "/" + modPath,
so it passes unchanged.

@eunomie
eunomie force-pushed the polyfill-removal-refresh branch 2 times, most recently from 1e52f4e to 1083681 Compare August 21, 2026 10:36
@eunomie
eunomie marked this pull request as ready for review August 24, 2026 10:12
@eunomie
eunomie requested a review from vito August 24, 2026 10:12
The Dang SDK used dagger/polyfill for managed module discovery, module
generation, and config edits. Those behaviors now live in Workspace and
ModuleSource.

Read managed modules from currentModule.asSDK(workspace).modules, thread the
Workspace through generation, and compare the final workspace with the
workspace the SDK received. Remove the polyfill and bump the engine
requirement in the same change so existing staged edits are not returned
twice.

Registering this module as the "dang" SDK is what makes asSDK resolvable, and
the entry has to be keyed by the module's own name, so the workspace module
renames from dagger-dang-sdk to dang-sdk.

engine.requireLatest now writes whatever release the engine resolves "latest"
to: the alias is resolved engine-side while the config is written, so it can
no longer land in dagger.json verbatim. The check and the README follow.

Signed-off-by: Guillaume de Rouville <guillaume@dagger.io>
Signed-off-by: Yves Brissaud <yves@dagger.io>
@eunomie
eunomie merged commit 5da2636 into main Aug 25, 2026
20 checks passed
@eunomie
eunomie deleted the polyfill-removal-refresh branch August 25, 2026 16:28
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.

3 participants