@crewhaus/docker-images 0.1.1 → 0.1.2
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/package.json +6 -11
- package/src/index.test.ts +53 -0
- package/src/index.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewhaus/docker-images",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Per-target-shape Docker images (multi-stage, non-root, healthchecked) + crewhaus build-image CLI wrapper (Section 32)",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
"test": "bun test src"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@crewhaus/errors": "0.1.
|
|
15
|
+
"@crewhaus/errors": "0.1.2"
|
|
16
16
|
},
|
|
17
17
|
"license": "Apache-2.0",
|
|
18
18
|
"author": {
|
|
19
19
|
"name": "Max Meier",
|
|
20
|
-
"email": "max@
|
|
21
|
-
"url": "https://
|
|
20
|
+
"email": "max@crewhaus.ai",
|
|
21
|
+
"url": "https://crewhaus.ai"
|
|
22
22
|
},
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
@@ -30,12 +30,7 @@
|
|
|
30
30
|
"url": "https://github.com/crewhaus/factory/issues"
|
|
31
31
|
},
|
|
32
32
|
"publishConfig": {
|
|
33
|
-
"access": "
|
|
33
|
+
"access": "public"
|
|
34
34
|
},
|
|
35
|
-
"files": [
|
|
36
|
-
"src",
|
|
37
|
-
"README.md",
|
|
38
|
-
"LICENSE",
|
|
39
|
-
"NOTICE"
|
|
40
|
-
]
|
|
35
|
+
"files": ["src", "README.md", "LICENSE", "NOTICE"]
|
|
41
36
|
}
|
package/src/index.test.ts
CHANGED
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
DockerImagesError,
|
|
9
9
|
TARGET_SHAPES,
|
|
10
10
|
buildImage,
|
|
11
|
+
defaultRunner,
|
|
12
|
+
digestsPath,
|
|
11
13
|
dockerRoot,
|
|
12
14
|
dockerfilePath,
|
|
13
15
|
dockerfileSize,
|
|
@@ -61,6 +63,11 @@ describe("Dockerfiles on disk", () => {
|
|
|
61
63
|
test("dockerRoot points inside the package", () => {
|
|
62
64
|
expect(dockerRoot()).toMatch(/packages\/docker-images\/docker$/);
|
|
63
65
|
});
|
|
66
|
+
|
|
67
|
+
test("digestsPath resolves to docker/digests.json inside the package", () => {
|
|
68
|
+
expect(digestsPath()).toMatch(/packages\/docker-images\/docker\/digests\.json$/);
|
|
69
|
+
expect(digestsPath()).toBe(join(dockerRoot(), "digests.json"));
|
|
70
|
+
});
|
|
64
71
|
});
|
|
65
72
|
|
|
66
73
|
describe("Dockerfile structural contract (T2)", () => {
|
|
@@ -252,3 +259,49 @@ CMD ["--help"]
|
|
|
252
259
|
expect(fp.exposedPorts).toEqual([]);
|
|
253
260
|
});
|
|
254
261
|
});
|
|
262
|
+
|
|
263
|
+
describe("defaultRunner (spawn integration, deterministic)", () => {
|
|
264
|
+
// We drive the real spawn-based runner using the running JS binary
|
|
265
|
+
// (`process.execPath`) with `-e` — no docker, no network, no external
|
|
266
|
+
// service. argv[0] is the program; the rest are passed verbatim.
|
|
267
|
+
const exe = process.execPath;
|
|
268
|
+
|
|
269
|
+
test("captures stdout, stderr, and a zero exit code", async () => {
|
|
270
|
+
const result = await defaultRunner(
|
|
271
|
+
[exe, "-e", 'process.stdout.write("hello-out");process.stderr.write("hello-err")'],
|
|
272
|
+
process.cwd(),
|
|
273
|
+
);
|
|
274
|
+
expect(result.exitCode).toBe(0);
|
|
275
|
+
expect(result.stdout).toBe("hello-out");
|
|
276
|
+
expect(result.stderr).toBe("hello-err");
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test("propagates a non-zero exit code", async () => {
|
|
280
|
+
const result = await defaultRunner(
|
|
281
|
+
[exe, "-e", 'process.stderr.write("boom");process.exit(7)'],
|
|
282
|
+
process.cwd(),
|
|
283
|
+
);
|
|
284
|
+
expect(result.exitCode).toBe(7);
|
|
285
|
+
expect(result.stderr).toBe("boom");
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
test("resolves with exitCode 1 when the program cannot be spawned (error event)", async () => {
|
|
289
|
+
const result = await defaultRunner(
|
|
290
|
+
["./crewhaus-nonexistent-binary-9f3a2c", "--version"],
|
|
291
|
+
process.cwd(),
|
|
292
|
+
);
|
|
293
|
+
expect(result.exitCode).toBe(1);
|
|
294
|
+
expect(result.stdout).toBe("");
|
|
295
|
+
expect(result.stderr.length).toBeGreaterThan(0);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
test("falls back to exitCode 1 when the child is killed by a signal (null code)", async () => {
|
|
299
|
+
// A child that SIGKILLs itself terminates via signal, so `close` fires with
|
|
300
|
+
// code === null — exercising the `code ?? 1` fallback deterministically.
|
|
301
|
+
const result = await defaultRunner(
|
|
302
|
+
[exe, "-e", "process.kill(process.pid, 'SIGKILL')"],
|
|
303
|
+
process.cwd(),
|
|
304
|
+
);
|
|
305
|
+
expect(result.exitCode).toBe(1);
|
|
306
|
+
});
|
|
307
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -152,7 +152,7 @@ export async function buildImage(opts: BuildImageOptions): Promise<BuildImageRes
|
|
|
152
152
|
return { tag: opts.tag, target: opts.target, buildArgv: argv };
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
const defaultRunner: BuildRunner = async (argv, cwd) => {
|
|
155
|
+
export const defaultRunner: BuildRunner = async (argv, cwd) => {
|
|
156
156
|
const { spawn } = await import("node:child_process");
|
|
157
157
|
return new Promise((resolve_) => {
|
|
158
158
|
const head = argv[0] ?? "docker";
|