Open History to see the last commit
1import * as Cloudflare from "@alchemy.run/cloudflare";
2import { GitApi } from "@alchemy.run/git/Api";
3import { expect } from "@alchemy.run/test";
4import * as Test from "@alchemy.run/test/Alchemy";
5/**
6 * Push-ingest profile against the LOCAL workerd (no cloud deploy): pushes
7 * the repository at `GIT_PROFILE_REPO` and prints the server's per-phase
8 * split. Skipped unless the env var is set — it is a measurement tool, not
9 * a regression test (DESIGN §22.4).
10 *
11 * GIT_PROFILE_REPO=/path/to/checkout pnpm test test/Git/GitIngestProfile.local.test.ts
12 *
13 * Do NOT export CLOUDFLARE_ACCOUNT_ID / CLOUDFLARE_API_TOKEN for this: the
14 * profile loader treats env credentials as "configure this profile as env"
15 * and rewrites ~/.alchemy/profiles.json.
16 */
17import * as Alchemy from "alchemy";
18import * as Effect from "effect/Effect";
19import * as FileSystem from "effect/FileSystem";
20import * as HttpApiClient from "effect/http-api/HttpApiClient";
21import * as HttpClient from "effect/http/HttpClient";
22import * as HttpClientRequest from "effect/http/HttpClientRequest";
23import * as ChildProcess from "effect/process/ChildProcess";
24import * as Schedule from "effect/Schedule";
25import * as Stream from "effect/Stream";
26import TestGitHost, { TEST_SECRET } from "./fixtures/stack.ts";
27
28const PROFILE_REPO = process.env.GIT_PROFILE_REPO;
29
30const { test, beforeAll, afterAll, deploy, destroy } = Test.make({
31 providers: Cloudflare.providers(),
32 dev: true,
33});
34
35const LocalStack = Alchemy.Stack(
36 "GitIngestProfileStack",
37 { providers: Cloudflare.providers(), state: Alchemy.localState() },
38 Effect.gen(function* () {
39 const host = yield* TestGitHost;
40 return { url: host.url.as<string>() };
41 }),
42);
43
44const git = Effect.fn(function* (cwd: string, ...args: Array<string>) {
45 const handle = yield* ChildProcess.make("git", args, {
46 cwd,
47 env: { GIT_TERMINAL_PROMPT: "0" },
48 extendEnv: true,
49 });
50 const [exitCode, stderr] = yield* Effect.all(
51 [handle.exitCode, Stream.mkString(Stream.decodeText(handle.stderr))],
52 { concurrency: 2 },
53 );
54 return { exitCode, stderr };
55}, Effect.timeout("10 minutes"));
56
57if (PROFILE_REPO === undefined) {
58 test.skip("profile: set GIT_PROFILE_REPO=/path/to/checkout to run", Effect.void, {
59 tags: ["provider:cloudflare", "local"],
60 });
61} else {
62 const stack = beforeAll(deploy(LocalStack));
63 afterAll(destroy(LocalStack));
64 test(
65 "profile: push GIT_PROFILE_REPO into local workerd and print the ingest split",
66 Effect.gen(function* () {
67 const { url } = yield* stack;
68 const client = yield* HttpApiClient.make(GitApi, {
69 baseUrl: url,
70 transformClient: HttpClient.mapRequest((r) =>
71 r.pipe(HttpClientRequest.bearerToken(TEST_SECRET)),
72 ),
73 });
74 yield* client.repos.get({ params: { owner: "profile", repo: "repo" } }).pipe(
75 Effect.retry({ schedule: Schedule.spaced("500 millis"), times: 20 }),
76 Effect.catchTag("RepoNotFound", () => Effect.void),
77 );
78 const created = yield* client.repos.create({ payload: { owner: "profile", name: "repo" } });
79 const parsed = new URL(url);
80 const remote = `${parsed.protocol}//x:${TEST_SECRET}@${parsed.host}/profile/repo.git`;
81 const t0 = performance.now();
82 const push = yield* git(PROFILE_REPO!, "push", "-q", remote, "HEAD:refs/heads/main");
83 const wall = performance.now() - t0;
84 if (push.exitCode !== 0)
85 console.log("[ingest-profile] PUSH FAILED:", push.stderr.slice(0, 2000));
86 expect(push.exitCode, push.stderr).toBe(0);
87 const meta = yield* client.repos.get({ params: { owner: "profile", repo: "repo" } });
88 // Clone it back and let real git verify — a promoted push must read
89 // back byte-for-byte through the wire pack.
90 const fs = yield* FileSystem.FileSystem;
91 const tmp = yield* fs.makeTempDirectory({ prefix: "git-ingest-profile-" });
92 const clone = yield* git(tmp, "clone", "-q", remote, "back");
93 if (clone.exitCode !== 0)
94 console.log("[ingest-profile] CLONE FAILED:", clone.stderr.slice(0, 2000));
95 expect(clone.exitCode, clone.stderr).toBe(0);
96 const fsck = yield* git(`${tmp}/back`, "fsck", "--connectivity-only");
97 if (fsck.exitCode !== 0)
98 console.log("[ingest-profile] FSCK FAILED:", fsck.stderr.slice(0, 2000));
99 expect(fsck.exitCode, fsck.stderr).toBe(0);
100 console.log(
101 `[ingest-profile] objects: ${JSON.stringify(meta.objects)}; clone back + fsck ok`,
102 );
103 const p = meta.lastPush!;
104 // Counts (chunks, regions, unresolved) are reported alongside the
105 // wall-clock phases; label them as such.
106 const counts = new Set(["chunks", "regions", "unresolved"]);
107 const phases = Object.entries(p.phases ?? {})
108 .sort((a, b) => b[1] - a[1])
109 .map(([k, v]) => (counts.has(k) ? `${k}=${v}` : `${k} ${v}ms`))
110 .join(", ");
111 console.log(
112 `[ingest-profile] ${p.objects} objects, ${(p.bytes / 1048576).toFixed(1)} MiB: ` +
113 `ingest ${p.ingestMs}ms (sql ${p.stageMs}ms, cpu ${p.ingestMs - p.stageMs}ms → ${((p.ingestMs - p.stageMs) / p.objects).toFixed(2)} ms/object) ` +
114 `connectivity ${p.connectivityMs}ms finalize ${p.finalizeMs}ms total ${p.totalMs}ms; wall ${wall.toFixed(0)}ms\n` +
115 `[ingest-profile] phases: ${phases}`,
116 );
117 }),
118 {
119 tags: [
120 "provider:cloudflare",
121 "provider:cloudflare:r2",
122 "provider:cloudflare:worker",
123 "local",
124 ],
125 timeout: 600_000,
126 },
127 );
128}