Skip to content

Deploy

Deploy #425

Workflow file for this run

name: Deploy
on:
push:
branches: [main]
schedule:
# Keeps the OSS Ledger subpage's live counts fresh even on days with no
# portfolio commits. Matches the tracker's old standalone-repo cadence.
- cron: "17 6 * * *"
workflow_dispatch:
repository_dispatch:
types: [refresh-tracker]
permissions:
contents: write
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- run: npm ci || npm install
- name: Refresh OSS Ledger subpage
run: python3 oss-contribution-tracker/refresh.py
env:
# Needs `gh` (issues/PRs), `curl` (Blender's Gitea API), and GitLab token for notes.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }}
- name: Commit refreshed OSS Ledger data
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add oss-contribution-tracker/data.json
if git diff --cached --quiet; then
echo "no changes"
else
git commit -m "oss-ledger: refresh data [skip ci]"
git push || echo "Branch protection prevented direct push; continuing deployment with generated data"
fi
- run: npm run build
env:
# `prebuild` calls `gh api` to refresh public repo stats
# (stars, language, last-push). The script falls back to the
# committed JSON if the token is missing.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/configure-pages@v6
- uses: actions/upload-pages-artifact@v5
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
outputs:
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v5
# Post-deploy synthetic perf check. Runs Lighthouse 3× against the
# live URL, averages the runs, uploads HTML + JSON reports to
# temporary-public-storage (linked from the Action summary) and as
# build artifacts. Assertions are all `warn`-level so a regression
# doesn't block deploys — it just shows up in the run log + the
# report link. Tighten to `error` once budgets stabilise.
lighthouse:
needs: deploy
runs-on: ubuntu-latest
if: needs.deploy.outputs.url != ''
# Why mobile is the gate and desktop is fail-soft:
#
# GitHub Actions runners have no GPU. Chrome M122+ disabled the
# SwiftShader software-WebGL fallback by default, so headless
# Lighthouse needs explicit chromeFlags (see lighthouserc.desktop.json)
# to render the WebGL scene at all. Even with SwiftShader enabled,
# the runner has to do all the GPU work on the CPU, which blocks the
# main thread for ~5 s during scene boot and tanks TBT + Speed Index
# to 0 — a CI-runner artifact, not a real-user signal.
#
# So: mobile preset's built-in CPU throttling masks the software-
# rasterizer cost (everything's slow and expected to be slow) and
# produces representative numbers we gate on. Desktop is collected
# for the report URL + the GPU-independent metrics (LCP, FCP, CLS,
# a11y, best-practices, SEO) which still pass strict assertions in
# the desktop config. CPU-bound desktop metrics (perf score, TBT,
# Speed Index) are warn-only because the CI runner can't represent
# them honestly — real desktop user perf gets measured by Cloudflare
# Web Analytics with actual GPUs in the loop.
continue-on-error: true
strategy:
fail-fast: false
matrix:
profile: [mobile, desktop]
name: lighthouse (${{ matrix.profile }})
steps:
- uses: actions/checkout@v7
- uses: treosh/lighthouse-ci-action@v12
with:
urls: |
${{ needs.deploy.outputs.url }}
${{ needs.deploy.outputs.url }}/oss-contribution-tracker/
${{ needs.deploy.outputs.url }}/404.html
configPath: ./.lighthouserc.${{ matrix.profile == 'mobile' && 'json' || 'desktop.json' }}
uploadArtifacts: true
temporaryPublicStorage: true
artifactName: lighthouse-results-${{ matrix.profile }}