Skip to main content

Continuous Integration

Adding Happo to your Continuous Integration setup is a great way to catch visual regressions early. Happo will compare your PRs with the base branch and let you know exactly what has changed in your UI.

Happo status on a GitHub pull request Example of a Happo status posted to a GitHub pull request.

Setup

The instructions on this page apply to all integrations except the Cypress and Playwright integrations. Refer to the Cypress integration page and the Playwright integration page for instructions on how to integrate with CI there.

Since a lot of projects these days follow a pull-request/merge-request model, Happo provides ready-made scripts that you can run in CI:

All these scrips will:

  1. Figure out the right baseline report to compare with
  2. Run Happo on the current HEAD commit
  3. Compare the baseline with the new report
  4. If allowed to, post back a status to the commit/PR

happo-ci-travis

This script knows about the Travis build environment, assuming a PR based model. To run it, first add this to your package.json:

{
"scripts": {
"happo": "happo",
"happo-ci-travis": "happo-ci-travis"
}
}

Then, configure .travis.yml to run this script:

language: node_js
script:
- npm run happo-ci-travis

The happo-ci-travis script assumes that your PRs are based off of the master branch. If you're using a different default branch, you can set the BASE_BRANCH environment variable.

{
"scripts": {
"happo": "happo",
"happo-ci-travis": "BASE_BRANCH=\"dev\" happo-ci-travis"
}
}

happo-ci-circleci

Before you start using this script, have a look at the Happo CircleCI Orb. It simplifies some of the setup required if you use the happo-ci-circleci script.

This script knows about the CircleCI build environment, assuming a PR based model. To run it, first add this to your package.json:

{
"scripts": {
"happo": "happo",
"happo-ci-circleci": "happo-ci-circleci"
}
}

Then, configure .circleci/config.yml to run this script. Something like this:

jobs:
build:
docker:
- image: cimg/node:lts
steps:
- checkout
- run:
name: happo
command: npm run happo-ci-circleci

The happo-ci-circleci script assumes your PRs are based off of the master branch. If you're using a different default branch, you can set the BASE_BRANCH environment variable.

{
"scripts": {
"happo": "happo",
"happo-ci-circleci": "BASE_BRANCH=\"origin/dev\" happo-ci-circleci"
}
}

happo-ci-github-actions

This script knows about the GitHub Actions build environment, assuming a PR based model. To run it, first add this to your package.json:

{
"scripts": {
"happo": "happo",
"happo-ci-github-actions": "happo-ci-github-actions"
}
}

Then, configure your workflow file to run this script. Here's an example:

name: Happo CI

on:
push:
branches: [main]
pull_request:

jobs:
happo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 100
- uses: actions/setup-node@v4
- run: npm ci
- run: npm run happo-ci-github-actions
env:
HAPPO_API_KEY: ${{ secrets.HAPPO_API_KEY }}
HAPPO_API_SECRET: ${{ secrets.HAPPO_API_SECRET }}

Make sure that the workflow is configured to run on pushes to your default branch. This will ensure that baselines exist for PR builds to compare against.

happo-ci-azure-pipelines

This script is targeted at Azure Pipelines. It can be used with pull requests and regular pushes. Start by adding the happo-ci-azure-pipelines script to your package.json file:

{
"scripts": {
"happo-ci-azure-pipelines": "happo-ci-azure-pipelines"
}
}

Then, configure azure-pipelines.yml to run the happo-ci-azure-pipelines script. In the example below the HAPPO_API_KEY and HAPPO_API_SECRET environment variables are populated from two user-defined secret variables.

trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
displayName: 'Install Node.js'
- script: |
npm ci
npm run happo-ci-azure-pipelines
displayName: 'Install dependencies and run Happo'
env:
HAPPO_API_KEY: $(happoApiKey)
HAPPO_API_SECRET: $(happoApiSecret)

The trigger is set to run for pushes to the main branch. You'll have to replace this if you are using a different main branch. To trigger builds for pull request, you can use a branch policy for the main branch.

happo-ci

This is a generic script that can run in most CI environments. Before using it, you need to set a few environment variables:

  • PREVIOUS_SHA - the sha of the baseline commit
  • CURRENT_SHA - the sha of the current HEAD
  • CHANGE_URL - a link back to the change (further instructions)
{
"scripts": {
"happo": "happo",
"happo-ci": "happo-ci"
}
}

A note on using yarn

If you are invoking any of the happo CI script using yarn and you are using yarn version 2 or later, there is a chance you'll run into this error:

node_modules/happo.io/bin/happo-ci-github-actions:3
# Make the whole script fail on errors
^
SyntaxError: Invalid or unexpected token

This is because starting with version 2, yarn assumes all scripts to be node scripts. All the happo-ci scripts are written in bash which yarn won't notice. To work around this, make the following changes:

  • Add nodeLinker: node-modules to .yarnrc.yml. This will ensure that scripts are available in node_modules/.bin.
  • Invoke the happo-ci script using npx -p happo.io <name_of_script>. When scripts are in node_modules/.bin, npx won't download the happo.io library again. npx will respect the bash script and execute it properly.

Posting build statuses

Your Happo account can be configured to post build statuses to your PRs/commits. Happo currently integrates with GitHub, Bitbucket, and Azure DevOps. See specific instructions for the different providers below.

GitHub

The instructions in this section only work if you are using github.com or the on-premise version of happo.io. If you're using a local GitHub Enterprise setup, there is an alternative solution described in the next section

