@@ -3,8 +3,28 @@ name: Lighthouse CI
33on :
44 pull_request :
55 branches : [main, develop, '**-harden-**']
6+ paths :
7+ - ' src/app/(storefront)/**'
8+ - ' src/app/(dashboard)/**'
9+ - ' src/app/api/**'
10+ - ' src/components/**'
11+ - ' src/app/layout.tsx'
12+ - ' src/app/page.tsx'
13+ - ' public/**'
14+ - ' lighthouserc*.js'
15+ - ' .github/workflows/lighthouse.yml'
616 push :
717 branches : ['**-harden-**']
18+ paths :
19+ - ' src/app/(storefront)/**'
20+ - ' src/app/(dashboard)/**'
21+ - ' src/app/api/**'
22+ - ' src/components/**'
23+ - ' src/app/layout.tsx'
24+ - ' src/app/page.tsx'
25+ - ' public/**'
26+ - ' lighthouserc*.js'
27+ - ' .github/workflows/lighthouse.yml'
828 workflow_dispatch :
929
1030concurrency :
5373 run : npx wait-on http://localhost:3000 -t 60000
5474
5575 - name : 💡 Run Lighthouse CI (Desktop)
76+ id : lhci-desktop
5677 run : |
5778 npm install -g @lhci/cli@0.13.x
58- lhci autorun --config=lighthouserc.js
79+ lhci autorun --config=lighthouserc.js || exit 1
5980 env :
6081 LHCI_GITHUB_APP_TOKEN : ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
6182
6687 name : lighthouse-desktop-results
6788 path : .lighthouseci
6889 retention-days : 30
90+
91+ - name : ❌ Fail if budgets breached
92+ if : failure()
93+ run : |
94+ echo "::error::❌ Lighthouse CI FAILED (Desktop) - Performance budgets breached"
95+ echo "::error::Constitution budgets: LCP < 2.0s, CLS < 0.1, FID < 100ms, TTI < 3.0s"
96+ echo "::error::Performance score ≥ 90, Accessibility ≥ 90, Bundle < 200KB"
97+ echo "::error::See artifacts for detailed reports"
98+ exit 1
6999
70100 lighthouse-mobile :
71101 name : Lighthouse (Mobile)
@@ -108,9 +138,10 @@ jobs:
108138 run : npx wait-on http://localhost:3000 -t 60000
109139
110140 - name : 💡 Run Lighthouse CI (Mobile)
141+ id : lhci-mobile
111142 run : |
112143 npm install -g @lhci/cli@0.13.x
113- lhci autorun --config=lighthouserc.mobile.js
144+ lhci autorun --config=lighthouserc.mobile.js || exit 1
114145 env :
115146 LHCI_GITHUB_APP_TOKEN : ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
116147
@@ -121,22 +152,33 @@ jobs:
121152 name : lighthouse-mobile-results
122153 path : .lighthouseci
123154 retention-days : 30
155+
156+ - name : ❌ Fail if budgets breached
157+ if : failure()
158+ run : |
159+ echo "::error::❌ Lighthouse CI FAILED (Mobile) - Performance budgets breached"
160+ echo "::error::Constitution budgets: LCP < 2.5s, CLS < 0.1, FID < 100ms, TTI < 3.0s"
161+ echo "::error::Performance score ≥ 90, Accessibility ≥ 90, Bundle < 200KB"
162+ echo "::error::See artifacts for detailed reports"
163+ exit 1
124164
125165 lighthouse-comment :
126166 name : Comment PR with Lighthouse Results
127167 runs-on : ubuntu-latest
128168 needs : [lighthouse-desktop, lighthouse-mobile]
129- if : github.event_name == 'pull_request'
169+ if : always() && github.event_name == 'pull_request'
130170
131171 steps :
132172 - name : 📥 Download desktop results
133173 uses : actions/download-artifact@v4
174+ continue-on-error : true
134175 with :
135176 name : lighthouse-desktop-results
136177 path : ./lighthouse-desktop
137178
138179 - name : 📥 Download mobile results
139180 uses : actions/download-artifact@v4
181+ continue-on-error : true
140182 with :
141183 name : lighthouse-mobile-results
142184 path : ./lighthouse-mobile
@@ -147,26 +189,48 @@ jobs:
147189 script : |
148190 const fs = require('fs');
149191
150- // Read results (simplified - actual implementation would parse JSON)
151- const desktopPassed = fs.existsSync('./lighthouse-desktop');
152- const mobilePassed = fs.existsSync('./lighthouse-mobile');
192+ // Check job statuses
193+ const desktopPassed = '${{ needs.lighthouse-desktop.result }}' === 'success';
194+ const mobilePassed = '${{ needs.lighthouse-mobile.result }}' === 'success';
195+
196+ const overallStatus = desktopPassed && mobilePassed ? '✅ PASSED' : '❌ FAILED';
197+ const emoji = desktopPassed && mobilePassed ? '✅' : '❌';
198+
199+ const comment = `## 💡 Lighthouse CI Results - ${overallStatus}
200+
201+ ### Desktop ${desktopPassed ? '✅' : '❌'}
202+ **Performance Budgets** (Constitution §128-134):
203+ - ✓ LCP (Largest Contentful Paint): < 2.0s
204+ - ✓ FID (First Input Delay): < 100ms
205+ - ✓ CLS (Cumulative Layout Shift): < 0.1
206+ - ✓ TTI (Time to Interactive): < 3.0s
207+ - ✓ TBT (Total Blocking Time): < 300ms
208+ - ✓ JavaScript Bundle: < 200KB (gzipped)
209+ - ✓ Performance Score: ≥ 90
210+ - ✓ Accessibility Score: ≥ 90
211+
212+ ${desktopPassed ? '✅ All budgets passed' : '❌ **BLOCKING**: Budgets breached - see artifacts for details'}
213+
214+ ### Mobile ${mobilePassed ? '✅' : '❌'}
215+ **Performance Budgets**:
216+ - ✓ LCP (Largest Contentful Paint): < 2.5s
217+ - ✓ FID (First Input Delay): < 100ms
218+ - ✓ CLS (Cumulative Layout Shift): < 0.1
219+ - ✓ TTI (Time to Interactive): < 3.0s
220+ - ✓ TBT (Total Blocking Time): < 300ms
221+ - ✓ JavaScript Bundle: < 200KB (gzipped)
222+ - ✓ Performance Score: ≥ 90
223+ - ✓ Accessibility Score: ≥ 90
153224
154- const comment = `## 💡 Lighthouse CI Results
225+ ${mobilePassed ? '✅ All budgets passed' : '❌ **BLOCKING**: Budgets breached - see artifacts for details'}
155226
156- ### Desktop
157- ${desktopPassed ? '✅ Passed' : '❌ Failed'}
227+ ---
158228
159- ### Mobile
160- ${mobilePassed ? '✅ Passed' : '❌ Failed'}
229+ ${emoji} **${overallStatus}** - ${desktopPassed && mobilePassed ? 'Merge allowed' : '**MERGE BLOCKED** - Fix performance/accessibility issues before merging'}
161230
162- **Performance Budgets:**
163- - LCP < 2.0s (desktop), < 2.5s (mobile)
164- - FID < 100ms
165- - CLS < 0.1
166- - TTI < 3.0s
167- - JS Bundle < 200KB (gzipped)
231+ 📊 Download artifacts for detailed Lighthouse reports.
168232
169- See artifacts for detailed reports.
233+ **Constitution Reference**: Performance requirements in §118-134, §177-195
170234 `;
171235
172236 github.rest.issues.createComment({
0 commit comments