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.

106 linesCodeBlameRaw
1---
2title: How g1t ships
3description: The monorepo's layout, how each kind of unit is built, how a push to main becomes a staged deploy on g1t's own Actions, the tests that guard it, and how this section stays true.
4---
5
6import Aside from '../../../components/Aside.astro';
7import Diagram from '../../../components/Diagram.astro';
8
9g1t is built on g1t. Its source is at
10[g1t.sh/flagon-io/g1t](https://g1t.sh/flagon-io/g1t), every change is a
11pull request with required checks, and its own workflows deploy it.
12
13## The repository
14
15| Folder | Holds |
16| --- | --- |
17| `apps/` | What people open: `web` (the site), `api`, `status`, `sudo`, `docs`, and the `desktop` (Tauri) and `mobile` (Expo) apps |
18| `services/` | The services, one folder each, with their `wrangler.jsonc` and `migrations` |
19| `crates/` | Shared Rust: `contracts`, `kit`, `rules`, `scan`, `secrets`, `blobstore`, `actions`, the `runner` binary and the `g1t` CLI |
20| `packages/` | Shared TypeScript: `contracts` and `theme` (the design tokens) |
21| `deploy/` | `stack.jsonc`, the inventory; `self-host`, the Docker Compose installation; `runner` and `sandbox`, the self-hosted runner's images |
22| `scripts/` | `deploy.mjs` and its helpers, releases, operations |
23| `plugins/` | The [Claude Code plugin](/guides/claude-code-plugin/), and setup for other coding agents |
24| `.g1t/workflows/` | CI, deploys and releases, run by g1t Actions |
25| `conformance/` | Checks that a job's environment matches what workflows expect |
26
27## Building
28
29`deploy/stack.jsonc` gives each unit a kind, and each kind builds its own
30way:
31
32| Kind | Built by | Units |
33| --- | --- | --- |
34| `rust-worker` | `scripts/build-rust-worker.mjs`: `worker-build` to WebAssembly, then `wasm-opt` | The Rust services and `apps/api` |
35| `ts-worker` | Wrangler's bundler | The TypeScript services |
36| `react-router` | `vite build`, then Wrangler | `apps/web`, `apps/sudo` |
37| `astro` | `astro build` | `apps/docs` |
38
39The runner's image is built in two layers: a large base with every
40toolchain, rebuilt only when its folder changes and recorded in
41`services/runner/base.json`, and a thin layer on top with the static
42`g1t-runner` binary.
43
44## Deploying
45
46<Diagram name="deploy-stages" />
47
48A push to `main` starts `.g1t/workflows/deploy.yml`, one run at a time,
49never cancelled:
50
511. **Check and plan.** The manifest is checked against every config and
52 `npm run test:deploy` runs. Beside it, `scripts/deploy.mjs plan` works
53 out which units changed since the commit each one is running.
542. **Migrations.** Every pending D1 migration, before any code.
553. **Core, edge, front.** The units in each stage deploy in parallel; a
56 stage starts only when the one before succeeded. A unit binds only to
57 units in its own stage or an earlier one, which a test checks, so new
58 code never calls a service that has not shipped yet.
594. **Smoke.** `scripts/ops/smoke.mjs` checks that sign-in and sign-up still
60 work, without making an account.
61
62Each run is one `production` deployment, shown on the commit as the
63`deploy / production` status. Only units whose inputs changed are
64deployed: their folder, or a crate or package they are built from, which
65`deploy.mjs` reads from Cargo's and npm's workspace metadata.
66[Deploy g1t to Cloudflare](/guides/deploy-to-cloudflare/) covers the
67tool, rollbacks and a first deploy.
68
69## Tests that guard the architecture
70
71Some of what this section describes is enforced by tests, so a change that
72breaks it fails CI:
73
74| Test | Fails when |
75| --- | --- |
76| `npm run test:deploy` | A unit is missing from `stack.jsonc`, a binding crosses stages the wrong way, a unit is missing from [How a self-hosted g1t runs](/guides/self-hosting-architecture/), or [Services and contracts](/architecture/services/) disagrees with a `wrangler.jsonc` |
77| `cargo test -p g1t-contracts` | The Rust and TypeScript access rules or scopes differ |
78| `cargo test -p g1t-api openapi` | The docs' copy of the OpenAPI document is out of date |
79| `app/lib/front-door-limits.test.ts` in `apps/web` | A `wrangler.jsonc` and `packages/contracts/src/rate-limits.ts` disagree |
80| `npm test` in `apps/docs` | A diagram's arrow names a box that does not exist, two boxes overlap, or a label does not fit its box |
81
82CI (`.g1t/workflows/ci.yml`) runs the Rust tests, the TypeScript checks and
83tests, and builds the site, sudo and these docs on every pull request.
84
85## Keeping this section true
86
87These pages describe the code on `main`. When you change how g1t is put
88together, change them in the same pull request:
89
90| If you change | Update |
91| --- | --- |
92| A service's bindings, storage or job | Its row in [Services and contracts](/architecture/services/#every-unit) and [Data and storage](/architecture/data/) |
93| A request's path, a limit or a deadline | [How a request is served](/architecture/requests/) |
94| An event type or a route to a subscriber | [Events](/architecture/events/) |
95| The push, fetch or merge path | [Git](/architecture/git/) and [Work and the merge queue](/architecture/work/) |
96| Sandboxes, runners or egress | [Actions, runners and sandboxes](/architecture/compute/) |
97| A new dependency on a Cloudflare product | Its port in [Data and storage](/architecture/data/#ports-and-adapters) |
98
99Diagrams are data, in `apps/docs/src/diagrams/architecture.ts`. Change the
100spec, and both the picture and the page's Markdown copy change with it.
101
102<Aside title="Run it yourself">
103 `docker compose -f deploy/self-host/docker-compose.yml up --build`
104 builds every unit from source and starts the site on port 8787 and the
105 API on 8789. [Run g1t yourself](/guides/self-hosting/) has the rest.
106</Aside>