Skip to content

yoavf/auto-pr-screenshots-action

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

Auto PR Screenshots πŸ“Έ

Automatically capture and post screenshots of your web app to pull requests. Perfect for visual regression testing, UI/UX reviews, and keeping tabs of AI generated PRs.

Screen showing comment posted by the Auto PR Screenshots GitHub action

Features

  • ⚑ Simple setup - no complex configuration needed
  • πŸ’¬ Smart PR comments that update with each push
  • πŸ—‚οΈ Organized storage in a dedicated branch
  • πŸ“Έ Multi-viewport screenshots (desktop & mobile)
  • 🌐 Multi-browser support (Chromium, Firefox, WebKit)

Quick Start

Basic Usage (Recommended)

name: Screenshots
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  screenshots:
    runs-on: ubuntu-latest
    permissions:
      contents: write      # Required for pushing screenshots
      pull-requests: write # Required for posting comments
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
      
      # Start your app (example)
      - run: npm install
      - run: npm run dev &
      
      # Wait for your app to be ready
      - run: npx wait-on http://localhost:3000
      
      - name: Take screenshots
        uses: yoavf/auto-pr-screenshots@v1
        with:
          url: http://localhost:3000
          github-token: ${{ secrets.GITHUB_TOKEN }}

Required Permissions

This action requires specific permissions to function properly:

  • contents: write - Required to create and push to the screenshots branch
  • pull-requests: write - Required to post comments on pull requests

Important: You must always provide the github-token input, even when permissions are set. The token is required for authentication, while permissions define what the token can do.

With Custom Configuration

For more control over screenshots, create .github/screenshots.config.yml:

version: 1

# Screenshot definitions
screenshots:
  - name: home-desktop
    url: http://localhost:3000
    viewport:
      width: 1440
      height: 900
    wait_for: '[data-testid="hero-section"]'
    
  - name: home-mobile
    url: http://localhost:3000
    viewport:
      width: 390
      height: 844
      deviceScaleFactor: 3
    
  - name: dashboard
    url: http://localhost:3000/dashboard
    viewport:
      width: 1440
      height: 900
    steps:
      - click: '[data-testid="login-button"]'
      - fill:
          selector: 'input[name="email"]'
          text: [email protected]
      - fill:
          selector: 'input[name="password"]'
          text: password123
      - click: 'button[type="submit"]'
      - wait_for: '[data-testid="dashboard-loaded"]'

# Output configuration
output:
  branch: gh-screenshots
  comment:
    template: default
    group_by: viewport

Action Inputs

The action needs either a url, a config-file, or will fall back to framework auto-detection.

Input Description Default Required
github-token GitHub token for posting comments and pushing screenshots - Yes
url URL of your frontend application - No*
config-file Path to config file .github/screenshots.config.yml No*
browsers Browsers to use (chromium, firefox, webkit) chromium No
skip-comment Skip posting comment to PR false No
fail-on-error Fail if screenshot capture fails true No
branch Branch for storing screenshots gh-screenshots No
working-directory Working directory to run the action in . No
show-attribution Show attribution link in PR comments false No

* At least one of url, config-file, or auto-detection must work for the action to run.

Configuration Options

Screenshot Configuration

Each screenshot can have:

  • name: Unique identifier for the screenshot
  • url: The URL to capture
  • viewport: Viewport dimensions and settings
    • width: Viewport width in pixels
    • height: Viewport height in pixels
    • deviceScaleFactor: Device scale factor (default: 2)
  • fullPage: Capture full page (default: false)
  • wait_for: CSS selector to wait for before capture
  • wait: Time to wait in milliseconds
  • steps: Array of interaction steps

Interaction Steps

Available step types:

  • click: Click an element
  • fill: Fill a form field
    • selector: CSS selector
    • text: Text to enter
  • wait: Wait for milliseconds
  • wait_for: Wait for element

Examples

Next.js App

- name: Setup and start Next.js
  run: |
    npm install
    npm run build
    npm start &
    npx wait-on http://localhost:3000

- name: Take screenshots
  uses: yoavf/auto-pr-screenshots-action@v1
  with:
    url: http://localhost:3000
    github-token: ${{ secrets.GITHUB_TOKEN }}

Docker Compose Setup

- name: Start services
  run: docker-compose up -d

- name: Wait for app
  run: npx wait-on http://localhost:8080

- name: Take screenshots
  uses: yoavf/auto-pr-screenshots-action@v1
  with:
    url: http://localhost:8080
    github-token: ${{ secrets.GITHUB_TOKEN }}

Multiple Pages

Create a config file with multiple screenshot definitions:

version: 1
screenshots:
  - name: home
    url: http://localhost:3000
    viewport:
      width: 1440
      height: 900
  
  - name: about
    url: http://localhost:3000/about
    viewport:
      width: 1440
      height: 900
  
  - name: contact
    url: http://localhost:3000/contact
    viewport:
      width: 1440
      height: 900

Framework Auto-Detection (Fallback)

If no URL or config is provided, the action will attempt to detect and use common frameworks:

  • Next.js
  • Vite
  • Create React App
  • Angular
  • Vue CLI
  • SvelteKit
  • Gatsby
  • Nuxt

Troubleshooting

Screenshots are blank or show loading state

Add a wait_for selector to ensure the page is fully loaded:

screenshots:
  - name: home
    url: http://localhost:3000
    wait_for: '[data-testid="content-loaded"]'

App takes time to start

Use wait-on or similar tools:

npm run dev &
npx wait-on http://localhost:3000 --timeout 60000

Need to test authenticated pages

Use the steps array to interact with your app:

steps:
  - click: 'button[id="login"]'
  - fill:
      selector: 'input[name="username"]'
      text: testuser
  - fill:
      selector: 'input[name="password"]'  
      text: testpass
  - click: 'button[type="submit"]'
  - wait_for: '[data-testid="user-dashboard"]'

Permission Errors

If you see the error:

Error: Resource not accessible by integration

License

MIT

About

GitHub action to generate screenshots on every PR

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •