Self-hosted instances no longer inherit the trails.cool flagship Sentry DSNs. Code paths now read DSN strictly from env — unset = no Sentry init, no events sent. Flagship continues to report unchanged: cd-apps.yml and cd-staging.yml inject the public DSNs as workflow env vars, which feed into: - runtime via \`infrastructure/app.env\` / \`staging.env\` (\`SENTRY_DSN_JOURNAL\` / \`SENTRY_DSN_PLANNER\` → compose env per service) - build time via docker build-arg \`VITE_SENTRY_DSN\` (journal only; planner has no client Sentry init). Sentry DSNs are public-by-design (transmitted unencrypted from the client JS bundle), so embedding them as plaintext workflow env vars is no worse than the runtime exposure. Forks should replace these with their own DSNs or remove the workflow env lines to ship Sentry-free. Files changed: - apps/journal/server.ts: \`process.env.SENTRY_DSN\` only, no fallback - apps/planner/server.ts: same - apps/journal/app/lib/sentry.client.ts: \`import.meta.env.VITE_SENTRY_DSN\` only; falsy = skip init - apps/journal/Dockerfile: new \`ARG VITE_SENTRY_DSN\` baked into build - infrastructure/docker-compose.yml: pass \`SENTRY_DSN\` per service - infrastructure/docker-compose.staging.yml: same - .github/workflows/cd-apps.yml: workflow env + build-arg + app.env echo - .github/workflows/cd-staging.yml: same Full repo: pnpm typecheck, pnpm lint, pnpm test, journal build all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
import * as Sentry from "@sentry/react";
|
|
import { useEffect } from "react";
|
|
import { useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from "react-router";
|
|
import { browserSentryConfig } from "@trails-cool/sentry-config";
|
|
|
|
let initialized = false;
|
|
|
|
// Build-time DSN injection. `VITE_SENTRY_DSN` (set during `pnpm build`,
|
|
// see apps/journal/Dockerfile + cd-apps.yml) determines whether the
|
|
// client emits Sentry events at all. Self-hosted builds without the
|
|
// env var produce a Sentry-free client bundle.
|
|
const CLIENT_DSN = (import.meta.env as Record<string, string | undefined>)
|
|
.VITE_SENTRY_DSN;
|
|
|
|
export function initSentryClient() {
|
|
if (initialized) return;
|
|
initialized = true;
|
|
if (!CLIENT_DSN) return;
|
|
|
|
Sentry.init({
|
|
dsn: CLIENT_DSN,
|
|
integrations: [
|
|
Sentry.reactRouterV7BrowserTracingIntegration({
|
|
useEffect,
|
|
useLocation,
|
|
useNavigationType,
|
|
createRoutesFromChildren,
|
|
matchRoutes,
|
|
}),
|
|
],
|
|
...browserSentryConfig("journal client", import.meta.env),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Tear down the Sentry client on logout. After this call, `Sentry.captureException`
|
|
* and other hub methods become no-ops until `initSentryClient` is called again.
|
|
*
|
|
* Fire-and-forget: the close flush happens async, but we don't want to block the
|
|
* logout UI on it.
|
|
*/
|
|
export function stopSentryClient() {
|
|
if (!initialized) return;
|
|
initialized = false;
|
|
void Sentry.close();
|
|
}
|