Automate Chromatic with GitHub Actions

Chromatic has a GitHub Action to help you automate your visual regression tests and publish Storybook.

Setup

In your .github/workflows directory, create a new file called chromatic.yml and add the following:

# .github/workflows/chromatic.yml

# Workflow name
name: 'Chromatic'

# Event for the workflow
on: push

# List of jobs
jobs:
  chromatic-deployment:
    # Operating System
    runs-on: ubuntu-latest
    # Job steps
    steps:
      - uses: actions/checkout@v1
      - name: Install dependencies
        run: yarn
        # 👇 Adds Chromatic as a step in the workflow
      - name: Publish to Chromatic
        uses: chromaui/action@v1
        # Chromatic GitHub Action options
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # 👇 Chromatic projectToken, refer to the manage page to obtain it.
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}

For extra security, you’ll need to configure secrets.

In a new browser window, navigate to your GitHub repository. Click the Settings tab, followed by Secrets and then New secret.

GitHub Secrets workflow

Fill in the form with the necessary information, as detailed below, replace Value with your own Chromatic project token.

GitHub repository secret configured

Finish by clicking the Add secret button.

Read the official GitHub secrets documentation.

Forked repositories

Secrets work at a repository level. Forked repositories will not have access to them. If you want to run Chromatic on cross-repository (forked) PRs, you’ll need to make the project-token public in your package.json as part of a script:

{
  scripts:{
    chromatic:"chromatic --project-token=CHROMATIC_PROJECT_TOKEN"
  }
}
Replace CHROMATIC_PROJECT_TOKEN with your own token obtained from Chromatic.

Or you could disable Chromatic on pull requests from forked repositories.

Available options

Chromatic’s GitHub Action includes additional options to customize your workflow. The table below lists what’s currently available:

Option Description Type Example value
buildScriptName The script that builds your Storybook String build-storybook
storybookBuildDir Provide a directory with your built Storybook. String storybook-static
allowConsoleErrors Do not exit when runtime errors occur in Storybook N/A N/A
autoAcceptChanges Automatically accepts all changes in Chromatic String or Boolean my-branch or true
exitZeroOnChanges Positive exit of action even when there are changes detected String or Boolean my-branch or true
exitOnceUploaded Exit with status 0 (OK) once the build has been sent to Chromatic String or Boolean my-branch or true

Support for actions/checkout@v2

Version 2 of the actions/checkout is supported. But it comes with a caveat. It will only retrieve a single commit without any additional history. Chromatic needs the full Git history to keep track of changes in your repository.

You’ll need to make the following change to your workflow:

# .github/workflows/chromatic.yml

# Other configuration required

jobs:
  chromatic-deployment:
    steps:
        # 👇 Version 2 of the action
      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          fetch-depth: 0 # 👈 Required to retrieve git history
      - name: Install dependencies
        run: yarn
        # 👇 Adds Chromatic as a step in the workflow
      - name: Publish to Chromatic
        uses: chromaui/action@v1
        # Options required to the GitHub Chromatic Action
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # 👇 Chromatic projectToken, refer to the manage page to obtain it.
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
Read the official GitHub Actions documentation.

Run Chromatic on specific branches

If you need to customize your workflow to run Chromatic on specific branches, adjust your workflow like so:

# .github/workflows/chromatic.yml

# Other necessary configuration

# 👇 Workflow event to trigger execution
on:
  push:
    branches-ignore: 
      - 'example' # 👈 Excludes the example branch

jobs:
# The list of jobs and steps

Now Chromatic will run for any branch except example.

Other branches can also be included such as the ones created by the Renovate bot.

GitHub’s Actions like other CI systems can run based on any type of event. Our recommendation is to run the Chromatic’s step on push events. All other event types except pull-request will not work.

The pull-request event requires special consideration. Like other CI systems, GitHub allows workflow execution on either commits pushed to a branch in a pull request. Or for “merge” commits between that branch and the base branch (master).

These specific types of commits (merge) don’t persist in the history of your repository. That can cause Chromatic’s baselines to be lost in certain situations. Hence why we recommend running Chromatic’s step on push.

UI Test and UI Review

UI Tests and UI Review rely on branch and baseline detection to keep track of snapshots. We recommend the following configuration.

