1import * as Docker from "@/Docker";
2import * as Test from "@/Test/Alchemy";
3import { expect } from "alchemy-test";
4import * as Effect from "effect/Effect";
5import * as Schedule from "effect/Schedule";
6import * as HttpClient from "effect/http/HttpClient";
7import {
8 materializeIsolatedProject,
9 removeIsolatedProject,
10} from "../IsolatedProject.ts";
11import IsolatedProjectService, {
12 SERVICE_EXTERNAL_PORT,
13 project,
14} from "./fixtures/isolated-project-service.ts";
15import { ensureDockerSwarm } from "./Runtime.ts";
16
17const { test } = Test.make({ providers: Docker.providers() });
18
19// Proof on the local engine that the Docker.Service bun bootstrap boots when
20// the service's `main` lives in an isolated project (see
21// test/IsolatedProject.ts) — the bundle `cwd` resolves none of alchemy's
22// dependencies, so the bootstrap's `@effect/platform-bun` / `alchemy/*`
23// imports must be bundled by the virtual-entry plugin rather than found from
24// the project root. With them left external bun dies at module load and the
25// swarm task never listens.
26test.provider(
27 "service bundled from an isolated project serves HTTP",
28 (stack) =>
29 Effect.gen(function* () {
30 yield* ensureDockerSwarm;
31 yield* materializeIsolatedProject(project);
32 yield* stack.destroy();
33
34 try {
35 const service = yield* stack.deploy(
36 Effect.gen(function* () {
37 return yield* IsolatedProjectService;
38 }),
39 );
40 expect(service.replicas).toBe(1);
41
42 const base = `http://localhost:${SERVICE_EXTERNAL_PORT}`;
43 const health = yield* HttpClient.get(`${base}/health`).pipe(
44 Effect.flatMap((res) =>
45 res.status === 200
46 ? res.json
47 : Effect.fail(new Error(`/health returned ${res.status}`)),
48 ),
49 Effect.retry({ schedule: Schedule.spaced("2 seconds"), times: 30 }),
50 );
51 expect(health).toEqual({ ok: true });
52
53 yield* stack.destroy();
54 } finally {
55 yield* removeIsolatedProject(project);
56 }
57 }),
58 {
59 tags: ["provider:docker", "provider:docker:service", "local"],
60 timeout: 420_000,
61 },
62);