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
|
import { describe, expect, it } from "bun:test";
import { readFileSync } from "fs";
const SRC = readFileSync("src/lib/first-repo-scaffold.ts", "utf8");
const WEB = readFileSync("src/routes/web.tsx", "utf8");
describe("wiring", () => {
it("POST /new scaffolds after bootstrapping", () => {
const handler = WEB.slice(
WEB.indexOf('web.post("/new"'),
WEB.indexOf("// Daily brief")
);
expect(handler.length).toBeGreaterThan(200);
expect(handler).toContain("bootstrapRepository");
expect(handler).toContain("scaffoldFirstRepo");
expect(handler.indexOf("bootstrapRepository")).toBeLessThan(
handler.indexOf("scaffoldFirstRepo")
);
});
it("a scaffold failure cannot break repo creation", () => {
const handler = WEB.slice(
WEB.indexOf('web.post("/new"'),
WEB.indexOf("// Daily brief")
);
const block = handler.slice(handler.indexOf("scaffoldFirstRepo") - 400);
expect(block).toContain("catch");
});
it("uses the same sync seam as the post-receive hook", () => {
expect(SRC).toContain("syncAndEnqueuePushWorkflows");
const hook = readFileSync("src/hooks/post-receive.ts", "utf8");
expect(hook).toContain("syncAndEnqueuePushWorkflows");
});
});
describe("what gets seeded", () => {
it("writes a README and a CI workflow at the discovered path", () => {
expect(SRC).toContain('"README.md"');
expect(SRC).toContain('".gluecron/workflows/ci.yml"');
});
it("the workflow triggers on push", () => {
const wf = SRC.slice(SRC.indexOf("function ciWorkflow"), SRC.indexOf("function readme"));
expect(wf).toMatch(/on:\s*\n\s*- push/);
});
it("the workflow has no external dependencies", () => {
const wf = SRC.slice(SRC.indexOf("function ciWorkflow"), SRC.indexOf("function readme"));
expect(wf).not.toMatch(/npm |yarn |pnpm |bun install|pip |cargo /);
});
});
describe("fault isolation", () => {
const ok = async () => ({ commitSha: "abc", blobSha: "b", parentSha: null });
const base = {
owner: "alice",
repoName: "demo",
repositoryId: "r1",
defaultBranch: "main",
authorName: "alice",
authorEmail: "a@b.c",
userId: "u1",
};
it("reports a write failure instead of throwing", async () => {
const { scaffoldFirstRepo } = await import("../lib/first-repo-scaffold");
const r = await scaffoldFirstRepo(base, {
createOrUpdateFileOnBranch: async () => ({ error: "write-failed" }),
syncAndEnqueuePushWorkflows: async () => ({ synced: 0, enqueued: 0, errors: [] }),
});
expect(r.readmeCommitted).toBe(false);
expect(r.workflowCommitted).toBe(false);
expect(r.errors.join(" ")).toContain("write-failed");
});
it("does not attempt workflow sync when the workflow never committed", async () => {
let syncCalled = false;
const { scaffoldFirstRepo } = await import("../lib/first-repo-scaffold");
const r = await scaffoldFirstRepo(base, {
createOrUpdateFileOnBranch: async (i) =>
i.filePath === "README.md" ? await ok() : { error: "write-failed" },
syncAndEnqueuePushWorkflows: async () => {
syncCalled = true;
return { synced: 1, enqueued: 1, errors: [] };
},
});
expect(r.readmeCommitted).toBe(true);
expect(r.workflowCommitted).toBe(false);
expect(syncCalled).toBe(false);
expect(r.runsEnqueued).toBe(0);
});
it("surfaces a sync failure without losing the commits", async () => {
const { scaffoldFirstRepo } = await import("../lib/first-repo-scaffold");
const r = await scaffoldFirstRepo(base, {
createOrUpdateFileOnBranch: ok,
syncAndEnqueuePushWorkflows: async () => {
throw new Error("sync exploded");
},
});
expect(r.readmeCommitted).toBe(true);
expect(r.workflowCommitted).toBe(true);
expect(r.errors.join(" ")).toContain("sync exploded");
});
it("reports the enqueued run on the happy path", async () => {
const { scaffoldFirstRepo } = await import("../lib/first-repo-scaffold");
const r = await scaffoldFirstRepo(base, {
createOrUpdateFileOnBranch: ok,
syncAndEnqueuePushWorkflows: async () => ({ synced: 1, enqueued: 1, errors: [] }),
});
expect(r.workflowsSynced).toBe(1);
expect(r.runsEnqueued).toBe(1);
expect(r.errors).toEqual([]);
});
});
|