---
name: railway-pr-deploy-triage
description: Triages failed Railway deployments for this multi-client monorepo using GitHub PR checks and the Railway CLI, mapping check names like talentco-api to the correct project and service. Use when a PR shows Railway status failures, deploy checks are red, or the user asks to debug Railway build vs deploy for yeshuman-agent-stack.
---

# Railway PR / deploy triage (multi-client)

## When to use

- A GitHub PR reports **Railway** status checks failed (e.g. `talentco - talentco-api`).
- Need to decide **build** (Nixpacks / `uv sync`) vs **deploy** (`preDeployCommand`, migrations, healthcheck, runtime).

## Project awareness (this repo)

- **Remote:** `yeshuman-io/yeshuman-agent-stack` (adjust if working in a fork).
- **Clients:** `yeshuman`, `bookedai`, `talentco`, `lumie`, `recruitrtech`, `lortsmith` (see [`AGENTS.md`](../../AGENTS.md)).
- **Railway services:** `<client>-api`, `<client>-ui`, `<client>-db` (see [`.cursor/rules/railway.mdc`](../../.cursor/rules/railway.mdc)).
- **Project slug:** PR check context / `gh` output is a **hint**; confirm the **actual** `--project` value with `railway list`, the deployment **targetUrl**, or the dashboard. Slug may differ from the code handle (e.g. `lortsmith.cc`).

## Step 1: Get failures without Railway login (GitHub)

From the repo root:

```bash
gh pr checks <PR_NUMBER> --repo yeshuman-io/yeshuman-agent-stack
```

Or from a linked clone:

```bash
gh pr checks <PR_NUMBER>
```

- Each row is a **StatusContext**: `context` looks like **`lumie - lumie-api`** → **project handle** = first token, **service** = third token (normalize spaces).
- **`targetUrl`** is a deep link to that deployment on Railway (open in browser when logged into Railway).

Use this when **`railway` CLI is Unauthorized** or not linked yet.

## Step 2: Interpret same-PR pass/fail

If **one** client API fails (e.g. `talentco-api`) while **another** passes (`lumie-api`) on the **same commit**:

- **Dependency / image build** may still be OK (shared `api/` tree).
- Suspect **deploy-time** issues: `preDeployCommand` in [`api/railway.toml`](../../api/railway.toml), env vars, DB connectivity, seeds, **healthcheck**, or **preview-environment** differences for that client.
- Still pull **`railway logs --build`** for the failing service to rule out client-specific build config.

## Step 3: Railway CLI (after auth)

**Load local env first:** the CLI does not read dotenv files automatically. Follow [railway-cli-local-auth](../railway-cli-local-auth/SKILL.md) (e.g. `cd api` then `set -a && . ./.env.lortsmith && set +a` for Lort Smith).

Per [`.cursor/rules/railway.mdc`](../../.cursor/rules/railway.mdc): use **`RAILWAY_API_TOKEN`** (account token, **No workspace** scope) for `whoami` / `link` / `logs`. **`RAILWAY_TOKEN`** is for project deploy tokens (`railway up`), not general log viewing.

**Do not** paste **`railway variable list --json`** output into chat (secrets). Use dashboard or redacted checks.

If the token is in a **local gitignored env file** (e.g. `api/.env.*` — see [`api/env.example`](../../api/env.example)), load it in the shell **without printing values**:

```bash
cd api
set -a && . ./.env.lortsmith && set +a   # Lort Smith; or . ./.env.employment / . ./.env as needed
railway whoami
```

**Deployment ID from GitHub:** the Railway `targetUrl` on a failed PR check often includes `id=<DEPLOYMENT_UUID>`. Use it to fetch the exact failing deploy:

```bash
railway logs --build <DEPLOYMENT_UUID> --lines 200
railway logs --deployment <DEPLOYMENT_UUID> --lines 200
```

If **`--build` succeeds** but the status check still fails, the problem is almost always **deploy/runtime** (`preDeployCommand`, env, migrations, **Django system check**, healthcheck) — prioritize **`--deployment`** logs.

```bash
cd api
railway link --project <slug> --environment production --service <client>-api
railway logs --build
railway logs --deployment
railway logs
```

**PR / preview environments** may not be `production`; use **`railway open`** or the **`targetUrl`** from `gh pr checks` to confirm environment, then link or select the matching environment if the CLI supports it.

If **`railway logs` shows "No deployments found"**: switch service (`railway service <client>-api`), re-link, or use the dashboard (see `railway.mdc`).

## Step 4: Quick mapping from check name to `railway link`

| Example `context`   | Project (`--project`) | Service (`--service`) |
|----------------------|-------------------------|-------------------------|
| `talentco - talentco-api` | `talentco` (confirm slug) | `talentco-api`          |
| `lumie - lumie-ui`      | `lumie` (confirm slug)   | `lumie-ui`              |

## Known failure pattern (preview / PR deploys)

- **`corsheaders.E013` — Origin `'https://'` in CORS_ALLOWED_ORIGINS**: a CORS entry was built from an **empty host** (e.g. `https://${{service.RAILWAY_PUBLIC_DOMAIN}}` before the preview URL exists). Fix in **Railway variables** for that environment: remove the bad origin or set a full origin (e.g. the PR UI URL). Not an application dependency issue.

## Related

- Thin CLI + safety rules: [`.cursor/rules/railway.mdc`](../../.cursor/rules/railway.mdc)
- Extended ops (volumes, media): [`.cursor/rules/railway-management.mdc`](../../.cursor/rules/railway-management.mdc)
- Email / Resend vars: [railway-email-configuration](../railway-email-configuration/SKILL.md)
