Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 

Repository files navigation

diffdeck-action

GitHub Action that renders + uploads Storybook screenshots and uploads Playwright recordings to DiffDeck for hosted visual review and screenshot diffs.

It is a thin wrapper around the @diffdeckai/cli npm package: it fills branch/commit metadata from the GitHub context, runs the CLI via npx, and surfaces the resulting DiffDeck URL as an action output. All upload logic lives in the CLI — this action implements none of it.

Modes

The command input selects what to do (default auto):

command CLI command What it does
auto (detected) Runs every applicable mode: a recording when video is set, and a screenshot pass when the Storybook dir exists.
screenshot screenshot-storybook Renders every story in CI (six variants) + render-check, then uploads the screenshots + build. A story that fails to render fails the job.
storybook upload-storybook Uploads the built Storybook only; the server renders the screenshots.
recording upload-recording Uploads a single Playwright recording (video + test metadata).

Screenshot mode needs Playwright in your project — add it as a devDependency (npm i -D playwright). The action runs playwright install chromium for you (unless install-browsers: false) and caches the download between runs. It does not run --with-deps by default (GitHub-hosted runners already have the system libraries, and the apt install is slow); set install-deps: true if your runner needs them.

Usage

Add your DiffDeck project token (shown when you add a repository in DiffDeck) as a repository secret named DIFFDECK_TOKEN.

Screenshot a Storybook in CI (recommended)

name: DiffDeck Storybook
on: [push, pull_request]

jobs:
  diffdeck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0 # so commit metadata is available
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm ci
      - run: npm run build-storybook -- --output-dir storybook-static
      - uses: diffdeck/diffdeck-action@v1
        with:
          # command: auto  # the default — a Storybook dir present ⇒ screenshot mode
          token: ${{ secrets.DIFFDECK_TOKEN }}
          dir: storybook-static

Incremental rendering (TurboSnap)

In screenshot mode the action renders only the stories affected by files changed since the baseline build, and the server carries the rest forward — so a typical PR renders a handful of stories instead of the whole library. It kicks in automatically when two things are present:

  • fetch-depth: 0 on actions/checkout (already in the example above) — so the CLI can git diff the baseline commit against HEAD. On a shallow clone the CLI now tries to fetch just the baseline commit on demand, so incremental often works even without this; fetch-depth: 0 is the reliable guarantee.

  • --webpack-stats-json when building Storybook — so preview-stats.json (the module graph) lands in the build dir:

          - run: npm run build-storybook -- --output-dir storybook-static --webpack-stats-json

It fails open to a full render whenever it can't scope safely (no baseline yet, no stats file, a shallow clone, or a global file like a lockfile / .storybook config changed). Set full: true for a periodic full render to bound any drift.

Upload a Storybook build (server renders)

      - uses: diffdeck/diffdeck-action@v1
        with:
          command: storybook
          token: ${{ secrets.DIFFDECK_TOKEN }}
          dir: storybook-static

Upload a Playwright recording

      - uses: diffdeck/diffdeck-action@v1
        with:
          command: recording
          token: ${{ secrets.DIFFDECK_TOKEN }}
          video: test-results/home.webm
          test: "Home page renders"
          file: "tests/home.spec.ts"
          status: passed

For a whole Playwright run, the @diffdeckai/playwright-reporter is the better fit — it uploads every recording with metadata automatically. Use this action's recording mode for one-off single-video uploads.

Using the URL output

      - uses: diffdeck/diffdeck-action@v1
        id: diffdeck
        with:
          token: ${{ secrets.DIFFDECK_TOKEN }}
          dir: storybook-static
      - run: echo "Review at ${{ steps.diffdeck.outputs.url }}"

Inputs

Input Required Default Description
command no auto auto, screenshot, storybook, or recording.
token yes DiffDeck project token. Use a repository secret (e.g. ${{ secrets.DIFFDECK_TOKEN }}).
dir no storybook-static Built Storybook static directory (for screenshot/storybook).
video no Recorded Playwright video file (for recording).
host no (CLI default — https://diffdeck.ai) DiffDeck base URL. Set only for self-hosted / non-default deployments.
branch no github.head_ref || github.ref_name Branch the upload is for.
commit no github.sha Commit SHA the upload is for.
message no (commit subject line) Commit message for Storybook builds.
default-branch no github.event.repository.default_branch Repository default branch. Persisted server-side so PR/feature-branch builds resolve their baseline against it.
pr-number no github.event.pull_request.number Pull request number the build is for. Persisted server-side so the build deep-links straight to the exact PR (else a branch-filtered PR search).
install-browsers no true In screenshot mode, run playwright install chromium first.
install-deps no false Also install system libs (--with-deps). Slow; usually unneeded on GitHub-hosted runners.
cache-browsers no true Cache ~/.cache/ms-playwright between runs (screenshot mode).
concurrency no (CLI default — ~3× CPU, capped 4–16) Parallel render workers.
locale no (CLI default — en-US) Browser locale for rendering.
timezone no (CLI default — UTC) Browser timezone for rendering.
settle no (CLI default — 500) Milliseconds to wait after each story renders before screenshotting.
full no false Force a full render (disable incremental/TurboSnap scoping).
stats no (<dir>/preview-stats.json) Webpack stats JSON for incremental scoping.
test no Recording: test title.
file no Recording: test file path.
test-id no Recording: stable test identifier.
status no Recording: test status (passed, failed, …).
duration no Recording: test duration in milliseconds.
retries no Recording: number of retries.
metadata no Recording: extra metadata as a JSON string.
cli-version no latest Version (npm dist-tag or semver) of @diffdeckai/cli to run.

Outputs

Output Description
url URL of the uploaded build / recording on DiffDeck (parsed from CLI).

How it works

The action runs (roughly):

# screenshot (the auto default when a Storybook dir is present)
DIFFDECK_TOKEN=<token> \
  npx @diffdeckai/cli@<cli-version> screenshot-storybook --dir <dir> --branch <branch> --commit <commit> [--message <msg>] [--host <host>]

# storybook (server renders)
DIFFDECK_TOKEN=<token> \
  npx @diffdeckai/cli@<cli-version> upload-storybook --dir <dir> --branch <branch> --commit <commit> [--message <msg>] [--host <host>]

# recording
DIFFDECK_TOKEN=<token> \
  npx @diffdeckai/cli@<cli-version> upload-recording --video <video> --branch <branch> --commit <commit> [metadata…] [--host <host>]

The token is passed to the CLI via the DIFFDECK_TOKEN environment variable (never on the command line); the CLI sends it to DiffDeck as the X-UI-Review-Token request header. The action captures the CLI's output and exposes the review URL it prints as the url output.

License

MIT

About

DiffDeck GitHub Action — upload Storybook builds and Playwright recordings to DiffDeck

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors