Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
141 linesCodeBlameRaw
1{
2 "$schema": "../../node_modules/wrangler/config-schema.json",
3 "name": "g1t-repos",
4 "account_id": "1e6f2cffa3f445920836e8ebe446bb58",
5 "compatibility_date": "2026-09-26",
6 // Runs next to its database: a request makes several queries in turn,
7 // and each would otherwise cross the distance to it.
8 "placement": { "mode": "off" },
9 "main": "build/index.js",
10 "build": { "command": "node ../../scripts/build-rust-worker.mjs" },
11 "workers_dev": false,
12 "d1_databases": [
13 {
14 "binding": "DB",
15 "database_name": "g1t-repos",
16 "database_id": "f9544c51-c3bf-4621-a96f-8a6d5cf24a97",
17 "migrations_dir": "migrations"
18 }
19 ],
20 // The git store: Cloudflare Artifacts, bound as GITSTORE (so "artifacts"
21 // in code means g1t's own Artifacts; the namespaces keep their names).
22 // Every repository made before sharding is in `g1t`.
23 // More namespaces (src/shards.rs) are more bindings, named in
24 // GITSTORE_NAMESPACES below, e.g.
25 // { "binding": "GITSTORE_1", "namespace": "g1t-us-1" },
26 // { "binding": "GITSTORE_EU", "namespace": "g1t-eu" }
27 // and new repositories go to those named in GITSTORE_NEW_REPOS. A
28 // namespace's jurisdiction is set when it is made, never in the binding.
29 "artifacts": [{ "binding": "GITSTORE", "namespace": "g1t" }],
30 // Shared between isolates (src/shared.rs): the git store's credentials
31 // (src/store.rs) and the ref listings git asks for first
32 // (src/refs_cache.rs), every value sealed with the REPOS_KEY secret (64
33 // hex characters). Without the binding or the secret each isolate keeps
34 // only its own. Made by `npx wrangler kv namespace create g1t-repos-git-cache`:
35 "kv_namespaces": [{ "binding": "GIT_CACHE", "id": "be765052d0124c2a935b3db4dff99f1f" }],
36 // Packs for fresh clones (wants and no haves), kept under the
37 // repository's refs version so the next clone of the same commit skips
38 // the git store (src/pack_cache.rs). Without the binding nothing is
39 // kept. Made with a lifecycle rule that deletes packs after 7 days and
40 // unfinished uploads after 1:
41 // npx wrangler r2 bucket create g1t-git-packs
42 // npx wrangler r2 bucket lifecycle add g1t-git-packs expire-packs packs/ --expire-days 7 --abort-multipart-days 1
43 // Nightly backups go to the second bucket: a git bundle per repository
44 // and a manifest of each chain (src/backups.rs). Made by
45 // `npx wrangler r2 bucket create g1t-backups`.
46 "r2_buckets": [
47 { "binding": "GIT_PACKS", "bucket_name": "g1t-git-packs" },
48 { "binding": "BACKUPS", "bucket_name": "g1t-backups" }
49 ],
50 "services": [
51 { "binding": "IDENTITY", "service": "g1t-identity" },
52 { "binding": "EVENTS", "service": "g1t-events" },
53 // Push protection asks which secrets were allowed, and records the rest.
54 { "binding": "SECURITY", "service": "g1t-security" },
55 // Whether a workspace far past its free git operations is on the
56 // plan (src/git_ops.rs); asked only then.
57 { "binding": "BILLING", "service": "g1t-billing" },
58 // Rulesets: which hold for a push or another change to a branch or
59 // tag, and where how they judged it is kept (src/rules.rs).
60 { "binding": "WORK", "service": "g1t-work" }
61 ],
62 // A free workspace past this many git operations in a month is slowed
63 // to this many an hour, never charged (src/git_ops.rs). It is billing's
64 // GIT_OPERATIONS_INCLUDED, the amount free for every workspace: past it,
65 // a workspace on the plan pays at cost plus 20% and is never slowed.
66 // FREE_PRIVATE_STORAGE_BYTES: a free workspace's private repositories may
67 // hold this much (1 GB); past it, pushes to them stop. Billing reads the
68 // same amount. FREE_PUBLIC_STORAGE_BYTES: a free workspace's public
69 // repositories may hold this much together (5 GB); past it, pushes to
70 // them stop. 0 is no cap.
71 //
72 // The git store:
73 // REPO_STORAGE_LIMIT_BYTES: pushes stop before a repository holds this
74 // much; the store holds 1 GB (src/pack_limits.rs).
75 // LARGE_PUSHES: a push too large to scan for secrets (24 MiB) is
76 // "refuse"d, or streamed to the store "unscanned" (src/git_http.rs).
77 // FORK_RETENTION_DAYS: a pull request working copy is removed this long
78 // after its pull request merges or closes (src/forks.rs).
79 // GITSTORE_NAMESPACES: JSON, each Artifacts binding and its namespace;
80 // GITSTORE_NEW_REPOS: comma-separated namespaces new repositories go
81 // to, the emptier healthy ones first (empty: g1t); GITSTORE_EU_NAMESPACE:
82 // where workspaces that keep their data in the EU put new repositories,
83 // and unset until that namespace exists (src/shards.rs);
84 // GITSTORE_NAMESPACE_LIMITS (optional): JSON, {"g1t": {"max_repos": N}},
85 // past which a namespace takes no new repositories while another can.
86 //
87 // The fallback git store (src/fallback.rs), all
88 // unset: nothing changes. Set as secrets, so switching takes no build:
89 // npx wrangler secret put GIT_FALLBACK_URL # https://gitstore.example
90 // npx wrangler secret put GIT_FALLBACK_SECRET # the store's API secret
91 // npx wrangler secret put GIT_FALLBACK_NAMESPACES # g1t (or g1t,g1t-us-1, or *)
92 // GIT_FALLBACK_WRITES: unset or "refuse" keeps a switched namespace
93 // read-only; "allow" lets it take pushes (reconcile them afterwards).
94 // GITSTORE_REMOTE_BASE (optional): where remotes start,
95 // https://<account>.artifacts.cloudflare.net/git, so a new isolate
96 // needs no info() call before its first credential (src/store.rs).
97 //
98 // Backups (src/backups.rs):
99 // BACKUP_STORE: r2 (the BACKUPS bucket) or s3 (BACKUP_S3_BUCKET on the
100 // installation's S3_ENDPOINT, as self-hosting uses).
101 // BACKUPS_PER_NIGHT: how many repositories one night queues, those
102 // longest since their last backup first.
103 // BACKUP_FULL_EVERY: incremental bundles before a full one again.
104 "vars": {
105 "BACKUP_STORE": "r2",
106 "BACKUPS_PER_NIGHT": "200",
107 "BACKUP_FULL_EVERY": "30",
108 "GIT_OPERATIONS_FREE_CAP": "50000",
109 "GIT_OPERATIONS_FREE_HOURLY": "60",
110 "FREE_PRIVATE_STORAGE_BYTES": "1000000000",
111 "FREE_PUBLIC_STORAGE_BYTES": "5000000000",
112 "REPO_STORAGE_LIMIT_BYTES": "950000000",
113 "LARGE_PUSHES": "unscanned",
114 "FORK_RETENTION_DAYS": "1",
115 "GITSTORE_NAMESPACES": "{\"GITSTORE\":\"g1t\"}",
116 "GITSTORE_NEW_REPOS": ""
117 },
118 // Every hour, deleted repositories whose 30 days to be restored have
119 // passed are purged, their git data with them (src/lifecycle.rs), and
120 // pull request working copies past FORK_RETENTION_DAYS are removed
121 // (src/forks.rs), and a repository queued to move to another namespace
122 // is moved (src/moves.rs). At 02:53 UTC, the repositories whose refs moved since
123 // their last backup are queued for one (src/backups.rs, BACKUP_CRON);
124 // the runner's sweep starts them a few at a time.
125 "triggers": { "crons": ["23 * * * *", "53 2 * * *"] },
126 // A workspace renamed moves its repositories to the new slug; one
127 // deleted purges the repositories it left in Recently deleted.
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" }]
130 },
131 // What an anonymous clone can cost a repository's owner (src/limits.rs):
132 // packs written to GIT_PACKS, and anonymous fetches the git store
133 // answers, each per repository. Ids and limits: RATE_LIMITS in
134 // packages/contracts. Without them, nothing is limited.
135 "ratelimits": [
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 } }
138 ],
139 // Logs of a tenth of requests: every git request and page is one.
140 "observability": { "enabled": true, "head_sampling_rate": 0.1 }
141}