Skip to content

feat: add Lighthouse CI for quality scoring #9

feat: add Lighthouse CI for quality scoring

feat: add Lighthouse CI for quality scoring #9

Workflow file for this run

name: Lighthouse CI
on:
pull_request:
branches:
- main
jobs:
lighthouse:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22.12.0"
cache: npm
cache-dependency-path: astro-site/package-lock.json
- name: Install dependencies
working-directory: astro-site
run: npm ci
- name: Create assets symlink
run: mkdir -p astro-site/src/content && ln -s ../../../assets astro-site/src/content/assets
- name: Build site
working-directory: astro-site
run: npm run build
- name: Lighthouse CI
id: lhci
uses: treosh/lighthouse-ci-action@v12
with:
configPath: ./lighthouserc.json
uploadArtifacts: true
- name: Post Lighthouse scores to PR
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const dir = '.lighthouseci';
const files = fs.readdirSync(dir).filter(f => f.endsWith('.json') && !f.startsWith('manifest'));
const rows = [];
for (const f of files) {
const raw = JSON.parse(fs.readFileSync(path.join(dir, f), 'utf8'));
const r = raw.lhr || raw;
if (!r.categories) continue;
const rawUrl = r.finalDisplayedUrl || r.finalUrl || r.requestedUrl || '';
const pagePath = rawUrl.startsWith('http') ? new URL(rawUrl).pathname : rawUrl || f;
const scores = r.categories;
const fmt = (cat) => {
if (!scores[cat]) return 'N/A';
const s = Math.round(scores[cat].score * 100);
const icon = s >= 90 ? '🟢' : s >= 50 ? '🟠' : '🔴';
return `${icon} ${s}`;
};
rows.push(`| ${pagePath} | ${fmt('performance')} | ${fmt('accessibility')} | ${fmt('best-practices')} | ${fmt('seo')} |`);
}
const body = [
'## Lighthouse Results',
'',
'| Page | Performance | Accessibility | Best Practices | SEO |',
'|------|------------|---------------|----------------|-----|',
...rows,
'',
'_Scores: 🟢 90+ · 🟠 50-89 · 🔴 0-49_'
].join('\n');
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find(c => c.body.includes('## Lighthouse Results'));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
}