Skip to content
Open
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
2 changes: 1 addition & 1 deletion .dagger/modules/e2e/dagger-module.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name = "e2e"
engineVersion = "latest"
engineVersion = "v1.0.0-0"

[runtime]
source = "dang"
Expand Down
Empty file.
7 changes: 7 additions & 0 deletions .dagger/modules/e2e/fixtures/deps/app/dagger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "deps-app",
"engineVersion": "latest",
"sdk": {
"source": "java"
}
}
7 changes: 7 additions & 0 deletions .dagger/modules/e2e/fixtures/generate/app/dagger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "generate-app",
"engineVersion": "latest",
"sdk": {
"source": "java"
}
}
7 changes: 7 additions & 0 deletions .dagger/modules/e2e/fixtures/lookup/app/dagger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "lookup-app",
"engineVersion": "latest",
"sdk": {
"source": "java"
}
}
Empty file.
7 changes: 7 additions & 0 deletions .dagger/modules/e2e/fixtures/lookup/not-java/dagger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "not-java",
"engineVersion": "latest",
"sdk": {
"source": "go"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name = "managed-toml-app"
engineVersion = "v1.0.0-beta.7"

[runtime]
source = "java"
Empty file.
7 changes: 7 additions & 0 deletions .dagger/modules/e2e/fixtures/skip/app/dagger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "skip-app",
"engineVersion": "latest",
"sdk": {
"source": "java"
}
}
80 changes: 80 additions & 0 deletions .dagger/modules/e2e/main.dang
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ End-to-end checks for the Java SDK helper module.
type E2e {
let outputRoot: String! = ".dagger/modules/e2e/out"

let fixtureRoot: String! = ".dagger/modules/e2e/fixtures"
let generateModulePath: String! = fixtureRoot + "/generate/app"
let lookupModulePath: String! = fixtureRoot + "/lookup/app"
let lookupNestedPath: String! = lookupModulePath + "/nested"
let depsModulePath: String! = fixtureRoot + "/deps/app"
let skipModulePath: String! = fixtureRoot + "/skip/app"
# A CLI 1.0 managed module: configured by dagger-module.toml, not dagger.json.
let managedTomlModulePath: String! = fixtureRoot + "/managed-toml/app"
# A module using a different SDK; this SDK must never manage it.
let nonJavaModulePath: String! = fixtureRoot + "/lookup/not-java"

"""Fail the current check when a condition is false."""
let assert(condition: Boolean!, message: String!): Void {
if (condition == false) { raise message }
Expand Down Expand Up @@ -81,4 +92,73 @@ type E2e {

null
}

"""
From the workspace root the whole workspace is in scope, so modules() should
return every Java SDK module this workspace manages — whether it is configured
by the legacy dagger.json or the CLI 1.0 dagger-module.toml — and nothing that
isn't managed by this SDK (e.g. a sibling module using another SDK).
"""
pub modulesCheck(ws: Workspace!): Void @check {
let pathRecords = javaSdk.modules(ws).{{rootPath}}

assert(pathRecords.filter { r => r.rootPath == lookupModulePath }.length > 0, "lookup Java module should be listed")
assert(pathRecords.filter { r => r.rootPath == skipModulePath }.length > 0, "skip-marked Java module should still be listed (skip only affects generate)")
assert(pathRecords.filter { r => r.rootPath == generateModulePath }.length > 0, "generate Java module should be listed")
assert(pathRecords.filter { r => r.rootPath == depsModulePath }.length > 0, "deps Java module should be listed")
assert(pathRecords.filter { r => r.rootPath == managedTomlModulePath }.length > 0, "a dagger-module.toml (CLI 1.0) managed module should be listed")
assert(pathRecords.filter { r => r.rootPath == nonJavaModulePath }.length == 0, "a module not managed by this SDK should be excluded from modules listing")

null
}

"""
Discovery is anchored at the client's cwd, not the workspace root. Re-anchoring
the workspace to a subdirectory scopes modules() to the managed modules in that
cone (walk-down) plus the nearest enclosing one (find-up), and excludes managed
modules that live outside it.
"""
pub modulesCwdCheck(ws: Workspace!): Void @check {
# A stable snapshot of the workspace, re-anchorable at any cwd. Snapshot the
# whole workspace (not just config files) so the re-anchored workspace keeps
# its dagger.toml — modules() reads the managed-module list from it via
# ws.sdk — alongside every module config (dagger.json and dagger-module.toml,
# for discovery) and lookup/app/nested (a config-less subdirectory).
let root = ws.directory("/")

# Walk-down: from fixtures/generate only generate/app is in the cone; the
# sibling managed modules live outside it and must be excluded. Its
# cwd-relative path is "app" — a directory beneath the cwd.
let fromGenerate = javaSdk.modules(root.asWorkspace(cwd: fixtureRoot + "/generate"))
let fromGenerateRoots = fromGenerate.{{rootPath}}
assert(fromGenerateRoots.filter { r => r.rootPath == generateModulePath }.length > 0, "cwd=generate: the managed module in the cone should be discovered")
assert(fromGenerateRoots.filter { r => r.rootPath == lookupModulePath }.length == 0, "cwd=generate: lookup/app is outside the cone and must be excluded")
assert(fromGenerateRoots.filter { r => r.rootPath == depsModulePath }.length == 0, "cwd=generate: deps/app is outside the cone and must be excluded")
assert(fromGenerateRoots.filter { r => r.rootPath == skipModulePath }.length == 0, "cwd=generate: skip/app is outside the cone and must be excluded")
assert(fromGenerateRoots.length == 1, "cwd=generate: exactly one managed module is in the cone")
assert(fromGenerate.{{path}}.filter { r => r.path == "app" }.length > 0, "cwd=generate: the discovered module's path should be cwd-relative (app)")

# Find-up: from inside lookup/app (a nested subdir with no config of its own)
# the enclosing managed module is discovered; siblings are not. Its
# cwd-relative path is ".." — an ancestor of the cwd.
let fromNested = javaSdk.modules(root.asWorkspace(cwd: lookupNestedPath))
let fromNestedRoots = fromNested.{{rootPath}}
assert(fromNestedRoots.filter { r => r.rootPath == lookupModulePath }.length > 0, "cwd=lookup/app/nested: find-up should discover the enclosing lookup/app")
assert(fromNestedRoots.filter { r => r.rootPath == generateModulePath }.length == 0, "cwd=lookup/app/nested: generate/app is outside the cone")
assert(fromNestedRoots.length == 1, "cwd=lookup/app/nested: only the enclosing module should be discovered")
assert(fromNested.{{path}}.filter { r => r.path == ".." }.length > 0, "cwd=lookup/app/nested: the enclosing module's path should be cwd-relative (..)")

# Root cwd: the whole workspace is in scope, so every managed module — and
# only the managed ones — is discovered, whether marked by dagger.json or
# dagger-module.toml.
let fromRoot = javaSdk.modules(root.asWorkspace(cwd: "/")).{{rootPath}}
assert(fromRoot.filter { r => r.rootPath == generateModulePath }.length > 0, "cwd=/: generate/app should be listed")
assert(fromRoot.filter { r => r.rootPath == lookupModulePath }.length > 0, "cwd=/: lookup/app should be listed")
assert(fromRoot.filter { r => r.rootPath == depsModulePath }.length > 0, "cwd=/: deps/app should be listed")
assert(fromRoot.filter { r => r.rootPath == skipModulePath }.length > 0, "cwd=/: skip/app should be listed")
assert(fromRoot.filter { r => r.rootPath == managedTomlModulePath }.length > 0, "cwd=/: the dagger-module.toml managed module should be listed")
assert(fromRoot.length == 5, "cwd=/: exactly the five managed modules should be listed")

null
}
}
7 changes: 6 additions & 1 deletion .dagger/modules/packager/main.dang
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@ type Packager {
.withDirectory("/dagger-io", sdkSource(ws))
.withWorkdir("/dagger-io")
.withExec(["mvn", "--projects", "dagger-codegen-maven-plugin", "--also-make", "install", "-T1C", "-Dmaven.test.skip=true", "-Dfmt.skip=true", "-Dproject.build.outputTimestamp=2024-01-01T00:00:00Z", "--no-transfer-progress"])
.withExec(["sh", "-c", "rm -rf /out && mkdir -p /out/io && cp -r /root/.m2/repository/io/dagger /out/io/dagger"])
# Strip Maven's install-time timestamps so the committed repo is
# byte-reproducible: drop the comment lines from _remote.repositories
# (keeping the ">=" local-install markers resolution needs) and pin
# <lastUpdated>. Otherwise every generate re-timestamps these files and
# the check reports perpetual drift.
.withExec(["sh", "-c", "rm -rf /out && mkdir -p /out/io && cp -r /root/.m2/repository/io/dagger /out/io/dagger && find /out -name _remote.repositories -exec sed -i '/>=/!d' {} ';' && find /out -name maven-metadata-local.xml -exec sed -i 's|<lastUpdated>[0-9]*</lastUpdated>|<lastUpdated>20240101000000</lastUpdated>|' {} ';'"])
.directory("/out")
}

Expand Down
4 changes: 2 additions & 2 deletions dagger-module.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ engineVersion = "v1.0.0-0"

[[dependencies]]
name = "polyfill"
source = "github.com/dagger/sdk-sdk/polyfill@main"
pin = "a16466390cacd68bd72f7ae9910d990966fb2226"
source = "github.com/dagger/polyfill@main"
pin = "e90bbfc4843258a877a3a95b8db1571e7981e65f"
5 changes: 3 additions & 2 deletions dagger.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"name": "java-sdk",
"engineVersion": "latest",
"engineVersion": "v1.0.0-0",
"sdk": {
"source": "dang"
},
"dependencies": [
{
"name": "polyfill",
"source": "github.com/dagger/sdk-sdk/polyfill"
"source": "github.com/dagger/polyfill@main",
"pin": "e90bbfc4843258a877a3a95b8db1571e7981e65f"
}
]
}
2 changes: 0 additions & 2 deletions dagger.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
[["version","1"]]
["","git.head",["https://github.com/dagger/dang-sdk"],"6c63cd08652f87c903f3b6fbc5e2fc26505b067a","float"]
["","git.head",["https://github.com/dagger/go"],"5683fb4f7e2e909a453eba727fb982077d5d11b5","float"]
["","git.head",["https://github.com/dagger/go-sdk"],"0d7261b1f889a28a12e9ad8cbbca1e5fe9747f68","float"]
62 changes: 28 additions & 34 deletions dagger.toml
Original file line number Diff line number Diff line change
@@ -1,46 +1,40 @@
[modules.go]
source = "github.com/dagger/go"

