Skip to content

Commit 03bd20f

Browse files
docs(cli-v3): document offline-build flow
Write build-offline.md describing TRIGGER_INDEX_OFFLINE + containerfile-module + offline CliApiClient shim + index-metadata.json copy pattern. Used by air-gapped operators (Apollo / Foundry) who can't reach the trigger.dev API at build time. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent c2a7629 commit 03bd20f

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Offline-build flow (`TRIGGER_INDEX_OFFLINE=1`)
2+
3+
This document covers the build pipeline for operators who need to build a
4+
tasks image **without calling out to a live trigger.dev API at build time**
5+
— e.g. air-gapped / regulated build environments (Apollo Foundry,
6+
GameWarden, GovCloud single-tenant deploys) where the build host can't
7+
reach the webapp the image will eventually be deployed against.
8+
9+
## How it works
10+
11+
Two pieces compose:
12+
13+
1. `TRIGGER_INDEX_OFFLINE=1` switches the in-image indexer to a stub
14+
`CliApiClient` that writes deployment metadata to disk instead of
15+
POST-ing it to the API. See
16+
[`packages/cli-v3/src/entryPoints/managed-index-controller.ts`](../src/entryPoints/managed-index-controller.ts)
17+
(`createOfflineCliApiClient`). The shim implements only the three
18+
methods that `indexDeployment` actually calls:
19+
- `getEnvironmentVariables()` → returns `{}` (no project env vars
20+
reachable at build time)
21+
- `createDeploymentBackgroundWorker(_id, body)` → writes
22+
`index-metadata.json` to `process.cwd()`
23+
- `failDeployment(_id, body)` → writes `index-error.json`
24+
2. The build script (a small `build.mjs` driven by `@trigger.dev/cli-v3`'s
25+
`internal` subpath — see [`packages/cli-v3/src/internal.ts`](../src/internal.ts))
26+
passes `offlineIndex: true` to `buildImage` and `--containerfile-module=<path>`
27+
to use a custom Containerfile generator. See
28+
[`packages/cli-v3/src/deploy/buildImage.ts`](../src/deploy/buildImage.ts)
29+
when `offlineIndex: true`, the generated Containerfile sets
30+
`ARG TRIGGER_INDEX_OFFLINE` and forwards it as a build arg into the
31+
indexer stage; the final stage copies `/app/index-metadata.json` into
32+
the runtime image at `/app/`.
33+
34+
The metadata gets baked into the runtime image, then re-played against
35+
the real webapp API later by a separate **register** process running
36+
inside the cluster (where it _can_ reach the webapp). The register
37+
process uses the same image, reads `/app/index-metadata.json`, hits the
38+
real webapp API via `getProjectClient`, and finalizes the deployment.
39+
40+
## Operator responsibilities
41+
42+
- Provide a `containerfileModule` if the default Containerfile doesn't fit
43+
(e.g. base on UBI / chainguard / a FIPS-validated runtime). The module's
44+
job is to emit the multi-stage Containerfile text that invokes the
45+
indexer stage with `TRIGGER_INDEX_OFFLINE=1` and copies
46+
`/app/index-metadata.json` into the final image.
47+
- Run your `build.mjs` equivalent on the build host (no API access
48+
required). The output is just the tasks image pushed to your registry.
49+
- Run your `register.mjs` equivalent on the deploy host (Kubernetes Job /
50+
systemd unit / etc.) using **the same image**. It reads
51+
`/app/index-metadata.json` and re-issues `createDeploymentBackgroundWorker`
52+
against the live webapp.
53+
54+
## Example (GovSignals)
55+
56+
The GovSignals umbrella ships a worked example of this pattern in its
57+
consumer repo (not in this chart):
58+
59+
- `infrastructure/containers/dockerfiles/trigger-dev/tasks/build.mjs`
60+
build-host entry point (calls `loadConfig``buildWorker``buildImage`
61+
with `offlineIndex: true` and a custom `containerfile.mjs`).
62+
- `infrastructure/containers/dockerfiles/trigger-dev/tasks/containerfile.mjs`
63+
— the operator-supplied Containerfile generator.
64+
- `infrastructure/containers/dockerfiles/trigger-dev/register-tasks/register.mjs`
65+
— in-cluster `register-tasks` Job that re-plays the indexed payload
66+
against the live webapp.
67+
68+
A reference implementation, not a supported public API.
69+
70+
## Caveats
71+
72+
- Project env vars are **not** available at build time in offline mode.
73+
Any task whose indexing step depends on a project env var will index
74+
with `{}`. If your tasks need env vars at index time, use the online
75+
flow.
76+
- The offline shim returns synthetic `id: "offline"` / `version: "offline"`
77+
from `createDeploymentBackgroundWorker`. Anything in your build pipeline
78+
reading those fields must be aware that the real id/version is assigned
79+
later, by the register step.
80+
- `TRIGGER_INDEX_OFFLINE=1` only affects the indexer stage. The rest of
81+
the runtime (the tasks themselves) still talks to the live API at
82+
runtime as normal.

0 commit comments

Comments
 (0)