Skip to content

g1t/packages/contracts/src/deployments.ts

382 lines14,948 bytesCodeBlame

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.

Deployments: a preview for every pull request, production on g1t.page1import type { User, Viewer } from "./identity";
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb972import type { RepoPath } from "./repos";
Deployments: a preview for every pull request, production on g1t.page3import type { Result } from "./result";
4
5/**
Projects: what a workspace builds and runs, first on every page6 * Deployments: a project's production, deployed from its default branch on
7 * every push, and a live preview of every branch with an open pull request.
8 * Apps run as Workers in a Workers for Platforms namespace, so an app no
9 * one visits costs nothing. A paid feature: the workspace turns it on with
10 * a monthly plan (see `Feature` in `./billing`), and each project then
11 * chooses for itself.
Deployments: a preview for every pull request, production on g1t.page12 */
13
14/** The domain apps are served on. Never g1t.sh, so they share no cookies with it. */
15export const DEPLOYMENTS_DOMAIN = "g1t.page";
16
Projects: what a workspace builds and runs, first on every page17/** A project, as deployments name it. */
18export type ProjectRef = { workspace: string; slug: string };
19
20/** A project's deployment settings. */
Deployments: a preview for every pull request, production on g1t.page21export type DeploySettings = {
Projects: what a workspace builds and runs, first on every page22 /** Whether this project deploys at all. Off until someone turns it on. */
Deployments: a preview for every pull request, production on g1t.page23 enabled: boolean;
Projects: what a workspace builds and runs, first on every page24 /** A preview for every branch with an open pull request. */
Deployments: a preview for every pull request, production on g1t.page25 previews: boolean;
26 /** The default branch deployed to production on every push. */
27 production: boolean;
28 /** Runs instead of the project's own `build` script. */
29 buildCommand: string | null;
30 /** What to serve, for a static site; found by itself when null. */
31 outputDir: string | null;
32 /** A preview no one has visited in this many days is taken down. */
33 idleDays: number;
34 /** Where production is served. */
35 productionUrl: string;
Agents and memory, checks and conflicts, profiles, slug renames, custom domains36 /**
37 * The project's own domain for production, once it is active: the first
38 * custom domain added that serves the app rather than redirecting. Null
39 * until one is.
40 */
41 primaryDomain: string | null;
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look42 /**
43 * What the last finished build found the project to be: a Workers
44 * project (it has a Workers config), a static site its build wrote, or
45 * plain HTML served as it is. Null until a build has finished. Read-only.
46 */
47 detected: DetectedKind | null;
Deployments: a preview for every pull request, production on g1t.page48};
49
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look50export type DetectedKind = "workers" | "static" | "html";
51
Deployments: a preview for every pull request, production on g1t.page52export type DeployKind = "preview" | "production";
53
54export type DeployStatus =
55 /** Waiting for a sandbox. */
56 | "queued"
57 | "building"
Builds say Replaced or Down once they are no longer live58 /** What its app serves now. */
Deployments: a preview for every pull request, production on g1t.page59 | "ready"
Builds say Replaced or Down once they are no longer live60 /** Built and served, until a newer build of the same app replaced it. */
61 | "replaced"
62 /** Built and served, until its app was taken down. */
63 | "down"
Deployments: a preview for every pull request, production on g1t.page64 | "failed"
65 /** Not built: the workspace's plan is off, or the build was replaced. */
66 | "skipped";
67
68/** One build of one commit, and where it went. */
69export type Deployment = {
70 id: string;
71 kind: DeployKind;
Projects: what a workspace builds and runs, first on every page72 /** For a preview: the branch, or `pr-<n>` for a pull request from a fork. */
73 branch: string | null;
74 /** For a preview: its pull request. */
Deployments: a preview for every pull request, production on g1t.page75 number: number | null;
76 commit: string;
77 status: DeployStatus;
78 url: string;
79 /** Why it failed or was skipped. */
80 error: string | null;
81 /** What the build could not provide, such as bindings not provisioned yet. */
82 warnings: string[];
83 /** How long the build ran, in seconds; charged at the container price. */
84 buildSeconds: number | null;
85 createdBy: string;
86 /** RFC 3339. */
87 createdAt: string;
88 finishedAt: string | null;
89};
90
Projects: what a workspace builds and runs, first on every page91/** An app that is up: production, or one branch's preview. */
Deployments: a preview for every pull request, production on g1t.page92export type LiveApp = {
93 kind: DeployKind;
Projects: what a workspace builds and runs, first on every page94 branch: string | null;
Deployments: a preview for every pull request, production on g1t.page95 number: number | null;
96 url: string;
97 commit: string;
98 /** RFC 3339: when it was last deployed. */
99 deployedAt: string;
100};
101
Projects: what a workspace builds and runs, first on every page102/** One project at a glance, for the workspace's page. */
103export type ProjectDeploys = {
104 slug: string;
105 enabled: boolean;
106 production: LiveApp | null;
107 previews: number;
108 /** The newest build, whatever its status. */
109 latest: Deployment | null;
110};
111
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas112/** What a workspace's apps used this month. Every request, CPU millisecond and build second is metered; apps are not. */
Deployments: a preview for every pull request, production on g1t.page113export type DeployUsage = {
114 /** `YYYY-MM`. */
115 month: string;
116 requests: number;
117 cpuMs: number;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas118 /** Apps up now (production and previews), and the most at once this month: for information, never charged. */
Deployments: a preview for every pull request, production on g1t.page119 apps: number;
120 peakApps: number;
121 buildSeconds: number;
122 /** Charged so far this month for builds, in millionths of a dollar. */
123 buildMicros: number;
124 /** RFC 3339: when requests and CPU time were last counted. */
125 countedAt: string | null;
126};
127
Agents and memory, checks and conflicts, profiles, slug renames, custom domains128/** Where custom domains point: a hostname on g1t.page that routes to the dispatcher. */
129export const CUSTOM_DOMAIN_TARGET = "domains.g1t.page";
130
131/**
132 * A custom domain's state: `pending` until its DNS points at g1t (or its
133 * ownership record is found), `verifying` while its certificate is
134 * issued, then `active`. `failed` says why in `error`; `removing` is on
135 * its way out.
136 */
137export type DomainStatus = "pending" | "verifying" | "active" | "failed" | "removing";
138
139/** A DNS record the domain's owner adds at their DNS provider. */
140export type DomainRecord = {
141 /** `ALIAS` stands for a flattened CNAME at the apex, whatever the provider calls it. */
142 type: "CNAME" | "TXT" | "ALIAS";
143 /** The record's full name. */
144 name: string;
145 value: string;
146 /** What it is for, in a few words. */
147 purpose: string;
148};
149
150/** A hostname of the project's own, serving its production. */
151export type Domain = {
152 id: string;
153 hostname: string;
154 /** What it serves: `production`. */
155 target: "production";
156 status: DomainStatus;
157 /** Cloudflare's state for its certificate, as given. */
158 sslStatus: string | null;
159 /** Whether it is a registrable domain itself (`example.com`), which needs a flattened CNAME. */
160 apex: boolean;
161 /** Every record to add: where traffic goes, then any Cloudflare asks for. */
162 records: DomainRecord[];
163 /** A hostname this one redirects to (308, path and query kept), for a www/apex pair. */
164 redirectTo: string | null;
165 /** Why it is not active yet, or failed. */
166 error: string | null;
167 createdBy: string;
168 createdAt: string;
169 verifiedAt: string | null;
170};
171
172export type ProjectDomains = {
173 domains: Domain[];
174 /** The hostname every domain points at. */
175 target: string;
176 /** False until custom domains are switched on for g1t.page; `notice` says so. */
177 available: boolean;
178 notice: string | null;
status.g1t.sh with incident management, invites that land you in the workspace, settings as pages, usage without quotas179 /** What one custom domain costs a month on the plan, in millionths of a dollar: g1t's cost plus 20%. */
180 monthlyMicros: number;
Agents and memory, checks and conflicts, profiles, slug renames, custom domains181 /** The workspace's custom domains now. */
182 used: number;
183};
184
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97185// ---- A repository's deployments, wherever they run ---------------------
186//
187// Every deployment of a repository, in one model: g1t.page builds (read
188// from the builds above, never copied), deployments g1t Actions makes for
189// a job with an `environment:`, and deployments any other system reports
190// through the API. These travel in `snake_case` between services too, as
191// the API shows them, so a deployment's `payload` reaches the API with its
192// keys as they were given.
193
194/** Where a deployment is, as its latest status says. */
195export type DeploymentState = "queued" | "in_progress" | "success" | "failure" | "error" | "inactive";
196
197export const DEPLOYMENT_STATES: readonly DeploymentState[] = ["queued", "in_progress", "success", "failure", "error", "inactive"];
198
199/**
200 * What made a deployment: `api` (reported with a token), `actions` (a g1t
201 * Actions job with an `environment:`) or `g1t_page` (a build on g1t.page).
202 */
203export type DeploymentSource = "api" | "actions" | "g1t_page";
204
205/** One deployment of one commit to one environment. */
206export type RepoDeployment = {
207 /** `dep_…` for a reported deployment, `dpl_…` for a g1t.page build. */
208 id: string;
209 /** Such as `production`, `staging` or `preview`. */
210 environment: string;
211 /** The branch, tag or commit asked for. */
212 ref: string;
213 sha: string;
214 /** What kind of deployment: `deploy` unless given, such as `deploy:migrations`. */
215 task: string;
216 description: string | null;
217 /** Whatever the reporter attached, as given. */
218 payload: Record<string, unknown>;
219 /** An environment that goes away, such as a pull request's preview. */
220 transient_environment: boolean;
221 /** An environment people use directly. */
222 production_environment: boolean;
223 /** Its latest status's state. */
224 state: DeploymentState;
225 /** Where it is served, from its latest status that gave one. */
226 environment_url: string | null;
227 /** Where its output can be read, from its latest status that gave one. */
228 log_url: string | null;
229 /** The username that created it, or `g1t`. */
230 creator: string;
231 source: DeploymentSource;
232 /** For `actions`: the workflow run, and its address on the site. */
233 run_id: string | null;
234 run_url: string | null;
235 /** For `g1t_page`: the project it built, and a preview's pull request. */
236 project: string | null;
237 number: number | null;
238 /** RFC 3339. */
239 created_at: string;
240 /** RFC 3339: its latest status. */
241 updated_at: string;
242};
243
244/** One status of a deployment: what it said, and when. */
245export type DeploymentStatus = {
246 id: string;
247 deployment_id: string;
248 state: DeploymentState;
249 description: string | null;
250 environment_url: string | null;
251 log_url: string | null;
252 creator: string;
253 /** RFC 3339. */
254 created_at: string;
255};
256
257/** A deployment with every status it has had, oldest first. */
258export type DeploymentDetail = RepoDeployment & { statuses: DeploymentStatus[] };
259
260/** An environment: a name deployments go to, made by the first. */
261export type DeploymentEnvironment = {
262 name: string;
263 /** Where its current deployment is served. */
264 url: string | null;
265 production_environment: boolean;
266 transient_environment: boolean;
267 /** How many deployments it has had. */
268 deployments_count: number;
269 /** Its newest deployment, whatever its state. */
270 latest: RepoDeployment | null;
271 /** The newest deployment that succeeded and is still active: what it serves. */
272 current: RepoDeployment | null;
273 /** RFC 3339: its newest deployment's latest status. */
274 updated_at: string;
275};
276
277/** A repository's environments, production first, and its count of deployments. */
278export type DeploymentEnvironments = {
279 /** Deployments across every environment. */
280 total_count: number;
281 environments: DeploymentEnvironment[];
282};
283
284/** Which deployments to list. Every field narrows the list. */
285export type DeploymentFilter = {
286 environment?: string | null;
287 ref?: string | null;
288 sha?: string | null;
289 task?: string | null;
290 state?: DeploymentState | null;
291 source?: DeploymentSource | null;
292 creator?: string | null;
293 /** From 1. */
294 page?: number | null;
295 /** 1 to 100; 30 unless given. */
296 per_page?: number | null;
297};
298
299/** One page of deployments, newest first. */
300export type DeploymentPage = {
301 deployments: RepoDeployment[];
302 total_count: number;
303 page: number;
304 per_page: number;
305};
306
307/** What `create_deployment` takes, as the API does. */
308export type NewDeployment = {
309 ref: string;
310 /** The commit; resolved from `ref` when left out. */
311 sha?: string | null;
312 environment?: string | null;
313 task?: string | null;
314 description?: string | null;
315 payload?: Record<string, unknown> | null;
316 transient_environment?: boolean | null;
317 production_environment?: boolean | null;
318 /** The state of its first status: `queued` unless given. */
319 state?: DeploymentState | null;
320 environment_url?: string | null;
321 log_url?: string | null;
322};
323
324/** What `create_deployment_status` takes. */
325export type NewDeploymentStatus = {
326 state: DeploymentState;
327 description?: string | null;
328 environment_url?: string | null;
329 log_url?: string | null;
330 /**
331 * On a success: the environment's older deployments that succeeded get
332 * an `inactive` status. True unless given.
333 */
334 auto_inactive?: boolean | null;
335};
336
Deployments: a preview for every pull request, production on g1t.page337export interface DeploymentsApi {
338 /** Members of the workspace only. */
Projects: what a workspace builds and runs, first on every page339 settings(project: ProjectRef, viewer: Viewer): Promise<Result<DeploySettings>>;
340 /** Members only. Turning deployments on needs the workspace's plan. */
341 updateSettings(actor: User, project: ProjectRef, changes: Partial<DeploySettings>): Promise<Result<DeploySettings>>;
342 /** The newest builds first, and what is up now. Members only. */
343 list(project: ProjectRef, viewer: Viewer): Promise<Result<{ deployments: Deployment[]; live: LiveApp[] }>>;
344 /** One build, with its log. Members only. */
345 get(project: ProjectRef, id: string, viewer: Viewer): Promise<Result<Deployment & { log: string | null }>>;
346 /** Builds production (`branch` null), or a branch's preview, again from its head. */
347 redeploy(actor: User, project: ProjectRef, branch: string | null): Promise<Result<Deployment>>;
Project dependencies: addresses, preview stacks, Affects, and agents who know348 /**
349 * Builds previews of the projects that use this one, under the same
350 * branch, each pointed at this branch's preview. Answers at once with the
351 * names of the projects being built; the builds go on in the
352 * background. Members only.
353 */
354 stack(actor: User, project: ProjectRef, branch: string): Promise<Result<string[]>>;
Projects: what a workspace builds and runs, first on every page355 /** Takes production (`branch` null), or a branch's preview, down now. */
356 takeDown(actor: User, project: ProjectRef, branch: string | null): Promise<Result<true>>;
357 /** Every project of a workspace at a glance. Members only. */
358 overview(workspace: string, viewer: Viewer): Promise<Result<ProjectDeploys[]>>;
Deployments: a preview for every pull request, production on g1t.page359 /** What the workspace's apps used this month. Members only. */
360 usage(workspace: string, viewer: Viewer): Promise<Result<DeployUsage>>;
Agents and memory, checks and conflicts, profiles, slug renames, custom domains361 /** The project's custom domains. Members only. */
362 domains(project: ProjectRef, viewer: Viewer): Promise<Result<ProjectDomains>>;
363 /**
364 * Adds a custom domain for production. With `twin`, its www or apex twin
365 * is added too, redirecting to it. Members only; needs the Deployments plan.
366 */
367 addDomain(actor: User, project: ProjectRef, hostname: string, options?: { twin?: boolean }): Promise<Result<Domain[]>>;
368 /** Removes a custom domain, and any domain redirecting to it. Members only. */
369 removeDomain(actor: User, project: ProjectRef, id: string): Promise<Result<true>>;
370 /** Asks Cloudflare to check the domain again now. Members only. */
371 refreshDomain(actor: User, project: ProjectRef, id: string): Promise<Result<Domain>>;
Merge branch 'main' into worktree-agent-a69aeabc4b0deeb97372 /** A repository's deployments, newest first, filtered. Anyone who can read it. */
373 repoDeployments(repo: RepoPath, viewer: Viewer, filter?: DeploymentFilter): Promise<Result<DeploymentPage>>;
374 /** One deployment with its statuses, oldest first. Anyone who can read the repository. */
375 repoDeployment(repo: RepoPath, id: string, viewer: Viewer): Promise<Result<DeploymentDetail>>;
376 /** A repository's environments with their current and latest deployments. Anyone who can read it. */
377 environments(repo: RepoPath, viewer: Viewer): Promise<Result<DeploymentEnvironments>>;
378 /** Reports a deployment. Takes the Write role. */
379 createDeployment(actor: User, repo: RepoPath, input: NewDeployment): Promise<Result<DeploymentDetail>>;
380 /** Adds a status to a reported deployment. Takes the Write role. */
381 createDeploymentStatus(actor: User, repo: RepoPath, id: string, input: NewDeploymentStatus): Promise<Result<DeploymentStatus>>;
Deployments: a preview for every pull request, production on g1t.page382}

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