Skip to content

Dependency Update and Visual Regression Testing #4

Dependency Update and Visual Regression Testing

Dependency Update and Visual Regression Testing #4

name: Auto update deps + Percy Web (single job)
on:
workflow_dispatch:
schedule:
- cron: "0 6 * * 1" # Mondays 11:30 IST
permissions:
contents: write
pull-requests: write
env:
PYTHON_VERSION: "3.11"
NODE_VERSION: "20"
UPDATE_BRANCH: "chore/dep-bumps-${{ github.run_id }}"
jobs:
update-pr-and-percy:
runs-on: ubuntu-latest
steps:
- name: Checkout (base)
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: "pip"
- name: Install Node deps
run: |
npm ci || npm install
- name: Create venv & install Python deps
run: |
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Bump Node deps to latest stable (incl. @percy/cli)
run: |
npx --yes npm-check-updates@latest -u --target latest
npm install --save-dev @percy/cli@latest
npm install
- name: Bump Python deps & repin requirements.txt
run: |
set -e
source .venv/bin/activate
pip install --upgrade -r requirements.txt
pip freeze > requirements.txt
- name: Verify percy CLI
run: npx percy --version
- name: Create Pull Request (if changes)
id: cpr
uses: peter-evans/create-pull-request@v6
with:
branch: ${{ env.UPDATE_BRANCH }}
commit-message: "chore: bump Node & Python deps (incl. @percy/cli) to latest stable"
title: "chore: bump deps to latest stable"
body: |
Automated dependency update:
- Node deps via npm-check-updates (stable) + npm install
- Python deps upgraded and re-pinned via pip freeze
- Ensures latest stable @percy/cli
labels: dependencies, percy
- name: Stop if no PR was created
if: ${{ steps.cpr.outputs.pull-request-number == '' }}
run: |
echo "No changes detected; no PR opened. Skipping Percy run."
echo "pr_created=0" >> $GITHUB_OUTPUT
id: nopr
# === Run Percy Web on the PR branch ===
- name: Checkout PR branch
if: ${{ steps.cpr.outputs.pull-request-number != '' }}
uses: actions/checkout@v4
with:
ref: ${{ env.UPDATE_BRANCH }}
- name: Install Node deps (PR branch)
if: ${{ steps.cpr.outputs.pull-request-number != '' }}
run: |
npm ci || npm install
- name: Re-create venv & install Python deps (PR branch)
if: ${{ steps.cpr.outputs.pull-request-number != '' }}
run: |
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
- name: Upgrade Playwright (python) and install browsers + OS deps
if: ${{ steps.cpr.outputs.pull-request-number != '' }}
env:
DEBIAN_FRONTEND: noninteractive
run: |
set -e
source .venv/bin/activate
python -m pip install --upgrade playwright
python -m playwright install --with-deps
- name: Percy Web run
if: ${{ steps.cpr.outputs.pull-request-number != '' }}
id: percy_web
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN_WEB }}
run: |
set -o pipefail
if [ -z "$PERCY_TOKEN" ]; then
echo "Missing PERCY_TOKEN_WEB secret; cannot run Percy Web."
echo "skipped=1" >> $GITHUB_OUTPUT
exit 0
fi
( source .venv/bin/activate && npx percy exec -- .venv/bin/python tests/web/test.py ) 2>&1 | tee percy_web.log
URL=$(grep -Eo 'https://percy.io[^ ]+' percy_web.log | tail -n1 || true)
ID=$(grep -Eo 'Finalized build #[0-9]+' percy_web.log | grep -Eo '[0-9]+' | tail -n1 || true)
STATUS=$?
# If command returned non-zero, mark failure
if [ $STATUS -ne 0 ]; then
echo "success=0" >> $GITHUB_OUTPUT
else
# Percy may still finalize with errors; treat URL presence as success signal
if [ -n "$URL" ]; then echo "success=1" >> $GITHUB_OUTPUT; else echo "success=0" >> $GITHUB_OUTPUT; fi
fi
echo "url=${URL}" >> $GITHUB_OUTPUT
echo "id=${ID}" >> $GITHUB_OUTPUT
- name: Comment on PR with Percy result
if: ${{ steps.cpr.outputs.pull-request-number != '' }}
uses: actions/github-script@v7
with:
script: |
const prNumber = Number('${{ steps.cpr.outputs.pull-request-number }}');
const url = '${{ steps.percy_web.outputs.url }}';
const id = '${{ steps.percy_web.outputs.id }}';
const skipped = '${{ steps.percy_web.outputs.skipped }}' === '1';
const success = '${{ steps.percy_web.outputs.success }}' === '1';
let body;
if (skipped) {
body = `## Percy Web\nSkipped (missing \`PERCY_TOKEN_WEB\`).`;
} else if (success && url) {
body = `## Percy Web\n✅ Build #${id}\n${url}`;
} else {
body = `## Percy Web\n❌ Build failed (see logs in workflow artifacts).`;
if (url) body += `\nFinalized build URL (may contain error details):\n${url}`;
}
const { context, getOctokit } = require('@actions/github');
const octokit = getOctokit(process.env.GITHUB_TOKEN);
await octokit.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body,
});
- name: Upload Percy logs
if: always() && ${{ steps.cpr.outputs.pull-request-number != '' }}
uses: actions/upload-artifact@v4
with:
name: percy-web-log
path: percy_web.log
if-no-files-found: ignore