Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions docs/product/snapshots/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: Snapshots
sidebar_order: 138
description: Snapshot testing to catch visual changes on every pull request.
beta: true
---

<Include name="feature-available-for-user-group-early-adopter" />

Snapshots helps you catch unintended visual changes before they reach users. Sentry handles image storage, diffing, CI checks, and more.

TODO: Arcade Walkthrough (1. status check showing diff, 2. click into sentry to see diff, 3. approve)

## How It Works

1. **Generate snapshots** — Your CI job produces screenshots however you like: Playwright, Paparazzi, or any tool that outputs PNGs
2. **Upload to Sentry** — `sentry-cli` uploads the snapshot directory to Sentry
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might not necessarily be sentry-cli. Could be fastlane/gradle

3. **Sentry diffs against the baseline** — Sentry compares images against corresponding base build (TODO: link to section explaining automated comparisons). With Sentry, you do not have to manage "Golden" images and everything is determined via git metadata.
4. **Results post to your PR** — Snapshot results post to your PR\*. You can configure settings(TODO: link to settings) to control status check and comment behavior.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

post might mean "comment" to some people. i think we should be clear that by default we only have status checks here but comments can also be added

5. **Review and approve** — View snapshot results on the Sentry UI. If the Snapshot "failed" you can approve it from either the PR or the Sentry UI.

\*Note: Snapshots EA only supports Github

## Prerequisites

- **Early Adopter access** — Enable the Early Adopter toggle in your [organization settings](/organization/early-adopter-features/).
- **Auth token** — A Sentry auth token with `project:write` scope (personal token) or `org:ci` scope (org-level token).
- **sentry-cli >= 3.3.5** — The `build snapshots` command requires version 3.3.5 or later.
- **GitHub integration** — Snapshots can be used with any VCS provider, but only Github is supported for status check integration and PR comments. Install the [Sentry GitHub App](/organization/integrations/source-code-mgmt/github/) and grant it access to your repository for PR integration.

## Supported Platforms

Snapshots works for any platform with a frontend and most platforms have a number of tools to help you generate snapshots. Sentry has a recommended worfklow for the following platforms:

TODO: idk if we even want this, but putting for now

- iOS
- Android
- React

<PageGrid />
44 changes: 44 additions & 0 deletions docs/product/snapshots/reviewing-snapshots/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: Reviewing Snapshots
sidebar_order: 20
description: Review snapshot diffs on your pull request and approve changes.
---

<Include name="feature-available-for-user-group-early-adopter" />

## Status Checks
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add PR comments on this page as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll put mention in the settings but since status check control a core workflow i think worth the callout. tbh this page is all slop rn and will get a rework


After you upload snapshots from a pull request branch, a **Snapshot Testing** GitHub Check appears on the pull request. If no snapshots changed, the check passes. If any snapshots were added, removed, or modified, the check fails and requires approval.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we explain that the default is that added snapshots don't fail here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will have that in the settings section and maybe just a link to "if you want to change your failure settings..."


IMAGE: GitHub Check showing Snapshot Testing results on a pull request

## Comparison Viewer

Click **Details** on the GitHub Check to open Sentry's comparison viewer. The viewer has two panels:

- **Sidebar** — Lists all snapshots grouped by status: modified, added, removed, renamed, and unchanged. Click a snapshot to view it.
- **Main panel** — Displays the selected snapshot's diff with three viewing modes:
- **Split** — Side-by-side view of base and current branch with a diff overlay highlighting changed pixels.
- **Wipe** — Drag a slider across the image to compare base and current branch.
- **Onion** — Overlay both images with an adjustable opacity slider.

IMAGE: Sentry Snapshot comparison viewer showing a modified image with split diff
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this a gif of using the onion mode on an ogre ? that would make my day.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol we'll save that for the EA blog


## Approve Changes

There are two ways to approve snapshot changes:

- Click the **Approve** button on the GitHub Check Run.
- Click **Approve** in the Sentry comparison viewer.

Approval resolves the failing check. If new changes are pushed to the PR, the check resets and requires approval again.

## Settings

Configure snapshot behavior in **Project Settings > Mobile Builds > Snapshots**.

| Setting | Default | Description |
| ------------------------- | :-----: | ----------------------------------------------------- |
| Status Checks Enabled | On | Post GitHub Check Runs for snapshot comparisons. |
| Fail on Added Snapshots | Off | Require approval when new snapshots are added. |
| Fail on Removed Snapshots | On | Require approval when existing snapshots are removed. |
150 changes: 150 additions & 0 deletions docs/product/snapshots/uploading-snapshots/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
---
title: Uploading Snapshots
sidebar_order: 10
description: Structure your snapshot directory and upload from CI with sentry-cli.
---

<Include name="feature-available-for-user-group-early-adopter" />

