Prettier leaves generated files alone and writes no trailing commas in .jsonc
Generated files that tests compare against their generator (reference/cli.md, data/openapi.json, worker-configuration.d.ts) go back to what generates them and into .prettierignore. Prettier 3's trailing commas in wrangler.jsonc broke the readers that strip comments and JSON.parse it (services/runner machines.test.ts), so .jsonc keeps trailingComma none.
- G1t-Session:
- ses_01m57b7r6jew3aqgyfmhw6yah6
35 files+679−6690/35 viewed
| 13 | 13 | *_fixtures.json | |
| 14 | 14 | # Prettier's MDX printer changes this page again on every run. | |
| 15 | 15 | apps/docs/src/content/docs/guides/self-hosted-runners.mdx | |
| 16 | + | # Generated, and checked against their generator by tests. | |
| 17 | + | apps/docs/src/content/docs/reference/cli.md | |
| 18 | + | apps/docs/src/data/openapi.json | |
| 19 | + | **/worker-configuration.d.ts |
| 1 | 1 | { | |
| 2 | − | "printWidth": 160 | |
| 2 | + | "printWidth": 160, | |
| 3 | + | "overrides": [ | |
| 4 | + | { | |
| 5 | + | "files": "*.jsonc", | |
| 6 | + | "options": { | |
| 7 | + | "trailingComma": "none" | |
| 8 | + | } | |
| 9 | + | } | |
| 10 | + | ] | |
| 3 | 11 | } |
| 11 | 11 | // adapters over the same operations. | |
| 12 | 12 | "routes": [ | |
| 13 | 13 | { "pattern": "api.g1t.sh", "custom_domain": true }, | |
| 14 | − | { "pattern": "mcp.g1t.sh", "custom_domain": true }, | |
| 14 | + | { "pattern": "mcp.g1t.sh", "custom_domain": true } | |
| 15 | 15 | ], | |
| 16 | 16 | "services": [ | |
| 17 | 17 | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| ⋯ | |||
| 36 | 36 | // Packages: list_packages, their settings, deleting and restoring them. | |
| 37 | 37 | { "binding": "PACKAGES", "service": "g1t-packages" }, | |
| 38 | 38 | // Artifacts (folios): the artifact tool and /workspaces/{ws}/artifacts. | |
| 39 | − | { "binding": "ARTIFACTS", "service": "g1t-artifacts" }, | |
| 39 | + | { "binding": "ARTIFACTS", "service": "g1t-artifacts" } | |
| 40 | 40 | ], | |
| 41 | 41 | // GitHub Actions artifacts older runners kept, in chunks, with KV's own | |
| 42 | 42 | // expiry, read until it passes (and cache | |
| ⋯ | |||
| 49 | 49 | // without one. Ids and limits: RATE_LIMITS in packages/contracts. | |
| 50 | 50 | "ratelimits": [ | |
| 51 | 51 | { "name": "API_ANONYMOUS_LIMIT", "namespace_id": "4401", "simple": { "limit": 60, "period": 60 } }, | |
| 52 | − | { "name": "API_TOKEN_LIMIT", "namespace_id": "4402", "simple": { "limit": 1000, "period": 60 } }, | |
| 52 | + | { "name": "API_TOKEN_LIMIT", "namespace_id": "4402", "simple": { "limit": 1000, "period": 60 } } | |
| 53 | 53 | ], | |
| 54 | 54 | // Logs of a tenth of requests: agents call it constantly. | |
| 55 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 55 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 56 | 56 | } | |
A large diff (1,482 lines) is not shown until you ask for it.
Binary or large file; its contents are not shown.
| 6 | 6 | // A static site: Astro builds it to ./dist and Workers serves the files. | |
| 7 | 7 | "assets": { | |
| 8 | 8 | "directory": "./dist", | |
| 9 | − | "not_found_handling": "404-page", | |
| 9 | + | "not_found_handling": "404-page" | |
| 10 | 10 | }, | |
| 11 | 11 | "routes": [{ "pattern": "docs.g1t.sh", "custom_domain": true }], | |
| 12 | 12 | // Logs of a tenth of requests: files only, nothing to debug in each. | |
| 13 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 13 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 14 | 14 | } |
| 21 | 21 | "binding": "DB", | |
| 22 | 22 | "database_name": "g1t-status", | |
| 23 | 23 | "database_id": "dba85721-96dc-401d-9121-a6c587d614b2", | |
| 24 | − | "migrations_dir": "migrations", | |
| 25 | − | }, | |
| 24 | + | "migrations_dir": "migrations" | |
| 25 | + | } | |
| 26 | 26 | ], | |
| 27 | 27 | // Billing has no public address: its price book is read through this. | |
| 28 | 28 | // Git storage (Cloudflare Artifacts) has none either: how it answered | |
| ⋯ | |||
| 30 | 30 | // is bound, so every other check goes over the internet. | |
| 31 | 31 | "services": [ | |
| 32 | 32 | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 33 | − | { "binding": "REPOS", "service": "g1t-repos" }, | |
| 33 | + | { "binding": "REPOS", "service": "g1t-repos" } | |
| 34 | 34 | ], | |
| 35 | 35 | // Email to subscribers (confirmations, incident and maintenance | |
| 36 | 36 | // updates) and the staff alert for detected drafts, through Cloudflare | |
| ⋯ | |||
| 66 | 66 | // 45 minutes, then every 6 hours). Empty sends none. | |
| 67 | 67 | "STATUS_ALERT_EMAIL": "hey@flagon.io", | |
| 68 | 68 | "STATUS_FROM": "g1t status <noreply@g1t.sh>", | |
| 69 | − | "OG_IMAGE": "https://og.g1t.sh/image?path=%2Fstatus&v=3", | |
| 69 | + | "OG_IMAGE": "https://og.g1t.sh/image?path=%2Fstatus&v=3" | |
| 70 | 70 | }, | |
| 71 | 71 | // Asking for a subscription sends an email: limited per client address | |
| 72 | 72 | // and per email address (src/index.ts). Ids and limits: RATE_LIMITS in | |
| 73 | 73 | // packages/contracts. | |
| 74 | 74 | "ratelimits": [ | |
| 75 | 75 | { "name": "STATUS_SUBSCRIBE_LIMIT", "namespace_id": "4601", "simple": { "limit": 3, "period": 60 } }, | |
| 76 | − | { "name": "STATUS_EMAIL_LIMIT", "namespace_id": "4602", "simple": { "limit": 2, "period": 60 } }, | |
| 76 | + | { "name": "STATUS_EMAIL_LIMIT", "namespace_id": "4602", "simple": { "limit": 2, "period": 60 } } | |
| 77 | 77 | ], | |
| 78 | 78 | // Every log kept: few requests, and the checks' failures are what it is for. | |
| 79 | − | "observability": { "enabled": true, "head_sampling_rate": 1 }, | |
| 79 | + | "observability": { "enabled": true, "head_sampling_rate": 1 } | |
| 80 | 80 | } | |
| 29 | 29 | // projects, and their telemetry ingest tokens. | |
| 30 | 30 | { "binding": "ACTIONS", "service": "g1t-actions" }, | |
| 31 | 31 | { "binding": "PROJECTS", "service": "g1t-projects" }, | |
| 32 | − | { "binding": "TELEMETRY", "service": "g1t-telemetry" }, | |
| 32 | + | { "binding": "TELEMETRY", "service": "g1t-telemetry" } | |
| 33 | 33 | ], | |
| 34 | 34 | "vars": { | |
| 35 | 35 | // The Zero Trust team domain, such as `g1t.cloudflareaccess.com`. | |
| ⋯ | |||
| 42 | 42 | // Access service tokens let in as staff: `<client id>=<name>`, comma | |
| 43 | 43 | // separated. Each acts, and is recorded, as `<name>@service.g1t.sh`. | |
| 44 | 44 | // The Access application needs a Service Auth policy including it. | |
| 45 | − | "STAFF_SERVICE_TOKENS": "434297ede60761875e84742d0486cf27.access=claude", | |
| 45 | + | "STAFF_SERVICE_TOKENS": "434297ede60761875e84742d0486cf27.access=claude" | |
| 46 | 46 | }, | |
| 47 | 47 | // Every log kept: staff only, few requests. | |
| 48 | 48 | "observability": { "enabled": true, "head_sampling_rate": 1 }, | |
| 49 | − | "upload_source_maps": true, | |
| 49 | + | "upload_source_maps": true | |
| 50 | 50 | } | |
| 15 | 15 | // their own that never sees g1t.sh's cookies (workers/usercontent.ts). | |
| 16 | 16 | "routes": [ | |
| 17 | 17 | { "pattern": "g1t.sh", "custom_domain": true }, | |
| 18 | − | { "pattern": "g1tusercontent.com", "custom_domain": true }, | |
| 18 | + | { "pattern": "g1tusercontent.com", "custom_domain": true } | |
| 19 | 19 | ], | |
| 20 | 20 | // The site holds no data of its own; everything goes through services. | |
| 21 | 21 | // GitHub Actions artifacts, as the API keeps them, for download from a run. | |
| ⋯ | |||
| 23 | 23 | // only here: the identity service checks and writes them. | |
| 24 | 24 | "kv_namespaces": [ | |
| 25 | 25 | { "binding": "BLOBS", "id": "16a4232cb746418db53782aa068be693" }, | |
| 26 | − | { "binding": "AVATARS", "id": "e627b571f07047e187c03e1fc2b3bbdd" }, | |
| 26 | + | { "binding": "AVATARS", "id": "e627b571f07047e187c03e1fc2b3bbdd" } | |
| 27 | 27 | ], | |
| 28 | 28 | // The self-hosted runner's releases, served at /downloads/runner/ | |
| 29 | 29 | // (routes/downloads-runner.ts); published by scripts/runner-release.mjs. | |
| ⋯ | |||
| 52 | 52 | // Observability: each project's requests, logs, traces, metrics and errors, and its live tail (services/telemetry). | |
| 53 | 53 | { "binding": "TELEMETRY", "service": "g1t-telemetry" }, | |
| 54 | 54 | // Production screenshots for a project's overview (services/og). | |
| 55 | − | { "binding": "SCREENSHOTS", "service": "g1t-og", "entrypoint": "Screenshots" }, | |
| 55 | + | { "binding": "SCREENSHOTS", "service": "g1t-og", "entrypoint": "Screenshots" } | |
| 56 | 56 | ], | |
| 57 | 57 | // The front door's limits (app/lib/front-door-limits.ts). Every id and | |
| 58 | 58 | // limit is in RATE_LIMITS (packages/contracts/src/rate-limits.ts), which | |
| ⋯ | |||
| 64 | 64 | { "name": "WEB_ADDRESS_LIMIT", "namespace_id": "4204", "simple": { "limit": 3000, "period": 60 } }, | |
| 65 | 65 | { "name": "GIT_ANONYMOUS_LIMIT", "namespace_id": "4205", "simple": { "limit": 120, "period": 60 } }, | |
| 66 | 66 | { "name": "GIT_SIGNED_LIMIT", "namespace_id": "4206", "simple": { "limit": 1200, "period": 60 } }, | |
| 67 | − | { "name": "WEB_TOKEN_LIMIT", "namespace_id": "4207", "simple": { "limit": 1000, "period": 60 } }, | |
| 67 | + | { "name": "WEB_TOKEN_LIMIT", "namespace_id": "4207", "simple": { "limit": 1000, "period": 60 } } | |
| 68 | 68 | ], | |
| 69 | 69 | // Logs of a tenth of requests: every page view is one, too many to keep all. | |
| 70 | 70 | // Cloudflare Turnstile on email sign-up (app/lib/turnstile.ts): the | |
| ⋯ | |||
| 72 | 72 | // secret. Either one empty turns it off. | |
| 73 | 73 | "vars": { "TURNSTILE_SITE_KEY": "0x4AAAAAAFWhRDwKfGS3CEvZ" }, | |
| 74 | 74 | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 75 | − | "upload_source_maps": true, | |
| 75 | + | "upload_source_maps": true | |
| 76 | 76 | } | |
| 29 | 29 | "16a4232cb746418db53782aa068be693": "g1t-actions-blobs", | |
| 30 | 30 | "e627b571f07047e187c03e1fc2b3bbdd": "g1t-avatars", | |
| 31 | 31 | "14bc5c233d4c46a5bbf23b5367cce5fd": "g1t-domains", | |
| 32 | − | "be765052d0124c2a935b3db4dff99f1f": "g1t-repos-git-cache", | |
| 33 | − | }, | |
| 32 | + | "be765052d0124c2a935b3db4dff99f1f": "g1t-repos-git-cache" | |
| 33 | + | } | |
| 34 | 34 | }, | |
| 35 | 35 | ||
| 36 | 36 | // Each deployable unit, by short name (`--only events,web`). | |
| ⋯ | |||
| 60 | 60 | "stage": "core", | |
| 61 | 61 | "secrets": [], | |
| 62 | 62 | "setup": [ | |
| 63 | − | "The dead-letter queue every queue consumer sends what it gave up on to, before any unit that names it deploys: npx wrangler queues create g1t-events-dlq", | |
| 63 | + | "The dead-letter queue every queue consumer sends what it gave up on to, before any unit that names it deploys: npx wrangler queues create g1t-events-dlq" | |
| 64 | 64 | ], | |
| 65 | − | "self_host": "run", | |
| 65 | + | "self_host": "run" | |
| 66 | 66 | }, | |
| 67 | 67 | "identity": { | |
| 68 | 68 | "path": "services/identity", | |
| ⋯ | |||
| 72 | 72 | "stage": "core", | |
| 73 | 73 | "secrets": ["GITHUB_APP_CLIENT_SECRET", "IDENTITY_KEY"], | |
| 74 | 74 | "setup": ["Email Sending on g1t.sh (the EMAIL binding)"], | |
| 75 | − | "self_host": "run", | |
| 75 | + | "self_host": "run" | |
| 76 | 76 | }, | |
| 77 | 77 | "repos": { | |
| 78 | 78 | "path": "services/repos", | |
| ⋯ | |||
| 87 | 87 | "setup": [ | |
| 88 | 88 | "The Artifacts namespace `g1t` (the ARTIFACTS binding)", | |
| 89 | 89 | "The R2 bucket `g1t-git-packs` (GIT_PACKS) with its lifecycle rule: `npx wrangler r2 bucket create g1t-git-packs`, then `npx wrangler r2 bucket lifecycle add g1t-git-packs expire-packs packs/ --expire-days 7 --abort-multipart-days 1`", | |
| 90 | − | "The R2 bucket for nightly backups: npx wrangler r2 bucket create g1t-backups", | |
| 90 | + | "The R2 bucket for nightly backups: npx wrangler r2 bucket create g1t-backups" | |
| 91 | 91 | ], | |
| 92 | − | "self_host": "run", | |
| 92 | + | "self_host": "run" | |
| 93 | 93 | }, | |
| 94 | 94 | "work": { | |
| 95 | 95 | "path": "services/work", | |
| ⋯ | |||
| 98 | 98 | "d1": { "database": "g1t-work", "migrations": "migrations" }, | |
| 99 | 99 | "stage": "core", | |
| 100 | 100 | "secrets": [], | |
| 101 | − | "self_host": "run", | |
| 101 | + | "self_host": "run" | |
| 102 | 102 | }, | |
| 103 | 103 | "search": { | |
| 104 | 104 | "path": "services/search", | |
| ⋯ | |||
| 107 | 107 | "d1": { "database": "g1t-search", "migrations": "migrations" }, | |
| 108 | 108 | "stage": "core", | |
| 109 | 109 | "secrets": [], | |
| 110 | − | "self_host": "run", | |
| 110 | + | "self_host": "run" | |
| 111 | 111 | }, | |
| 112 | 112 | "projects": { | |
| 113 | 113 | "path": "services/projects", | |
| ⋯ | |||
| 116 | 116 | "d1": { "database": "g1t-projects", "migrations": "migrations" }, | |
| 117 | 117 | "stage": "core", | |
| 118 | 118 | "secrets": [], | |
| 119 | − | "self_host": "run", | |
| 119 | + | "self_host": "run" | |
| 120 | 120 | }, | |
| 121 | 121 | "chat": { | |
| 122 | 122 | "path": "services/chat", | |
| ⋯ | |||
| 126 | 126 | "stage": "core", | |
| 127 | 127 | "secrets": [], | |
| 128 | 128 | "setup": ["The D1 database, before the first deploy: npx wrangler d1 create g1t-chat, then put its id in services/chat/wrangler.jsonc"], | |
| 129 | − | "self_host": "run", | |
| 129 | + | "self_host": "run" | |
| 130 | 130 | }, | |
| 131 | 131 | // Artifacts: docs (a doc is one kind of artifact), their spaces, | |
| 132 | 132 | // sharing and live rooms. It was g1t-docs-service (services/docs) | |
| ⋯ | |||
| 145 | 145 | "The R2 bucket for files in pages: npx wrangler r2 bucket create g1t-docs-files", | |
| 146 | 146 | "The queue the events service sends it merges and pushes on (pages whose cited code changed, projects' docs): npx wrangler queues create g1t-events-docs. The service also sends its own backfill jobs to it (JOBS)", | |
| 147 | 147 | "The Vectorize index Docs are searched by meaning from: npx wrangler vectorize create g1t-docs --dimensions=768 --metric=cosine, with string metadata indexes on workspace_id and space_id (npx wrangler vectorize create-metadata-index g1t-docs --property-name=<name> --type=string)", | |
| 148 | − | "The Vectorize index for artifacts (folios), before the first deploy with FOLIO_VECTORS: npx wrangler vectorize create g1t-folios --dimensions=768 --metric=cosine, with string metadata indexes on workspace_id, scope and kind (npx wrangler vectorize create-metadata-index g1t-folios --property-name=<name> --type=string). Without it, artifacts are searched by words", | |
| 148 | + | "The Vectorize index for artifacts (folios), before the first deploy with FOLIO_VECTORS: npx wrangler vectorize create g1t-folios --dimensions=768 --metric=cosine, with string metadata indexes on workspace_id, scope and kind (npx wrangler vectorize create-metadata-index g1t-folios --property-name=<name> --type=string). Without it, artifacts are searched by words" | |
| 149 | 149 | ], | |
| 150 | − | "self_host": "run", | |
| 150 | + | "self_host": "run" | |
| 151 | 151 | }, | |
| 152 | 152 | "telemetry": { | |
| 153 | 153 | "path": "services/telemetry", | |
| ⋯ | |||
| 161 | 161 | // export of the apps), so it is not listed. | |
| 162 | 162 | "secrets": [], | |
| 163 | 163 | "setup": [ | |
| 164 | − | "Deployed once before the deployments service and the dispatcher, which name it (`node scripts/deploy.mjs deploy --only telemetry`): a binding or Tail Worker that names a Worker not yet there is refused", | |
| 164 | + | "Deployed once before the deployments service and the dispatcher, which name it (`node scripts/deploy.mjs deploy --only telemetry`): a binding or Tail Worker that names a Worker not yet there is refused" | |
| 165 | 165 | ], | |
| 166 | − | "self_host": "run", | |
| 166 | + | "self_host": "run" | |
| 167 | 167 | }, | |
| 168 | 168 | "notify": { | |
| 169 | 169 | "path": "services/notify", | |
| ⋯ | |||
| 179 | 179 | // is not listed. | |
| 180 | 180 | "secrets": ["VAPID_PRIVATE_KEY"], | |
| 181 | 181 | "setup": [ | |
| 182 | − | "The VAPID key pair for browser push: `node scripts/ops/vapid-keys.mjs` prints both halves and stores nothing. Put the public half in VAPID_PUBLIC_KEY in services/notify/wrangler.jsonc, and the private half with `npx wrangler secret put VAPID_PRIVATE_KEY` in services/notify", | |
| 182 | + | "The VAPID key pair for browser push: `node scripts/ops/vapid-keys.mjs` prints both halves and stores nothing. Put the public half in VAPID_PUBLIC_KEY in services/notify/wrangler.jsonc, and the private half with `npx wrangler secret put VAPID_PRIVATE_KEY` in services/notify" | |
| 183 | 183 | ], | |
| 184 | − | "self_host": "run", | |
| 184 | + | "self_host": "run" | |
| 185 | 185 | }, | |
| 186 | 186 | "billing": { | |
| 187 | 187 | "path": "services/billing", | |
| ⋯ | |||
| 190 | 190 | "d1": { "database": "g1t-billing", "migrations": "migrations" }, | |
| 191 | 191 | "stage": "core", | |
| 192 | 192 | "secrets": ["STRIPE_SECRET_KEY", "STRIPE_WEBHOOK_SECRET", "CLOUDFLARE_USAGE_TOKEN", "BILLING_KEY"], | |
| 193 | − | "self_host": "run", | |
| 193 | + | "self_host": "run" | |
| 194 | 194 | }, | |
| 195 | 195 | "integrations": { | |
| 196 | 196 | "path": "services/integrations", | |
| ⋯ | |||
| 199 | 199 | "d1": { "database": "g1t-integrations", "migrations": "migrations" }, | |
| 200 | 200 | "stage": "core", | |
| 201 | 201 | "secrets": ["INTEGRATIONS_KEY", "GITHUB_APP_PRIVATE_KEY", "GITHUB_APP_WEBHOOK_SECRET"], | |
| 202 | − | "self_host": "run", | |
| 202 | + | "self_host": "run" | |
| 203 | 203 | }, | |
| 204 | 204 | "webhooks": { | |
| 205 | 205 | "path": "services/webhooks", | |
| ⋯ | |||
| 208 | 208 | "d1": { "database": "g1t-webhooks", "migrations": "migrations" }, | |
| 209 | 209 | "stage": "core", | |
| 210 | 210 | "secrets": ["WEBHOOKS_KEY"], | |
| 211 | − | "self_host": "run", | |
| 211 | + | "self_host": "run" | |
| 212 | 212 | }, | |
| 213 | 213 | "actions": { | |
| 214 | 214 | "path": "services/actions", | |
| ⋯ | |||
| 217 | 217 | "d1": { "database": "g1t-actions", "migrations": "migrations" }, | |
| 218 | 218 | "stage": "core", | |
| 219 | 219 | "secrets": ["ACTIONS_KEY"], | |
| 220 | − | "self_host": "run", | |
| 220 | + | "self_host": "run" | |
| 221 | 221 | }, | |
| 222 | 222 | "packages": { | |
| 223 | 223 | "path": "services/packages", | |
| ⋯ | |||
| 230 | 230 | "The D1 database: npx wrangler d1 create g1t-packages, its id in services/packages/wrangler.jsonc", | |
| 231 | 231 | "The R2 bucket for packages' files: npx wrangler r2 bucket create g1t-packages", | |
| 232 | 232 | "The events queue: npx wrangler queues create g1t-events-packages", | |
| 233 | − | "For signed downloads: an R2 API token with read access to g1t-packages, as R2_ACCESS_KEY_ID and R2_SECRET_ACCESS_KEY", | |
| 233 | + | "For signed downloads: an R2 API token with read access to g1t-packages, as R2_ACCESS_KEY_ID and R2_SECRET_ACCESS_KEY" | |
| 234 | 234 | ], | |
| 235 | − | "self_host": "run", | |
| 235 | + | "self_host": "run" | |
| 236 | 236 | }, | |
| 237 | 237 | "security": { | |
| 238 | 238 | "path": "services/security", | |
| ⋯ | |||
| 241 | 241 | "d1": { "database": "g1t-security", "migrations": "migrations" }, | |
| 242 | 242 | "stage": "core", | |
| 243 | 243 | "secrets": [], | |
| 244 | − | "self_host": "run", | |
| 244 | + | "self_host": "run" | |
| 245 | 245 | }, | |
| 246 | 246 | "deployments": { | |
| 247 | 247 | "path": "services/deployments", | |
| ⋯ | |||
| 252 | 252 | "secrets": ["CLOUDFLARE_API_TOKEN"], | |
| 253 | 253 | "setup": [ | |
| 254 | 254 | "Workers for Platforms, and the dispatch namespace: scripts/setup-deployments.sh", | |
| 255 | − | "Custom domains (Cloudflare for SaaS on g1t.page): scripts/setup-custom-domains.sh", | |
| 255 | + | "Custom domains (Cloudflare for SaaS on g1t.page): scripts/setup-custom-domains.sh" | |
| 256 | 256 | ], | |
| 257 | − | "self_host": "run", | |
| 257 | + | "self_host": "run" | |
| 258 | 258 | }, | |
| 259 | 259 | "runner": { | |
| 260 | 260 | "path": "services/runner", | |
| ⋯ | |||
| 268 | 268 | // The binary the image adds to its base (scripts/build-runner.mjs). | |
| 269 | 269 | "crate": "g1t-runner", | |
| 270 | 270 | "base": { "context": "services/runner/base", "lock": "services/runner/base.json" }, | |
| 271 | − | "repository": "g1t-runner", | |
| 271 | + | "repository": "g1t-runner" | |
| 272 | 272 | }, | |
| 273 | − | "self_host": "off", | |
| 273 | + | "self_host": "off" | |
| 274 | 274 | }, | |
| 275 | 275 | "og": { | |
| 276 | 276 | "path": "services/og", | |
| ⋯ | |||
| 281 | 281 | "setup": ["Browser Rendering on the account (the BROWSER binding)"], | |
| 282 | 282 | // The roadmap cards read the site's roadmap. | |
| 283 | 283 | "inputs": ["apps/web/app/lib/roadmap.ts"], | |
| 284 | − | "self_host": "none", | |
| 284 | + | "self_host": "none" | |
| 285 | 285 | }, | |
| 286 | 286 | "api": { | |
| 287 | 287 | "path": "apps/api", | |
| ⋯ | |||
| 295 | 295 | "secrets": ["ACTIONS_OIDC_KEY"], | |
| 296 | 296 | "setup": [ | |
| 297 | 297 | "The OIDC signing key for workflow jobs: an RSA key made with `openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048`, stored with `npx wrangler secret put ACTIONS_OIDC_KEY` (docs.g1t.sh/guides/deploy-to-cloudflare/#oidc-tokens-for-workflow-jobs)", | |
| 298 | − | "The actions cache bucket's lifecycle rule limited to `c/`, so artifacts under `a/` are kept their retention-days (docs.g1t.sh/guides/deploy-to-cloudflare/#a-first-deploy-to-a-new-account)", | |
| 298 | + | "The actions cache bucket's lifecycle rule limited to `c/`, so artifacts under `a/` are kept their retention-days (docs.g1t.sh/guides/deploy-to-cloudflare/#a-first-deploy-to-a-new-account)" | |
| 299 | 299 | ], | |
| 300 | − | "self_host": "separate", | |
| 300 | + | "self_host": "separate" | |
| 301 | 301 | }, | |
| 302 | 302 | "pages": { | |
| 303 | 303 | "path": "services/pages", | |
| ⋯ | |||
| 306 | 306 | "stage": "edge", | |
| 307 | 307 | "secrets": [], | |
| 308 | 308 | "setup": ["A proxied wildcard DNS record on g1t.page (`*`, AAAA 100::): scripts/setup-deployments.sh"], | |
| 309 | − | "self_host": "none", | |
| 309 | + | "self_host": "none" | |
| 310 | 310 | }, | |
| 311 | 311 | "status": { | |
| 312 | 312 | "path": "apps/status", | |
| ⋯ | |||
| 316 | 316 | "stage": "edge", | |
| 317 | 317 | "secrets": ["STATUS_SECRET"], | |
| 318 | 318 | "setup": ["Email Sending on g1t.sh (the EMAIL binding)"], | |
| 319 | − | "self_host": "separate", | |
| 319 | + | "self_host": "separate" | |
| 320 | 320 | }, | |
| 321 | 321 | "web": { | |
| 322 | 322 | "path": "apps/web", | |
| ⋯ | |||
| 330 | 330 | "setup": [ | |
| 331 | 331 | "The R2 bucket g1t-downloads, for the releases of the self-hosted runner, the CLI and the desktop app: npx wrangler r2 bucket create g1t-downloads", | |
| 332 | 332 | "The zone g1tusercontent.com on the account; the Worker's custom domain on it is made by the deploy", | |
| 333 | − | "The key for private files' addresses: `node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\" | npx wrangler secret put USERCONTENT_KEY` in apps/web", | |
| 333 | + | "The key for private files' addresses: `node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\" | npx wrangler secret put USERCONTENT_KEY` in apps/web" | |
| 334 | 334 | ], | |
| 335 | − | "self_host": "run", | |
| 335 | + | "self_host": "run" | |
| 336 | 336 | }, | |
| 337 | 337 | "sudo": { | |
| 338 | 338 | "path": "apps/sudo", | |
| ⋯ | |||
| 341 | 341 | "stage": "front", | |
| 342 | 342 | "secrets": [], | |
| 343 | 343 | "setup": ["A Cloudflare Access application on sudo.g1t.sh; its AUD tag is ACCESS_AUD"], | |
| 344 | − | "self_host": "none", | |
| 344 | + | "self_host": "none" | |
| 345 | 345 | }, | |
| 346 | 346 | "docs": { | |
| 347 | 347 | "path": "apps/docs", | |
| ⋯ | |||
| 349 | 349 | "worker": "g1t-docs", | |
| 350 | 350 | "stage": "front", | |
| 351 | 351 | "secrets": [], | |
| 352 | − | "self_host": "none", | |
| 353 | − | }, | |
| 354 | − | }, | |
| 352 | + | "self_host": "none" | |
| 353 | + | } | |
| 354 | + | } | |
| 355 | 355 | } | |
| 14 | 14 | "binding": "DB", | |
| 15 | 15 | "database_name": "g1t-actions", | |
| 16 | 16 | "database_id": "95ccaa88-8e15-4b90-81e2-0d02d8ce869d", | |
| 17 | − | "migrations_dir": "migrations", | |
| 18 | − | }, | |
| 17 | + | "migrations_dir": "migrations" | |
| 18 | + | } | |
| 19 | 19 | ], | |
| 20 | 20 | // ACTIONS_KEY (secret): seals secrets at rest. Never regenerate it: | |
| 21 | 21 | // secrets saved under the old key could no longer be opened. | |
| ⋯ | |||
| 32 | 32 | // A job with an `environment:` makes its run's deployment there. | |
| 33 | 33 | { "binding": "DEPLOYMENTS", "service": "g1t-deployments" }, | |
| 34 | 34 | // Pages open on a repository hear its runs' jobs start and finish. | |
| 35 | − | { "binding": "NOTIFY", "service": "g1t-notify" }, | |
| 35 | + | { "binding": "NOTIFY", "service": "g1t-notify" } | |
| 36 | 36 | ], | |
| 37 | 37 | // actions/cache entries and artifacts, which the API writes: deleted here when they | |
| 38 | 38 | // are evicted or expire. | |
| 39 | 39 | "r2_buckets": [{ "binding": "ACTIONS_CACHE", "bucket_name": "g1t-actions-cache" }], | |
| 40 | 40 | // Every event on the bus: what starts workflows, and pushes that change them. | |
| 41 | 41 | "queues": { | |
| 42 | − | "consumers": [{ "queue": "g1t-events-actions", "max_batch_size": 10, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 42 | + | "consumers": [{ "queue": "g1t-events-actions", "max_batch_size": 10, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 43 | 43 | }, | |
| 44 | 44 | // What g1t keeps and allows (src/limits.rs): days a finished job's log is | |
| 45 | 45 | // kept (0: for good); what a workspace without the plan may keep in | |
| ⋯ | |||
| 48 | 48 | "vars": { | |
| 49 | 49 | "LOG_RETENTION_DAYS": "90", | |
| 50 | 50 | "FREE_ACTIONS_STORAGE_BYTES": "2147483648", | |
| 51 | − | "FREE_SELF_HOSTED_JOBS": "4", | |
| 51 | + | "FREE_SELF_HOSTED_JOBS": "4" | |
| 52 | 52 | }, | |
| 53 | 53 | // Schedules, jobs waiting for room, and jobs whose runner went quiet. | |
| 54 | 54 | "triggers": { "crons": ["* * * * *"] }, | |
| 55 | 55 | // Every log kept: few requests, and a failed job must be traceable. | |
| 56 | − | "observability": { "enabled": true, "head_sampling_rate": 1 }, | |
| 56 | + | "observability": { "enabled": true, "head_sampling_rate": 1 } | |
| 57 | 57 | } | |
| 22 | 22 | // npx wrangler d1 create g1t-docs | |
| 23 | 23 | // npx wrangler d1 migrations apply g1t-docs --remote | |
| 24 | 24 | "database_id": "8f2193ed-fd2b-4322-b6cb-c79090e7603d", | |
| 25 | − | "migrations_dir": "migrations", | |
| 26 | − | }, | |
| 25 | + | "migrations_dir": "migrations" | |
| 26 | + | } | |
| 27 | 27 | ], | |
| 28 | 28 | // Files people put in pages (images, attachments), served from the | |
| 29 | 29 | // usercontent origin at /docs-files/<key> (apps/web/workers/usercontent.ts). | |
| ⋯ | |||
| 52 | 52 | "ai": { "binding": "AI" }, | |
| 53 | 53 | "vectorize": [ | |
| 54 | 54 | { "binding": "VECTORS", "index_name": "g1t-docs" }, | |
| 55 | − | { "binding": "FOLIO_VECTORS", "index_name": "g1t-folios" }, | |
| 55 | + | { "binding": "FOLIO_VECTORS", "index_name": "g1t-folios" } | |
| 56 | 56 | ], | |
| 57 | 57 | "services": [ | |
| 58 | 58 | // Workspaces by slug, people's names and avatars, and teams. | |
| ⋯ | |||
| 67 | 67 | // doc.page.* events on the bus (src/events.ts). | |
| 68 | 68 | { "binding": "EVENTS", "service": "g1t-events" }, | |
| 69 | 69 | // Whether a workspace has the plan, once its files pass the free cap (src/quota.ts). | |
| 70 | − | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 70 | + | { "binding": "BILLING", "service": "g1t-billing" } | |
| 71 | 71 | ], | |
| 72 | 72 | // What a workspace without the plan may keep in files put in its pages | |
| 73 | 73 | // and artifacts, in bytes; past it, new uploads are refused (src/quota.ts). | |
| ⋯ | |||
| 82 | 82 | // src/indexer.ts): a workspace's pages and projects' docs indexed in | |
| 83 | 83 | // batches, and waiting out the hourly embedding cap. | |
| 84 | 84 | "producers": [{ "binding": "JOBS", "queue": "g1t-events-docs" }], | |
| 85 | − | "consumers": [{ "queue": "g1t-events-docs", "max_batch_size": 20, "max_batch_timeout": 2, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 85 | + | "consumers": [{ "queue": "g1t-events-docs", "max_batch_size": 20, "max_batch_timeout": 2, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 86 | 86 | }, | |
| 87 | 87 | // One room per page: it holds the page's Yjs document and open sockets, | |
| 88 | 88 | // hibernating while nobody types (src/room.ts). And one per folio | |
| ⋯ | |||
| 91 | 91 | "durable_objects": { | |
| 92 | 92 | "bindings": [ | |
| 93 | 93 | { "name": "PAGES", "class_name": "PageRoom" }, | |
| 94 | − | { "name": "FOLIOS", "class_name": "FolioRoom" }, | |
| 95 | − | ], | |
| 94 | + | { "name": "FOLIOS", "class_name": "FolioRoom" } | |
| 95 | + | ] | |
| 96 | 96 | }, | |
| 97 | 97 | // Both classes were made on g1t-docs-service (v1 PageRoom, v2 FolioRoom, | |
| 98 | 98 | // both SQLite). v3 transfers them, every room's storage with them, when | |
| ⋯ | |||
| 108 | 108 | "tag": "v3", | |
| 109 | 109 | "transferred_classes": [ | |
| 110 | 110 | { "from": "PageRoom", "from_script": "g1t-docs-service", "to": "PageRoom" }, | |
| 111 | − | { "from": "FolioRoom", "from_script": "g1t-docs-service", "to": "FolioRoom" }, | |
| 112 | − | ], | |
| 113 | − | }, | |
| 111 | + | { "from": "FolioRoom", "from_script": "g1t-docs-service", "to": "FolioRoom" } | |
| 112 | + | ] | |
| 113 | + | } | |
| 114 | 114 | ], | |
| 115 | 115 | // Daily: folios in the trash for over 30 days are deleted for good. Every | |
| 116 | 116 | // quarter hour: each workspace's month of search embeddings is reported | |
| 117 | 117 | // to billing (src/embed-billing.ts; DAILY_CRON in src/index.ts). | |
| 118 | 118 | "triggers": { "crons": ["17 3 * * *", "*/15 * * * *"] }, | |
| 119 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 119 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 120 | 120 | } | |
| 15 | 15 | "binding": "DB", | |
| 16 | 16 | "database_name": "g1t-billing", | |
| 17 | 17 | "database_id": "695a6979-fd07-4850-bc97-904a6b4b7a04", | |
| 18 | − | "migrations_dir": "migrations", | |
| 19 | − | }, | |
| 18 | + | "migrations_dir": "migrations" | |
| 19 | + | } | |
| 20 | 20 | ], | |
| 21 | 21 | // Identity emails owners as their workspace nears its usage limit. | |
| 22 | 22 | // Repos says which repositories are public (the open-source pool pays | |
| ⋯ | |||
| 25 | 25 | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| 26 | 26 | { "binding": "REPOS", "service": "g1t-repos" }, | |
| 27 | 27 | // What each workspace's packages hold, measured daily (src/storage.rs). | |
| 28 | − | { "binding": "PACKAGES", "service": "g1t-packages" }, | |
| 28 | + | { "binding": "PACKAGES", "service": "g1t-packages" } | |
| 29 | 29 | ], | |
| 30 | 30 | // Margin alerts to staff (src/margin.rs), through Cloudflare Email | |
| 31 | 31 | // Sending like identity's and the status page's mail. | |
| ⋯ | |||
| 33 | 33 | // Events from the bus: a workspace renamed moves its billing to the | |
| 34 | 34 | // new slug (src/rename.rs). | |
| 35 | 35 | "queues": { | |
| 36 | − | "consumers": [{ "queue": "g1t-events-billing", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 36 | + | "consumers": [{ "queue": "g1t-events-billing", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 37 | 37 | }, | |
| 38 | 38 | "vars": { | |
| 39 | 39 | // What is added to what g1t runs at cost, in percent: g1t's overhead | |
| ⋯ | |||
| 171 | 171 | "AUTO_PAUSE": "schedules,indexing", | |
| 172 | 172 | // Cloudflare's fixed subscriptions a month, for sudo's figures only: | |
| 173 | 173 | // Workers Paid ($5) and Workers for Platforms ($25). | |
| 174 | − | "CLOUDFLARE_FIXED_MONTHLY_MICROS": "30000000", | |
| 174 | + | "CLOUDFLARE_FIXED_MONTHLY_MICROS": "30000000" | |
| 175 | 175 | }, | |
| 176 | 176 | // The tick every 15 minutes (Stripe, autopay, closing months), which at | |
| 177 | 177 | // a quarter past each hour also runs the platform watch; checking costs | |
| ⋯ | |||
| 187 | 187 | // (src/provider_costs.rs). Without it none can be connected; changing it | |
| 188 | 188 | // means every provider has to be connected again. | |
| 189 | 189 | // Every log kept: money moves here, and every failure matters. | |
| 190 | − | "observability": { "enabled": true, "head_sampling_rate": 1 }, | |
| 190 | + | "observability": { "enabled": true, "head_sampling_rate": 1 } | |
| 191 | 191 | } | |
| 14 | 14 | "binding": "DB", | |
| 15 | 15 | "database_name": "g1t-chat", | |
| 16 | 16 | "database_id": "e837affd-a435-4408-9345-14d55d520316", | |
| 17 | − | "migrations_dir": "migrations", | |
| 18 | − | }, | |
| 17 | + | "migrations_dir": "migrations" | |
| 18 | + | } | |
| 19 | 19 | ], | |
| 20 | 20 | "services": [ | |
| 21 | 21 | // Workspaces by slug, and people's names and avatars for members. | |
| ⋯ | |||
| 24 | 24 | { "binding": "NOTIFY", "service": "g1t-notify" }, | |
| 25 | 25 | // Ask (services/integrations): @g1t's answers in a direct message with | |
| 26 | 26 | // it, from the workspace's own AI provider. The channel's room asks. | |
| 27 | − | { "binding": "INTEGRATIONS", "service": "g1t-integrations" }, | |
| 27 | + | { "binding": "INTEGRATIONS", "service": "g1t-integrations" } | |
| 28 | 28 | ], | |
| 29 | 29 | // One room per channel for live delivery: it holds the channel's open | |
| 30 | 30 | // sockets, hibernating while nobody says anything (src/room.ts). | |
| 31 | 31 | "durable_objects": { | |
| 32 | − | "bindings": [{ "name": "ROOMS", "class_name": "ChannelRoom" }], | |
| 32 | + | "bindings": [{ "name": "ROOMS", "class_name": "ChannelRoom" }] | |
| 33 | 33 | }, | |
| 34 | 34 | "migrations": [{ "tag": "v1", "new_sqlite_classes": ["ChannelRoom"] }], | |
| 35 | 35 | // Custom emoji images, kept by their hash under `emoji/` in the avatars | |
| 36 | 36 | // namespace and served from the usercontent origin at /emoji/<hash> | |
| 37 | 37 | // (apps/web/workers/usercontent.ts), never from the site. | |
| 38 | 38 | "kv_namespaces": [{ "binding": "AVATARS", "id": "e627b571f07047e187c03e1fc2b3bbdd" }], | |
| 39 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 39 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 40 | 40 | } | |
| 12 | 12 | "binding": "DB", | |
| 13 | 13 | "database_name": "g1t-deployments", | |
| 14 | 14 | "database_id": "aa935a8f-845b-4132-8fa3-98f1afba1db5", | |
| 15 | − | "migrations_dir": "migrations", | |
| 16 | − | }, | |
| 15 | + | "migrations_dir": "migrations" | |
| 16 | + | } | |
| 17 | 17 | ], | |
| 18 | 18 | "services": [ | |
| 19 | 19 | { "binding": "REPOS", "service": "g1t-repos" }, | |
| ⋯ | |||
| 32 | 32 | { "binding": "EVENTS", "service": "g1t-events" }, | |
| 33 | 33 | // Observability: the token each project's apps send OpenTelemetry | |
| 34 | 34 | // with. Every app also names g1t-telemetry as its Tail Worker. | |
| 35 | − | { "binding": "TELEMETRY", "service": "g1t-telemetry" }, | |
| 35 | + | { "binding": "TELEMETRY", "service": "g1t-telemetry" } | |
| 36 | 36 | ], | |
| 37 | 37 | // Pull requests opened, pushed to, closed and merged; pushes to the | |
| 38 | 38 | // default branch. | |
| 39 | 39 | "queues": { | |
| 40 | − | "consumers": [{ "queue": "g1t-events-deployments", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 40 | + | "consumers": [{ "queue": "g1t-events-deployments", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 41 | 41 | }, | |
| 42 | 42 | // Builds that died, usage counts, idle previews, apps of ended plans, | |
| 43 | 43 | // and charging a month that is over. | |
| ⋯ | |||
| 64 | 64 | // D1 and other call), sent to this Workers Observability destination | |
| 65 | 65 | // on the account, which points at otel.g1t.sh/cloudflare/v1/traces | |
| 66 | 66 | // with the telemetry service's CLOUDFLARE_EXPORT_KEY. Empty: none. | |
| 67 | − | "TRACES_DESTINATION": "g1t-traces", | |
| 67 | + | "TRACES_DESTINATION": "g1t-traces" | |
| 68 | 68 | }, | |
| 69 | 69 | // Custom domains: hostname to app, written here and read by the | |
| 70 | 70 | // dispatcher (services/pages). Made by scripts/setup-custom-domains.sh. | |
| ⋯ | |||
| 75 | 75 | // Containers (edit), for applications and registry logins. Without it | |
| 76 | 76 | // nothing deploys. | |
| 77 | 77 | // Every log kept: few requests, and a failed deploy must be traceable. | |
| 78 | − | "observability": { "enabled": true, "head_sampling_rate": 1 }, | |
| 78 | + | "observability": { "enabled": true, "head_sampling_rate": 1 } | |
| 79 | 79 | } | |
| 14 | 14 | "binding": "DB", | |
| 15 | 15 | "database_name": "g1t-events", | |
| 16 | 16 | "database_id": "dd889749-0d01-4c94-8b9b-d789dec1c0e4", | |
| 17 | − | "migrations_dir": "migrations", | |
| 18 | − | }, | |
| 17 | + | "migrations_dir": "migrations" | |
| 18 | + | } | |
| 19 | 19 | ], | |
| 20 | 20 | "queues": { | |
| 21 | 21 | "producers": [ | |
| ⋯ | |||
| 38 | 38 | // Pages that cite code a merge changed, and projects' docs folders | |
| 39 | 39 | // (services/artifacts/src/staleness.ts). Create it once: | |
| 40 | 40 | // npx wrangler queues create g1t-events-docs | |
| 41 | − | { "binding": "SUBSCRIBER_DOCS", "queue": "g1t-events-docs" }, | |
| 41 | + | { "binding": "SUBSCRIBER_DOCS", "queue": "g1t-events-docs" } | |
| 42 | 42 | ], | |
| 43 | − | "consumers": [{ "queue": "g1t-events", "max_batch_size": 100, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 43 | + | "consumers": [{ "queue": "g1t-events", "max_batch_size": 100, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 44 | 44 | }, | |
| 45 | 45 | // Each workspace's audit log keeps as many days as billing says (7 free, | |
| 46 | 46 | // 90 on the plan, or what staff set), asked for over this binding. | |
| ⋯ | |||
| 54 | 54 | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| 55 | 55 | // Each new inbox item, told live in the person's tabs and pushed, and | |
| 56 | 56 | // what changed in each repository, for the pages open on it (services/notify). | |
| 57 | − | { "binding": "NOTIFY", "service": "g1t-notify" }, | |
| 57 | + | { "binding": "NOTIFY", "service": "g1t-notify" } | |
| 58 | 58 | ], | |
| 59 | 59 | // Once a day, audit entries older than AUDIT_MAX_DAYS are removed for | |
| 60 | 60 | // everyone (keep it at least billing's AUDIT_MAX_DAYS), then each | |
| ⋯ | |||
| 65 | 65 | "triggers": { "crons": ["41 3 * * *", "0 8 * * *"] }, | |
| 66 | 66 | "vars": { "AUDIT_MAX_DAYS": "400", "AUDIT_MIN_DAYS": "7" }, | |
| 67 | 67 | // Logs of a tenth of requests: every change in g1t is an event. | |
| 68 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 68 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 69 | 69 | } | |
| 18 | 18 | "binding": "DB", | |
| 19 | 19 | "database_name": "g1t", | |
| 20 | 20 | "database_id": "b7d49c93-2666-4006-a3c3-073a01838dc9", | |
| 21 | − | "migrations_dir": "migrations", | |
| 22 | − | }, | |
| 21 | + | "migrations_dir": "migrations" | |
| 22 | + | } | |
| 23 | 23 | ], | |
| 24 | 24 | "send_email": [{ "name": "EMAIL", "remote": true }], | |
| 25 | 25 | // Uploaded avatars, keyed by the SHA-256 of their bytes. Only this | |
| ⋯ | |||
| 37 | 37 | // audit log, which billing keeps (src/deletion.rs). | |
| 38 | 38 | { "binding": "REPOS", "service": "g1t-repos" }, | |
| 39 | 39 | { "binding": "PROJECTS", "service": "g1t-projects" }, | |
| 40 | − | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 40 | + | { "binding": "BILLING", "service": "g1t-billing" } | |
| 41 | 41 | ], | |
| 42 | 42 | // Signing in with GitHub (src/github.rs), through g1t's GitHub App. | |
| 43 | 43 | // Its client ID is public. Secrets: GITHUB_APP_CLIENT_SECRET, the app's | |
| ⋯ | |||
| 64 | 64 | "PROTECTED_ACCOUNTS": "", | |
| 65 | 65 | "GITHUB_APP_CLIENT_ID": "Iv23liZS94alfjIUn1eW", | |
| 66 | 66 | "INVITE_TTL_DAYS": "30", | |
| 67 | − | "INVITES_PER_USER": "20", | |
| 67 | + | "INVITES_PER_USER": "20" | |
| 68 | 68 | }, | |
| 69 | 69 | // Every log kept: sign-ins and tokens, where every failure matters. | |
| 70 | − | "observability": { "enabled": true, "head_sampling_rate": 1 }, | |
| 70 | + | "observability": { "enabled": true, "head_sampling_rate": 1 } | |
| 71 | 71 | } | |
| 16 | 16 | "binding": "DB", | |
| 17 | 17 | "database_name": "g1t-integrations", | |
| 18 | 18 | "database_id": "86c6c1a9-4192-42d8-8c59-8da8d4f99c5e", | |
| 19 | − | "migrations_dir": "migrations", | |
| 20 | − | }, | |
| 19 | + | "migrations_dir": "migrations" | |
| 20 | + | } | |
| 21 | 21 | ], | |
| 22 | 22 | "services": [ | |
| 23 | 23 | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| ⋯ | |||
| 25 | 25 | // Where a transferred repository is now, for moving its links. | |
| 26 | 26 | { "binding": "REPOS", "service": "g1t-repos" }, | |
| 27 | 27 | // An imported repository's project takes GitHub's description. | |
| 28 | − | { "binding": "PROJECTS", "service": "g1t-projects" }, | |
| 28 | + | { "binding": "PROJECTS", "service": "g1t-projects" } | |
| 29 | 29 | ], | |
| 30 | 30 | // Work starting on, and finishing, what an outside system is waiting on. | |
| 31 | 31 | // Every minute: sessions started on workspaces' Anthropic accounts are | |
| 32 | 32 | // followed until they end (src/agent_sessions.rs). | |
| 33 | 33 | "triggers": { "crons": ["* * * * *"] }, | |
| 34 | 34 | "queues": { | |
| 35 | − | "consumers": [ | |
| 36 | − | { "queue": "g1t-events-integrations", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }, | |
| 37 | − | ], | |
| 35 | + | "consumers": [{ "queue": "g1t-events-integrations", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 38 | 36 | }, | |
| 39 | 37 | "vars": { | |
| 40 | 38 | "API_URL": "https://api.g1t.sh", | |
| ⋯ | |||
| 50 | 48 | // GITHUB_APP_WEBHOOK_SECRET. Leave the slug empty to turn it off. | |
| 51 | 49 | "GITHUB_APP_ID": "5203641", | |
| 52 | 50 | "GITHUB_APP_SLUG": "g1t-sh", | |
| 53 | − | "GITHUB_APP_CLIENT_ID": "Iv23liZS94alfjIUn1eW", | |
| 51 | + | "GITHUB_APP_CLIENT_ID": "Iv23liZS94alfjIUn1eW" | |
| 54 | 52 | }, | |
| 55 | 53 | // Secret: INTEGRATIONS_KEY, 64 hex characters. Connections' secrets are | |
| 56 | 54 | // sealed with it; without it nothing can be connected. | |
| 57 | 55 | // Logs of a tenth of requests: every page and event asks it. | |
| 58 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 56 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 59 | 57 | } | |
| 11 | 11 | "placement": { "mode": "off" }, | |
| 12 | 12 | "services": [ | |
| 13 | 13 | // Who a username is, for the inbox's notices (they name people by username). | |
| 14 | − | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| 14 | + | { "binding": "IDENTITY", "service": "g1t-identity" } | |
| 15 | 15 | ], | |
| 16 | 16 | // One feed per person: their tabs' sockets (hibernating), their latest | |
| 17 | 17 | // notifications, unread counts and push subscriptions, in the object's | |
| ⋯ | |||
| 26 | 26 | "bindings": [ | |
| 27 | 27 | { "name": "FEEDS", "class_name": "Feed" }, | |
| 28 | 28 | { "name": "ROOMS", "class_name": "Room" }, | |
| 29 | − | { "name": "TOPICS", "class_name": "Topic" }, | |
| 30 | − | ], | |
| 29 | + | { "name": "TOPICS", "class_name": "Topic" } | |
| 30 | + | ] | |
| 31 | 31 | }, | |
| 32 | 32 | "migrations": [ | |
| 33 | 33 | { "tag": "v1", "new_sqlite_classes": ["Feed"] }, | |
| 34 | 34 | { "tag": "v2", "new_sqlite_classes": ["Room"] }, | |
| 35 | − | { "tag": "v3", "new_sqlite_classes": ["Topic"] }, | |
| 35 | + | { "tag": "v3", "new_sqlite_classes": ["Topic"] } | |
| 36 | 36 | ], | |
| 37 | 37 | // Web Push (RFC 8292): the public half of the VAPID key pair browsers | |
| 38 | 38 | // subscribe with, and who the push services may contact. The private | |
| ⋯ | |||
| 41 | 41 | // through Expo and need nothing here; the secret EXPO_ACCESS_TOKEN is | |
| 42 | 42 | // needed only once the Expo project turns on enhanced push security. | |
| 43 | 43 | "vars": { "VAPID_PUBLIC_KEY": "BBAhBFy-jgfEKm4IDEWKNN_5Nft9SjHqahXtpuZf1Aohop03XduSZgyat-hhDKXAP2hdtMv8yPX7TfqWyR6vJTo", "VAPID_SUBJECT": "https://g1t.sh" }, | |
| 44 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 44 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 45 | 45 | } | |
| 38 | 38 | { "binding": "PROJECTS", "service": "g1t-projects" }, | |
| 39 | 39 | // Whether rendering is paused across g1t (billing's platform_pause): | |
| 40 | 40 | // cards fall back to a static image while it is (src/paused.ts). | |
| 41 | − | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 41 | + | { "binding": "BILLING", "service": "g1t-billing" } | |
| 42 | 42 | ], | |
| 43 | 43 | // Cards drawn for a cache miss, per address (src/index.ts). Past it, | |
| 44 | 44 | // the brand card. Id and limit: RATE_LIMITS in packages/contracts. | |
| 45 | 45 | "ratelimits": [{ "name": "OG_RENDER_LIMIT", "namespace_id": "4501", "simple": { "limit": 60, "period": 60 } }], | |
| 46 | 46 | // Logs of a tenth of requests: every link shared is one. | |
| 47 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 47 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 48 | 48 | } |
| 24 | 24 | // Low, so the 429 can be seen by hand: about 30 requests a minute. | |
| 25 | 25 | "ratelimits": [ | |
| 26 | 26 | { "name": "ANONYMOUS_LIMIT", "namespace_id": "1", "simple": { "limit": 30, "period": 60 } }, | |
| 27 | − | { "name": "SIGNED_LIMIT", "namespace_id": "2", "simple": { "limit": 5000, "period": 60 } }, | |
| 27 | + | { "name": "SIGNED_LIMIT", "namespace_id": "2", "simple": { "limit": 5000, "period": 60 } } | |
| 28 | 28 | ], | |
| 29 | 29 | "services": [ | |
| 30 | 30 | { "binding": "IDENTITY", "service": "g1t-packages-stubs" }, | |
| 31 | 31 | { "binding": "REPOS", "service": "g1t-packages-stubs" }, | |
| 32 | 32 | { "binding": "EVENTS", "service": "g1t-packages-stubs" }, | |
| 33 | − | { "binding": "BILLING", "service": "g1t-packages-stubs" }, | |
| 33 | + | { "binding": "BILLING", "service": "g1t-packages-stubs" } | |
| 34 | 34 | ], | |
| 35 | 35 | "vars": { | |
| 36 | 36 | "BLOB_STORE": "r2", | |
| 37 | 37 | "MAX_REQUEST_BYTES": "100000000", | |
| 38 | 38 | "REGISTRY_HOST": "localhost:8790", | |
| 39 | 39 | "STORAGE_LIMITS": "on", | |
| 40 | − | "PACKAGES_TOKEN_SECRET": "a-local-secret-that-is-long-enough-to-sign", | |
| 40 | + | "PACKAGES_TOKEN_SECRET": "a-local-secret-that-is-long-enough-to-sign" | |
| 41 | 41 | }, | |
| 42 | − | "triggers": { "crons": ["37 * * * *"] }, | |
| 42 | + | "triggers": { "crons": ["37 * * * *"] } | |
| 43 | 43 | } |
| 4 | 4 | "main": "stubs.js", | |
| 5 | 5 | "compatibility_date": "2026-09-26", | |
| 6 | 6 | "compatibility_flags": ["nodejs_compat"], | |
| 7 | − | "vars": { "DEV_TOKEN": "g1t_devtoken", "MEMBER_TOKEN": "g1t_member", "OUTSIDER_TOKEN": "g1t_outsider", "FREE_PRIVATE_BYTES": "50000000" }, | |
| 7 | + | "vars": { "DEV_TOKEN": "g1t_devtoken", "MEMBER_TOKEN": "g1t_member", "OUTSIDER_TOKEN": "g1t_outsider", "FREE_PRIVATE_BYTES": "50000000" } | |
| 8 | 8 | } |
| 15 | 15 | "binding": "DB", | |
| 16 | 16 | "database_name": "g1t-packages", | |
| 17 | 17 | "database_id": "e541c872-a2a8-47aa-bfe8-419d0d50fe3c", | |
| 18 | − | "migrations_dir": "migrations", | |
| 19 | − | }, | |
| 18 | + | "migrations_dir": "migrations" | |
| 19 | + | } | |
| 20 | 20 | ], | |
| 21 | 21 | // Every package's files, by digest (src/store). Made by | |
| 22 | 22 | // `npx wrangler r2 bucket create g1t-packages`. | |
| ⋯ | |||
| 26 | 26 | // installations have neither binding, and no limit. | |
| 27 | 27 | "ratelimits": [ | |
| 28 | 28 | { "name": "ANONYMOUS_LIMIT", "namespace_id": "4101", "simple": { "limit": 300, "period": 60 } }, | |
| 29 | − | { "name": "SIGNED_LIMIT", "namespace_id": "4102", "simple": { "limit": 5000, "period": 60 } }, | |
| 29 | + | { "name": "SIGNED_LIMIT", "namespace_id": "4102", "simple": { "limit": 5000, "period": 60 } } | |
| 30 | 30 | ], | |
| 31 | 31 | "services": [ | |
| 32 | 32 | // Who a token or password belongs to. | |
| ⋯ | |||
| 37 | 37 | { "binding": "EVENTS", "service": "g1t-events" }, | |
| 38 | 38 | // Whether a workspace is on the plan, and its free package storage | |
| 39 | 39 | // (src/quota.rs); asked at most every five minutes per workspace. | |
| 40 | − | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 40 | + | { "binding": "BILLING", "service": "g1t-billing" } | |
| 41 | 41 | ], | |
| 42 | 42 | // BLOB_STORE: r2 (the BLOBS binding) or s3 (S3_ENDPOINT, S3_BUCKET, | |
| 43 | 43 | // S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_REGION, and optionally | |
| ⋯ | |||
| 62 | 62 | "MAX_REQUEST_BYTES": "100000000", | |
| 63 | 63 | "REGISTRY_HOST": "g1t.sh", | |
| 64 | 64 | "STORAGE_LIMITS": "on", | |
| 65 | − | "PROTECTED_WORKSPACES": "flagon-io", | |
| 65 | + | "PROTECTED_WORKSPACES": "flagon-io" | |
| 66 | 66 | }, | |
| 67 | 67 | // Every hour, expired uploads are let go, and blobs no version has used | |
| 68 | 68 | // for a day are deleted. | |
| ⋯ | |||
| 70 | 70 | // Workspaces renamed or deleted, repositories that change visibility, | |
| 71 | 71 | // are renamed, move or are purged. | |
| 72 | 72 | "queues": { | |
| 73 | − | "consumers": [{ "queue": "g1t-events-packages", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 73 | + | "consumers": [{ "queue": "g1t-events-packages", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 74 | 74 | }, | |
| 75 | 75 | // Logs of a tenth of requests: every registry pull is one. | |
| 76 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 76 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 77 | 77 | } | |
| 18 | 18 | { "pattern": "*.g1t.page/*", "zone_name": "g1t.page" }, | |
| 19 | 19 | // Custom domains (Cloudflare for SaaS is on for the zone). | |
| 20 | 20 | { "pattern": "*/*", "zone_name": "g1t.page" }, | |
| 21 | − | { "pattern": "g1t.page", "custom_domain": true }, | |
| 21 | + | { "pattern": "g1t.page", "custom_domain": true } | |
| 22 | 22 | ], | |
| 23 | 23 | // The apps, uploaded by the deployments service. | |
| 24 | 24 | "dispatch_namespaces": [{ "binding": "APPS", "namespace": "g1t-deployments" }], | |
| ⋯ | |||
| 28 | 28 | // project) goes to observability, which files it with the app's own. | |
| 29 | 29 | "tail_consumers": [{ "service": "g1t-telemetry" }], | |
| 30 | 30 | // Logs of a tenth of requests: every visit to a deployed site is one. | |
| 31 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 31 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 32 | 32 | } | |
| 12 | 12 | "binding": "DB", | |
| 13 | 13 | "database_name": "g1t-projects", | |
| 14 | 14 | "database_id": "0af698be-2b60-4bd9-aa93-81e84828e991", | |
| 15 | − | "migrations_dir": "migrations", | |
| 16 | − | }, | |
| 15 | + | "migrations_dir": "migrations" | |
| 16 | + | } | |
| 17 | 17 | ], | |
| 18 | 18 | "services": [ | |
| 19 | 19 | { "binding": "REPOS", "service": "g1t-repos" }, | |
| ⋯ | |||
| 27 | 27 | // address is set or changed and when a production deployment is | |
| 28 | 28 | // reported for it (src/index.ts). | |
| 29 | 29 | { "binding": "SCREENSHOTS", "service": "g1t-og", "entrypoint": "Screenshots" }, | |
| 30 | − | { "binding": "EVENTS", "service": "g1t-events" }, | |
| 30 | + | { "binding": "EVENTS", "service": "g1t-events" } | |
| 31 | 31 | ], | |
| 32 | 32 | // Uploaded production images, under `production/<sha256>` in the same | |
| 33 | 33 | // namespace as avatars, which the usercontent origin serves | |
| ⋯ | |||
| 36 | 36 | // A repository created is given its own project; a production | |
| 37 | 37 | // deployment reported from elsewhere asks for its screenshot. | |
| 38 | 38 | "queues": { | |
| 39 | − | "consumers": [{ "queue": "g1t-events-projects", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 39 | + | "consumers": [{ "queue": "g1t-events-projects", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 40 | 40 | }, | |
| 41 | 41 | // Logs of a tenth of requests: every repository page asks it. | |
| 42 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 42 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 43 | 43 | } | |
| 4 | 4 | "name": "g1t-gitstore", | |
| 5 | 5 | "main": "../../../deploy/self-host/workers/gitstore/index.js", | |
| 6 | 6 | "compatibility_date": "2026-09-26", | |
| 7 | − | "vars": { "GITSTORE_URL": "http://localhost:8799", "GITSTORE_SECRET": "dev-gitstore-secret-0123" }, | |
| 7 | + | "vars": { "GITSTORE_URL": "http://localhost:8799", "GITSTORE_SECRET": "dev-gitstore-secret-0123" } | |
| 8 | 8 | } |
| 26 | 26 | { "binding": "IDENTITY", "service": "g1t-repos-stubs" }, | |
| 27 | 27 | { "binding": "EVENTS", "service": "g1t-repos-stubs" }, | |
| 28 | 28 | { "binding": "SECURITY", "service": "g1t-repos-stubs" }, | |
| 29 | − | { "binding": "BILLING", "service": "g1t-repos-stubs" }, | |
| 29 | + | { "binding": "BILLING", "service": "g1t-repos-stubs" } | |
| 30 | 30 | ], | |
| 31 | 31 | "vars": { | |
| 32 | 32 | "GIT_OPERATIONS_FREE_CAP": "50000", | |
| ⋯ | |||
| 36 | 36 | "LARGE_PUSHES": "unscanned", | |
| 37 | 37 | "FORK_RETENTION_DAYS": "1", | |
| 38 | 38 | "GITSTORE_NAMESPACES": "{\"GITSTORE\":\"g1t\"}", | |
| 39 | − | "GITSTORE_NEW_REPOS": "", | |
| 40 | − | }, | |
| 39 | + | "GITSTORE_NEW_REPOS": "" | |
| 40 | + | } | |
| 41 | 41 | } | |
| 2 | 2 | { | |
| 3 | 3 | "name": "g1t-repos-stubs", | |
| 4 | 4 | "main": "stubs.js", | |
| 5 | − | "compatibility_date": "2026-09-26", | |
| 5 | + | "compatibility_date": "2026-09-26" | |
| 6 | 6 | } |
| 14 | 14 | "binding": "DB", | |
| 15 | 15 | "database_name": "g1t-repos", | |
| 16 | 16 | "database_id": "f9544c51-c3bf-4621-a96f-8a6d5cf24a97", | |
| 17 | − | "migrations_dir": "migrations", | |
| 18 | − | }, | |
| 17 | + | "migrations_dir": "migrations" | |
| 18 | + | } | |
| 19 | 19 | ], | |
| 20 | 20 | // The git store: Cloudflare Artifacts, bound as GITSTORE (so "artifacts" | |
| 21 | 21 | // in code means g1t's own Artifacts; the namespaces keep their names). | |
| ⋯ | |||
| 45 | 45 | // `npx wrangler r2 bucket create g1t-backups`. | |
| 46 | 46 | "r2_buckets": [ | |
| 47 | 47 | { "binding": "GIT_PACKS", "bucket_name": "g1t-git-packs" }, | |
| 48 | − | { "binding": "BACKUPS", "bucket_name": "g1t-backups" }, | |
| 48 | + | { "binding": "BACKUPS", "bucket_name": "g1t-backups" } | |
| 49 | 49 | ], | |
| 50 | 50 | "services": [ | |
| 51 | 51 | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| ⋯ | |||
| 57 | 57 | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 58 | 58 | // Rulesets: which hold for a push or another change to a branch or | |
| 59 | 59 | // tag, and where how they judged it is kept (src/rules.rs). | |
| 60 | − | { "binding": "WORK", "service": "g1t-work" }, | |
| 60 | + | { "binding": "WORK", "service": "g1t-work" } | |
| 61 | 61 | ], | |
| 62 | 62 | // A free workspace past this many git operations in a month is slowed | |
| 63 | 63 | // to this many an hour, never charged (src/git_ops.rs). It is billing's | |
| ⋯ | |||
| 113 | 113 | "LARGE_PUSHES": "unscanned", | |
| 114 | 114 | "FORK_RETENTION_DAYS": "1", | |
| 115 | 115 | "GITSTORE_NAMESPACES": "{\"GITSTORE\":\"g1t\"}", | |
| 116 | − | "GITSTORE_NEW_REPOS": "", | |
| 116 | + | "GITSTORE_NEW_REPOS": "" | |
| 117 | 117 | }, | |
| 118 | 118 | // Every hour, deleted repositories whose 30 days to be restored have | |
| 119 | 119 | // passed are purged, their git data with them (src/lifecycle.rs), and | |
| ⋯ | |||
| 126 | 126 | // A workspace renamed moves its repositories to the new slug; one | |
| 127 | 127 | // deleted purges the repositories it left in Recently deleted. | |
| 128 | 128 | "queues": { | |
| 129 | − | "consumers": [{ "queue": "g1t-events-repos", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 129 | + | "consumers": [{ "queue": "g1t-events-repos", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 130 | 130 | }, | |
| 131 | 131 | // What an anonymous clone can cost a repository's owner (src/limits.rs): | |
| 132 | 132 | // packs written to GIT_PACKS, and anonymous fetches the git store | |
| ⋯ | |||
| 134 | 134 | // packages/contracts. Without them, nothing is limited. | |
| 135 | 135 | "ratelimits": [ | |
| 136 | 136 | { "name": "PACK_FILL_LIMIT", "namespace_id": "4301", "simple": { "limit": 30, "period": 60 } }, | |
| 137 | − | { "name": "ANONYMOUS_FETCH_LIMIT", "namespace_id": "4302", "simple": { "limit": 120, "period": 60 } }, | |
| 137 | + | { "name": "ANONYMOUS_FETCH_LIMIT", "namespace_id": "4302", "simple": { "limit": 120, "period": 60 } } | |
| 138 | 138 | ], | |
| 139 | 139 | // Logs of a quarter of requests: every git request and page is one, so | |
| 140 | 140 | // keeping every one costs more than it tells, and a quarter still | |
| ⋯ | |||
| 143 | 143 | // (src/lib.rs, SLOW_RPC_MS) and a slow or partial About run | |
| 144 | 144 | // `{"about_run", "took_ms"}` (src/about.rs), so in the quarter kept they | |
| 145 | 145 | // can be counted by method without reading request lines. | |
| 146 | − | "observability": { "enabled": true, "head_sampling_rate": 0.25 }, | |
| 146 | + | "observability": { "enabled": true, "head_sampling_rate": 0.25 } | |
| 147 | 147 | } | |
| 30 | 30 | // --containers-rollout=immediate). Ones that are busy are given | |
| 31 | 31 | // this long, in seconds, to finish first, so shipping g1t does not | |
| 32 | 32 | // kill work in the middle. | |
| 33 | − | "rollout_active_grace_period": 7200, | |
| 33 | + | "rollout_active_grace_period": 7200 | |
| 34 | 34 | }, | |
| 35 | 35 | { | |
| 36 | 36 | // Workflow jobs with `runs-on: g1t-2core`: the standard machine. | |
| ⋯ | |||
| 38 | 38 | "image": "./Dockerfile", | |
| 39 | 39 | "instance_type": "standard-3", | |
| 40 | 40 | "max_instances": 10, | |
| 41 | − | "rollout_active_grace_period": 7200, | |
| 41 | + | "rollout_active_grace_period": 7200 | |
| 42 | 42 | }, | |
| 43 | 43 | { | |
| 44 | 44 | // Workflow jobs with `runs-on: g1t-4core`: 4 vCPU, 12 GiB, 20 GB. | |
| ⋯ | |||
| 46 | 46 | "image": "./Dockerfile", | |
| 47 | 47 | "instance_type": "standard-4", | |
| 48 | 48 | "max_instances": 10, | |
| 49 | − | "rollout_active_grace_period": 7200, | |
| 50 | − | }, | |
| 49 | + | "rollout_active_grace_period": 7200 | |
| 50 | + | } | |
| 51 | 51 | ], | |
| 52 | 52 | "durable_objects": { | |
| 53 | 53 | "bindings": [ | |
| 54 | 54 | { "name": "SANDBOX", "class_name": "AttemptSandbox" }, | |
| 55 | 55 | { "name": "SANDBOX_2CORE", "class_name": "Sandbox2Core" }, | |
| 56 | − | { "name": "SANDBOX_4CORE", "class_name": "Sandbox4Core" }, | |
| 57 | − | ], | |
| 56 | + | { "name": "SANDBOX_4CORE", "class_name": "Sandbox4Core" } | |
| 57 | + | ] | |
| 58 | 58 | }, | |
| 59 | 59 | "migrations": [ | |
| 60 | 60 | { "tag": "v1", "new_sqlite_classes": ["AttemptSandbox"] }, | |
| 61 | 61 | { "tag": "v2", "new_sqlite_classes": ["Sandbox2Core", "Sandbox4Core"] }, | |
| 62 | 62 | { "tag": "v3", "new_sqlite_classes": ["AgentComputer"] }, | |
| 63 | 63 | // Workspace agents' computers are gone, and with them their objects. | |
| 64 | − | { "tag": "v4", "deleted_classes": ["AgentComputer"] }, | |
| 64 | + | { "tag": "v4", "deleted_classes": ["AgentComputer"] } | |
| 65 | 65 | ], | |
| 66 | 66 | "services": [ | |
| 67 | 67 | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| ⋯ | |||
| 71 | 71 | { "binding": "ACTIONS", "service": "g1t-actions" }, | |
| 72 | 72 | { "binding": "DEPLOYMENTS", "service": "g1t-deployments" }, | |
| 73 | 73 | // The event bus: abuse.flagged, when a sandbox looks like it is mining. | |
| 74 | − | { "binding": "EVENTS", "service": "g1t-events" }, | |
| 74 | + | { "binding": "EVENTS", "service": "g1t-events" } | |
| 75 | 75 | ], | |
| 76 | 76 | // A sweep for lifecycle steps whose trigger was missed or whose sandbox | |
| 77 | 77 | // died before reporting, which also starts queued nightly backups. | |
| ⋯ | |||
| 79 | 79 | // Events it reacts to: a pull request that may now merge by its | |
| 80 | 80 | // repository's settings, a merge check or the merge queue to start. | |
| 81 | 81 | "queues": { | |
| 82 | − | "consumers": [{ "queue": "g1t-events-runner", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 82 | + | "consumers": [{ "queue": "g1t-events-runner", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 83 | 83 | }, | |
| 84 | 84 | "vars": { | |
| 85 | 85 | "CLOUDFLARE_ACCOUNT_ID": "1e6f2cffa3f445920836e8ebe446bb58", | |
| ⋯ | |||
| 101 | 101 | // backups the repos service queued, with at most BACKUPS_RUNNING at | |
| 102 | 102 | // once. "0" starts none. | |
| 103 | 103 | "BACKUPS_PER_SWEEP": "4", | |
| 104 | − | "BACKUPS_RUNNING": "6", | |
| 104 | + | "BACKUPS_RUNNING": "6" | |
| 105 | 105 | }, | |
| 106 | 106 | // Every log kept: few requests, and a failed run must be traceable. | |
| 107 | − | "observability": { "enabled": true, "head_sampling_rate": 1 }, | |
| 107 | + | "observability": { "enabled": true, "head_sampling_rate": 1 } | |
| 108 | 108 | } | |
| 16 | 16 | "database_name": "g1t-search", | |
| 17 | 17 | // Create with `wrangler d1 create g1t-search` and put its id here. | |
| 18 | 18 | "database_id": "9d04cbf3-cd02-4544-b3e3-2d78767e13bf", | |
| 19 | − | "migrations_dir": "migrations", | |
| 20 | − | }, | |
| 19 | + | "migrations_dir": "migrations" | |
| 20 | + | } | |
| 21 | 21 | ], | |
| 22 | 22 | "services": [ | |
| 23 | 23 | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| ⋯ | |||
| 25 | 25 | { "binding": "WORK", "service": "g1t-work" }, | |
| 26 | 26 | // Whether indexing is paused across g1t (billing's platform_pause): | |
| 27 | 27 | // backfills wait while it is. Read at most every 30 seconds. | |
| 28 | − | { "binding": "BILLING", "service": "g1t-billing" }, | |
| 28 | + | { "binding": "BILLING", "service": "g1t-billing" } | |
| 29 | 29 | ], | |
| 30 | 30 | "queues": { | |
| 31 | 31 | // Its own jobs: a push's files, a repository compared whole, a page | |
| ⋯ | |||
| 34 | 34 | "consumers": [ | |
| 35 | 35 | // The events that change what is indexed, to keep it current. | |
| 36 | 36 | { "queue": "g1t-events-search", "max_batch_size": 20, "max_batch_timeout": 2, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }, | |
| 37 | − | { "queue": "g1t-search-jobs", "max_batch_size": 1, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }, | |
| 38 | − | ], | |
| 37 | + | { "queue": "g1t-search-jobs", "max_batch_size": 1, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" } | |
| 38 | + | ] | |
| 39 | 39 | }, | |
| 40 | 40 | // Logs of a tenth of requests: every search is one. | |
| 41 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 41 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 42 | 42 | } | |
| 16 | 16 | "database_name": "g1t-security", | |
| 17 | 17 | // Create with `wrangler d1 create g1t-security` and put its id here. | |
| 18 | 18 | "database_id": "a7febbca-768a-4828-97b8-dd69b2636e1e", | |
| 19 | − | "migrations_dir": "migrations", | |
| 20 | − | }, | |
| 19 | + | "migrations_dir": "migrations" | |
| 20 | + | } | |
| 21 | 21 | ], | |
| 22 | 22 | "services": [ | |
| 23 | 23 | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| ⋯ | |||
| 28 | 28 | // The secrets a dependency update file's private registries name. | |
| 29 | 29 | { "binding": "ACTIONS", "service": "g1t-actions" }, | |
| 30 | 30 | // Security events (webhooks, the inbox) and audit entries. | |
| 31 | − | { "binding": "EVENTS", "service": "g1t-events" }, | |
| 31 | + | { "binding": "EVENTS", "service": "g1t-events" } | |
| 32 | 32 | ], | |
| 33 | 33 | // Pushes to a default branch (dependencies are read again), pushes too | |
| 34 | 34 | // large to scan first (scanned after they land), security updates' | |
| ⋯ | |||
| 36 | 36 | // failing checks (security updates move on), new repositories (their | |
| 37 | 37 | // history is scanned once) and renamed workspaces. | |
| 38 | 38 | "queues": { | |
| 39 | − | "consumers": [{ "queue": "g1t-events-security", "max_batch_size": 10, "max_batch_timeout": 5, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 39 | + | "consumers": [{ "queue": "g1t-events-security", "max_batch_size": 10, "max_batch_timeout": 5, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 40 | 40 | }, | |
| 41 | 41 | // Continues history scans a page at a time, and reads every | |
| 42 | 42 | // repository's dependencies again once a day (every 30 minutes); runs | |
| 43 | 43 | // version updates that are due and looks at their pull requests (every 5). | |
| 44 | 44 | "triggers": { "crons": ["*/30 * * * *", "*/5 * * * *"] }, | |
| 45 | 45 | "vars": { | |
| 46 | − | "SITE_URL": "https://g1t.sh", | |
| 46 | + | "SITE_URL": "https://g1t.sh" | |
| 47 | 47 | }, | |
| 48 | 48 | // Logs of a tenth of requests: every push and page asks it. | |
| 49 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 49 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 50 | 50 | } | |
| 18 | 18 | "durable_objects": { | |
| 19 | 19 | "bindings": [ | |
| 20 | 20 | { "name": "STORES", "class_name": "TelemetryStore" }, | |
| 21 | − | { "name": "METERS", "class_name": "TelemetryMeter" }, | |
| 22 | − | ], | |
| 21 | + | { "name": "METERS", "class_name": "TelemetryMeter" } | |
| 22 | + | ] | |
| 23 | 23 | }, | |
| 24 | 24 | "migrations": [ | |
| 25 | 25 | { "tag": "v1", "new_sqlite_classes": ["TelemetryStore"] }, | |
| 26 | − | { "tag": "v2", "new_sqlite_classes": ["TelemetryMeter"] }, | |
| 26 | + | { "tag": "v2", "new_sqlite_classes": ["TelemetryMeter"] } | |
| 27 | 27 | ], | |
| 28 | 28 | // What the deployments service notes under each app's hostname (its | |
| 29 | 29 | // project and deployment), read to file a request the dispatcher saw | |
| ⋯ | |||
| 44 | 44 | // packages/contracts. | |
| 45 | 45 | "ratelimits": [{ "name": "TELEMETRY_INGEST_LIMIT", "namespace_id": "4701", "simple": { "limit": 600, "period": 60 } }], | |
| 46 | 46 | // Its own logs: few, as every request to an app is a tail event here. | |
| 47 | − | "observability": { "enabled": true, "head_sampling_rate": 0.05 }, | |
| 47 | + | "observability": { "enabled": true, "head_sampling_rate": 0.05 } | |
| 48 | 48 | } | |
| 14 | 14 | "binding": "DB", | |
| 15 | 15 | "database_name": "g1t-webhooks", | |
| 16 | 16 | "database_id": "7da97a7e-b4a7-40e3-a129-3b78d654e9bb", | |
| 17 | − | "migrations_dir": "migrations", | |
| 18 | − | }, | |
| 17 | + | "migrations_dir": "migrations" | |
| 18 | + | } | |
| 19 | 19 | ], | |
| 20 | 20 | "services": [ | |
| 21 | 21 | { "binding": "REPOS", "service": "g1t-repos" }, | |
| 22 | − | { "binding": "IDENTITY", "service": "g1t-identity" }, | |
| 22 | + | { "binding": "IDENTITY", "service": "g1t-identity" } | |
| 23 | 23 | ], | |
| 24 | 24 | // Every event on the bus, to deliver to the webhooks that want it. | |
| 25 | 25 | "queues": { | |
| 26 | − | "consumers": [{ "queue": "g1t-events-webhooks", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 26 | + | "consumers": [{ "queue": "g1t-events-webhooks", "max_batch_size": 20, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 27 | 27 | }, | |
| 28 | 28 | // Every minute: retries. At 37 past each hour: deliveries older than a | |
| 29 | 29 | // fortnight forgotten (PURGE_CRON in src/lib.rs). | |
| ⋯ | |||
| 31 | 31 | // Secret: WEBHOOKS_KEY, 64 hex characters. Webhooks' signing secrets are | |
| 32 | 32 | // sealed with it; without it none can be made. | |
| 33 | 33 | // Logs of a tenth of requests: every event is a delivery to look up. | |
| 34 | − | "observability": { "enabled": true, "head_sampling_rate": 0.1 }, | |
| 34 | + | "observability": { "enabled": true, "head_sampling_rate": 0.1 } | |
| 35 | 35 | } | |
| 18 | 18 | "binding": "DB", | |
| 19 | 19 | "database_name": "g1t-work", | |
| 20 | 20 | "database_id": "f35a9022-e36b-4547-b596-9ab9d5f1c47a", | |
| 21 | − | "migrations_dir": "migrations", | |
| 22 | − | }, | |
| 21 | + | "migrations_dir": "migrations" | |
| 22 | + | } | |
| 23 | 23 | ], | |
| 24 | 24 | // Attachments' bytes (src/attachments.rs), in the namespace the | |
| 25 | 25 | // usercontent origin serves from (apps/web/workers/usercontent.ts), | |
| ⋯ | |||
| 32 | 32 | { "binding": "ACTIONS", "service": "g1t-actions" }, | |
| 33 | 33 | // The workspace's AI provider, which names sessions from what they | |
| 34 | 34 | // did (src/coordination/titles.rs, integrations' `ai_brief`). | |
| 35 | − | { "binding": "INTEGRATIONS", "service": "g1t-integrations" }, | |
| 35 | + | { "binding": "INTEGRATIONS", "service": "g1t-integrations" } | |
| 36 | 36 | ], | |
| 37 | 37 | "queues": { | |
| 38 | − | "consumers": [{ "queue": "g1t-events-work", "max_batch_size": 100, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }], | |
| 38 | + | "consumers": [{ "queue": "g1t-events-work", "max_batch_size": 100, "max_batch_timeout": 1, "max_retries": 3, "dead_letter_queue": "g1t-events-dlq" }] | |
| 39 | 39 | }, | |
| 40 | 40 | // Logs of a quarter of requests: every work item and pull request page asks | |
| 41 | 41 | // it, so keeping every one costs more than it tells, and a quarter | |
| 42 | 42 | // still catches a rare error within hours. Repos, which it asks most, | |
| 43 | 43 | // logs its slow answers as fields (`answered_ms`, services/repos/src/lib.rs). | |
| 44 | − | "observability": { "enabled": true, "head_sampling_rate": 0.25 }, | |
| 44 | + | "observability": { "enabled": true, "head_sampling_rate": 0.25 } | |
| 45 | 45 | } | |
Comments
Sign in to comment.