Skip to content

Lighthouse CI

Lighthouse CI #216

Workflow file for this run

name: Lighthouse CI
on:
workflow_run:
workflows: ["pages-deploy"]
types:
- completed
jobs:
build-and-get-urls:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
outputs:
urls: ${{ steps.get_urls.outputs.urls }}
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: "latest" # Or your specific Hugo version
extended: true
- name: Build site
run: hugo --minify
- name: List public directory (for debugging)
run: ls -R public
- name: Install yq (for parsing XML)
run: sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq && sudo chmod +x /usr/bin/yq
- name: Extract URLs from sitemap
id: get_urls
run: |
SITEMAP_PATH="public/sitemap.xml"
BASE_URL="https://isaaclins.com" # Your website's base URL
if [ -f "$SITEMAP_PATH" ]; then
# Extract URLs, ensure they are absolute, and create a JSON array string
URLS=$(yq -p=xml -o=json '.urlset.url[].loc' "$SITEMAP_PATH" | jq -r --arg BASE_URL "$BASE_URL" 'if type == "array" then .[] else . end | if test("^/") then $BASE_URL + . else . end' | jq -R . | jq -s -c .)
echo "Found URLs: $URLS"
echo "urls=$URLS" >> $GITHUB_OUTPUT
else
echo "sitemap.xml not found at $SITEMAP_PATH!"
echo "urls=[]" >> $GITHUB_OUTPUT # Output empty array if sitemap not found
fi
shell: bash
lighthouse-test:
needs: build-and-get-urls
# This condition ensures 'urls' output from previous job is a non-empty array when this job runs
if: fromJson(needs.build-and-get-urls.outputs.urls)[0] != null
runs-on: ubuntu-latest
permissions: # Add this to grant write permissions for committing
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Prepare URLs for Lighthouse
id: prepare_lighthouse_urls
run: |
JSON_URL_ARRAY='${{ needs.build-and-get-urls.outputs.urls }}'
COMMA_SEPARATED_URLS=$(echo "$JSON_URL_ARRAY" | jq -r '. | join(",")')
echo "Lighthouse URLs: $COMMA_SEPARATED_URLS"
echo "LIGHTHOUSE_URL_LIST=$COMMA_SEPARATED_URLS" >> $GITHUB_ENV
shell: bash
- name: Create Lighthouse reports directory
run: mkdir -p ./lighthouse-reports
- name: Run Lighthouse CI for all pages
id: lighthouse_run
uses: foo-software/lighthouse-check-action@master
with:
urls: ${{ env.LIGHTHOUSE_URL_LIST }}
outputDirectory: ./lighthouse-reports
# Optional: Set budget to fail the check if scores are below thresholds
# budgetPath: .github/lighthouse-budget.json
- name: Generate Lighthouse Summary Report File
# This condition makes the step always run, so you see the table even if some Lighthouse audits fail.
if: always()
shell: bash
run: |
RESULTS_JSON_CONTENT='${{ steps.lighthouse_run.outputs.lighthouseCheckResults || '{"data":[]}' }}'
( # Start subshell to redirect all output to lighthousetest.md
echo "### Lighthouse Score Summary"
echo "| URL | Accessibility | Best Practices | Performance | SEO |"
echo "|-----|---------------|----------------|-------------|-----|"
# Generate data rows for each URL
echo "$RESULTS_JSON_CONTENT" | jq -r '
.data[]? # Iterate over each item in the data array, gracefully handle if .data is null or item is null
| select(.url) # Ensure the item has a URL
| (
"| " + .url + " | " +
# Access scores, provide "N/A" if a score is null or missing, then convert to string
(.scores.accessibility // "N/A" | tostring) + " | " +
(.scores.bestPractices // "N/A" | tostring) + " | " +
(.scores.performance // "N/A" | tostring) + " | " +
(.scores.seo // "N/A" | tostring) + " |"
)
'
# Generate average row and final score line
echo "$RESULTS_JSON_CONTENT" | jq -r '
# Pass the data array directly to this jq instance
.data
# Check if .data is a non-empty array
| if (type != "array") or (length == 0) then
"| Overall Average | N/A | N/A | N/A | N/A |\\\\n\\\\n# Average Score: N/A"
else
# Extract all valid numerical scores for each category from the .data array
[.[].scores.accessibility | select(type == "number")] as $acc_scores |
[.[].scores.bestPractices | select(type == "number")] as $bp_scores |
[.[].scores.performance | select(type == "number")] as $perf_scores |
[.[].scores.seo | select(type == "number")] as $seo_scores |
# Calculate average for accessibility, format as string (integer or "N/A")
(if ($acc_scores | length) > 0 then ($acc_scores | add / length | floor | tostring) else "N/A" end) as $avg_acc_str |
# Store raw numerical average for final calculation, or null if not calculable
(if ($acc_scores | length) > 0 then ($acc_scores | add / length) else null end) as $raw_avg_acc |
(if ($bp_scores | length) > 0 then ($bp_scores | add / length | floor | tostring) else "N/A" end) as $avg_bp_str |
(if ($bp_scores | length) > 0 then ($bp_scores | add / length) else null end) as $raw_avg_bp |
(if ($perf_scores | length) > 0 then ($perf_scores | add / length | floor | tostring) else "N/A" end) as $avg_perf_str |
(if ($perf_scores | length) > 0 then ($perf_scores | add / length) else null end) as $raw_avg_perf |
# Calculate average for seo, format as string (integer or "N/A")
(if ($seo_scores | length) > 0 then ($seo_scores | add / length | floor | tostring) else "N/A" end) as $avg_seo_str |
(if ($seo_scores | length) > 0 then ($seo_scores | add / length) else null end) as $raw_avg_seo |
# Construct the Markdown table row for averages
"| Overall Average | \($avg_acc_str) | \($avg_bp_str) | \($avg_perf_str) | \($avg_seo_str) |" as $avg_row_str |
# Collect all valid raw numerical averages (those that are not null)
([$raw_avg_acc, $raw_avg_bp, $raw_avg_perf, $raw_avg_seo] | map(select(. != null))) as $valid_raw_category_averages |
# Calculate the final average score from the valid category averages
(if ($valid_raw_category_averages | length) > 0 then
($valid_raw_category_averages | add / length | floor | tostring)
else
"N/A"
end) as $final_avg_score_str |
# Combine the average row and the final score line
$avg_row_str + "\n\n# Average Score: \($final_avg_score_str)"
end
'
) > lighthousetest.md # All echos inside () go to lighthousetest.md
# This echo goes to the workflow log, not the lighthousetest.md
echo "Lighthouse summary report generated: lighthousetest.md"
- name: Commit and Push Lighthouse Report
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: "docs: update Lighthouse report [skip ci]"
branch: main # Or your default branch
file_pattern: lighthousetest.md
commit_user_name: "GitHub Actions Bot"
commit_user_email: "actions@github.com"
commit_author: "GitHub Actions Bot <actions@github.com>"
- name: Upload Lighthouse Reports Artifact
uses: actions/upload-artifact@v7
with:
name: lighthouse-reports # A single artifact for all reports
path: ./lighthouse-reports
if-no-files-found: ignore