Command exit code for “required” checks

If you are using pull request statuses as required checks before merging, you may not want your workflow step to fail if test snapshots render without errors (but with changes). To achieve this, pass the option exitZeroOnChanges to the with clause, and your workflow will continue in such cases. For example:

# .github/workflows/chromatic.yml

# Other necessary configuration

jobs:
  chromatic-deployment:
    steps:
        # 👇 Adds Chromatic as a step in the workflow
      - name: Publish to Chromatic
        uses: chromaui/action@v1
        # Options required to the GitHub chromatic action
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # 👇 Chromatic projectToken, refer to the manage page to obtain it.
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
          exitZeroOnChanges: true # 👈 Option to prevent the workflow from failing
Read about the available options.

When using exitZeroOnChanges your workflow will still stop and fail if your Storybook contains stories that error.

Re-run failed builds after verifying UI test results

Builds that contain visual changes need to be verified. They will fail if you are not using the exitZeroOnChanges option. Once you accept all the changes, re-run the workflow and the chromatic-deployment job will pass.

If you deny any change, you will need to make the necessary code changes to fix the test (and thus start a new run) to get Chromatic to pass again.

Maintain a clean “master” branch

A clean master branch is a development best practice and highly recommended for Chromatic. In practice, this means ensuring that test builds in your master branch are passing.

If the builds are a result of direct commits to master, you will need to accept changes to keep master clean. If they’re merged from feature-branches, you will need to make sure those branches are passing before you merge into master.

GitHub squash/rebase merge and the “master” branch

GitHub’s squash/rebase merge functionality creates new commits that have no association to the branch being merged. If you’ve enabled our GitHub application in the UI Review workflow, then we will automatically detect this situation and bring baselines over (see Branching and Baselines for more details).

If you’re using this functionality but notice the incoming changes were not accepted as baselines in Chromatic, then you’ll need to adjust the workflow to include a new step with the autoAcceptChanges option. For example:

# .github/workflows/chromatic.yml

# Other necessary configuration for the action

jobs:
  chromatic-deployment:
    steps:
        # Other steps
      
        # 👇 Checks if the branch is not master and runs Chromatic
      - name: Publish to Chromatic
        if: github.ref != 'refs/heads/master' 
        uses: chromaui/action@v1
        # Required options for the Chromatic GitHub Action
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # 👇 Chromatic projectToken, refer to the manage page to obtain it.
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
        # 👇 Checks if the branch is master and accepts all changes in Chromatic
      - name: Publish to Chromatic and auto accept changes
        if: github.ref == 'refs/heads/master' 
        uses: chromaui/action@v1
        # Required options for the Chromatic GitHub Action
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          # 👇 Chromatic projectToken, refer to the manage page to obtain it.
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
          autoAcceptChanges: true # 👈 Option to accept all changes

Read about the available options.

Including the autoAcceptChanges option ensures all incoming changes will be accepted as baselines. Additionally you’ll maintain a clean master branch.

Run Chromatic on external forks of open source projects

You can enable PR checks for external forks by sharing your project-token where you configured the Chromatic command (often in package.json or in the workflow step).

There are tradeoffs. Sharing project-token‘s allows contributors and others to run Chromatic. They’ll be able to use your snapshots. They will not be able to get access to your account, settings, or accept baselines. This can be an acceptable tradeoff for open source projects who value community contributions.

Skipping builds for certain branches

Sometimes you might want to skip running a build for a certain branch, but still have Chromatic mark the latest commit on that branch as “passed”. Otherwise pull requests could be blocked due to required checks that remain pending. To avoid this issue, you can run chromatic with the --skip flag. This flag accepts a branch name or glob pattern.

One use case for this feature is skipping builds for branches created by a bot. For instance, Dependabot automatically updates a projects dependencies. Although some dependencies can result in UI changes, you might not find it worthwhile to run Chromatic for every single dependency update. Instead, you could rely on Chromatic running against the master or develop branch.

To skip builds for dependabot branches, use the following:

chromatic --skip 'dependabot/**'

To apply this to multiple branches, use an “extended glob”. See picomatch for details.

chromatic --skip '@(renovate/**|dependabot/**)'