Integrating Snapshots Into CI
Set up Snapshots in CI to receive automated visual diff status checks on every pull request.
This feature is currently in Beta. Beta features are still in progress and may have bugs. We recognize the irony.
The GitHub integration brings Snapshots directly into your pull request workflow by adding status checks. This alerts reviewers to any visual changes a pull request introduces, and requires approval before the check passes.
Snapshots works by comparing a head vs. base build, similar to how code review compares your new code to the baseline code.
Install the Sentry GitHub App by following the installation instructions in the GitHub integration documentation.
a. If you have previously installed the Sentry App, ensure you have accepted the latest permissions to receive status checks.
b. GitHub Enterprise users: After installing the GitHub Enterprise app, navigate to Settings > Developer Settings > GitHub Apps > [your Sentry app] > Edit > Permissions & events and confirm the following are set:
- Repository permissions: Checks — Read & write
- Repository permissions: Pull requests — Read & write
- Subscribe to events: Check run
Generate snapshots in your build using the tool that fits your platform. Common options include:
- Playwright (web)
- Paparazzi or Roborazzi
- XCUITest snapshots
- Laravel Dusk (PHP)
- Any tool that produces PNG or JPEG files
For a production reference, see Sentry's
frontend-snapshots.ymlworkflow.Modify an existing workflow or create a new workflow to upload snapshots on pushes to your main branch and on pull requests:
Upload snapshots on every commit to main to ensure the base build is always available.
sentry_snapshots.ymlname: Sentry Snapshots Upload
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
snapshots:
# Add your snapshot generation step here
# Then upload with `sentry-cli snapshots upload` — see /product/snapshots/uploading-snapshots/
name: Sentry Snapshots Upload
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
snapshots:
# Add your snapshot generation step here
# Then upload with `sentry-cli snapshots upload` — see /product/snapshots/uploading-snapshots/
Confirm that snapshots uploaded on push have the correct head-sha and no base-sha set, and that snapshots uploaded on pull_request have both head-sha and base-sha set.
- Confirm the status check appears
After configuring the workflow, a Snapshot Testing status check will appear on every pull request.
For details on the review and approval flow, see Reviewing Snapshots.
Your team may require a Snapshot Testing check on every pull request, even when some CI workflows don't produce snapshots. For example, a pull request that changes only documentation or other files that don't affect the rendered UI may not need new snapshots. In these cases, use the skip endpoint to create a neutral check for the pull request's head commit so that it can merge without generating unnecessary snapshots.
The upload and skip paths should be mutually exclusive. Each workflow should either upload snapshots or mark the check as skipped.
The example below assumes an earlier path-filtering step with an ID of changes sets a should_upload output. Use the same condition for your upload step and the inverse condition for the skip step so that only one runs. Reuse the SENTRY_AUTH_TOKEN configured for uploads and store it as an encrypted GitHub Actions secret.
skip_status_checks_example.yml- name: Mark Snapshot Testing as skipped
if: github.event_name == 'pull_request' && steps.changes.outputs.should_upload == 'false'
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
jq -n \
--arg sha "$HEAD_SHA" \
--arg repository "$GITHUB_REPOSITORY" \
'{sha: $sha, repository: $repository, provider: "github"}' |
curl --fail-with-body \
--request POST \
--header "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
--header "Content-Type: application/json" \
--data-binary @- \
"https://sentry.io/api/0/projects/$SENTRY_ORG/$SENTRY_PROJECT/preprod/snapshots/status-checks/skip/"
- name: Mark Snapshot Testing as skipped
if: github.event_name == 'pull_request' && steps.changes.outputs.should_upload == 'false'
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
jq -n \
--arg sha "$HEAD_SHA" \
--arg repository "$GITHUB_REPOSITORY" \
'{sha: $sha, repository: $repository, provider: "github"}' |
curl --fail-with-body \
--request POST \
--header "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
--header "Content-Type: application/json" \
--data-binary @- \
"https://sentry.io/api/0/projects/$SENTRY_ORG/$SENTRY_PROJECT/preprod/snapshots/status-checks/skip/"
This example is configured for GitHub.com. For GitHub Enterprise, set provider to github_enterprise.
Check that:
- The Sentry GitHub App is installed and has access to your repository.
- You're uploading snapshots from both your main branch (on
push) and your pull request branches (onpull_request). - The
--app-idvalue matches between the head and base uploads. - Your uploads include the correct git metadata (auto-detected in CI).
The first time you set up Snapshots, your main branch may not have any uploads yet:
- Merge a PR or push to your main branch to trigger an upload.
- Future PRs will be able to compare against this base build.
If diffs look unexpected, the wrong base may be selected. When checking out the PR commit, use the PR head SHA (not the merge commit) so Sentry resolves the correct base:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").