Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .dagger/modules/e2e/util.dang
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ type Fixtures {
that depends on the runtime, deno.json instead of package.json + tsconfig.
"""
let denoModule: String! = root + "/generate-deno/app"

"""
The runtime execution fixtures, managed so `dagger generate` keeps them
current, and registered by the engine when the runtimes module loads them.
"""
let runtimeFixtures: [String!]! = [
".dagger/modules/runtimes/fixtures/bun",
".dagger/modules/runtimes/fixtures/deno",
".dagger/modules/runtimes/fixtures/node",
]
let configBareModule: String! = root + "/config/bare"

# A client binds to client/app (which depends on client/dep) and is generated
Expand Down Expand Up @@ -193,5 +203,5 @@ type Fixtures {
depLibModule,
denoModule,
parentSourceModule,
]
] + runtimeFixtures
}
17 changes: 17 additions & 0 deletions .dagger/modules/runtimes/dagger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "runtimes",
"engineVersion": "v1.0.0-0",
"sdk": {
"source": "dang"
},
"dependencies": [
{
"name": "typescript-sdk",
"source": "../../../"
},
{
"name": "sdk-sdk",
"source": "github.com/dagger/sdk-sdk"
}
]
}
5 changes: 5 additions & 0 deletions .dagger/modules/runtimes/fixtures/bun/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/sdk
/__dagger.entrypoint.ts
/tsconfig.json
/**/node_modules/**
/.env
Empty file.
5 changes: 5 additions & 0 deletions .dagger/modules/runtimes/fixtures/bun/dagger-module.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name = "runtime-bun"
engineVersion = "v1.0.0-beta.9"

[runtime]
source = "typescript"
3 changes: 3 additions & 0 deletions .dagger/modules/runtimes/fixtures/bun/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
9 changes: 9 additions & 0 deletions .dagger/modules/runtimes/fixtures/bun/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { object, func } from "@dagger.io/dagger"

@object()
export class RuntimeBun {
@func()
greet(name: string): string {
return "hello " + name + " from bun"
}
}
5 changes: 5 additions & 0 deletions .dagger/modules/runtimes/fixtures/deno/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/sdk
/__dagger.entrypoint.ts
/tsconfig.json
/**/node_modules/**
/.env
5 changes: 5 additions & 0 deletions .dagger/modules/runtimes/fixtures/deno/dagger-module.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name = "runtime-deno"
engineVersion = "v1.0.0-beta.9"

[runtime]
source = "typescript"
20 changes: 20 additions & 0 deletions .dagger/modules/runtimes/fixtures/deno/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"tasks": {
"dev": "deno run main.ts"
},
"imports": {
"typescript": "npm:typescript@5.9.3",
"@dagger.io/dagger": "./sdk/index.ts",
"@dagger.io/dagger/telemetry": "./sdk/telemetry.ts"
},
"nodeModulesDir": "auto",
"unstable": [
"bare-node-builtins",
"sloppy-imports",
"node-globals",
"byonm"
],
"compilerOptions": {
"experimentalDecorators": true
}
}
9 changes: 9 additions & 0 deletions .dagger/modules/runtimes/fixtures/deno/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { object, func } from "@dagger.io/dagger"

@object()
export class RuntimeDeno {
@func()
greet(name: string): string {
return "hello " + name + " from deno"
}
}
5 changes: 5 additions & 0 deletions .dagger/modules/runtimes/fixtures/node/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/sdk
/__dagger.entrypoint.ts
/tsconfig.json
/**/node_modules/**
/.env
5 changes: 5 additions & 0 deletions .dagger/modules/runtimes/fixtures/node/dagger-module.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name = "runtime-node"
engineVersion = "v1.0.0-beta.9"

[runtime]
source = "typescript"
3 changes: 3 additions & 0 deletions .dagger/modules/runtimes/fixtures/node/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
9 changes: 9 additions & 0 deletions .dagger/modules/runtimes/fixtures/node/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { object, func } from "@dagger.io/dagger"

@object()
export class RuntimeNode {
@func()
greet(name: string): string {
return "hello " + name + " from node"
}
}
103 changes: 103 additions & 0 deletions .dagger/modules/runtimes/main.dang
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""
Execution checks: does a module this SDK generates actually run?

Every other check in this repo inspects what generation *writes*. These load
the result, which for a dagger-module.toml module means the engine builds the
runtime container and executes the generated entrypoint to discover its types —
there is no codegen at call time to paper over a bad tree.

That makes them the only checks covering the contract the whole move rests on:
sdk/ resolving as @dagger.io/dagger, the bundle it holds being loadable, the
entrypoint importing the user's classes and registering them. A break here is a
module that generates cleanly and then fails at `dagger call`.

One fixture per TypeScript runtime, because this is where they stop being
interchangeable: generation differs only in which config file it writes, but
node, bun and deno each run the entrypoint in a different container, with a
different interpreter, resolving @dagger.io/dagger a different way.
"""
type Runtimes {
let fixtures: String! = ".dagger/modules/runtimes/fixtures"

"""
A node module should generate and run.
"""
nodeRunsCheck(ws: Workspace!): Void @check {
assertRuns(ws, "node", "RuntimeNode")
}

"""
A bun module should generate and run.

The engine picks bun over node by finding a lockfile next to package.json, so
the generated tree is byte-identical to the node one — only the container it
is executed in differs. Nothing else in this repo has ever run bun.
"""
bunRunsCheck(ws: Workspace!): Void @check {
assertRuns(ws, "bun", "RuntimeBun")
}

"""
A deno module should generate and run.

Deno has no node_modules to fall back on: if generation writes the wrong
config, the runtime cannot resolve @dagger.io/dagger at all.
"""
denoRunsCheck(ws: Workspace!): Void @check {
assertRuns(ws, "deno", "RuntimeDeno")
}

"""
A scaffolded module should answer a function call.

Loading a module proves the entrypoint registers its types; this proves the
other half of the dispatcher — that a call reaches the user's code and its
return value comes back. It goes through sdk-sdk's harness, which builds a
scratch workspace and drives a release CLI the way a user would: `sdk
install`, `module init`, `generate`, then the call.

The function is the default template's `baseImageAddress`, whose value is set
by the module's constructor, so a passing call also means the constructor ran
and its default was applied.
"""
invokesFunctionCheck(ws: Workspace!): Void @check {
let target = sdkSdk.target(ws.directory("/"), ".")
let run = target.run(["call", target.moduleName, "base-image-address"])

run.assertSuccess

if (run.stdout.contains("alpine") == false) {
raise "calling a scaffolded module returned unexpected output: " + run.stdout
}

null
}

"""
Generate a fixture, stage the result, and load the module from it.

Staging through withChanges rather than writing to disk keeps the generated
tree out of the fixture entirely — which also sidesteps the trap that a
module whose .gitignore covers sdk/ hides its own generated files from the
engine's module context.

Reading the module's objects is what forces execution: the TypeScript SDK has
no ModuleTypes function, so type discovery goes through the runtime and the
committed entrypoint's register().
"""
let assertRuns(ws: Workspace!, runtime: String!, objectName: String!): Void {
let path = fixtures + "/" + runtime
let staged = ws.withChanges(typescriptSdk.mod(ws, path: path).generate(ws))

let objects = staged.moduleSource("/" + path).asModule.objects
.{{ asObject.{{ name }} }}
.map { o => o.asObject.name }

if (objects.filter { name => name == objectName }.length == 0) {
raise runtime + " module did not load: expected object " + objectName +
", got [" + objects.join(", ") + "]"
}

null
}
}
12 changes: 12 additions & 0 deletions dagger.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ source = ".dagger/modules/e2e"
[modules.packager]
source = ".dagger/modules/packager"

[modules.runtimes]
source = ".dagger/modules/runtimes"

[modules.typescript-sdk]
source = "."
check.skip = ["*"]
Expand Down Expand Up @@ -51,6 +54,15 @@ path = ".dagger/modules/e2e/fixtures/generate-deps/dep"
[[modules.typescript-sdk.as-sdk.modules]]
path = ".dagger/modules/e2e/fixtures/parent-source/.dagger/modules/app"

[[modules.typescript-sdk.as-sdk.modules]]
path = ".dagger/modules/runtimes/fixtures/bun"

[[modules.typescript-sdk.as-sdk.modules]]
path = ".dagger/modules/runtimes/fixtures/deno"

[[modules.typescript-sdk.as-sdk.modules]]
path = ".dagger/modules/runtimes/fixtures/node"

[[modules.typescript-sdk.as-sdk.clients]]
path = ".dagger/modules/e2e/fixtures/client/out"
module = ".dagger/modules/e2e/fixtures/client/app"