Guard
Fail your CI build when animation performance drops below a grade.
Guard
MotionScore Guard is a CI gate that prevents you from shipping animation performance regressions.
It audits your site on every pull request and posts the grades as a comment. That part is free, for everyone, with no account. Adding a MotionScore API token and a threshold upgrades the comment into a gate: the build fails when animation performance drops below the grade you set.
Guard runs a browser on your own CI runner, so it's unmetered: audits consume none of your monthly allowance, whatever your plan. Only the gate requires a paid MotionScore plan.
GitHub Actions
The MotionScore Guard action audits your preview deployment on every pull request and posts a comment with per-page grades, updated in place on every push.
It works out of the box with Vercel, Cloudflare Pages and Netlify: all three tell GitHub when a preview deployment finishes building (the deployment_status event), which is what triggers the audit.
1. Create the workflow file
Add this file to your repository as .github/workflows/motionscore.yml. GitHub runs everything in that folder automatically; there is no install step on GitHub's side (the Marketplace listing only supplies a snippet), so this file is the whole setup:
name: MotionScore Guard
on: deployment_status
permissions:
pull-requests: write
jobs:
guard:
runs-on: ubuntu-latest
steps:
- uses: motiondivision/motionscore-guard@v1
The action waits for the preview deploy, reads its URL from the deployment event, and audits your homepage. To audit specific paths, add a with: block:
- uses: motiondivision/motionscore-guard@v1
with:
pages: |
/
/pricing
2. Open a pull request
Once the preview deployment finishes, Guard appears in the pull request's checks and comments the grades. This runs free on any repository: no token, no account, nothing metered.
3. Add the gate
To fail the build when a page grades below your bar, you need a paid MotionScore plan. Copy a token from your Motion dashboard and add it as a repository secret named MOTIONSCORE_TOKEN: in your repo, open Settings → Secrets and variables → Actions → New repository secret, or from the terminal:
gh secret set MOTIONSCORE_TOKEN
Then add the threshold and token to the action's with: block:
threshold: A
token: ${{ secrets.MOTIONSCORE_TOKEN }}
threshold is the lowest grade you'll allow through. If any audited page grades below it, the check fails.
A failing check only blocks merging if you require it: in your repo, Settings → Branches, add a branch protection rule for your default branch and mark the MotionScore Guard check as required.
What it costs
Each page takes roughly one to three runner minutes, and Chrome is cached between runs. Audit your money pages, not your sitemap: three to five pages is the sweet spot. Guard runs consume none of your monthly audit allowance; set upload: true if you also want full reports on score.motion.dev (those consume audit slots and add report links to the PR comment).
Other CIs
Guard is one command, exit-code driven:
npx motionscore https://preview.example.com --threshold A --token $MOTIONSCORE_TOKEN
- Exit
0: threshold met. - Exit
1: the overall grade is below the threshold. Fail the build. - Exit
2: the audit could not run (configuration or infrastructure error).
Add --summary result.json for a compact machine-readable result to post wherever your CI reports.
If api.motion.dev cannot be reached to verify your plan, Guard warns and continues rather than failing your build; pass --strict to fail instead.
Reliable grades in CI
MotionScore analyses performance from first principles, rather than measuring FPS.
FPS can fluctuate between environments and runs depending on load. MotionScore instead detects which elements are animating, how they animate, how they are triggered, which elements are layers, how big is the layer etc. Therefore, grades are more stable between runs and between environments.
The GitHub Action launches Chrome with --no-sandbox automatically: modern Ubuntu (23.10+, including GitHub's standard runners) blocks Chrome's sandbox for unprivileged processes, and on an ephemeral CI runner that flag is the standard answer. If you run the CLI in any other CI and the audit fails at launch with Failed to launch the browser process… No usable sandbox, set MOTIONSCORE_NO_SANDBOX=1 as an environment variable; the CLI suggests this itself when it hits that error.