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.
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:
happo-ci-travis
- a script designed to be run in a Travis environment.happo-ci-circleci
- for CircleCI environments.happo-ci-github-actions
- used with GitHub Actions.happo-ci-azure-pipelines
- used with Azure DevOps Pipelines.happo-ci
- a generic script designed to work in any CI environment. This script is used by all the other CI scripts under the hood.
All these scrips will:
- Figure out the right baseline report to compare with
- Run Happo on the current HEAD commit
- Compare the baseline with the new report
- 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:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
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 commitCURRENT_SHA
- the sha of the current HEADCHANGE_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 innode_modules/.bin
. - Invoke the happo-ci script using
npx -p happo.io <name_of_script>
. When scripts are innode_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 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.
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:
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.
The status over on github.com will then change to success (green) for the PR/commit.
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 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:
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.
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 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:
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.
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
Setting the right link
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