feat(observability): add GlitchTip source map uploads for un-minified stack traces
Some checks failed
CI / Check ui (pull_request) Failing after 11s
CI / Docker / caddy (pull_request) Failing after 11s
CI / Docker / ui (pull_request) Has been skipped
CI / Test backend (pull_request) Successful in 30s
Release / Check ui (push) Failing after 38s
Release / Upload source maps (push) Has been skipped
Release / Docker / ui (push) Has been skipped
Release / Test backend (push) Successful in 48s
Release / Docker / caddy (push) Successful in 45s
CI / Docker / backend (pull_request) Has been cancelled
CI / Docker / runner (pull_request) Has been cancelled
Release / Docker / runner (push) Has been cancelled
Release / Gitea Release (push) Has been cancelled
Release / Docker / backend (push) Has been cancelled
Some checks failed
CI / Check ui (pull_request) Failing after 11s
CI / Docker / caddy (pull_request) Failing after 11s
CI / Docker / ui (pull_request) Has been skipped
CI / Test backend (pull_request) Successful in 30s
Release / Check ui (push) Failing after 38s
Release / Upload source maps (push) Has been skipped
Release / Docker / ui (push) Has been skipped
Release / Test backend (push) Successful in 48s
Release / Docker / caddy (push) Successful in 45s
CI / Docker / backend (pull_request) Has been cancelled
CI / Docker / runner (pull_request) Has been cancelled
Release / Docker / runner (push) Has been cancelled
Release / Gitea Release (push) Has been cancelled
Release / Docker / backend (push) Has been cancelled
- Enable sourcemap:true in vite.config.ts - Add sentryVitePlugin: uploads maps to errors.libnovel.cc, deletes them post-upload so they never ship in the Docker image - Wire release: PUBLIC_BUILD_VERSION in both hooks.client.ts and hooks.server.ts so events correlate to the correct artifact - Add upload-sourcemaps CI job in release.yaml (parallel to docker-ui, uses GLITCHTIP_AUTH_TOKEN secret)
This commit is contained in:
@@ -135,6 +135,35 @@ jobs:
|
|||||||
cache-from: type=registry,ref=${{ secrets.DOCKER_USER }}/libnovel-runner:latest
|
cache-from: type=registry,ref=${{ secrets.DOCKER_USER }}/libnovel-runner:latest
|
||||||
cache-to: type=inline
|
cache-to: type=inline
|
||||||
|
|
||||||
|
# ── ui: source map upload ─────────────────────────────────────────────────────
|
||||||
|
# Builds the UI with source maps and uploads them to GlitchTip so that error
|
||||||
|
# stack traces resolve to original .svelte/.ts file names and line numbers.
|
||||||
|
# Runs in parallel with docker-ui (both need check-ui to pass first).
|
||||||
|
upload-sourcemaps:
|
||||||
|
name: Upload source maps
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [check-ui]
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: ui
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "22"
|
||||||
|
cache: npm
|
||||||
|
cache-dependency-path: ui/package-lock.json
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build with source maps and upload to GlitchTip
|
||||||
|
env:
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||||
|
BUILD_VERSION: ${{ gitea.ref_name }}
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
# ── docker: ui ────────────────────────────────────────────────────────────────
|
# ── docker: ui ────────────────────────────────────────────────────────────────
|
||||||
docker-ui:
|
docker-ui:
|
||||||
name: Docker / ui
|
name: Docker / ui
|
||||||
@@ -213,7 +242,7 @@ jobs:
|
|||||||
release:
|
release:
|
||||||
name: Gitea Release
|
name: Gitea Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [docker-backend, docker-runner, docker-ui, docker-caddy]
|
needs: [docker-backend, docker-runner, docker-ui, docker-caddy, upload-sourcemaps]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
1
ui/package-lock.json
generated
1
ui/package-lock.json
generated
@@ -17,6 +17,7 @@
|
|||||||
"pocketbase": "^0.26.8"
|
"pocketbase": "^0.26.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@sentry/vite-plugin": "^5.1.1",
|
||||||
"@sveltejs/adapter-auto": "^7.0.0",
|
"@sveltejs/adapter-auto": "^7.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.5.4",
|
"@sveltejs/adapter-node": "^5.5.4",
|
||||||
"@sveltejs/kit": "^2.50.2",
|
"@sveltejs/kit": "^2.50.2",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@sentry/vite-plugin": "^5.1.1",
|
||||||
"@sveltejs/adapter-auto": "^7.0.0",
|
"@sveltejs/adapter-auto": "^7.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.5.4",
|
"@sveltejs/adapter-node": "^5.5.4",
|
||||||
"@sveltejs/kit": "^2.50.2",
|
"@sveltejs/kit": "^2.50.2",
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import { env } from '$env/dynamic/public';
|
|||||||
if (env.PUBLIC_GLITCHTIP_DSN) {
|
if (env.PUBLIC_GLITCHTIP_DSN) {
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: env.PUBLIC_GLITCHTIP_DSN,
|
dsn: env.PUBLIC_GLITCHTIP_DSN,
|
||||||
tracesSampleRate: 0.1
|
tracesSampleRate: 0.1,
|
||||||
|
// Must match the release name used when uploading source maps in CI
|
||||||
|
// (BUILD_VERSION injected by Dockerfile as PUBLIC_BUILD_VERSION).
|
||||||
|
release: env.PUBLIC_BUILD_VERSION || undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ import { drain as drainPresignCache } from '$lib/server/presignCache';
|
|||||||
if (pubEnv.PUBLIC_GLITCHTIP_DSN) {
|
if (pubEnv.PUBLIC_GLITCHTIP_DSN) {
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: pubEnv.PUBLIC_GLITCHTIP_DSN,
|
dsn: pubEnv.PUBLIC_GLITCHTIP_DSN,
|
||||||
tracesSampleRate: 0.1
|
tracesSampleRate: 0.1,
|
||||||
|
// Must match the release name used when uploading source maps in CI
|
||||||
|
// (BUILD_VERSION injected by Dockerfile as PUBLIC_BUILD_VERSION).
|
||||||
|
release: pubEnv.PUBLIC_BUILD_VERSION || undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,36 @@
|
|||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import tailwindcss from '@tailwindcss/vite';
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
|
import { sentryVitePlugin } from '@sentry/vite-plugin';
|
||||||
|
|
||||||
|
// Source maps are always generated so that the CI pipeline can upload them to
|
||||||
|
// GlitchTip after a release build. The sentryVitePlugin upload step is only
|
||||||
|
// active when SENTRY_AUTH_TOKEN is present (i.e. in the release CI job).
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [tailwindcss(), sveltekit()],
|
build: {
|
||||||
|
sourcemap: true
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
tailwindcss(),
|
||||||
|
sveltekit(),
|
||||||
|
sentryVitePlugin({
|
||||||
|
org: 'libnovel',
|
||||||
|
project: 'libnovel-ui',
|
||||||
|
url: 'https://errors.libnovel.cc/',
|
||||||
|
// Auth token injected by CI via SENTRY_AUTH_TOKEN env var.
|
||||||
|
// When the env var is absent the plugin is a no-op.
|
||||||
|
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||||
|
// Release name matches the Docker image tag (e.g. "1.2.3").
|
||||||
|
release: { name: process.env.BUILD_VERSION },
|
||||||
|
// Don't upload source maps in local dev or CI type-check jobs.
|
||||||
|
disable: !process.env.SENTRY_AUTH_TOKEN,
|
||||||
|
// Source maps are uploaded to GlitchTip; do not ship them in the
|
||||||
|
// production bundle served to browsers.
|
||||||
|
sourceMapsUploadOptions: {
|
||||||
|
filesToDeleteAfterUpload: ['./build/**/*.map']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
ssr: {
|
ssr: {
|
||||||
// Force these packages to be bundled into the server output rather than
|
// Force these packages to be bundled into the server output rather than
|
||||||
// treated as external requires. The production Docker image has no
|
// treated as external requires. The production Docker image has no
|
||||||
|
|||||||
Reference in New Issue
Block a user