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.

102 lines · 3.4 KBRaw History
1/**
2 * Contract between the Diffinery control plane (Worker) and the runner agent
3 * that executes a single job inside a Cloudflare Container.
4 *
5 * All runner endpoints live under `${apiUrl}/runner/jobs/:jobId/...` and are
6 * authenticated with `Authorization: Bearer <job token>`. The job token is
7 * scoped to one job, one repository (read access for clone) and expires when
8 * the job's timeout elapses.
9 */
10
11export type Conclusion = "success" | "failure" | "cancelled" | "skipped";
12
13export interface StepSpec {
14 id?: string;
15 name?: string;
16 if?: string;
17 run?: string;
18 uses?: string;
19 with?: Record<string, string>;
20 env?: Record<string, string>;
21 shell?: string;
22 "working-directory"?: string;
23 "continue-on-error"?: boolean | string;
24 "timeout-minutes"?: number;
25}
26
27export interface NeedsResult {
28 result: Conclusion;
29 outputs: Record<string, string>;
30}
31
32export interface JobSpec {
33 runId: string;
34 jobId: string;
35 /** Key of the job in the workflow file, e.g. `build`. */
36 jobKey: string;
37 /** Display name, already evaluated (matrix values substituted). */
38 name: string;
39 repo: { owner: string; name: string; cloneUrl: string; defaultBranch: string };
40 sha: string;
41 ref: string;
42 workflowPath: string;
43 /** The full `github` context (event name, payload, actor, sha, ref, ...). */
44 github: Record<string, unknown>;
45 /** Workflow-level env merged with job-level env; values may contain `${{ }}`. */
46 env: Record<string, string>;
47 defaults?: { run?: { shell?: string; "working-directory"?: string } };
48 matrix: Record<string, unknown>;
49 strategy: { "fail-fast": boolean; "job-index": number; "job-total": number; "max-parallel"?: number };
50 needs: Record<string, NeedsResult>;
51 inputs: Record<string, unknown>;
52 vars: Record<string, string>;
53 /** Only the secrets this job may see. Values must be masked in logs. */
54 secrets: Record<string, string>;
55 /** Job `outputs:` map; values are expressions evaluated after the steps. */
56 outputs: Record<string, string>;
57 steps: StepSpec[];
58 timeoutMinutes: number;
59 continueOnError: boolean;
60 /** Whether `permissions: id-token: write` was granted. */
61 idToken: boolean;
62 /** Base URL of the Diffinery API, e.g. `https://diffinery.com`. */
63 apiUrl: string;
64 /** Bearer token for runner endpoints and for `git clone` (as password). */
65 token: string;
66}
67
68export interface LogLine {
69 /** ISO timestamp. */
70 t: string;
71 /** Index of the step this line belongs to; -1 for job setup/teardown. */
72 step: number;
73 text: string;
74}
75
76export interface StepReport {
77 status: "in_progress" | "completed";
78 conclusion?: Conclusion;
79 name: string;
80 startedAt?: string;
81 completedAt?: string;
82}
83
84export interface JobCompletion {
85 conclusion: Conclusion;
86 outputs: Record<string, string>;
87 /** Markdown written to $GITHUB_STEP_SUMMARY, if any. */
88 summary?: string;
89 /** Short machine-readable reason when the job failed (for agents). */
90 failure?: { step?: number; message: string };
91}
92
93/** Runner API paths, relative to `${apiUrl}/runner/jobs/${jobId}`. */
94export const RunnerPaths = {
95 spec: "",
96 logs: "/logs", // POST { lines: LogLine[] }
97 step: (index: number) => `/steps/${index}`, // POST StepReport
98 complete: "/complete", // POST JobCompletion
99 cache: "/cache", // GET ?key=&restore=a,b -> { key, url } | 404 ; PUT /cache/:key body=tar.gz
100 artifacts: "/artifacts", // PUT /artifacts/:name body=zip|tar ; GET /artifacts/:name
101 oidc: "/oidc", // POST { audience } -> { value }
102} as const;