fix(sentry): remove hardcoded DSN fallbacks; supply via env in CI
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>
This commit is contained in:
parent
f239b4adee
commit
edb618fe40
8 changed files with 55 additions and 21 deletions
|
|
@ -23,11 +23,16 @@ RUN pnpm install --frozen-lockfile
|
|||
|
||||
FROM base AS build
|
||||
ARG SENTRY_RELEASE
|
||||
# Client-side Sentry DSN baked into the bundle at build time. Empty (or
|
||||
# unset) produces a Sentry-free client. Public-by-design: the DSN
|
||||
# appears in the shipped client JS regardless.
|
||||
ARG VITE_SENTRY_DSN=""
|
||||
COPY --from=deps /app/ ./
|
||||
COPY . .
|
||||
RUN --mount=type=secret,id=SENTRY_AUTH_TOKEN \
|
||||
SENTRY_AUTH_TOKEN="$(cat /run/secrets/SENTRY_AUTH_TOKEN 2>/dev/null | tr -d '\n\r')" \
|
||||
SENTRY_RELEASE="$SENTRY_RELEASE" \
|
||||
VITE_SENTRY_DSN="$VITE_SENTRY_DSN" \
|
||||
pnpm --filter @trails-cool/journal build
|
||||
|
||||
FROM base AS runtime
|
||||
|
|
|
|||
|
|
@ -5,15 +5,12 @@ import { browserSentryConfig } from "@trails-cool/sentry-config";
|
|||
|
||||
let initialized = false;
|
||||
|
||||
// Build-time DSN injection: `VITE_SENTRY_DSN` (if set during `pnpm build`)
|
||||
// overrides the flagship default so self-hosters can ship their own
|
||||
// Sentry project. Set it to `""` (empty string) to disable Sentry on
|
||||
// the client entirely.
|
||||
const FLAGSHIP_JOURNAL_DSN =
|
||||
"https://a32ffcc575d34be072e91b20f247eeee@o4509530546634752.ingest.de.sentry.io/4509530555547728";
|
||||
const CLIENT_DSN =
|
||||
(import.meta.env as Record<string, string | undefined>).VITE_SENTRY_DSN ??
|
||||
FLAGSHIP_JOURNAL_DSN;
|
||||
// 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;
|
||||
|
|
|
|||
|
|
@ -11,14 +11,13 @@ import { createBoss, startWorker } from "@trails-cool/jobs";
|
|||
import { getDatabaseUrl } from "@trails-cool/db";
|
||||
import postgres, { type Sql } from "postgres";
|
||||
|
||||
// Sentry DSN is read from env so self-hosted instances don't ship their
|
||||
// errors to the trails.cool flagship Sentry by default. The flagship
|
||||
// keeps its DSN as the fallback; setting SENTRY_DSN="" (or any other
|
||||
// truthy value) overrides. SENTRY_DISABLED=true skips init entirely.
|
||||
const FLAGSHIP_JOURNAL_SENTRY_DSN =
|
||||
"https://a32ffcc575d34be072e91b20f247eeee@o4509530546634752.ingest.de.sentry.io/4509530555547728";
|
||||
const sentryDsn = process.env.SENTRY_DSN ?? FLAGSHIP_JOURNAL_SENTRY_DSN;
|
||||
if (process.env.SENTRY_DISABLED !== "true" && sentryDsn !== "") {
|
||||
// Sentry DSN is supplied via env. No hardcoded fallback — self-hosted
|
||||
// instances default to no Sentry. Flagship sets SENTRY_DSN via
|
||||
// docker-compose env (see infrastructure/docker-compose.yml).
|
||||
// SENTRY_DISABLED=true is an explicit opt-out even when a DSN is set
|
||||
// (useful for local prod-mode debugging).
|
||||
const sentryDsn = process.env.SENTRY_DSN;
|
||||
if (process.env.SENTRY_DISABLED !== "true" && sentryDsn) {
|
||||
Sentry.init({
|
||||
dsn: sentryDsn,
|
||||
...nodeSentryConfig("journal server"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue