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