-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.dang
More file actions
218 lines (196 loc) · 8.3 KB
/
Copy pathmod.dang
File metadata and controls
218 lines (196 loc) · 8.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
"""
A Dagger module that uses the Java SDK.
"""
type Mod {
"""
Workspace-relative path of this module root.
"""
pub path: String!
"""
Workspace containing this module.
"""
let ws: Workspace!
"""
Marker filename that skips generate when found at or above this module root.
"""
let skipGenerateFilename: String!
"""
Whether this module or an ancestor contains the configured generate skip marker.
"""
pub skipGenerate(ws: Workspace!): Boolean! {
hasMarker(ws, skipGenerateFilename)
}
"""
Whether this module root or an ancestor containes a marker filename.
"""
let hasMarker(ws: Workspace!, filename: String!): Boolean! {
let markerPath = ws.findUp(name: filename, from: path)
markerPath != null
}
"""
Generate this module.
If the generate skip marker is present, the changeset is empty.
"""
pub generate(ws: Workspace!): Changeset! {
if (skipGenerate(ws)) {
polyfill.workspace(ws).fork.changes
} else {
generateModule(ws, path).changes
}
}
"""
Maven container used for codegen (pinned digest, matches the builtin runtime).
"""
let mvn: Container! {
container.from("maven:3.9.9-eclipse-temurin-21-alpine@sha256:4cbb8bf76c46b97e028998f2486ed014759a8e932480431039bdb93dffe6813e")
}
"""
The vendored Java SDK Maven reactor shipped with this module.
"""
let sdkSourceDir: Directory! { currentModule.source.directory("sdk") }
"""
Vendor the Java SDK as buildable source for a module:
src/main/java the hand-written SDK library
src/processor/java the annotation processor that generates the entrypoint
src/generated/java the client bindings generated from the engine schema
src/processor/resources/META-INF/services/...Processor
The returned directory is dropped at <module>/sdk.
"""
let prebuiltCodegenRepo: String! { "prebuilt/m2" }
let prebuiltCodegenPlugin: String! { "prebuilt/dagger-codegen-maven-plugin.jar" }
"""
A maven container with the codegen plugin available in the local repository.
Fast path: when the packager module has committed the plugin's local Maven
repository under prebuilt/m2, drop it into ~/.m2/repository with a plain copy —
no maven invocation. Otherwise fall back to installing a committed plugin jar,
and finally to compiling the plugin from the vendored sources.
"""
let codegenBase(introspectionJSON: File!): Container! {
let base = mvn
.withoutEntrypoint
.withMountedCache("/root/.m2", cacheVolume("sdk-java-maven-m2"))
.withMountedFile("/schema.json", introspectionJSON)
.withDirectory("/dagger-io", sdkSourceDir)
.withWorkdir("/dagger-io")
if (currentModule.source.exists(prebuiltCodegenRepo + "/io/dagger")) {
base
.withDirectory("/prebuilt-m2", currentModule.source.directory(prebuiltCodegenRepo))
.withExec(["sh", "-c", "mkdir -p /root/.m2/repository && cp -r /prebuilt-m2/. /root/.m2/repository/"])
} else if (currentModule.source.exists(prebuiltCodegenPlugin)) {
base
.withMountedFile("/codegen-plugin.jar", currentModule.source.file(prebuiltCodegenPlugin))
.withExec(["mvn", "install:install-file", "-Dfile=/dagger-io/pom.xml", "-Dpackaging=pom", "-DpomFile=/dagger-io/pom.xml", "--no-transfer-progress"])
.withExec(["mvn", "install:install-file", "-Dfile=/codegen-plugin.jar", "-DpomFile=/dagger-io/dagger-codegen-maven-plugin/pom.xml", "--no-transfer-progress"])
} else {
base.withExec(["mvn", "--projects", "dagger-codegen-maven-plugin", "--also-make", "install", "-T1C", "-Dmaven.test.skip=true", "-Dfmt.skip=true", "--no-transfer-progress"])
}
}
let vendoredSdk(introspectionJSON: File!, name: String!): Directory! {
# install (rather than generate-sources) so the compiled SDK and annotation
# processor jars land in the local Maven repository — the dagger-prebuilt-sdk
# pom profile compiles the entrypoint against them instead of recompiling the
# vendored SDK sources.
#
# The jars are installed under a per-module version so modules that resolve to
# different schemas (different dependencies, or a different engine) never share
# a Maven coordinate in the local repository. The codegen plugin is referenced
# via its own fixed version, so it keeps resolving from the prebuilt repo. The
# vendored source that gets committed is version-independent; only the build
# artifacts are versioned. This step is cached across a module's own edits.
let built = codegenBase(introspectionJSON)
.withExec(["mvn", "versions:set", "-DnewVersion=" + name, "-DgenerateBackupPoms=false", "--no-transfer-progress"])
.withExec(["mvn", "--projects", "dagger-java-sdk,dagger-java-annotation-processor", "install", "-Ddaggerengine.schema=/schema.json", "-Dmaven.test.skip=true", "-Dfmt.skip=true", "--no-transfer-progress"])
directory
.withDirectory("src/main/java", built.directory("/dagger-io/dagger-java-sdk/src/main/java"))
.withDirectory(
"src/processor/java",
built.directory("/dagger-io/dagger-java-annotation-processor/src/main/java"),
)
.withDirectory(
"src/generated/java",
built.directory("/dagger-io/dagger-java-sdk/target/generated-sources/dagger"),
)
.withNewFile(
"src/processor/resources/META-INF/services/javax.annotation.processing.Processor",
"io.dagger.annotation.processor.DaggerModuleAnnotationProcessor\n",
)
}
"""
Compile the module with the annotation processor enabled (proc=full) so it
emits io.dagger.gen.entrypoint.Entrypoint, and return the generated-sources
directory (the entrypoint) for vendoring under <module>/src/generated/java.
"""
let generatedEntrypoint(moduleDir: Directory!, name: String!): Directory! {
mvn
.withoutEntrypoint
.withMountedCache("/root/.m2", cacheVolume("sdk-java-maven-m2"))
.withDirectory("/module", moduleDir)
.withWorkdir("/module")
.withEnvVariable("_DAGGER_JAVA_SDK_MODULE_NAME", name)
.withExec(["mvn", "compile", "-Ddagger.proc=full", "-Ddagger.sdk=prebuilt", "-Ddagger.sdk.version=" + name, "--no-transfer-progress"])
.directory("/module/target/generated-sources/annotations")
}
"""
Stage the vendored SDK + generated entrypoint for one module.
"""
let generateModule(ws: Workspace!, modPathArg: String!): PolyfillWorkspaceFork! {
let pws = polyfill.workspace(ws)
let modSource = pws.moduleSource(modPathArg)
let name = modSource.core.moduleName
let vendored = vendoredSdk(modSource.core.introspectionSchemaJSON, name)
# the module as committed, with the freshly vendored SDK overlaid and any
# stale generated entrypoint dropped, so the processor regenerates it
let baseDir = moduleDir(ws, modPathArg)
.withoutDirectory("sdk/src")
.withDirectory("sdk", vendored)
.withoutDirectory("src/generated")
let entrypoint = generatedEntrypoint(baseDir, name)
pws
.fork
.withDirectory(joinPath(modPathArg, "sdk"), vendored)
.withDirectory(joinPath(modPathArg, "src/generated/java"), entrypoint)
}
"""
The module's committed source directory, workspace-rooted.
"""
let moduleDir(ws: Workspace!, modPathArg: String!): Directory! {
if (modPathArg == ".") {
ws.directory("/", include: ["**"])
} else {
ws.directory("/", include: [modPathArg + "/**"]).directory(modPathArg)
}
}
"""
Join a module path with a sub-path, handling the root (".") module.
"""
let joinPath(modPathArg: String!, sub: String!): String! {
if (modPathArg == ".") { sub } else { modPathArg + "/" + sub }
}
"""
Return the default new module path for `init`.
"""
let defaultModulePath(ws: Workspace!, name: String!): String! {
let daggerDir = ws.findUp(".dagger", ".")
if (daggerDir == null) {
".dagger/modules/" + name
} else {
daggerDir.trimPrefix("/") + "/modules/" + name
}
}
"""
Return a valid module path relative to the workspace.
"""
let cleanModulePath(path: String!): String! {
let rawPath = path.trimPrefix("./").trimPrefix("/")
if (rawPath == "" or rawPath == ".") {
"."
} else if (rawPath == ".."
or rawPath.trimPrefix("../") != rawPath
or rawPath.contains("/../")
or rawPath.trimSuffix("/..") != rawPath) {
raise "path escapes workspace: " + rawPath
} else {
rawPath.trimSuffix("/")
}
}
}