# Go version used for the default Go base image.
# settings.version = ""
# Base image used for Go test, generate, and helper containers.
# settings.base = "alpine:latest"
# Extra workspace-root include patterns mounted for each module's Go commands.
# settings.includeExtraFiles = [""]
# Module roots to lint. A bare pattern selects, a "!"-prefixed pattern
# settings.lint = [""]
# Module roots to test. Same selection rules as `lint`.
# settings.test = [""]
# Module roots to run go generate in. Same selection rules as `lint`.
# settings.generate = [""]

[modules.dagger-go-sdk]
source = "github.com/dagger/go-sdk"

# Marker filename that skips generate when found at or above a Go SDK module root.
# settings.skipGenerateFilename = ""
# Dagger workspace configuration
# Install modules with: dagger install <module>

[modules.dagger-go-sdk.as-sdk]
name = "go"
[modules.e2e]
source = ".dagger/modules/e2e"

[[modules.dagger-go-sdk.as-sdk.modules]]
path = "./runtime"
[modules.java-sdk]
source = "."
check.skip = ["*"]

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

[modules.dagger-dang-sdk]
[modules.dang-sdk]
source = "github.com/dagger/dang-sdk"

# Marker filename that skips generate when found at or above a Dang SDK module root.
# settings.skipGenerateFilename = ""

