add workflow #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Auto update dependencies and create PR | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 6 * * 1" # Mondays 11:30 IST | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| branches: | |
| - "**" | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| concurrency: | |
| group: percy-auto-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| PYTHON_VERSION: "3.11" | |
| NODE_VERSION: "20" | |
| jobs: | |
| update-and-pr: | |
| name: Check & bump deps, open PR | |
| if: github.event_name != 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| 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 (existing lock or fresh) | |
| run: | | |
| npm ci || npm install | |
| - name: Install Python deps (venv) | |
| 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 --rejectPrerelease | |
| # ensure percy CLI is present and latest stable | |
| npm install --save-dev @percy/cli@latest | |
| npm install | |
| - name: Bump Python deps & repin requirements.txt | |
| run: | | |
| set -e | |
| source .venv/bin/activate | |
| # Upgrade all installed pkgs from requirements.txt | |
| pip install --upgrade -r requirements.txt | |
| # Fully pin back the environment | |
| pip freeze > requirements.txt | |
| - name: Verify percy CLI version | |
| run: | | |
| npx percy --version | |
| - name: Create Pull Request | |
| id: cpr | |
| uses: peter-evans/create-pull-request@v6 | |
| with: | |
| branch: chore/dep-bumps-${{ github.run_id }} | |
| commit-message: "chore: bump Node & Python deps (incl. @percy/cli) to latest stable" | |
| title: "chore: bump deps to latest stable" | |
| body: | | |
| This PR updates all dependencies to the latest stable versions: | |
| - Node deps via `npm-check-updates` + `npm install` | |
| - Python deps upgraded and re-pinned via `pip freeze > requirements.txt` | |
| - Ensures latest stable `@percy/cli` | |
| CI will run Percy Web and Percy on Automate on this PR. | |
| labels: dependencies, percy | |
| signoff: false | |
| - name: PR URL | |
| if: steps.cpr.outputs.pull-request-url | |
| run: echo "PR=${{ steps.cpr.outputs.pull-request-url }}" | |
| percy-on-pr: | |
| name: Run Percy Web & Automate, comment result | |
| # Only run on PRs (including the one created above) – ensure deps are tested before merge | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| 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 project deps (README Step 1) | |
| run: | | |
| # Node | |
| npm ci || npm install | |
| # Python (venv) | |
| python -m venv .venv | |
| source .venv/bin/activate | |
| python -m pip install --upgrade pip | |
| pip install -r requirements.txt | |
| python -m pip install --upgrade playwright | |
| - name: Install Playwright browsers | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| run: | | |
| source .venv/bin/activate | |
| python -m playwright install --with-deps | |
| - name: Percy Web run | |
| id: percy_web | |
| env: | |
| PERCY_TOKEN: ${{ secrets.PERCY_TOKEN_WEB }} | |
| run: | | |
| set -o pipefail | |
| if [ -z "$PERCY_TOKEN" ]; then | |
| echo "no_token=1" >> $GITHUB_OUTPUT | |
| echo "Missing PERCY_TOKEN_WEB secret; skipping Percy Web." | |
| exit 0 | |
| fi | |
| # Run test and capture percy output to file | |
| ( npx percy exec -- python3 tests/web/test.py ) 2>&1 | tee percy_web.log | |
| # Extract finalized build URL/ID from CLI output | |
| 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) | |
| echo "url=${URL}" >> $GITHUB_OUTPUT | |
| echo "id=${ID}" >> $GITHUB_OUTPUT | |
| - name: Percy Automate run | |
| id: percy_auto | |
| env: | |
| PERCY_TOKEN: ${{ secrets.PERCY_TOKEN_AUTO }} | |
| BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} | |
| BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} | |
| run: | | |
| set -o pipefail | |
| if [ -z "$PERCY_TOKEN" ] || [ -z "$BROWSERSTACK_USERNAME" ] || [ -z "$BROWSERSTACK_ACCESS_KEY" ]; then | |
| echo "missing_secrets=1" >> $GITHUB_OUTPUT | |
| echo "Missing one or more Automate secrets; skipping Percy on Automate." | |
| exit 0 | |
| fi | |
| ( npx percy exec -- python3 tests/automate/test.py ) 2>&1 | tee percy_auto.log | |
| URL=$(grep -Eo 'https://percy.io[^ ]+' percy_auto.log | tail -n1 || true) | |
| ID=$(grep -Eo 'Finalized build #[0-9]+' percy_auto.log | grep -Eo '[0-9]+' | tail -n1 || true) | |
| echo "url=${URL}" >> $GITHUB_OUTPUT | |
| echo "id=${ID}" >> $GITHUB_OUTPUT | |
| - name: Summarize & comment on PR | |
| id: comment | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const core = require('@actions/core'); | |
| const { context, getOctokit } = require('@actions/github'); | |
| const w_no_token = core.getInput('percy_web.no_token') || process.env['percy_web_no_token']; | |
| const webId = '${{ steps.percy_web.outputs.id }}'; | |
| const webUrl = '${{ steps.percy_web.outputs.url }}'; | |
| const autoMissing = '${{ steps.percy_auto.outputs.missing_secrets }}'; | |
| const autoId = '${{ steps.percy_auto.outputs.id }}'; | |
| const autoUrl = '${{ steps.percy_auto.outputs.url }}'; | |
| function statusLine(name, id, url, skipped) { | |
| if (skipped) return `**${name}:** skipped (missing secrets)`; | |
| if (url) return `**${name}:** ✅ Build #${id} — ${url}`; | |
| return `**${name}:** ❌ Failed (see logs in workflow artifacts)`; | |
| } | |
| const lines = []; | |
| lines.push('## Percy results'); | |
| lines.push(statusLine('Percy Web', webId, webUrl, '${{ steps.percy_web.outputs.no_token }}' === '1')); | |
| lines.push(statusLine('Percy on Automate', autoId, autoUrl, autoMissing === '1')); | |
| const body = lines.join('\n'); | |
| const token = process.env.GITHUB_TOKEN || '${{ secrets.GITHUB_TOKEN }}'; | |
| const octokit = getOctokit(token); | |
| await octokit.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body | |
| }); | |
| - name: Upload logs (always) | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: percy-logs | |
| path: | | |
| percy_web.log | |
| percy_auto.log | |
| if-no-files-found: ignore |