Skip to content
441 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

The balance shows what was spent this month and in total1import type { User, Viewer } from "./identity";
2import type { RepoPath } from "./repos";
3import type { Result } from "./result";
4
5/**
6 * GitHub Actions workflows, run on g1t as they are. Mirrors
7 * `crates/contracts/src/actions.rs`.
8 */
9
10export type WorkflowNote = {
11 severity: "info" | "warning" | "unsupported";
12 job: string | null;
13 message: string;
14};
15
16/** One `workflow_dispatch` input, as written in the workflow. */
17export type DispatchInput = {
18 description?: string;
19 required?: boolean;
20 default?: string | number | boolean;
21 type?: "string" | "boolean" | "number" | "choice" | "environment";
22 options?: string[];
23};
24
Merge branch 'worktree-agent-a3abfcce648e87dca'25/**
26 * `action_required`: a pull request's run from outside, waiting for someone
27 * with the Write role to approve it. `waiting`: its jobs are held by an
28 * environment's protection rules (a run's detail says so; lists do not).
29 */
30export type RunStatus = "pending" | "action_required" | "queued" | "in_progress" | "waiting" | "completed";
The balance shows what was spent this month and in total31export type Conclusion = "success" | "failure" | "cancelled" | "skipped";
32
33export type WorkflowRun = {
34 id: string;
35 workflowId: string;
36 path: string;
37 name: string;
38 title: string;
39 number: number;
40 attempt: number;
41 event: string;
42 ref: string;
43 sha: string;
44 pull: number | null;
45 status: RunStatus;
46 conclusion: Conclusion | null;
47 error: string | null;
48 actor: string | null;
49 createdAt: string;
50 startedAt: string | null;
51 finishedAt: string | null;
52};
53
54export type Workflow = {
55 id: string;
56 path: string;
57 name: string;
58 events: string[];
59 state: "active" | "disabled";
60 error: string | null;
61 notes: WorkflowNote[];
62 dispatch: Record<string, DispatchInput> | null;
63 lastRun: WorkflowRun | null;
64};
65
66export type StepState = {
67 number: number;
68 name: string;
69 status: "queued" | "in_progress" | "completed";
70 conclusion: Conclusion | null;
71 startedAt: string | null;
72 finishedAt: string | null;
73};
74
75export type Annotation = {
76 level: "error" | "warning" | "notice";
77 message: string;
78 title: string | null;
79 file: string | null;
80 line: number | null;
81};
82
83export type Job = {
84 id: string;
85 runId: string;
86 key: string;
87 name: string;
88 needs: string[];
Merge branch 'worktree-agent-a3abfcce648e87dca'89 /**
90 * `calling`: running the reusable workflow it calls, whose jobs follow it.
91 * `pending`: held by its environment's protection rules; `reason` says for what.
92 */
93 status: "waiting" | "pending" | "queued" | "in_progress" | "calling" | "completed";
The balance shows what was spent this month and in total94 conclusion: Conclusion | null;
95 steps: StepState[];
96 annotations: Annotation[];
97 reason: string | null;
98 startedAt: string | null;
99 finishedAt: string | null;
Merge branch 'worktree-agent-a3abfcce648e87dca'100 /** The environment it names, once its needs are done. */
101 environment?: string | null;
Fast pages, required checks on the branch, self-hosted runners, honest incidents102 /** Its `runs-on` names self-hosted runners. */
103 selfHosted?: boolean;
104 /** The self-hosted runner that took it, by name. */
105 runner?: string | null;
Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)106 /** Cancelled, and running its `if: always()` and `cancelled()` steps and post steps before it ends. */
107 cancelling?: boolean;
A run opens on its summary: what triggered it, its status, duration and artifacts, a graph of its jobs (what needs what, matrices folded, called workflows boxed, deploys with their address), annotations, and each job's summary; the job list groups the same way108 /** Where its deployment is (`environment.url`), for a job that deploys and says; the current attempt's only. */
109 environmentUrl?: string | null;
110 /** For a job that calls a reusable workflow: that workflow's file. Its jobs' keys are this job's key, `/`, their own. */
111 uses?: string | null;
Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)112};
113
114/** One attempt of a run: the first, or a re-run. */
115export type RunAttempt = {
116 attempt: number;
117 status: RunStatus;
118 conclusion: Conclusion | null;
119 /** Who started it: whoever caused the run, then whoever re-ran it. */
120 actor: string | null;
121 /** It ran with debug logging. */
122 debug: boolean;
123 startedAt: string | null;
124 finishedAt: string | null;
The balance shows what was spent this month and in total125};
126
Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)127/** What a job's steps wrote to `$GITHUB_STEP_SUMMARY`, in Markdown, masked. */
128export type JobSummary = { jobId: string; name: string; steps: { step: number; markdown: string }[] };
129
130/** A job's whole log, to download. `omitted`: left out of a run's logs that grew too large. */
131export type JobLogText = {
132 jobId: string;
133 name: string;
134 steps: StepState[];
135 chunks: LogChunk[];
136 done: boolean;
137 omitted?: boolean;
138};
139
Merge branch 'worktree-agent-a3abfcce648e87dca'140export type RunDetail = {
141 run: WorkflowRun;
142 jobs: Job[];
143 notes: WorkflowNote[];
144 /** For a pull request's run from outside: whether it waits for, or had, approval. */
145 approval?: RunApproval | null;
146 /** The environments whose protection rules hold its jobs, this attempt. */
147 pendingDeployments?: PendingDeployment[];
Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)148 /** Every attempt, oldest first, the one shown (`run.attempt`) included. */
149 attempts?: RunAttempt[];
Merge branch 'worktree-agent-a3abfcce648e87dca'150};
151
152export type RunApproval = {
153 state: "required" | "approved";
154 /** Why it waits, in words. */
155 reason: string;
156 approvedBy: string | null;
157};
158
159/** One person or team who may approve an environment's jobs. */
160export type EnvironmentReviewer = { type: "user" | "team"; name: string };
161
162/** A branch or tag pattern an environment takes deployments from. */
163export type BranchPattern = { name: string; type: "branch" | "tag" };
164
165/** The most reviewers an environment may have. */
166export const MAX_ENVIRONMENT_REVIEWERS = 6;
167/** The longest wait timer, in minutes (30 days). */
168export const MAX_WAIT_MINUTES = 43_200;
169
170/**
171 * An environment and its protection rules. Jobs naming it with
172 * `environment:` wait until the rules let them through, and only then get
173 * its secrets.
174 */
175export type Environment = {
176 /** Lowercase. */
177 name: string;
178 reviewers: EnvironmentReviewer[];
179 preventSelfReview: boolean;
180 waitMinutes: number;
181 /** `protected`: branches the rules protect; `selected`: `branchPatterns`. */
182 branchPolicy: "all" | "protected" | "selected";
183 branchPatterns: BranchPattern[];
184 adminsBypass: boolean;
185 /** Whether it has rules saved; false for one only named by a workflow or a secret. */
186 protected: boolean;
187 updatedAt: string | null;
188 updatedBy: string | null;
189};
190
191/** What changes an environment's rules; left out is unchanged. */
192export type EnvironmentChange = Partial<
193 Pick<Environment, "reviewers" | "preventSelfReview" | "waitMinutes" | "branchPolicy" | "branchPatterns" | "adminsBypass">
194>;
195
196/** An environment holding a run's jobs, and where its rules stand. */
197export type PendingDeployment = {
198 environment: string;
199 state: "waiting" | "approved" | "rejected";
200 needsReview: boolean;
201 /** When its wait timer lets its jobs start. */
202 waitUntil: string | null;
203 reviewers: EnvironmentReviewer[];
204 /** The jobs it holds, by name. */
205 jobs: string[];
206 /** Whether the viewer may approve or reject it now. */
207 canReview: boolean;
208 reviewedBy: string | null;
209 comment: string | null;
210 reviewedAt: string | null;
211};
212
213/** Which pull requests' runs wait for approval, least strict first. */
214export const APPROVAL_POLICIES = ["first_time_contributors", "outside_contributors", "all_external_contributors"] as const;
215export type ApprovalPolicy = (typeof APPROVAL_POLICIES)[number];
The balance shows what was spent this month and in total216
Merge branch 'worktree-agent-a3abfcce648e87dca'217/** A repository's choices for its workflows. */
218export type ActionsSettings = {
219 /**
220 * What a workflow without `permissions:` gets. Unchosen, a repository made
221 * before restricted tokens keeps `write`; a newer one takes its
222 * workspace's default. Never more than `maxPermissions`.
223 */
224 defaultPermissions: "read" | "write";
225 /** Whether the repository chose it. */
226 defaultChosen: boolean;
227 /** The most the workspace lets a repository's default be. */
228 maxPermissions: "read" | "write";
229 approvalPolicy: ApprovalPolicy;
230 /** "Allow g1t Actions to create and approve pull requests". */
231 canApprovePullRequests: boolean;
232 /** Whether the workspace lets its repositories turn that on. */
233 workspaceAllowsPullRequests: boolean;
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts234 /**
235 * Who may use the repository's actions and reusable workflows while it is
236 * private: only itself (`none`), or private repositories of its workspace
237 * (`organization`). A public repository's are anyone's.
238 */
239 accessLevel: ActionsAccessLevel;
Merge branch 'worktree-agent-a3abfcce648e87dca'240};
241
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts242/** Settings, Actions, Access. */
243export const ACTIONS_ACCESS_LEVELS = ["none", "organization"] as const;
244export type ActionsAccessLevel = (typeof ACTIONS_ACCESS_LEVELS)[number];
245
Merge branch 'worktree-agent-a3abfcce648e87dca'246/** What changes a repository's choices; `inherit` unchooses its default. */
247export type ActionsSettingsChange = {
248 defaultPermissions?: "read" | "write" | "inherit";
249 approvalPolicy?: ApprovalPolicy;
250 canApprovePullRequests?: boolean;
Merge Actions: cross-repo workflows and actions, release and deployment triggers, step timeouts251 accessLevel?: ActionsAccessLevel;
Merge branch 'worktree-agent-a3abfcce648e87dca'252};
253
254/** A workspace's policy for its repositories' job tokens. */
255export type WorkspaceActionsSettings = {
256 /** What a repository made from now on gets by default. */
257 defaultPermissions: "read" | "write";
258 /** The most any repository's default may be. */
259 maxPermissions: "read" | "write";
260 canApprovePullRequests: boolean;
261};
262
The balance shows what was spent this month and in total263export type LogChunk = { seq: number; step: number; text: string };
264export type JobLog = { chunks: LogChunk[]; done: boolean };
265
266/**
267 * Who may read a secret or variable: `workflows` (`secrets.*`, `vars.*` in
268 * GitHub Actions) and `deployments` (a deploy build's environment and the
269 * running app's bindings). Agents, checks and the merge queue never read
270 * any.
271 */
272export type SettingReader = "workflows" | "deployments";
273
274/**
275 * One row of secrets and variables, as Vercel lists environment variables:
276 * a key, its type, the environments it applies to and who reads it. A key
277 * may have one row per environment. Secrets' values are never returned.
278 */
279export type Setting = {
280 id: string;
281 name: string;
282 /** `variable` is shown as Config. Config may become a secret, never back. */
283 kind: SettingKind;
284 /** A variable's value. */
285 value: string | null;
286 /** A project's (a repository's belong to its project) or the workspace's. */
287 scope: "project" | "workspace";
288 updatedAt: string;
289 availableTo: SettingReader[];
290 /** The environments it applies to; empty is every environment. */
291 environments: string[];
292 /** A workspace's row: the projects it reaches, by slug; empty is every one. */
293 projects: string[];
294 /** Where to rotate it, or who to ask. */
295 note: string | null;
296 updatedBy: string | null;
297};
298
299/** What saving a row sets beyond its value; left out is unchanged. */
300export type SettingOptions = {
301 /** The row to change; left out, the key's row for every environment. */
302 id?: string;
303 availableTo?: SettingReader[];
304 environments?: string[];
305 /** A workspace's row: project slugs; empty for every one. */
306 projects?: string[];
307 note?: string;
308};
309
310export type SettingsOwner = { repo: RepoPath } | { workspace: string };
311export type SettingKind = "secret" | "variable";
312/** `all` lists both. */
313export type SettingKindFilter = SettingKind | "all";
314
315export type RunsFilter = {
316 workflow?: string;
317 branch?: string;
318 event?: string;
319 pull?: number;
320 sha?: string;
321 limit?: number;
322};
323
324export interface ActionsApi {
325 workflows(repo: RepoPath, viewer: Viewer): Promise<Result<Workflow[]>>;
326 runs(repo: RepoPath, viewer: Viewer, filter?: RunsFilter): Promise<Result<WorkflowRun[]>>;
Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)327 /** The latest attempt, or an earlier one. */
328 run(repo: RepoPath, viewer: Viewer, id: string, attempt?: number): Promise<Result<RunDetail>>;
The balance shows what was spent this month and in total329 logs(repo: RepoPath, viewer: Viewer, job: string, after?: number): Promise<Result<JobLog>>;
Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)330 /** The job summaries of an attempt (the latest by default), jobs without one left out. */
331 summaries(repo: RepoPath, viewer: Viewer, id: string, attempt?: number): Promise<Result<JobSummary[]>>;
332 /** A job's whole log, any attempt's, by the id the run gave the job. */
333 jobLogText(repo: RepoPath, viewer: Viewer, job: string): Promise<Result<JobLogText>>;
334 /** Every job's whole log for an attempt, to download as one archive. */
335 runLogs(repo: RepoPath, viewer: Viewer, id: string, attempt?: number): Promise<Result<JobLogText[]>>;
The balance shows what was spent this month and in total336 dispatch(
337 actor: User,
338 repo: RepoPath,
339 workflow: string,
340 ref: string | undefined,
341 inputs: Record<string, unknown>,
342 ): Promise<Result<WorkflowRun>>;
Merge Actions runs: summaries, attempts and re-runs, graceful cancel, log downloads, badges (actions 0009)343 /** Running jobs clean up first; `force` (or cancelling a run that is cancelling) stops them outright. */
344 cancel(actor: User, repo: RepoPath, id: string, force?: boolean): Promise<Result<WorkflowRun>>;
345 /** A new attempt: every job, the failed ones, or `job` and what needs it; `debug` for debug logging. */
346 rerun(
347 actor: User,
348 repo: RepoPath,
349 id: string,
350 failedOnly?: boolean,
351 options?: { job?: string; debug?: boolean },
352 ): Promise<Result<WorkflowRun>>;
The balance shows what was spent this month and in total353 setWorkflowEnabled(actor: User, repo: RepoPath, workflow: string, enabled: boolean): Promise<Result<Workflow>>;
354 settings(actor: User, owner: SettingsOwner, kind: SettingKindFilter): Promise<Result<Setting[]>>;
355 /** `value` null keeps an existing entry's default value. */
356 setSetting(
357 actor: User,
358 owner: SettingsOwner,
359 kind: SettingKind,
360 name: string,
361 value: string | null,
362 options?: SettingOptions,
363 ): Promise<Result<Setting>>;
364 /** One row by `id`, or every row of the key. */
365 deleteSetting(actor: User, owner: SettingsOwner, kind: SettingKindFilter, name: string, id?: string): Promise<Result<boolean>>;
Merge branch 'worktree-agent-a3abfcce648e87dca'366 /** Lets a pull request's run from outside start. Write role. */
367 approveRun(actor: User, repo: RepoPath, id: string): Promise<Result<WorkflowRun>>;
368 pendingDeployments(repo: RepoPath, viewer: Viewer, id: string): Promise<Result<PendingDeployment[]>>;
369 /** Approves or rejects the jobs `environments` hold (every waiting one when empty). */
370 reviewDeployments(
371 actor: User,
372 repo: RepoPath,
373 id: string,
374 state: "approved" | "rejected",
375 environments?: string[],
376 comment?: string,
377 ): Promise<Result<PendingDeployment[]>>;
378 actionsSettings(repo: RepoPath, viewer: Viewer): Promise<Result<ActionsSettings>>;
379 /** Admin role. Left out is unchanged. */
380 setActionsSettings(actor: User, repo: RepoPath, change: ActionsSettingsChange): Promise<Result<ActionsSettings>>;
381 /** Members. */
382 workspaceActionsSettings(workspace: string, viewer: Viewer): Promise<Result<WorkspaceActionsSettings>>;
383 /** Owners. Left out is unchanged. */
384 setWorkspaceActionsSettings(
385 actor: User,
386 workspace: string,
387 change: Partial<WorkspaceActionsSettings>,
388 ): Promise<Result<WorkspaceActionsSettings>>;
389 /** Every environment the repository's rules, secrets, workflows or jobs name. */
390 environments(repo: RepoPath, viewer: Viewer): Promise<Result<Environment[]>>;
391 /** Admin role. */
392 setEnvironment(actor: User, repo: RepoPath, name: string, change: EnvironmentChange): Promise<Result<Environment>>;
393 deleteEnvironment(actor: User, repo: RepoPath, name: string): Promise<Result<boolean>>;
Actions: OIDC tokens, the toolkit's cache and artifact services, and artifacts in R2394 /** A repository's artifacts, newest first, or one run's. */
395 artifacts(repo: RepoPath, viewer: Viewer, filter?: { run?: string; name?: string; page?: number; per_page?: number }): Promise<Result<ArtifactList>>;
396 /** One artifact by id, or by run and name, with a token to download it for a few minutes. */
397 artifactDownload(repo: RepoPath, viewer: Viewer, by: { id?: number; run?: string; name?: string }): Promise<Result<ArtifactBlob>>;
398 /** Needs the Write role. */
399 deleteArtifact(actor: User, repo: RepoPath, id: number): Promise<Result<Artifact>>;
400 /** How long the repository keeps artifacts; with `days`, sets it (Maintain). */
401 artifactRetention(repo: RepoPath, viewer: Viewer, days?: number): Promise<Result<ArtifactRetention>>;
The balance shows what was spent this month and in total402}
Actions: OIDC tokens, the toolkit's cache and artifact services, and artifacts in R2403
404/**
405 * A workflow run's artifact, kept in R2 for its retention days. Mirrors
406 * `g1t_contracts::actions::Artifact` (which travels in `snake_case`).
407 */
408export type Artifact = {
409 id: number;
410 name: string;
411 size: number;
412 /** `sha256:<hex>`, when the uploader said. */
413 digest: string | null;
414 /** `zip`, or `tgz` for one an older runner sent. */
415 format: string;
416 run_id: string;
417 job_id: string;
418 repo_id: string;
419 expired: boolean;
420 created_at: string;
421 updated_at: string;
422 expires_at: string;
423 head_branch?: string | null;
424 head_sha?: string | null;
425};
426
427export type ArtifactList = { total_count: number; artifacts: Artifact[] };
428
429/** An artifact, where it is, and a signed token for the API's `/actions/toolkit/blobs/{blob}`. */
430export type ArtifactBlob = { artifact: Artifact; object: string; blob: string };
431
432export type ArtifactRetention = { days: number; maximum_allowed_days: number };
Merge branch 'claude/cool-newton-7nm8r9' (#36): real GitHub Actions on g1t, managed deploy workflows, g1t/deploy and the Sysbox runner 0.2.0. The merge keeps both sides' webhook events and API operations, says agent images need tar, guards the job engine's stop to Unix so the runner builds on Windows again, and keeps the moves tests' previews from going idle as the calendar passes their fixture's date.433
434/**
435 * Whether a workflow's path is a managed workflow's: one g1t installed in
436 * the repository without committing it (crates/actions/src/managed.rs), so
437 * no file in the repository holds it.
438 */
439export function isManagedWorkflow(path: string): boolean {
440 return path.startsWith("managed/");
441}

This file's history is long; its oldest lines are credited to the oldest commit read.