Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 40 additions & 31 deletions apps/gittensory-ui/src/routes/docs.self-hosting-rees.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,51 @@ function SelfHostingRees() {
]}
/>

<h2>Engine configuration</h2>
<h2>Run REES</h2>
<p>
REES runs as its own small HTTP service, separate from the engine. The simplest way to run
it is in-network alongside the engine, using the docker-compose stack in the repo root — no
separate hosting to manage, and nothing published to the host (the engine reaches it only
over the compose network):
</p>
<CodeBlock lang="bash" code={`docker compose --profile rees up -d`} />
<p>Point the engine at it and generate a fresh shared secret:</p>
<CodeBlock
filename=".env"
code={`GITTENSORY_REVIEW_REPOS=owner/repo
GITTENSORY_REVIEW_ENRICHMENT=true
REES_URL=http://rees:8080
REES_SHARED_SECRET=<generate-a-new-shared-secret>`}
/>
<p>
No <code>SENTRY_*</code> variables are required for a working local REES. Set them only if
you want REES error reporting — see "Service configuration" below for the variables REES
reads, and add them for the <code>rees</code> service through a{" "}
<code>docker-compose.override.yml</code> rather than the root <code>.env</code>: REES reads
the same <code>SENTRY_DSN</code> name the main engine uses, so forwarding the whole{" "}
<code>.env</code> file would point REES's error reporting at the engine's Sentry project
instead of a dedicated one.
</p>

<h3>Pointing at an external or managed instance instead</h3>
<p>
If you'd rather run REES elsewhere — a separate host, a managed provider, or one shared
instance across multiple self-hosted installs — point <code>REES_URL</code> at it directly
and skip the <code>rees</code> compose profile entirely. Generate a dedicated shared secret
for that instance; never reuse a secret across two different REES instances you run:
</p>
<CodeBlock
filename=".env"
code={`GITTENSORY_REVIEW_REPOS=owner/repo
GITTENSORY_REVIEW_ENRICHMENT=true
REES_URL=https://enrichment.example.internal
REES_SHARED_SECRET=<shared-secret>
REES_TIMEOUT_MS=8000
REES_SHARED_SECRET=<shared-secret>`}
/>

