@platforma-sdk/package-builder-lib 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/conda-dockerfile.template +45 -0
- package/assets/python-dockerfile.template +22 -0
- package/dist/_virtual/_rolldown/runtime.cjs +33 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/core/archive.cjs +52 -0
- package/dist/core/archive.cjs.map +1 -0
- package/dist/core/archive.js +47 -0
- package/dist/core/archive.js.map +1 -0
- package/dist/core/conda/builder.cjs +226 -0
- package/dist/core/conda/builder.cjs.map +1 -0
- package/dist/core/conda/builder.js +220 -0
- package/dist/core/conda/builder.js.map +1 -0
- package/dist/core/conda/validate-spec.cjs +76 -0
- package/dist/core/conda/validate-spec.cjs.map +1 -0
- package/dist/core/conda/validate-spec.js +73 -0
- package/dist/core/conda/validate-spec.js.map +1 -0
- package/dist/core/core.cjs +403 -0
- package/dist/core/core.cjs.map +1 -0
- package/dist/core/core.d.ts +82 -0
- package/dist/core/core.d.ts.map +1 -0
- package/dist/core/core.js +397 -0
- package/dist/core/core.js.map +1 -0
- package/dist/core/docker-conda.cjs +75 -0
- package/dist/core/docker-conda.cjs.map +1 -0
- package/dist/core/docker-conda.js +71 -0
- package/dist/core/docker-conda.js.map +1 -0
- package/dist/core/docker-python.cjs +147 -0
- package/dist/core/docker-python.cjs.map +1 -0
- package/dist/core/docker-python.js +144 -0
- package/dist/core/docker-python.js.map +1 -0
- package/dist/core/docker.cjs +223 -0
- package/dist/core/docker.cjs.map +1 -0
- package/dist/core/docker.js +207 -0
- package/dist/core/docker.js.map +1 -0
- package/dist/core/envs.cjs +58 -0
- package/dist/core/envs.cjs.map +1 -0
- package/dist/core/envs.d.ts +26 -0
- package/dist/core/envs.d.ts.map +1 -0
- package/dist/core/envs.js +51 -0
- package/dist/core/envs.js.map +1 -0
- package/dist/core/package-info.cjs +450 -0
- package/dist/core/package-info.cjs.map +1 -0
- package/dist/core/package-info.d.ts +57 -0
- package/dist/core/package-info.d.ts.map +1 -0
- package/dist/core/package-info.js +447 -0
- package/dist/core/package-info.js.map +1 -0
- package/dist/core/paths.cjs +15 -0
- package/dist/core/paths.cjs.map +1 -0
- package/dist/core/paths.js +14 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/resolver.cjs +99 -0
- package/dist/core/resolver.cjs.map +1 -0
- package/dist/core/resolver.js +95 -0
- package/dist/core/resolver.js.map +1 -0
- package/dist/core/schemas/artifacts.cjs +136 -0
- package/dist/core/schemas/artifacts.cjs.map +1 -0
- package/dist/core/schemas/artifacts.d.ts +280 -0
- package/dist/core/schemas/artifacts.d.ts.map +1 -0
- package/dist/core/schemas/artifacts.js +122 -0
- package/dist/core/schemas/artifacts.js.map +1 -0
- package/dist/core/schemas/entrypoints.cjs +43 -0
- package/dist/core/schemas/entrypoints.cjs.map +1 -0
- package/dist/core/schemas/entrypoints.d.ts +32 -0
- package/dist/core/schemas/entrypoints.d.ts.map +1 -0
- package/dist/core/schemas/entrypoints.js +41 -0
- package/dist/core/schemas/entrypoints.js.map +1 -0
- package/dist/core/schemas/sw-json.cjs +111 -0
- package/dist/core/schemas/sw-json.cjs.map +1 -0
- package/dist/core/schemas/sw-json.js +110 -0
- package/dist/core/schemas/sw-json.js.map +1 -0
- package/dist/core/storage.cjs +86 -0
- package/dist/core/storage.cjs.map +1 -0
- package/dist/core/storage.js +83 -0
- package/dist/core/storage.js.map +1 -0
- package/dist/core/sw-json-render.cjs +327 -0
- package/dist/core/sw-json-render.cjs.map +1 -0
- package/dist/core/sw-json-render.js +322 -0
- package/dist/core/sw-json-render.js.map +1 -0
- package/dist/core/util.cjs +313 -0
- package/dist/core/util.cjs.map +1 -0
- package/dist/core/util.d.ts +66 -0
- package/dist/core/util.d.ts.map +1 -0
- package/dist/core/util.js +281 -0
- package/dist/core/util.js.map +1 -0
- package/dist/defaults.cjs +54 -0
- package/dist/defaults.cjs.map +1 -0
- package/dist/defaults.d.ts +21 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +37 -0
- package/dist/defaults.js.map +1 -0
- package/dist/index.cjs +31 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
- package/src/__test__/Dockerfile +1 -0
- package/src/__test__/docker.test.ts +67 -0
- package/src/__test__/package.json +39 -0
- package/src/__test__/python-example/main.py +1 -0
- package/src/__test__/python-example/requirements.txt +0 -0
- package/src/__test__/vite.config.mts +7 -0
- package/src/core/__tests__/docker-conda.test.ts +145 -0
- package/src/core/__tests__/docker-entrypoint-generation.test.ts +119 -0
- package/src/core/__tests__/docker-python.test.ts +374 -0
- package/src/core/__tests__/publish-docker-images.test.ts +309 -0
- package/src/core/archive.ts +102 -0
- package/src/core/conda/builder.test.ts +71 -0
- package/src/core/conda/builder.ts +384 -0
- package/src/core/conda/validate-spec.test.ts +213 -0
- package/src/core/conda/validate-spec.ts +107 -0
- package/src/core/core.ts +835 -0
- package/src/core/docker-conda.ts +149 -0
- package/src/core/docker-python.ts +283 -0
- package/src/core/docker.ts +300 -0
- package/src/core/envs.ts +31 -0
- package/src/core/package-info.test.ts +82 -0
- package/src/core/package-info.ts +843 -0
- package/src/core/paths.ts +16 -0
- package/src/core/resolver.ts +195 -0
- package/src/core/schemas/artifacts.test.ts +72 -0
- package/src/core/schemas/artifacts.ts +279 -0
- package/src/core/schemas/entrypoints.test.ts +171 -0
- package/src/core/schemas/entrypoints.ts +150 -0
- package/src/core/schemas/sw-json.ts +216 -0
- package/src/core/schemas/test-artifacts.ts +362 -0
- package/src/core/storage.ts +125 -0
- package/src/core/sw-json-render.test.ts +215 -0
- package/src/core/sw-json-render.ts +682 -0
- package/src/core/util.ts +390 -0
- package/src/defaults.ts +38 -0
- package/src/index.ts +31 -0
- package/src/requirements.txt +1 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
export const PackageVersion: string = "1.2.3";
|
|
2
|
+
export const PackageNameNoAt: string = "the-software";
|
|
3
|
+
export const PackageName: string = "@" + PackageNameNoAt;
|
|
4
|
+
|
|
5
|
+
export const BinaryRegistry: string = "some-binary-registry";
|
|
6
|
+
export const BinaryRegistryURL: string = "http://example.com/registry";
|
|
7
|
+
export const BinaryCustomName1: string = "custom-package-name-1";
|
|
8
|
+
export const BinaryCustomVersion: string = "4.4.4";
|
|
9
|
+
|
|
10
|
+
export const EPNameAsset: string = "pAsset";
|
|
11
|
+
export const EPNameBinary: string = "binary-package";
|
|
12
|
+
export const EPNameCustomName: string = "custom-name";
|
|
13
|
+
export const EPNameJavaEnvironment: string = "java-environment";
|
|
14
|
+
export const EPNamePythonEnvironment: string = "python-environment";
|
|
15
|
+
export const EPNameREnvironment: string = "R-environment";
|
|
16
|
+
export const EPNameJava: string = "java-package";
|
|
17
|
+
export const EPNameDocker: string = "docker-test-entrypoint";
|
|
18
|
+
|
|
19
|
+
const merge = (data: string, patch: Record<string, unknown>): string => {
|
|
20
|
+
const v = JSON.parse(data) as Record<string, unknown>;
|
|
21
|
+
return JSON.stringify({ ...v, ...patch });
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const PackageJsonNoSoftware = `{
|
|
25
|
+
"name": "${PackageName}",
|
|
26
|
+
"version": "${PackageVersion}"
|
|
27
|
+
}`;
|
|
28
|
+
|
|
29
|
+
export const AssetArtifact = `{
|
|
30
|
+
"registry": "${BinaryRegistry}",
|
|
31
|
+
"root": "./src"
|
|
32
|
+
}`;
|
|
33
|
+
|
|
34
|
+
export const BinaryArtifact = `{
|
|
35
|
+
"type": "binary",
|
|
36
|
+
"roots": {
|
|
37
|
+
"linux-x64": "./src/",
|
|
38
|
+
"linux-aarch64": "./src/",
|
|
39
|
+
"macosx-x64": "./src/",
|
|
40
|
+
"macosx-aarch64": "./src/",
|
|
41
|
+
"windows-x64": "./src/"
|
|
42
|
+
}
|
|
43
|
+
}`;
|
|
44
|
+
|
|
45
|
+
export const CondaArtifact = `{
|
|
46
|
+
"roots": {
|
|
47
|
+
"linux-x64": "./src/",
|
|
48
|
+
"linux-aarch64": "./src/",
|
|
49
|
+
"macosx-x64": "./src/",
|
|
50
|
+
"macosx-aarch64": "./src/",
|
|
51
|
+
"windows-x64": "./src/"
|
|
52
|
+
}
|
|
53
|
+
}`;
|
|
54
|
+
|
|
55
|
+
export const CondaArtifactWithType = merge(CondaArtifact, { type: "conda" });
|
|
56
|
+
export const CondaArtifactWithSpec = merge(CondaArtifactWithType, {
|
|
57
|
+
spec: "./some-specification.yaml",
|
|
58
|
+
});
|
|
59
|
+
export const CondaArtifactWithMicromambaVersion = merge(CondaArtifactWithSpec, {
|
|
60
|
+
"micromamba-version": "2.3.2-0",
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export const PythonArtifact = `{
|
|
64
|
+
"type": "python",
|
|
65
|
+
|
|
66
|
+
"root": "./src",
|
|
67
|
+
"environment": ":${EPNamePythonEnvironment}"
|
|
68
|
+
}`;
|
|
69
|
+
|
|
70
|
+
export const RArtifact = `{
|
|
71
|
+
"type": "R",
|
|
72
|
+
|
|
73
|
+
"root": "./src",
|
|
74
|
+
"environment": ":${EPNameREnvironment}"
|
|
75
|
+
}`;
|
|
76
|
+
|
|
77
|
+
export const CustomVersionArtifact = `{
|
|
78
|
+
"type": "binary",
|
|
79
|
+
|
|
80
|
+
"registry": {
|
|
81
|
+
"name": "${BinaryRegistry}"
|
|
82
|
+
},
|
|
83
|
+
"name": "${BinaryCustomName1}",
|
|
84
|
+
"version": "${BinaryCustomVersion}",
|
|
85
|
+
|
|
86
|
+
"roots": {
|
|
87
|
+
"linux-x64": "./src/",
|
|
88
|
+
"linux-aarch64": "./src/",
|
|
89
|
+
"macosx-x64": "./src/",
|
|
90
|
+
"macosx-aarch64": "./src/",
|
|
91
|
+
"windows-x64": "./src/"
|
|
92
|
+
}
|
|
93
|
+
}`;
|
|
94
|
+
|
|
95
|
+
export const JavaArtifact = `{
|
|
96
|
+
"type": "java",
|
|
97
|
+
|
|
98
|
+
"registry": {
|
|
99
|
+
"name": "${BinaryRegistry}"
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
"root": "./src",
|
|
103
|
+
"environment": ":${EPNameJavaEnvironment}"
|
|
104
|
+
}`;
|
|
105
|
+
|
|
106
|
+
export const JavaEnvironmentArtifact = `{
|
|
107
|
+
"runtime": "java",
|
|
108
|
+
|
|
109
|
+
"registry": {
|
|
110
|
+
"name": "${BinaryRegistry}"
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
"roots": {
|
|
114
|
+
"linux-x64": "./src/",
|
|
115
|
+
"linux-aarch64": "./src/",
|
|
116
|
+
"macosx-x64": "./src/",
|
|
117
|
+
"macosx-aarch64": "./src/",
|
|
118
|
+
"windows-x64": "./src/"
|
|
119
|
+
},
|
|
120
|
+
"binDir": "."
|
|
121
|
+
}`;
|
|
122
|
+
|
|
123
|
+
export const JavaEnvironmentArtifactWithType = merge(JavaEnvironmentArtifact, {
|
|
124
|
+
type: "environment",
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
export const DockerArtifact = `{
|
|
128
|
+
"context": "./src"
|
|
129
|
+
}`;
|
|
130
|
+
|
|
131
|
+
export const DockerArtifactWithType = merge(DockerArtifact, { type: "docker" });
|
|
132
|
+
export const DockerArtifactWithPkg = merge(DockerArtifactWithType, { pkg: "/app" });
|
|
133
|
+
export const DockerArtifactWithDockerfile = merge(DockerArtifactWithType, {
|
|
134
|
+
dockerfile: "Dockerfile",
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
export const DockerAsset = `{
|
|
138
|
+
"tag": "some-docker-tag",
|
|
139
|
+
"entrypoint": ["/usr/bin/env", "printf"],
|
|
140
|
+
"cmd": ["Hello, world!"]
|
|
141
|
+
}`;
|
|
142
|
+
|
|
143
|
+
export const EPNameLimitedPlatformsBinary = "multi-root-bin";
|
|
144
|
+
|
|
145
|
+
// This binary artifact intentionally has only part of roots, meaning
|
|
146
|
+
// software is not available for some platforms.
|
|
147
|
+
export const LimitedPlatformsBinary = `{
|
|
148
|
+
"type": "binary",
|
|
149
|
+
|
|
150
|
+
"registry": {
|
|
151
|
+
"name": "${BinaryRegistry}"
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
"roots": {
|
|
155
|
+
"linux-x64": "./linux-x64/",
|
|
156
|
+
"macosx-aarch64": "./macosx-aarch64/"
|
|
157
|
+
}
|
|
158
|
+
}`;
|
|
159
|
+
|
|
160
|
+
export const AssetEntrypoint = `{
|
|
161
|
+
"asset": ${AssetArtifact}
|
|
162
|
+
}`;
|
|
163
|
+
|
|
164
|
+
export const BinaryEntrypoint = `{
|
|
165
|
+
"binary": {
|
|
166
|
+
"artifact": ${BinaryArtifact},
|
|
167
|
+
"cmd": ["aaa"]
|
|
168
|
+
}
|
|
169
|
+
}`;
|
|
170
|
+
|
|
171
|
+
export const BinaryEntrypointWithDocker = `{
|
|
172
|
+
"binary": {
|
|
173
|
+
"artifact": ${BinaryArtifact},
|
|
174
|
+
"cmd": ["aaa"]
|
|
175
|
+
},
|
|
176
|
+
"docker": {
|
|
177
|
+
"artifact": ${DockerArtifact},
|
|
178
|
+
"cmd": ["aaa"]
|
|
179
|
+
}
|
|
180
|
+
}`;
|
|
181
|
+
|
|
182
|
+
export const BinaryEntrypointWithReference = `{
|
|
183
|
+
"binary": {
|
|
184
|
+
"artifact": "binaryArtifactID",
|
|
185
|
+
"cmd": ["aaa"]
|
|
186
|
+
}
|
|
187
|
+
}`;
|
|
188
|
+
|
|
189
|
+
export const CustomBinaryEntrypoint = `{
|
|
190
|
+
"binary": {
|
|
191
|
+
"artifact": ${CustomVersionArtifact},
|
|
192
|
+
"cmd": ["bbb"]
|
|
193
|
+
}
|
|
194
|
+
}`;
|
|
195
|
+
|
|
196
|
+
export const LimitedPlatformsBinaryEntrypoint = `{
|
|
197
|
+
"binary": {
|
|
198
|
+
"artifact": ${LimitedPlatformsBinary},
|
|
199
|
+
"cmd": ["bbb"]
|
|
200
|
+
}
|
|
201
|
+
}`;
|
|
202
|
+
|
|
203
|
+
export const JavaEnvironmentEntrypoint = `{
|
|
204
|
+
"environment": {
|
|
205
|
+
"artifact": ${JavaEnvironmentArtifact}
|
|
206
|
+
}
|
|
207
|
+
}`;
|
|
208
|
+
|
|
209
|
+
export const JavaEnvironmentEntrypointWithReference = `{
|
|
210
|
+
"environment": {
|
|
211
|
+
"artifact": "javaEnvironmentArtifactID"
|
|
212
|
+
}
|
|
213
|
+
}`;
|
|
214
|
+
|
|
215
|
+
export const JavaEntrypoint = `{
|
|
216
|
+
"binary": {
|
|
217
|
+
"artifact": ${JavaArtifact},
|
|
218
|
+
"cmd": ["java", "-jar", "hello.jar"]
|
|
219
|
+
}
|
|
220
|
+
}`;
|
|
221
|
+
|
|
222
|
+
export const JavaEntrypointWithReference = `{
|
|
223
|
+
"binary": {
|
|
224
|
+
"artifact": "javaArtifactID",
|
|
225
|
+
"cmd": ["java", "-jar", "hello.jar"]
|
|
226
|
+
}
|
|
227
|
+
}`;
|
|
228
|
+
|
|
229
|
+
export const JavaEntrypointWithDocker = `{
|
|
230
|
+
"binary": {
|
|
231
|
+
"artifact": ${JavaArtifact},
|
|
232
|
+
"cmd": ["java", "-jar", "hello.jar"]
|
|
233
|
+
},
|
|
234
|
+
"docker": {
|
|
235
|
+
"artifact": ${DockerArtifact},
|
|
236
|
+
"cmd": ["java", "-jar", "hello.jar"]
|
|
237
|
+
}
|
|
238
|
+
}`;
|
|
239
|
+
|
|
240
|
+
export const PythonEntrypoint = `{
|
|
241
|
+
"binary": {
|
|
242
|
+
"artifact": ${PythonArtifact},
|
|
243
|
+
"cmd": ["python", "hello.py"]
|
|
244
|
+
}
|
|
245
|
+
}`;
|
|
246
|
+
|
|
247
|
+
export const PythonEntrypointWithReference = `{
|
|
248
|
+
"binary": {
|
|
249
|
+
"artifact": "pythonArtifactID",
|
|
250
|
+
"cmd": ["python", "hello.py"]
|
|
251
|
+
}
|
|
252
|
+
}`;
|
|
253
|
+
|
|
254
|
+
export const PythonEntrypointWithDocker = `{
|
|
255
|
+
"binary": {
|
|
256
|
+
"artifact": ${PythonArtifact},
|
|
257
|
+
"cmd": ["python", "hello.py"]
|
|
258
|
+
},
|
|
259
|
+
"docker": {
|
|
260
|
+
"artifact": ${DockerArtifact},
|
|
261
|
+
"cmd": ["python", "hello.py"]
|
|
262
|
+
}
|
|
263
|
+
}`;
|
|
264
|
+
|
|
265
|
+
export const REntrypoint = `{
|
|
266
|
+
"binary": {
|
|
267
|
+
"artifact": ${RArtifact},
|
|
268
|
+
"cmd": ["Rscript", "hello.R"]
|
|
269
|
+
}
|
|
270
|
+
}`;
|
|
271
|
+
|
|
272
|
+
export const REntrypointWithReference = `{
|
|
273
|
+
"binary": {
|
|
274
|
+
"artifact": "RArtifactID",
|
|
275
|
+
"cmd": ["Rscript", "hello.R"]
|
|
276
|
+
}
|
|
277
|
+
}`;
|
|
278
|
+
|
|
279
|
+
export const REntrypointWithDocker = `{
|
|
280
|
+
"binary": {
|
|
281
|
+
"artifact": ${RArtifact},
|
|
282
|
+
"cmd": ["Rscript", "hello.R"]
|
|
283
|
+
},
|
|
284
|
+
"docker": {
|
|
285
|
+
"artifact": ${DockerArtifact},
|
|
286
|
+
"cmd": ["Rscript", "hello.R"]
|
|
287
|
+
}
|
|
288
|
+
}`;
|
|
289
|
+
|
|
290
|
+
export const CondaEntrypoint = `{
|
|
291
|
+
"conda": {
|
|
292
|
+
"artifact": ${CondaArtifact},
|
|
293
|
+
"cmd": ["python", "hello.py"]
|
|
294
|
+
}
|
|
295
|
+
}`;
|
|
296
|
+
|
|
297
|
+
export const CondaEntrypointWithReference = `{
|
|
298
|
+
"conda": {
|
|
299
|
+
"artifact": "condaArtifactID",
|
|
300
|
+
"cmd": ["ANARCI"]
|
|
301
|
+
}
|
|
302
|
+
}`;
|
|
303
|
+
|
|
304
|
+
export const CondaEntrypointWithDocker = `{
|
|
305
|
+
"conda": {
|
|
306
|
+
"artifact": ${CondaArtifactWithMicromambaVersion},
|
|
307
|
+
"cmd": ["ls"]
|
|
308
|
+
},
|
|
309
|
+
"docker": {
|
|
310
|
+
"artifact": ${DockerArtifact},
|
|
311
|
+
"cmd": ["ls"]
|
|
312
|
+
}
|
|
313
|
+
}`;
|
|
314
|
+
|
|
315
|
+
export const DockerEntrypoint = `{
|
|
316
|
+
"docker": {
|
|
317
|
+
"artifact": ${DockerArtifact},
|
|
318
|
+
"cmd": ["echo", "hello"]
|
|
319
|
+
}
|
|
320
|
+
}`;
|
|
321
|
+
|
|
322
|
+
export const DockerEntrypointWithReference = `{
|
|
323
|
+
"docker": {
|
|
324
|
+
"artifact": "dockerArtifactID",
|
|
325
|
+
"cmd": ["echo", "hello"]
|
|
326
|
+
}
|
|
327
|
+
}`;
|
|
328
|
+
|
|
329
|
+
export const PackageJson = `{
|
|
330
|
+
"name": "${PackageName}",
|
|
331
|
+
"version": "${PackageVersion}",
|
|
332
|
+
"block-software": {
|
|
333
|
+
"registries": {
|
|
334
|
+
"binary": {
|
|
335
|
+
"${BinaryRegistry}": {"downloadURL": "${BinaryRegistryURL}"}
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
"entrypoints": {
|
|
339
|
+
"${EPNameAsset}": ${AssetEntrypoint},
|
|
340
|
+
"${EPNameCustomName}": ${CustomBinaryEntrypoint},
|
|
341
|
+
"${EPNameLimitedPlatformsBinary}": ${LimitedPlatformsBinaryEntrypoint},
|
|
342
|
+
"${EPNameJavaEnvironment}": ${JavaEnvironmentEntrypoint},
|
|
343
|
+
"${EPNameJava}": ${JavaEntrypointWithDocker},
|
|
344
|
+
"${EPNameDocker}": ${DockerEntrypoint}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}`;
|
|
348
|
+
|
|
349
|
+
export const SingleBinaryackageJson = `{
|
|
350
|
+
"name": "${PackageName}",
|
|
351
|
+
"version": "${PackageVersion}",
|
|
352
|
+
"block-software": {
|
|
353
|
+
"entrypoints": {
|
|
354
|
+
"${EPNameBinary}": {
|
|
355
|
+
"binary": {
|
|
356
|
+
"artifact": ${BinaryArtifact},
|
|
357
|
+
"cmd": ["run-some-binary"]
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}`;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import pathPosix from "node:path/posix";
|
|
2
|
+
import { S3 } from "@aws-sdk/client-s3";
|
|
3
|
+
import { Upload } from "@aws-sdk/lib-storage";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import * as util from "./util";
|
|
6
|
+
import type { Readable } from "node:stream";
|
|
7
|
+
|
|
8
|
+
export const supportedTypes = ["S3"] as const; // add other types when we support them
|
|
9
|
+
export type storageType = (typeof supportedTypes)[number];
|
|
10
|
+
|
|
11
|
+
export function typeToURLScheme(sType: storageType): string {
|
|
12
|
+
switch (sType) {
|
|
13
|
+
case "S3":
|
|
14
|
+
return "s3";
|
|
15
|
+
default:
|
|
16
|
+
util.assertNever(sType);
|
|
17
|
+
throw new Error("no schema defined for storage type"); // just to calm down TS type analyzer
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface RegistryStorage {
|
|
22
|
+
exists(file: string): Promise<boolean>;
|
|
23
|
+
putFile(file: string, data: Buffer | Readable): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function objectExists(client: S3, bucket: string, key: string): Promise<boolean> {
|
|
27
|
+
try {
|
|
28
|
+
await client.headObject({
|
|
29
|
+
Bucket: bucket,
|
|
30
|
+
Key: key,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return true;
|
|
34
|
+
} catch (error) {
|
|
35
|
+
if (error instanceof Error && error.name === "NotFound") {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
throw util.wrapErr(error, `failed to check if object exists in S3 bucket ${bucket}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function newS3(
|
|
44
|
+
options: NonNullable<ConstructorParameters<typeof S3>[0]>,
|
|
45
|
+
bucket: string,
|
|
46
|
+
): Promise<S3> {
|
|
47
|
+
const client = new S3(options);
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
await objectExists(client, bucket, "/");
|
|
51
|
+
} catch (error) {
|
|
52
|
+
throw util.CLIError(
|
|
53
|
+
`credentials given to package builder do not have access to S3 bucket '${bucket}': ${error}`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return client;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export class S3Storage implements RegistryStorage {
|
|
61
|
+
constructor(
|
|
62
|
+
public readonly client: S3,
|
|
63
|
+
public readonly bucket: string,
|
|
64
|
+
public readonly root: string = "",
|
|
65
|
+
) {}
|
|
66
|
+
|
|
67
|
+
async exists(file: string): Promise<boolean> {
|
|
68
|
+
return objectExists(this.client, this.bucket, pathPosix.join(this.root, file));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async putFile(file: string, data: Buffer | Readable): Promise<void> {
|
|
72
|
+
try {
|
|
73
|
+
const upload = new Upload({
|
|
74
|
+
client: this.client,
|
|
75
|
+
params: {
|
|
76
|
+
Bucket: this.bucket,
|
|
77
|
+
Key: pathPosix.join(this.root, file),
|
|
78
|
+
Body: data,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await upload.done();
|
|
83
|
+
} catch (e) {
|
|
84
|
+
throw util.wrapErr(e, `failed to put object into S3 bucket ${this.bucket}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function initByUrl(address: string, pkgRoot: string): Promise<RegistryStorage> {
|
|
90
|
+
if (address === "") {
|
|
91
|
+
throw util.CLIError(`Empty registry storage address`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const url = new URL(address, `file:${pkgRoot.split(path.sep).join(pathPosix.sep)}/`);
|
|
96
|
+
switch (url.protocol) {
|
|
97
|
+
case "s3:": {
|
|
98
|
+
const s3Options: NonNullable<ConstructorParameters<typeof S3>[0]> = {};
|
|
99
|
+
const s3Region = url.searchParams.get("region");
|
|
100
|
+
if (s3Region) s3Options.region = s3Region;
|
|
101
|
+
const s3Bucket = url.hostname;
|
|
102
|
+
const s3KeyPrefix = util.trimPrefix(url.pathname, "/");
|
|
103
|
+
const s3Client = await newS3(s3Options, s3Bucket);
|
|
104
|
+
return new S3Storage(s3Client, s3Bucket, s3KeyPrefix);
|
|
105
|
+
}
|
|
106
|
+
case "s3e:": {
|
|
107
|
+
const s3eOptions: NonNullable<ConstructorParameters<typeof S3>[0]> = {};
|
|
108
|
+
const s3eRegion = url.searchParams.get("region");
|
|
109
|
+
if (s3eRegion) s3eOptions.region = s3eRegion;
|
|
110
|
+
|
|
111
|
+
const s3ePath = url.pathname.split("/").slice(1); // '/bucket/keyPrefix' -> ['', 'bucket', 'keyPrefix'] -> ['bucket', 'keyPrefix']
|
|
112
|
+
const s3eBucket = s3ePath[0];
|
|
113
|
+
const s3eKeyPrefix = s3ePath.length > 1 ? util.trimPrefix(s3ePath[1], "/") : "";
|
|
114
|
+
const s3eClient = await newS3(s3eOptions, s3eBucket);
|
|
115
|
+
return new S3Storage(s3eClient, s3eBucket, s3eKeyPrefix);
|
|
116
|
+
}
|
|
117
|
+
default:
|
|
118
|
+
throw util.CLIError(
|
|
119
|
+
`Protocol ${url.protocol} is not supported for software registries yet. Use your own tooling for package upload`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
} catch (e) {
|
|
123
|
+
throw util.wrapErr(e, `failed to init storage driver from URL`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { randomBytes } from "node:crypto";
|
|
5
|
+
|
|
6
|
+
import * as defaults from "../defaults";
|
|
7
|
+
import * as artifacts from "./schemas/artifacts";
|
|
8
|
+
import { PackageInfo } from "./package-info";
|
|
9
|
+
import { descriptorFilePath, readDescriptorFile } from "./resolver";
|
|
10
|
+
import { SwJsonRenderer, writeBuiltArtifactInfo } from "./sw-json-render";
|
|
11
|
+
import * as test_assets from "./schemas/test-artifacts";
|
|
12
|
+
import { createLogger } from "./util";
|
|
13
|
+
import { describe, test, expect, beforeAll, beforeEach, afterAll } from "vitest";
|
|
14
|
+
import * as docker from "./docker";
|
|
15
|
+
import * as util from "./util";
|
|
16
|
+
|
|
17
|
+
describe("Renderer tests", () => {
|
|
18
|
+
let tempDir: string;
|
|
19
|
+
let i: PackageInfo;
|
|
20
|
+
const l = createLogger("error");
|
|
21
|
+
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "vitest-temp-dir-"));
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
const fakePackageRoot = path.join(tempDir, randomBytes(16).toString("hex"));
|
|
28
|
+
i = new PackageInfo(l, { pkgJsonData: test_assets.PackageJson, packageRoot: fakePackageRoot });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterAll(() => {
|
|
32
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("render asset", () => {
|
|
36
|
+
const epName = test_assets.EPNameAsset;
|
|
37
|
+
const assetPkg = i.getArtifact(epName, "asset");
|
|
38
|
+
const sw = new SwJsonRenderer(l, i);
|
|
39
|
+
|
|
40
|
+
writeTestArtifactInfo(i, "archive", assetPkg);
|
|
41
|
+
const eps = new Map([[epName, i.getMainEntrypoint(epName)]]);
|
|
42
|
+
const descriptor = sw.renderSoftwareEntrypoints("release", eps).get(epName)!;
|
|
43
|
+
|
|
44
|
+
const url = descriptor.asset!.url;
|
|
45
|
+
const expectedPath = `${test_assets.BinaryRegistryURL}/assets/${test_assets.PackageNameNoAt}/pAsset/${test_assets.PackageVersion}.zip`;
|
|
46
|
+
expect(url).toEqual(expectedPath);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("render os-dependant", () => {
|
|
50
|
+
const epName = test_assets.EPNameCustomName;
|
|
51
|
+
const binPkg = i.getArtifact(epName, "binary");
|
|
52
|
+
const sw = new SwJsonRenderer(l, i);
|
|
53
|
+
|
|
54
|
+
writeTestArtifactInfo(i, "archive", binPkg);
|
|
55
|
+
const eps = new Map([[epName, i.getMainEntrypoint(epName)]]);
|
|
56
|
+
const descriptor = sw.renderSoftwareEntrypoints("release", eps).get(epName)!;
|
|
57
|
+
|
|
58
|
+
expect(descriptor.binary!.package).toEqual(
|
|
59
|
+
`software/${test_assets.BinaryCustomName1}/${test_assets.BinaryCustomVersion}-{os}-{arch}.tgz`,
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("render environment", () => {
|
|
64
|
+
const epName = test_assets.EPNameJavaEnvironment;
|
|
65
|
+
const envPkg = i.getArtifact(epName, "environment");
|
|
66
|
+
const sw = new SwJsonRenderer(l, i);
|
|
67
|
+
|
|
68
|
+
writeTestArtifactInfo(i, "archive", envPkg);
|
|
69
|
+
const eps = new Map([[epName, i.entrypoints.get(epName)!]]);
|
|
70
|
+
const descriptor = sw.renderSoftwareEntrypoints("release", eps).get(epName)!;
|
|
71
|
+
|
|
72
|
+
expect(descriptor.runEnv!.package).toEqual(
|
|
73
|
+
`software/${test_assets.PackageNameNoAt}/${test_assets.EPNameJavaEnvironment}/${test_assets.PackageVersion}-{os}-{arch}.tgz`,
|
|
74
|
+
);
|
|
75
|
+
expect(descriptor.runEnv!.type).toEqual("java");
|
|
76
|
+
expect(descriptor.runEnv!.binDir).toEqual(".");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("read descriptor after render", () => {
|
|
80
|
+
const epName = test_assets.EPNameCustomName;
|
|
81
|
+
const binPkg = i.getArtifact(epName, "binary");
|
|
82
|
+
const sw = new SwJsonRenderer(l, i);
|
|
83
|
+
|
|
84
|
+
writeTestArtifactInfo(i, "archive", binPkg);
|
|
85
|
+
const eps = new Map([[epName, i.getMainEntrypoint(epName)]]);
|
|
86
|
+
const renderedDescriptor = sw.renderSoftwareEntrypoints("release", eps).get(epName)!;
|
|
87
|
+
sw.writeSwJson(renderedDescriptor);
|
|
88
|
+
|
|
89
|
+
const epPath = descriptorFilePath(
|
|
90
|
+
i.packageRoot,
|
|
91
|
+
renderedDescriptor.asset ? "asset" : "software",
|
|
92
|
+
epName,
|
|
93
|
+
);
|
|
94
|
+
const parsedDescriptor = readDescriptorFile(i.packageName, epName, epPath);
|
|
95
|
+
|
|
96
|
+
expect(parsedDescriptor.binary).toEqual(renderedDescriptor.binary);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("render with environment dependency", () => {
|
|
100
|
+
const envEpName = test_assets.EPNameJavaEnvironment;
|
|
101
|
+
const envPkg = i.getArtifact(envEpName, "environment");
|
|
102
|
+
const epName = test_assets.EPNameJava;
|
|
103
|
+
const javaPkg = i.getArtifact(epName, "java");
|
|
104
|
+
|
|
105
|
+
const renderer = new SwJsonRenderer(l, i);
|
|
106
|
+
|
|
107
|
+
writeTestArtifactInfo(i, "archive", envPkg);
|
|
108
|
+
const envEps = new Map([[envEpName, i.getMainEntrypoint(envEpName)]]);
|
|
109
|
+
const envDescriptor = renderer.renderSoftwareEntrypoints("release", envEps).get(envEpName)!;
|
|
110
|
+
renderer.writeSwJson(envDescriptor);
|
|
111
|
+
|
|
112
|
+
writeTestArtifactInfo(i, "archive", javaPkg);
|
|
113
|
+
const eps = new Map([[epName, i.getMainEntrypoint(epName)]]);
|
|
114
|
+
const descriptor = renderer.renderSoftwareEntrypoints("release", eps).get(epName)!;
|
|
115
|
+
expect(descriptor.binary!.package).toEqual(
|
|
116
|
+
`software/${test_assets.PackageNameNoAt}/${test_assets.EPNameJava}/${test_assets.PackageVersion}.tgz`,
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("render docker with binary", () => {
|
|
121
|
+
const envEpName = test_assets.EPNameJavaEnvironment;
|
|
122
|
+
const envArtifact = i.getArtifact(envEpName, "environment");
|
|
123
|
+
writeTestArtifactInfo(i, "archive", envArtifact);
|
|
124
|
+
|
|
125
|
+
const javaEpName = test_assets.EPNameJava;
|
|
126
|
+
const javaArtifact = i.getArtifact(javaEpName, "java");
|
|
127
|
+
writeTestArtifactInfo(i, "archive", javaArtifact);
|
|
128
|
+
|
|
129
|
+
const javaDockerEpName = docker.entrypointName(javaEpName);
|
|
130
|
+
const dockerPkg = i.getArtifact(javaEpName, "docker");
|
|
131
|
+
writeTestArtifactInfo(i, "docker", dockerPkg);
|
|
132
|
+
|
|
133
|
+
fs.mkdirSync(path.join(i.packageRoot, i.packageRoot), { recursive: true });
|
|
134
|
+
fs.mkdirSync(path.join(i.packageRoot, "docker-context"), { recursive: true });
|
|
135
|
+
fs.writeFileSync(path.join(i.packageRoot, "Dockerfile"), "FROM scratch");
|
|
136
|
+
fs.writeFileSync(path.join(i.packageRoot, "package.json"), test_assets.PackageJson);
|
|
137
|
+
|
|
138
|
+
const render = new SwJsonRenderer(l, i);
|
|
139
|
+
|
|
140
|
+
const envEps = new Map([[envEpName, i.getMainEntrypoint(envEpName)]]);
|
|
141
|
+
const envDescriptor = render.renderSoftwareEntrypoints("release", envEps).get(envEpName)!;
|
|
142
|
+
render.writeSwJson(envDescriptor);
|
|
143
|
+
|
|
144
|
+
const eps = new Map([
|
|
145
|
+
[javaDockerEpName, i.getMainEntrypoint(javaDockerEpName)],
|
|
146
|
+
[javaEpName, i.getMainEntrypoint(javaEpName)],
|
|
147
|
+
]);
|
|
148
|
+
const javaDescriptor = render.renderSoftwareEntrypoints("release", eps).get(javaEpName)!;
|
|
149
|
+
render.writeSwJson(javaDescriptor);
|
|
150
|
+
|
|
151
|
+
const expectedTag = new RegExp(
|
|
152
|
+
`${defaults.DOCKER_REGISTRY}:${test_assets.PackageNameNoAt}\\.${javaEpName}\\.(?<hash>.*)`,
|
|
153
|
+
);
|
|
154
|
+
expect(javaDescriptor.docker).toBeDefined();
|
|
155
|
+
expect(javaDescriptor.docker!.tag).toMatch(expectedTag);
|
|
156
|
+
expect(javaDescriptor.docker!.cmd).toEqual(["java", "-jar", "hello.jar"]);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("render docker indinvidual entrypoint", () => {
|
|
160
|
+
const dockerEpName = test_assets.EPNameDocker;
|
|
161
|
+
const dockerPkg = i.getArtifact(dockerEpName, "docker");
|
|
162
|
+
writeTestArtifactInfo(i, "docker", dockerPkg);
|
|
163
|
+
|
|
164
|
+
fs.mkdirSync(path.join(i.packageRoot, i.packageRoot), { recursive: true });
|
|
165
|
+
fs.mkdirSync(path.join(i.packageRoot, "docker-context"), { recursive: true });
|
|
166
|
+
fs.writeFileSync(path.join(i.packageRoot, "Dockerfile"), "FROM scratch");
|
|
167
|
+
fs.writeFileSync(path.join(i.packageRoot, "package.json"), test_assets.PackageJson);
|
|
168
|
+
|
|
169
|
+
const render = new SwJsonRenderer(l, i);
|
|
170
|
+
|
|
171
|
+
const eps = new Map([[dockerEpName, i.getMainEntrypoint(dockerEpName)]]);
|
|
172
|
+
const dockerDescriptor = render.renderSoftwareEntrypoints("release", eps).get(dockerEpName)!;
|
|
173
|
+
|
|
174
|
+
const expectedTag = new RegExp(
|
|
175
|
+
`${defaults.DOCKER_REGISTRY}:${test_assets.PackageNameNoAt}\\.${dockerEpName}\\.(?<hash>.*)`,
|
|
176
|
+
);
|
|
177
|
+
expect(dockerDescriptor.docker).toBeDefined();
|
|
178
|
+
expect(dockerDescriptor.docker!.tag).toMatch(expectedTag);
|
|
179
|
+
expect(dockerDescriptor.docker!.cmd).toEqual(["echo", "hello"]);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
function writeTestArtifactInfo(
|
|
184
|
+
i: PackageInfo,
|
|
185
|
+
artifactType: "docker" | "archive",
|
|
186
|
+
artifact: artifacts.withId<artifacts.anyArtifactType>,
|
|
187
|
+
) {
|
|
188
|
+
let artInfoPath: string;
|
|
189
|
+
if (artifactType === "docker") {
|
|
190
|
+
// Docker artifacts are always cross-compiled to linux/amd64 (see
|
|
191
|
+
// core.buildDockerImage + sw-json-render.renderDockerInfo).
|
|
192
|
+
artInfoPath = i.artifactInfoLocation(artifact.id, "docker", "x64");
|
|
193
|
+
} else if (artifacts.isCrossPlatform(artifact.type)) {
|
|
194
|
+
artInfoPath = i.artifactInfoLocation(artifact.id, "archive", undefined);
|
|
195
|
+
} else {
|
|
196
|
+
artInfoPath = i.artifactInfoLocation(artifact.id, "archive", util.currentPlatform());
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const registry = i.artifactRegistrySettings(artifact);
|
|
200
|
+
|
|
201
|
+
writeBuiltArtifactInfo(artInfoPath, {
|
|
202
|
+
type: artifact.type,
|
|
203
|
+
platform: util.currentPlatform(),
|
|
204
|
+
registryURL: artifact.type === "asset" ? registry.downloadURL : undefined,
|
|
205
|
+
registryName: registry.name,
|
|
206
|
+
remoteArtifactLocation:
|
|
207
|
+
artifactType === "docker"
|
|
208
|
+
? docker.generateRemoteTagName(i.artifactName(artifact), "beefface")
|
|
209
|
+
: i.artifactArchiveAddressPattern(artifact),
|
|
210
|
+
uploadPath:
|
|
211
|
+
artifactType === "docker"
|
|
212
|
+
? undefined
|
|
213
|
+
: i.artifactArchiveFullName(artifact, util.currentPlatform()),
|
|
214
|
+
});
|
|
215
|
+
}
|