feat(alerts): a deploy_failed alert now says why #493

Merged
gmackie merged 1 commit from feat/deploy-failure-alerts into main 2026-08-27 19:46:27 +00:00
Owner

Eight deploy_failed alerts were firing at once, every one of them saying the same thing:

Deployment failed for npm-registry → production

Telling them apart meant querying journal_output in the database by hand. They turned out to be six unrelated causes — and npm-registry had been red since 2026-08-13 behind that message, on a Nix hash mismatch three lines from the end of a log nobody had a reason to open (#491 fixes that one).

The actionable line is always in the journal. This puts it in the alert:

App Alert now reads
npm-registry nix hash mismatch in forgegraph-registry-pnpm-deps.drv (pnpmDeps hash is stale)
playtrek ERR_PNPM_NO_OFFLINE_TARBALL (pnpmDeps hash is stale)
latchflow-beta cp: cannot stat 'wrangler.beta.jsonc': No such file or directory
gt-ops-edge …frappe-edge-proxy.service failed to start
linear-clone better-sqlite3 native install failed
jobs-pulse \wrangler deploy --name jobs-pulse-onebox` exited 1`

deployFailureCause scans the last 4KB for known shapes, most specific first, and otherwise falls back to the last line carrying signal — skipping the git progress chatter these logs are mostly made of (remote: Enumerating objects…). Output is clamped to 180 chars so an alert stays readable.

No journal yields the old message unchanged, so nothing regresses where there is nothing to say.

11 tests, each fixture taken from one of the eight real failures rather than invented. Typecheck clean.

🤖 Generated with Claude Code

Eight `deploy_failed` alerts were firing at once, every one of them saying the same thing: > Deployment failed for npm-registry → production Telling them apart meant querying `journal_output` in the database by hand. They turned out to be **six unrelated causes** — and npm-registry had been red **since 2026-08-13** behind that message, on a Nix hash mismatch three lines from the end of a log nobody had a reason to open (#491 fixes that one). The actionable line is always in the journal. This puts it in the alert: | App | Alert now reads | |---|---| | npm-registry | `nix hash mismatch in forgegraph-registry-pnpm-deps.drv (pnpmDeps hash is stale)` | | playtrek | `ERR_PNPM_NO_OFFLINE_TARBALL (pnpmDeps hash is stale)` | | latchflow-beta | `cp: cannot stat 'wrangler.beta.jsonc': No such file or directory` | | gt-ops-edge | `…frappe-edge-proxy.service failed to start` | | linear-clone | `better-sqlite3 native install failed` | | jobs-pulse | `\`wrangler deploy --name jobs-pulse-onebox\` exited 1` | `deployFailureCause` scans the last 4KB for known shapes, most specific first, and otherwise falls back to the last line carrying signal — skipping the git progress chatter these logs are mostly made of (`remote: Enumerating objects…`). Output is clamped to 180 chars so an alert stays readable. **No journal yields the old message unchanged**, so nothing regresses where there is nothing to say. 11 tests, each fixture taken from one of the eight real failures rather than invented. Typecheck clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(alerts): a deploy_failed alert now says why
Some checks failed
CI / gitleaks (pull_request) Successful in 6s
CI / storybook (pull_request) Successful in 1m24s
forgegraph/ci CI failed
CI / ci (pull_request) Failing after 1m27s
8560f97a0f
The alert read only 'Deployment failed for x -> y'. Eight were firing at once
and telling them apart meant querying journal_output by hand -- they turned
out to be six unrelated causes. npm-registry had been red for two weeks behind
that message, on a Nix hash mismatch three lines from the end of a log nobody
had reason to open.

deployFailureCause scans the log tail for known shapes and otherwise falls
back to the last line carrying signal, skipping git progress chatter. No
journal still yields the old message, so nothing regresses.
gmackie force-pushed feat/deploy-failure-alerts from 8560f97a0f
Some checks failed
CI / gitleaks (pull_request) Successful in 6s
CI / storybook (pull_request) Successful in 1m24s
forgegraph/ci CI failed
CI / ci (pull_request) Failing after 1m27s
to f555875acb
All checks were successful
CI / gitleaks (pull_request) Successful in 7s
CI / storybook (pull_request) Successful in 1m33s
forgegraph/ci CI passed
CI / ci (pull_request) Successful in 9m42s
2026-08-27 19:31:01 +00:00
Compare
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
gmackie/ForgeGraph!493
No description provided.