Step 1: Install Happo GitHub app

First you need to install the Happo GitHub App in the repository/repositories you want to run Happo in.

Installing the Happo GitHub App Installing the Happo app at https://github.com/apps/happo

Step 2: Connect with repository

Once you have the Happo GitHub app installed, you need to connect/activate the right repository with your Happo.io account on the GitHub integration page on happo.io. Once you're done with that, you're all set to have Happo automatically post statuses on your PRs/commits.

Connecting repository with the Happo account Activating the GitHub repository at https://happo.io/github-integration

Happo build statuses

Here's what it looks like when Happo posts a status on a pull request:

Happo status posted on a commit on github

If there is a diff, the status will be set to failure. To manually flip this to a success status, just go to the Happo comparison page (linked to by the "Details" link next to the Happo status) and click the Accept button at the top.

Accepting diffs

The status over on github.com will then change to success (green) for the PR/commit.

Happo status manually accepted cross-posted to github

If there are no diffs, the status is automatically set to success.

Posting statuses without installing the Happo GitHub App

If you for some reason can't install the Happo GitHub App (e.g. when using GitHub Enterprise) you can still get the Happo status posted to your PR -- as a comment on the pull request. To get this working, you have to provide the Happo CI script with user credentials containing a username and a personal access token, through HAPPO_GITHUB_USER_CREDENTIALS. E.g.

HAPPO_GITHUB_USER_CREDENTIALS="trotzig:21A4XgnSkt7f36ehlK5"

Here's a guide from github.com on how to generate the personal token.

The environment variable must contain both the username of the profile and the personal access token, separated by a colon.

If you're using GitHub Enterprise, apart from defining the environment variable you also need to add githubApiUrl to .happo.js.

Bitbucket

Step 1: Generate an app password

To authorize Happo to post statuses to your PRs/commits, you need to generate an app password.

Generating a Bitbucket app password Generating an app password through the Bitbucket UI

Step 2: Fill in form at Happo.io

Once you have the app password, you can go to the Bitbucket integration page on happo.io and fill out the form. Once you're done with that, you're all set to have Happo automatically post statuses on your PRs/commits.

Happo build statuses

Here's what it looks like when Happo posts a status on a pull request:

Happo status posted on a bitbucket commit

If there is a diff, the status will be set to failure. To manually flip this to a success status, just go to the Happo comparison page (linked to from the status) and accept the diffs.

Accepting diffs

The status over on bitbucket.org will then change to success (green) for the PR/commit. If there are no diffs, the status is automatically set to success.

Azure

Step 1: Generate a Personal Access Token (PAT)

To authorize Happo to post statuses to your PRs/commits, you need to generate an Personal Access Token.

Generating an Azure Personal Access Token Generating a Personal Access Token through the Azure UI

Set the "Code" scope to Read and Status. We need the read scope to figure out the right baseline reports to use. The status scope is used when posting build statuses to PRs.

Step 2: Fill in form at Happo.io

Once you have the PAT, you can go to the Azure integration page on happo.io and fill out the form. Once you're done with that, you're all set to have Happo automatically post statuses on your PRs/commits.

Happo build statuses

Here's what it looks like when Happo posts a status on a pull request:

Happo status posted on an azure PR

If there is a diff, the status will be set to failure. To manually flip this to a success status, just go to the Happo comparison page (linked to from the status) and accept the diffs.

Accepting diffs

The status over on Azure DevOps will then change to success (green) for the PR/commit. If there are no diffs, the status is automatically set to success.

Sync mode (optional)

By default, happo-ci will generate screenshots asynchronously, meaning your CI run will finish before screenshots are ready. You can disable this behavior by setting a HAPPO_IS_ASYNC=false environment variable. If set, Happo will do two things differently:

  • The CI run will wait for reports to be ready before finishing
  • The baseline report is generated on the fly, by checking out the previous commit on the main branch and running happo once more.

In sync mode, your npm client is automatically detected (yarn or npm), and Happo will run npm install/yarn install before generating screenshots. If you have other dependencies/preprocessing steps that need to happen, you can override this with the INSTALL_CMD environment variable. E.g.

INSTALL_CMD="lerna bootstrap" npm run happo-ci-travis

In this example, the lerna bootstrap command will be invoked before running happo run on each commit, instead of yarn install/npm install.

Email notifications

You can set up the CI integration to send email notifications when comparison reports are ready. Set aHAPPO_NOTIFY environment variable to one or more (comma-separated) email addresses and emails will be sent from Happo when results are available.

export HAPPO_NOTIFY=user@example.com

In many cases, you want to send the email to the person responsible for the change/PR that triggered the Happo tests. You can do that via a git show one-liner. This example is for Circle CI:

steps:
- checkout
- run: npm ci
- run:
echo 'export HAPPO_NOTIFY=$(git show -s --format=%ae HEAD)' >> $BASH_ENV
- happo/run_happo

Here's an example for GitHub Actions:

- name: Set Happo notification email address
run: echo "HAPPO_NOTIFY=$(git show -s --format=%ae HEAD)" >> $GITHUB_ENV

Multiple recipients

Use a comma-separated list of email addresses to send the notification to several recipients:

export HAPPO_NOTIFY=user@example.com,service-account@mycompany.com

The CHANGE_URL environment variable is be sent to Happo and will be used to contextualize the report. Happo will link back to the CHANGE_URL whenever the report is shown. Some good examples of links to use:

  • A URL that leads to the pull request/merge request that started the build
  • A link to the commit associated with the build