[modules.dagger-dang-sdk.as-sdk]
name = "dang"
[modules.dang-sdk.as-sdk]

[[modules.dagger-dang-sdk.as-sdk.modules]]
[[modules.dang-sdk.as-sdk.modules]]
path = "."

[[modules.dagger-dang-sdk.as-sdk.modules]]
path = ".dagger/modules/packager"
[modules.java-sdk.as-sdk]
name = "java"

[modules.packager]
source = ".dagger/modules/packager"
[[modules.java-sdk.as-sdk.modules]]
path = ".dagger/modules/e2e/fixtures/generate/app"

[[modules.java-sdk.as-sdk.modules]]
path = ".dagger/modules/e2e/fixtures/lookup/app"

[[modules.java-sdk.as-sdk.modules]]
path = ".dagger/modules/e2e/fixtures/deps/app"

[[modules.java-sdk.as-sdk.modules]]
path = ".dagger/modules/e2e/fixtures/skip/app"

[[modules.java-sdk.as-sdk.modules]]
path = ".dagger/modules/e2e/fixtures/managed-toml/app"
69 changes: 66 additions & 3 deletions main.dang
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ type JavaSdk {
"""
pub skipGenerateFilename: String! = ".dagger-java-sdk-skip-generate"

"""
Config filenames that mark a Dagger module root: the CLI 1.0
`dagger-module.toml` (workspace-managed modules) and the legacy `dagger.json`.
A managed module is discovered by whichever it uses.
"""
let moduleConfigFilenames: [String!]! = ["dagger-module.toml", "dagger.json"]

"""
Commit the compiled Dagger Java SDK as a jar into each generated module so its
runtime build compiles only the module's own code against the jar instead of
Expand Down Expand Up @@ -74,12 +81,68 @@ type JavaSdk {
}

"""
Generate all discovered new-style Java SDK modules (runs at `dagger generate`).
Return every Java SDK module this workspace manages that is visible from the
client's current location.

Discovery is anchored at the client's cwd (never the workspace root): the
nearest enclosing module plus every module at or below the cwd, intersected
with the SDK's engine-owned list of managed modules
(currentModule.asSDK.modules). So running from a subdirectory acts on the
project you're in — and the projects beneath it — not the whole workspace.

Discovery is the polyfill's cwd-aware findConfigDirs (dagger/dagger#13688);
this maps its cwd-relative results to workspace-root-relative paths and keeps
the ones this SDK manages, whether they use dagger-module.toml or dagger.json.
"""
pub modules(ws: Workspace!): [Mod!]! {
let managed = ws.sdk(name: currentModule.name).modules.{{source}}
let cwd = normalizePath(ws.cwd)
polyfill.workspace(ws)
.findConfigDirs(moduleConfigFilenames, exclude: ["**/target/**"])
.map { dir => moduleRelPath(cwd, dir) }
.uniq
.filter { path => managed.filter { m => normalizePath(m.source) == path }.length > 0 }
.map { path => Mod(rootPath: path, ws: ws, skipGenerateFilename: skipGenerateFilename, vendorSdkJar: vendorSdkJar) }
}

"""
Normalize a workspace path: strip a leading "./" or "/" and any trailing "/",
and map the empty/root path to ".".
"""
let normalizePath(path: String!): String! {
let normalized = path.trimPrefix("./").trimPrefix("/").trimSuffix("/")
if (normalized == "") { "." } else { normalized }
}

"""
Resolve a findConfigDirs result — a cwd-relative path, at or below the cwd
("." , "sub/dir") or a strict ancestor (".." , "../..") — against the cwd into a
workspace-root-relative path, the format both managed module sources and
Mod.rootPath use.
"""
let moduleRelPath(cwd: String!, dir: String!): String! {
let base = if (cwd == "" or cwd == ".") { [] } else { cwd.split("/") }
let segs = dir.split("/").reduce(base) { acc, seg =>
if (seg == "..") {
acc.dropLast(1)
} else if (seg == "." or seg == "") {
acc
} else {
acc + [seg]
}
}
if (segs.length == 0) { "." } else { segs.join("/") }
}

"""
Generate every managed Java SDK module visible from the client's current
location (runs at `dagger generate`). Discovery goes through modules(ws), so
running from a subdirectory generates only the project you're in and the
projects beneath it.
"""
pub generateAll(ws: Workspace!): Changeset! @generate {
changeset.withChangesets(
currentModule.asSDK.modules.{{path}}
.map { m => Mod(path: m.path, ws: ws, skipGenerateFilename: skipGenerateFilename, vendorSdkJar: vendorSdkJar) }
modules(ws)
.filter { mod => mod.skipGenerate(ws) == false }
.map { mod => mod.generate(ws) },
)
Expand Down
Loading