Skip to content
298 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.

GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs1import 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
Actions: keep workflow runs safe25/**
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";
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs31export 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[];
Actions: keep workflow runs safe89 /**
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";
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs94 conclusion: Conclusion | null;
95 steps: StepState[];
96 annotations: Annotation[];
97 reason: string | null;
98 startedAt: string | null;
99 finishedAt: string | null;
Actions: keep workflow runs safe100 /** 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;
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs106};
107
Actions: keep workflow runs safe108export type RunDetail = {
109 run: WorkflowRun;
110 jobs: Job[];
111 notes: WorkflowNote[];
112 /** For a pull request's run from outside: whether it waits for, or had, approval. */
113 approval?: RunApproval | null;
114 /** The environments whose protection rules hold its jobs, this attempt. */
115 pendingDeployments?: PendingDeployment[];
116};
117
118export type RunApproval = {
119 state: "required" | "approved";
120 /** Why it waits, in words. */
121 reason: string;
122 approvedBy: string | null;
123};
124
125/** One person or team who may approve an environment's jobs. */
126export type EnvironmentReviewer = { type: "user" | "team"; name: string };
127
128/** A branch or tag pattern an environment takes deployments from. */
129export type BranchPattern = { name: string; type: "branch" | "tag" };
130
131/** The most reviewers an environment may have. */
132export const MAX_ENVIRONMENT_REVIEWERS = 6;
133/** The longest wait timer, in minutes (30 days). */
134export const MAX_WAIT_MINUTES = 43_200;
135
136/**
137 * An environment and its protection rules. Jobs naming it with
138 * `environment:` wait until the rules let them through, and only then get
139 * its secrets.
140 */
141export type Environment = {
142 /** Lowercase. */
143 name: string;
144 reviewers: EnvironmentReviewer[];
145 preventSelfReview: boolean;
146 waitMinutes: number;
147 /** `protected`: branches the rules protect; `selected`: `branchPatterns`. */
148 branchPolicy: "all" | "protected" | "selected";
149 branchPatterns: BranchPattern[];
150 adminsBypass: boolean;
151 /** Whether it has rules saved; false for one only named by a workflow or a secret. */
152 protected: boolean;
153 updatedAt: string | null;
154 updatedBy: string | null;
155};
156
157/** What changes an environment's rules; left out is unchanged. */
158export type EnvironmentChange = Partial<
159 Pick<Environment, "reviewers" | "preventSelfReview" | "waitMinutes" | "branchPolicy" | "branchPatterns" | "adminsBypass">
160>;
161
162/** An environment holding a run's jobs, and where its rules stand. */
163export type PendingDeployment = {
164 environment: string;
165 state: "waiting" | "approved" | "rejected";
166 needsReview: boolean;
167 /** When its wait timer lets its jobs start. */
168 waitUntil: string | null;
169 reviewers: EnvironmentReviewer[];
170 /** The jobs it holds, by name. */
171 jobs: string[];
172 /** Whether the viewer may approve or reject it now. */
173 canReview: boolean;
174 reviewedBy: string | null;
175 comment: string | null;
176 reviewedAt: string | null;
177};
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs178
Actions: keep workflow runs safe179/** Which pull requests' runs wait for approval, least strict first. */
180export const APPROVAL_POLICIES = ["first_time_contributors", "outside_contributors", "all_external_contributors"] as const;
181export type ApprovalPolicy = (typeof APPROVAL_POLICIES)[number];
182
183/** A repository's choices for its workflows. */
184export type ActionsSettings = {
185 /** What a workflow without `permissions:` gets: `read` (the default) or `write`. */
186 defaultPermissions: "read" | "write";
187 approvalPolicy: ApprovalPolicy;
188};
189
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs190export type LogChunk = { seq: number; step: number; text: string };
191export type JobLog = { chunks: LogChunk[]; done: boolean };
192
Secrets and variables: one list, rows per environment, for workflows and deployments193/**
194 * Who may read a secret or variable: `workflows` (`secrets.*`, `vars.*` in
195 * GitHub Actions) and `deployments` (a deploy build's environment and the
196 * running app's bindings). Agents, checks and the merge queue never read
197 * any.
198 */
199export type SettingReader = "workflows" | "deployments";
200
201/**
202 * One row of secrets and variables, as Vercel lists environment variables:
203 * a key, its type, the environments it applies to and who reads it. A key
204 * may have one row per environment. Secrets' values are never returned.
205 */
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs206export type Setting = {
Secrets and variables: one list, rows per environment, for workflows and deployments207 id: string;
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs208 name: string;
Secrets and variables: one list, rows per environment, for workflows and deployments209 /** `variable` is shown as Config. Config may become a secret, never back. */
210 kind: SettingKind;
211 /** A variable's value. */
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs212 value: string | null;
Projects: what a workspace builds and runs, first on every page213 /** A project's (a repository's belong to its project) or the workspace's. */
214 scope: "project" | "workspace";
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs215 updatedAt: string;
Secrets and variables: one list, rows per environment, for workflows and deployments216 availableTo: SettingReader[];
217 /** The environments it applies to; empty is every environment. */
218 environments: string[];
Projects: what a workspace builds and runs, first on every page219 /** A workspace's row: the projects it reaches, by slug; empty is every one. */
220 projects: string[];
Secrets and variables: one list, rows per environment, for workflows and deployments221 /** Where to rotate it, or who to ask. */
222 note: string | null;
223 updatedBy: string | null;
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs224};
225
Secrets and variables: one list, rows per environment, for workflows and deployments226/** What saving a row sets beyond its value; left out is unchanged. */
227export type SettingOptions = {
228 /** The row to change; left out, the key's row for every environment. */
229 id?: string;
230 availableTo?: SettingReader[];
231 environments?: string[];
Projects: what a workspace builds and runs, first on every page232 /** A workspace's row: project slugs; empty for every one. */
233 projects?: string[];
Secrets and variables: one list, rows per environment, for workflows and deployments234 note?: string;
235};
236
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs237export type SettingsOwner = { repo: RepoPath } | { workspace: string };
238export type SettingKind = "secret" | "variable";
Secrets and variables: one list, rows per environment, for workflows and deployments239/** `all` lists both. */
240export type SettingKindFilter = SettingKind | "all";
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs241
242export type RunsFilter = {
243 workflow?: string;
244 branch?: string;
245 event?: string;
246 pull?: number;
247 sha?: string;
248 limit?: number;
249};
250
251export interface ActionsApi {
252 workflows(repo: RepoPath, viewer: Viewer): Promise<Result<Workflow[]>>;
253 runs(repo: RepoPath, viewer: Viewer, filter?: RunsFilter): Promise<Result<WorkflowRun[]>>;
254 run(repo: RepoPath, viewer: Viewer, id: string): Promise<Result<RunDetail>>;
255 logs(repo: RepoPath, viewer: Viewer, job: string, after?: number): Promise<Result<JobLog>>;
256 dispatch(
257 actor: User,
258 repo: RepoPath,
259 workflow: string,
260 ref: string | undefined,
261 inputs: Record<string, unknown>,
262 ): Promise<Result<WorkflowRun>>;
263 cancel(actor: User, repo: RepoPath, id: string): Promise<Result<WorkflowRun>>;
264 rerun(actor: User, repo: RepoPath, id: string, failedOnly?: boolean): Promise<Result<WorkflowRun>>;
265 setWorkflowEnabled(actor: User, repo: RepoPath, workflow: string, enabled: boolean): Promise<Result<Workflow>>;
Secrets and variables: one list, rows per environment, for workflows and deployments266 settings(actor: User, owner: SettingsOwner, kind: SettingKindFilter): Promise<Result<Setting[]>>;
267 /** `value` null keeps an existing entry's default value. */
268 setSetting(
269 actor: User,
270 owner: SettingsOwner,
271 kind: SettingKind,
272 name: string,
273 value: string | null,
274 options?: SettingOptions,
275 ): Promise<Result<Setting>>;
276 /** One row by `id`, or every row of the key. */
277 deleteSetting(actor: User, owner: SettingsOwner, kind: SettingKindFilter, name: string, id?: string): Promise<Result<boolean>>;
Actions: keep workflow runs safe278 /** Lets a pull request's run from outside start. Write role. */
279 approveRun(actor: User, repo: RepoPath, id: string): Promise<Result<WorkflowRun>>;
280 pendingDeployments(repo: RepoPath, viewer: Viewer, id: string): Promise<Result<PendingDeployment[]>>;
281 /** Approves or rejects the jobs `environments` hold (every waiting one when empty). */
282 reviewDeployments(
283 actor: User,
284 repo: RepoPath,
285 id: string,
286 state: "approved" | "rejected",
287 environments?: string[],
288 comment?: string,
289 ): Promise<Result<PendingDeployment[]>>;
290 actionsSettings(repo: RepoPath, viewer: Viewer): Promise<Result<ActionsSettings>>;
291 /** Admin role. Left out is unchanged. */
292 setActionsSettings(actor: User, repo: RepoPath, change: Partial<ActionsSettings>): Promise<Result<ActionsSettings>>;
293 /** Every environment the repository's rules, secrets, workflows or jobs name. */
294 environments(repo: RepoPath, viewer: Viewer): Promise<Result<Environment[]>>;
295 /** Admin role. */
296 setEnvironment(actor: User, repo: RepoPath, name: string, change: EnvironmentChange): Promise<Result<Environment>>;
297 deleteEnvironment(actor: User, repo: RepoPath, name: string): Promise<Result<boolean>>;
GitHub Actions on g1t, part three: .g1t/workflows, the pages, the docs298}