Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions .github/workflows/lighthouse.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: Lighthouse Audit

on:
pull_request_target:
types: [opened, synchronize]

permissions:
contents: read
pull-requests: write

jobs:
lighthouse:
if: github.actor != 'dependabot[bot]'
runs-on: ubuntu-latest

steps:
- name: ⬇️ Checkout PR code
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}

- name: ⏳ Wait for Netlify preview to be live
run: |
PREVIEW_URL="https://deploy-preview-${{ github.event.pull_request.number }}--expressjscom-preview.netlify.app"
echo "PREVIEW_URL=$PREVIEW_URL" >> "$GITHUB_ENV"
for i in {1..3}; do
if curl -s --head "$PREVIEW_URL" | grep "200 OK" > /dev/null; then
echo "Preview is live!"
break
fi
echo "Waiting for Netlify to deploy... ($i/3)"
sleep 10
done

- name: ⚙️ Install Lighthouse
run: npm install -g lighthouse

- name: 📊 Run Lighthouse audits
run: |
mkdir -p lighthouse-report
URLS=(
"$PREVIEW_URL"
"$PREVIEW_URL/en/blog/posts.html"
"$PREVIEW_URL/en/support/"
"$PREVIEW_URL/en/resources/glossary.html"
"$PREVIEW_URL/en/5x/api.html"
)
echo "[" > lighthouse-report/manifest.json
for url in "${URLS[@]}"; do
name=$(echo "$url" | sed 's|https://||;s|[/.]|_|g')
path="./lighthouse-report/$name.report.json"
lighthouse "$url" \
--output json \
--output-path="$path" \
--chrome-flags="--headless"
jq -n --arg url "$url" \
--argjson summary "$(jq '.categories | {
performance: .performance.score,
accessibility: .accessibility.score,
"best-practices": .["best-practices"].score,
seo: .seo.score
}' "$path")" \
'{url: $url, summary: $summary}' >> lighthouse-report/manifest.json
echo "," >> lighthouse-report/manifest.json
done
sed -i '$ s/,$//' lighthouse-report/manifest.json
echo "]" >> lighthouse-report/manifest.json

# create dummy links file
jq -n '{
'"$(for url in "${URLS[@]}"; do echo "\"$url\": \"$url\","; done | sed '$ s/,$//')"'
}' > lighthouse-report/links.json

- name: 📝 Format comment
id: format
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');

const stoplight = res => (res >= 90 ? '🟢' : res >= 75 ? '🟠' : '🔴');
const normalizeScore = res => Math.round(res * 100);
const formatScore = res => {
const s = normalizeScore(res);
return `${stoplight(s)} ${s}`;
};

const results = JSON.parse(fs.readFileSync('./lighthouse-report/manifest.json', 'utf8'));
const links = JSON.parse(fs.readFileSync('./lighthouse-report/links.json', 'utf8'));

const header = [
'## 🚦 Lighthouse Results',
'| URL | Perf | A11y | Best Practices | SEO | Report |',
'| --- | ---- | ---- | -------------- | --- | ------ |',
];

const rows = results.map(({ url, summary }) => {
const short = `[${new URL(url).pathname}](${url})`;
const perf = formatScore(summary.performance);
const a11y = formatScore(summary.accessibility);
const bp = formatScore(summary['best-practices']);
const seo = formatScore(summary.seo);
return `${short} | ${perf} | ${a11y} | ${bp} | ${seo} | [🔗](${links[url]})`;
});

const comment = [...header, ...rows].join('\n');
core.setOutput('comment', comment);

- name: 💬 Comment on PR
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.payload.pull_request.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `${{ steps.format.outputs.comment }}`
});