Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
claude/adoring-hopper-5x74bqclaude/affectionate-feynman-ykrf1hclaude/architecture-audit-design-wxprenclaude/build-status-update-3MXsfclaude/charming-meitner-mllb5rclaude/compare-gate-gluecron-s4mFQclaude/confident-faraday-tikcwbclaude/continue-work-XMTlIclaude/crontech-gluecron-deploy-7MIECclaude/crontech-platform-setup-SeKfwclaude/design-2026claude/ecstatic-ptolemy-jMdigclaude/enhance-github-integration-QNHdGclaude/fix-aa-loop-issue-PonMQclaude/fix-actions-and-processclaude/fix-desktop-errors-XqoW8claude/fix-red-workflowsclaude/fix-website-access-6FKJNclaude/gatetest-integration-hardeningclaude/github-audit-improvements-bDFr9claude/gluecron-launch-status-FoMRlclaude/hopeful-lamport-olfCTclaude/issue-to-pr-and-protectionsclaude/jolly-heisenberg-2sg1Qclaude/launch-preparation-QmTb6claude/new-session-xk1l7claude/plan-platform-architecture-kkN4yclaude/platform-analysis-roadmap-1nUGLclaude/platform-launch-assessment-8dWV8claude/polish-platform-release-AeDrUclaude/resume-previous-work-KzyLwclaude/review-crontech-handoff-qYEVqclaude/review-project-completeness-lHhS2claude/review-readme-docs-ulqPKclaude/serene-edison-rj87weclaude/setup-multi-repo-dev-BCwNQclaude/ship-fixes-and-tests-Jvz1cclaude/site-audit-competitive-pctlwgclaude/site-migration-vercel-XstpKclaude/standalone-product-repos-XHFTDcopilot/feat-smart-empty-states-keyboard-first-enhancementcopilot/feat-smart-morning-digest-review-context-restorecopilot/fix-and-process-workflowscopilot/update-ai-powered-code-reviewfeat/debt-mapfeat/push-policy-codeowners-hardeningfeat/smart-digest-contextfeat/stage-impactfeat/t1-secret-migrationfeat/u-polishfeat/w-self-hostfeat/w2-claude-configfix/agent-journey-orphan-sweepfix/audit-sweep-2026-07-26gatetest/auto-fix-1776586424172gatetest/auto-fix-1776586534814gatetest/auto-fix-1776590685143gatetest/auto-fix-1776590808199mainops/redeploy-retriggerstyle/dxt-cta-themeworktree-agent-a3377aad30d55da26worktree-agent-a7ef607b7ee1d6c74
first-repo-scaffold.test.ts6.0 KB · 148 lines
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
/**
 * A new repository should arrive working, not empty.
 *
 * POST /new called bootstrapRepository(), which creates the DB side only —
 * gate settings, branch protection, labels, welcome issue. It created no git
 * content, so a new user landed on an EMPTY repository: no commit, no README,
 * no workflow, and therefore no CI run to be green. Every push-triggered
 * feature the product sells had nothing to act on, and the first thing a new
 * user saw was an empty state telling them to go and configure something.
 *
 * scaffoldFirstRepo seeds a README and a CI workflow, then calls the SAME
 * syncAndEnqueuePushWorkflows() seam the git post-receive hook calls. That
 * last step is the one that is easy to miss and impossible to notice: files
 * written through the plumbing API do not fire the git hook, so without it
 * the workflow sits on disk with no `workflows` row and no run — the repo
 * looks configured and does nothing.
 */

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");
    // Bootstrap first: the scaffold's CI run is gated by settings that
    // bootstrapRepository creates.
    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", () => {
    // Writing via the plumbing API does not fire the git hook, so the
    // workflow would never be discovered without calling this directly.
    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"');
    // workflows.tsx documents .gluecron/workflows/ as the discovery dir;
    // a workflow written anywhere else is invisible.
    expect(SRC).toContain('".gluecron/workflows/ci.yml"');
  });

  it("the workflow triggers on push", () => {
    // syncAndEnqueuePushWorkflows only enqueues workflows whose `on:`
    // includes push — a workflow without it syncs but never runs.
    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", () => {
    // It runs on a bare runner. The point is proving the pipeline works end
    // to end, not guessing the user's stack — anything needing a package
    // manager would fail and hand a new user a red X as their first result.
    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);
    // Syncing a commit with no workflow in it would report a phantom run.
    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);
    // This is the whole point: a green CI run with zero configuration.
    expect(r.runsEnqueued).toBe(1);
    expect(r.errors).toEqual([]);
  });
});