Diffinery

codician/diffinerypublic

Open-source, agent-first GitHub and GitHub Actions alternative that runs on your own Cloudflare account: git hosting, pull requests, code review and drop-in GitHub Actions YAML on Workers, Durable Objects, R2 and Containers.

48 lines · 2.1 KBRaw History
1import { Container } from "@cloudflare/containers";
2import type { StopParams } from "@cloudflare/containers";
3import type { Env } from "../env.js";
4import { ImportService } from "./service.js";
5
6/**
7 * One container per GitHub import's Git transfer: the runner image in import
8 * mode (`DIFFINERY_IMPORT_ID`), which clones from GitHub, pushes to Diffinery in
9 * size-bounded chunks and reports back through the import's agent endpoints.
10 */
11export class ImportContainer extends Container<Env> {
12 // The agent makes no inbound requests, so activity-based sleep is the only timer; a little over the 6h transfer cap.
13 override sleepAfter = "7h";
14 override enableInternet = true;
15
16 async startImport(input: { importId: string; token: string; apiUrl: string; chunkBytes?: number; stamp?: string }): Promise<void> {
17 await this.ctx.storage.put("import", input.importId);
18 // The attempt-try this container serves, so a late stop of an old try is ignored (M4 / Correctness 7).
19 if (input.stamp) await this.ctx.storage.put("stamp", input.stamp);
20 await this.start({
21 envVars: {
22 DIFFINERY_API_URL: input.apiUrl,
23 DIFFINERY_IMPORT_ID: input.importId,
24 DIFFINERY_IMPORT_TOKEN: input.token,
25 ...(input.chunkBytes ? { DIFFINERY_IMPORT_CHUNK_BYTES: String(input.chunkBytes) } : {}),
26 },
27 });
28 }
29
30 async stopImport(): Promise<void> {
31 if (this.ctx.container?.running) await this.stop("SIGTERM");
32 }
33
34 override async onStop(params: StopParams): Promise<void> {
35 const importId = await this.ctx.storage.get<string>("import");
36 if (!importId) return;
37 const stamp = await this.ctx.storage.get<string>("stamp");
38 // A transfer that stopped without reporting (crash, out of memory, platform restart) fails so the workflow can retry it;
39 // a stale stamp (an old try stopping late) is ignored by the service.
40 await new ImportService(this.env).gitStopped(importId, params.exitCode ?? null, stamp);
41 await this.ctx.storage.delete("import");
42 await this.ctx.storage.delete("stamp");
43 }
44
45 override onError(error: unknown): void {
46 console.error("import container error", error);
47 }
48}