Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

64 linesCodeBlameRaw
1/**
2 * Guardrails: how long a workspace's runs may take, kept by the work
3 * service. Mirrors `g1t_contracts::guardrails`. Sandboxes reach the
4 * internet as any CI machine does; guardrails say nothing about the
5 * network.
6 */
7import type { ServiceBinding } from "./clients";
8import type { User, Viewer } from "./identity";
9import type { RepoPath } from "./repos";
10import type { Result } from "./result";
11
12/** What one level, the workspace or a project, sets. Unset is inherited. */
13export type GuardrailSettings = {
14 /** How long each kind of run may take, in minutes. */
15 minutes?: Record<string, number>;
16 updatedBy?: string | null;
17 updatedAt?: string | null;
18};
19
20/** What a run actually gets. */
21export type Guardrails = {
22 minutes: Record<string, number>;
23};
24
25export type GuardrailsView = {
26 workspace: GuardrailSettings;
27 project: GuardrailSettings | null;
28 defaults: Guardrails;
29 /** g1t's defaults with the workspace's: what a project inherits. */
30 inherited: Guardrails;
31 effective: Guardrails;
32};
33
34export interface GuardrailsApi {
35 /** Members only. With `repo`, that project's level too. */
36 getGuardrails(viewer: Viewer, workspace: string, repo?: RepoPath | null): Promise<Result<GuardrailsView>>;
37 /** The workspace's level (owners), or with `repo`, that project's (members). */
38 updateGuardrails(actor: User, workspace: string, repo: RepoPath | null, settings: GuardrailSettings): Promise<Result<GuardrailsView>>;
39 /**
40 * For the runner: what a run in `repo` gets, which is always its
41 * project's. `repoId` names the project however it has moved since; a
42 * pull request's working copy (`pulls/<pull id>`) stands for the
43 * repository the pull request is to.
44 */
45 runGuardrails(repo: RepoPath, repoId?: string | null): Promise<Result<Guardrails>>;
46}
47
48/** The guardrails methods of the work service. */
49export function guardrailsClient(service: ServiceBinding): GuardrailsApi {
50 const call = async <T>(method: string, args: object): Promise<T> => {
51 const response = await service.fetch(`https://service/rpc/${method}`, {
52 method: "POST",
53 headers: { "content-type": "application/json" },
54 body: JSON.stringify(args),
55 });
56 if (!response.ok) throw new Error(`${method} failed with status ${response.status}`);
57 return (await response.json()) as T;
58 };
59 return {
60 getGuardrails: (viewer, workspace, repo) => call("get_guardrails", { viewer, workspace, repo: repo ?? null }),
61 updateGuardrails: (actor, workspace, repo, settings) => call("update_guardrails", { actor, workspace, repo, settings }),
62 runGuardrails: (repo, repoId) => call("run_guardrails", { repo, repo_id: repoId ?? null }),
63 };
64}