<h3>Common options (either path)</h3>
<CodeBlock
filename=".env"
code={`REES_TIMEOUT_MS=8000
REES_PROFILE=balanced
REES_FORWARD_GITHUB_TOKEN=false
REES_ANALYZERS=all`}
Expand Down Expand Up @@ -115,34 +152,6 @@ REES_ANALYZERS=all`}
]}
/>

<h2>Self-hosting REES</h2>
<p>
The docker-compose stack in the repo root can run REES for you instead of pointing{" "}
<code>REES_URL</code> at a managed or external instance. Start it alongside the engine with
the <code>rees</code> profile:
</p>
<CodeBlock lang="bash" code={`docker compose --profile rees up -d`} />
<p>
REES is not published to the host — the engine reaches it only over the compose network.
Point the engine at it and generate a fresh shared secret; do not reuse a secret from any
other REES instance (for example a managed Railway deployment) you also run:
</p>
<CodeBlock
filename=".env"
code={`GITTENSORY_REVIEW_ENRICHMENT=true
REES_URL=http://rees:8080
REES_SHARED_SECRET=<generate-a-new-shared-secret>`}
/>
<p>
No <code>SENTRY_*</code> variables are required for a working local REES. Set them only if
you want REES error reporting — see "Service configuration" below for the variables REES
reads, and add them for the <code>rees</code> service through a{" "}
<code>docker-compose.override.yml</code> rather than the root <code>.env</code>: REES reads
the same <code>SENTRY_DSN</code> name the main engine uses, so forwarding the whole{" "}
<code>.env</code> file would point REES's error reporting at the engine's Sentry project
instead of a dedicated one.
</p>

<h2>Disable cleanly</h2>
<p>
Set <code>GITTENSORY_REVIEW_ENRICHMENT=false</code> to turn off REES for the whole instance.
Expand Down
26 changes: 17 additions & 9 deletions review-enrichment/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Review-enrichment service (REES)

A standalone Railway microservice that produces a structured **review brief** for the gittensory review engine.
A standalone microservice that produces a structured **review brief** for the gittensory review engine. Run it
in-network alongside a self-hosted engine via the repo-root `docker-compose --profile rees` service (the simplest
path, no separate hosting to manage — see the [self-hosting REES docs](https://gittensory.aethereal.dev/docs/self-hosting-rees)),
or deploy it as its own service on any platform that can run a Dockerfile-based Node service — see
[Deploy (Railway)](#deploy-railway) below for one example.

The engine reviews PRs by running a headless `claude --print` subprocess with `Bash`/`WebFetch` disallowed and **no
repo checkout**, so it cannot run a linter, hit a CVE database, resolve a dependency tree, or query git history. REES
Expand All @@ -12,7 +16,7 @@ treats any timeout/error as "no brief" and proceeds.

| Route | Purpose |
| ----------------- | ------------------------------------------------------------------------------- |
| `GET /health` | Liveness (Railway healthcheck). |
| `GET /health` | Liveness health check. |
| `GET /ready` | Readiness. |
| `POST /v1/ping` | Auth check only — the engine calls this at startup to verify the shared secret matches. Returns `{ok:true}` or 401. |
| `POST /v1/enrich` | `Authorization: Bearer <REES_SHARED_SECRET>` → `EnrichRequest` → `ReviewBrief`. |
Expand Down Expand Up @@ -160,9 +164,9 @@ category, skipped/capped work counts by category, and elapsed time. Never put re
comments, tokens, private configs, or raw external payloads into cache categories, metric keys, Sentry tags, or logs.

The engine also sends `budget.timeoutMs` with one second of headroom below `REES_TIMEOUT_MS`, so REES can return a
partial/degraded brief before the caller aborts the HTTP request. If Railway is still running an older REES build,
temporarily raise the engine-side `REES_TIMEOUT_MS` above the REES analyzer budget, or set `REES_ANALYZERS` to a
bounded list that excludes `history` until the budget-aware build is deployed.
partial/degraded brief before the caller aborts the HTTP request. If your REES deployment is still running an older
build, temporarily raise the engine-side `REES_TIMEOUT_MS` above the REES analyzer budget, or set `REES_ANALYZERS` to
a bounded list that excludes `history` until the budget-aware build is deployed.

## Run locally

Expand All @@ -176,10 +180,14 @@ curl -XPOST localhost:8080/v1/enrich -H 'authorization: Bearer dev' \

## Deploy (Railway)

Separate service from the engine. Set **Root Directory = `review-enrichment`** so Railway reads this folder's
`railway.json` + `Dockerfile`. Set `REES_SHARED_SECRET` (same value the engine holds) as a service variable — never
commit it. The engine reaches the service over Railway **private networking** (`<service>.railway.internal`); no public
domain is required.
For a self-hosted engine, `docker compose --profile rees up -d` from the repo root (see the
[self-hosting REES docs](https://gittensory.aethereal.dev/docs/self-hosting-rees)) is the simplest path — no
separate service to host. If you'd rather run REES on its own outside that compose network, it's a plain
Dockerfile-based Node service and can go anywhere that builds one; Railway is one option this repo has release
tooling for (the Sentry/source-map wiring below). Point **Root Directory = `review-enrichment`** at a `railway.json`
you add there (see Railway's Dockerfile-builder docs) and set `REES_SHARED_SECRET` (same value the engine holds) as a
service variable — never commit it. The engine reaches the service over Railway **private networking**
(`<service>.railway.internal`); no public domain is required.

## Sentry releases and source maps

Expand Down
18 changes: 0 additions & 18 deletions review-enrichment/railway.json

This file was deleted.

Loading