-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
ci: Add Lighthouse Test as Nightly CI run #20850
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
d496226
36c3f76
cc37d4d
ae9b8b8
2a7c378
0119764
cfa2092
e8cb7f8
e04bc37
9e28f29
254f973
b766f80
db8a4bb
b29aada
b96bb65
9809ea1
1549ea8
760b128
8288dcb
7c24cff
06f87a5
bb5ee63
df529c5
d876721
a271b87
1800bf0
48c2db9
cad23e0
9ba92f4
62896cc
ca35738
12ab6e8
8113edd
86cfe88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| name: 'Nightly: Lighthouse' | ||
|
|
||
| # Nightly: builds the Lighthouse fixture app and uploads bundles to the | ||
| # lighthouse.sentry.gg lab. Never blocks merges. | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: '0 0 * * *' | ||
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: lighthouse-${{ github.run_id }} | ||
| cancel-in-progress: false | ||
|
|
||
| env: | ||
| CACHED_DEPENDENCY_PATHS: | | ||
| ${{ github.workspace }}/node_modules | ||
| ${{ github.workspace }}/packages/*/node_modules | ||
| ${{ github.workspace }}/dev-packages/*/node_modules | ||
|
|
||
| jobs: | ||
| build-and-upload: | ||
| name: Bundle and upload Lighthouse cells | ||
| runs-on: ubuntu-24.04 | ||
| timeout-minutes: 30 | ||
| env: | ||
| LIGHTHOUSE_LAB_URL: ${{ secrets.LIGHTHOUSE_LAB_URL }} | ||
| LIGHTHOUSE_UPLOAD_TOKEN: ${{ secrets.LIGHTHOUSE_UPLOAD_TOKEN }} | ||
| VITE_E2E_TEST_DSN: 'https://username@domain/123' | ||
| steps: | ||
| - uses: actions/checkout@v6 | ||
| - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 | ||
| with: | ||
| version: 9.15.9 | ||
| - uses: actions/setup-node@v6 | ||
| with: | ||
| node-version-file: 'package.json' | ||
| - uses: ./.github/actions/install-dependencies | ||
| - run: yarn build:ci | ||
| - run: yarn build:tarball | ||
| - run: yarn test:prepare | ||
| working-directory: dev-packages/e2e-tests | ||
| - run: node dev-packages/lighthouse-bundle/bundle-and-upload.mjs | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <link rel="icon" type="image/svg+xml" href="/logo.svg" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
| <title>Lighthouse Fixture</title> | ||
| </head> | ||
| <body> | ||
| <div id="root"></div> | ||
| <script type="module" src="/src/main.tsx"></script> | ||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| { | ||
| "name": "lighthouse-react-test-app", | ||
| "private": true, | ||
| "type": "module", | ||
| "sentryTest": { | ||
| "skip": true | ||
| }, | ||
| "scripts": { | ||
| "build": "vite build", | ||
| "build:no-sentry": "vite build --mode no-sentry", | ||
| "build:init-only": "vite build --mode init-only", | ||
| "build:tracing-replay": "vite build --mode tracing-replay", | ||
| "preview": "vite preview", | ||
| "clean": "npx rimraf node_modules pnpm-lock.yaml dist", | ||
| "test:build": "pnpm install && pnpm build" | ||
| }, | ||
| "dependencies": { | ||
| "@sentry/react": "file:../../packed/sentry-react-packed.tgz", | ||
| "react": "^18.3.1", | ||
| "react-dom": "^18.3.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/react": "^18.3.0", | ||
| "@types/react-dom": "^18.3.0", | ||
| "@vitejs/plugin-react-swc": "^3.7.0", | ||
| "typescript": "~5.4.0", | ||
| "vite": "^5.4.0" | ||
| }, | ||
| "volta": { | ||
| "extends": "../../package.json" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| import { useEffect, useState } from 'react'; | ||
|
|
||
| const CARDS = [ | ||
| { title: 'Performance', body: 'Measure and optimize your app render times and interaction latency.' }, | ||
| { title: 'Accessibility', body: 'Ensure your interface is usable by everyone, including assistive technologies.' }, | ||
| { title: 'Best Practices', body: 'Follow modern web development patterns for secure and maintainable code.' }, | ||
| { title: 'SEO', body: 'Optimize discoverability with semantic markup and structured metadata.' }, | ||
| { title: 'PWA', body: 'Add offline support and installability via service workers and manifests.' }, | ||
| { title: 'Security', body: 'Protect users with CSP headers, HTTPS, and input validation.' }, | ||
| ]; | ||
|
|
||
| export default function App() { | ||
| const [count, setCount] = useState(0); | ||
|
|
||
| useEffect(() => { | ||
| document.title = `Lighthouse Fixture (${count})`; | ||
| }, [count]); | ||
|
|
||
| return ( | ||
| <main> | ||
| <header> | ||
| <nav> | ||
| <a href="/">Home</a> | ||
| <a href="/docs">Docs</a> | ||
| <a href="/about">About</a> | ||
| </nav> | ||
| </header> | ||
|
|
||
| <section className="hero"> | ||
| <img src="/logo.svg" alt="Lighthouse logo" width={120} height={120} /> | ||
| <h1>Lighthouse Fixture</h1> | ||
| <p> | ||
| This app exists to measure JavaScript bundle size and runtime cost across three Sentry instrumentation | ||
| configurations. Each build mode ships a different level of SDK integration. | ||
| </p> | ||
| </section> | ||
|
|
||
| <section className="cards"> | ||
| {CARDS.map(card => ( | ||
| <article key={card.title} className="card"> | ||
| <h2>{card.title}</h2> | ||
| <p>{card.body}</p> | ||
| </article> | ||
| ))} | ||
| </section> | ||
|
|
||
| <form | ||
| onSubmit={e => { | ||
| e.preventDefault(); | ||
| setCount(c => c + 1); | ||
| }} | ||
| > | ||
| <input type="text" name="name" placeholder="Name" aria-label="Name" /> | ||
| <input type="email" name="email" placeholder="Email" aria-label="Email" /> | ||
| <input type="text" name="message" placeholder="Message" aria-label="Message" /> | ||
| <button type="submit">Submit ({count})</button> | ||
| </form> | ||
| </main> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { createRoot } from 'react-dom/client'; | ||
| import App from './App'; | ||
|
|
||
| async function bootstrap() { | ||
| const mode = import.meta.env.MODE; | ||
| if (mode === 'init-only') { | ||
| const { initSentry } = await import('./sentry/init-only'); | ||
| initSentry(); | ||
| } else if (mode === 'tracing-replay') { | ||
| const { initSentry } = await import('./sentry/tracing-replay'); | ||
| initSentry(); | ||
| } | ||
| // 'no-sentry' mode: do not import any sentry module — the dynamic-import | ||
| // branches above are unreachable and Vite drops them from the bundle. | ||
|
|
||
| const root = createRoot(document.getElementById('root')!); | ||
| root.render(<App />); | ||
| } | ||
|
|
||
| void bootstrap(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import * as Sentry from '@sentry/react'; | ||
|
|
||
| export function initSentry(): void { | ||
| // enabled: false makes the SDK a guaranteed no-op (no transport allocation, | ||
| // no DSN warning). We're measuring pure SDK-loading + tree-shaking cost. | ||
| Sentry.init({ enabled: false }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| export function initSentry(): void { | ||
| // no-op: this mode intentionally excludes all Sentry imports | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused dead code file never imported anywhereLow Severity The Reviewed by Cursor Bugbot for commit 8113edd. Configure here. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import * as Sentry from '@sentry/react'; | ||
|
|
||
| export function initSentry(): void { | ||
| Sentry.init({ | ||
| dsn: import.meta.env.VITE_E2E_TEST_DSN as string | undefined, | ||
| release: 'lighthouse-fixture', | ||
| environment: 'qa', | ||
| integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], | ||
| tracesSampleRate: 1.0, | ||
| replaysSessionSampleRate: 1.0, | ||
| replaysOnErrorSampleRate: 1.0, | ||
| }); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "target": "ES2020", | ||
| "useDefineForClassFields": true, | ||
| "lib": ["ES2020", "DOM", "DOM.Iterable"], | ||
| "module": "ESNext", | ||
| "skipLibCheck": true, | ||
| "moduleResolution": "bundler", | ||
| "allowImportingTsExtensions": true, | ||
| "resolveJsonModule": true, | ||
| "isolatedModules": true, | ||
| "noEmit": true, | ||
| "jsx": "react-jsx", | ||
| "strict": true, | ||
| "noUnusedLocals": true, | ||
| "noUnusedParameters": true, | ||
| "noFallthroughCasesInSwitch": true | ||
| }, | ||
| "include": ["src"], | ||
| "references": [{ "path": "./tsconfig.node.json" }] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "composite": true, | ||
| "skipLibCheck": true, | ||
| "module": "ESNext", | ||
| "moduleResolution": "bundler", | ||
| "allowSyntheticDefaultImports": true | ||
| }, | ||
| "include": ["vite.config.ts"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import { defineConfig } from 'vite'; | ||
| import react from '@vitejs/plugin-react-swc'; | ||
|
|
||
| export default defineConfig({ | ||
| plugins: [react()], | ||
| }); |


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concurrency group with run_id is a no-op
Low Severity
The concurrency group uses
github.run_id, which is unique per workflow run, making the entireconcurrencyblock a no-op — no run can ever conflict with another. Other workflows in this repo use the standard pattern${{ github.workflow }}-${{ github.head_ref || github.run_id }}for meaningful concurrency control. This block gives a false impression of concurrency management when none exists.Reviewed by Cursor Bugbot for commit 8113edd. Configure here.