Snapshots works for any platform with a frontend. You can view specific platform examples [here](/product/snapshots#supported-platforms). This page covers the general upload structure and metadata schema.

## Upload command

You upload snapshots with the `sentry-cli build snapshots` command, which takes a directory of images and optional JSON metadata files.

```bash
sentry-cli build snapshots <output-dir> \
--auth-token "$SENTRY_AUTH_TOKEN" \
--app-id <app-id> \
--project <project-slug> \
```

You can reference our [example workflow](#upload-with-ci) and [full flag reference](#sentry-cli-build-snapshots-reference) below.

### Upload Structure

Each snapshot consists of two files: a `.png` image and an optional `.json` metadata file with the same base name and path. You can optionally organize snapshots into subdirectories. If using subdirectories, the filename property in the Sentry UX will include the subdirectory path.

```
snapshots/
├── homepage.png
├── homepage.json
├── settings/
│ ├── profile.png
│ ├── profile.json
│ ├── billing.png
│ └── billing.json
```

Filenames are the identity key for each snapshot. Keep them stable across runs so Sentry can accurately diff head against base.

### JSON Metadata

You can include an optional JSON file to add metadata to each image:

```json
{
"display_name": "Billing Page",
"group": "Settings"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can also add other fields as extras here, they will become tags.
For example:

  "device": "id:pixel_5",
  "nightMode": true

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't want to put that until they're actually used downstream (my understanding is that it's not in any way atm)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, that's true

}
```

| Field | Type | Description |
| -------------- | ------ | ---------------------------------------------------------- |
| `display_name` | string | Human-readable label shown in the comparison viewer. |
| `group` | string | Groups related snapshots in the comparison viewer sidebar. |

TODO: IMAGE OF DISPLAY NAME AND GROUP
TODO: if diff_threshold makes it in, add

### Supported Formats

Snapshots supports the following image formats:

- PNG
- JPEG

## Upload With CI
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should re-use the uploading with CI like we did for size analysis, or just bring it to a separate section since we are repeating ourselves everywhere https://docs.sentry.io/product/size-analysis/integrating-into-ci/


For a production example, Sentry's Github action is available [here](https://github.com/getsentry/sentry/blob/master/.github/workflows/frontend-snapshots.yml). Below is an example GitHub Actions workflow you can use as a starting point. Replace the placeholder values with your own snapshot generation command, app ID, and Sentry project slug.

```yml {filename:.github/workflows/snapshots.yml}
name: Snapshots

on:
push:
branches: [main]
pull_request:

env:
SNAPSHOT_OUTPUT_DIR: .artifacts/snapshots

jobs:
snapshots:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
with:
# Use PR head SHA, not the merge commit — avoids phantom diffs
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

took from our sentry yml, not sure if we want in example workflow or not: https://github.com/getsentry/sentry/blob/master/.github/workflows/frontend-snapshots.yml#L42

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rbro112 I read through the commit history and looks like we'll probably want to recommend this to customers? WDYT?

ref: ${{ github.event.pull_request.head.sha || github.sha }}

# -------------------------------------------------------
# YOUR SNAPSHOT GENERATION STEP(S) HERE
# -------------------------------------------------------
# Generate PNG + JSON pairs into $SNAPSHOT_OUTPUT_DIR.
# Examples:
# - Playwright screenshots
# - iOS/Android screenshots
# - Laravel Dusk screenshots
# - Any tool that produces PNGs
# -------------------------------------------------------
- name: Generate snapshots
run: <your-snapshot-command>

- name: Install sentry-cli
if: ${{ !cancelled() }}
run: curl -sL https://sentry.io/get-cli/ | SENTRY_CLI_VERSION=3.3.4 sh
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3.3.5 is the latest, but we can probably use a placeholder here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're saying dynamic value, can you link to how I would do that? Or are you saying literally put a placeholder value


- name: Upload snapshots
if: ${{ !cancelled() }}
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
run: |
ARGS=(
--auth-token "$SENTRY_AUTH_TOKEN"
build snapshots "${{ env.SNAPSHOT_OUTPUT_DIR }}"
--app-id <your-app-id>
--project <your-sentry-project>
)


sentry-cli "${ARGS[@]}"
```

## `sentry-cli build snapshots` Reference

```bash
sentry-cli build snapshots [OPTIONS] --app-id <APP_ID> <PATH>
```

| Flag | Description |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<PATH>` | Directory containing `.png` images (and optional `.json`). |
| `--app-id <APP_ID>` | Identifier for the app or bundle (e.g., `web-frontend`, `ios-app`). Must be consistent across uploads — Sentry uses it to match head and base snapshots. Max 255 characters. |
| `--auth-token <TOKEN>` | Sentry auth token with `project:write` or `org:ci` scope. Can also be set via `SENTRY_AUTH_TOKEN`. |
| `-o`, `--org <ORG>` | Sentry organization slug. Can also be set via `SENTRY_ORG`. |
| `-p`, `--project <PROJECT>` | Sentry project slug. Can also be set via `SENTRY_PROJECT`. |
| `--head-sha <SHA>` | 40-character commit SHA of the snapshot build. Auto-detected in CI. |
| `--base-sha <SHA>` | Base branch commit SHA for comparison (PR only). Auto-detected in CI. |
| `--vcs-provider <PROVIDER>` | VCS provider, e.g., `github`. Auto-detected from git remote. |
| `--head-repo-name <OWNER/REPO>` | Repository in `owner/repo` format. Auto-detected from git remote. |
| `--base-repo-name <OWNER/REPO>` | Base repository in `owner/repo` format (PR only, for forks). Auto-detected in CI. |
| `--head-ref <BRANCH>` | Head branch name. Auto-detected in CI. |
| `--base-ref <BRANCH>` | Base branch name (PR only). Auto-detected in CI. |
| `--pr-number <NUMBER>` | Pull request number (PR only). Auto-detected in GitHub Actions. |
| `--diff-threshold <THRESHOLD>` | Float between 0.0 and 1.0. Sentry only reports images as changed if the percentage of changed pixels exceeds this value. For example, `0.01` ignores changes under 1%. |
| `--no-git-metadata` | Skip automatic git metadata detection. |
| `--force-git-metadata` | Force git metadata collection even outside CI. |
| `--log-level <LEVEL>` | Logging verbosity: `debug`, `info`, `warn`, or `error`. |
| `--url <URL>` | Sentry instance URL. Defaults to `https://sentry.io`. |
Loading