Skip to content

feat(examples): Add Paparazzi snapshot setup to instrumentation sample#1145

Open
runningcode wants to merge 5 commits intomainfrom
no/add-paparazzi-snapshot-example
Open

feat(examples): Add Paparazzi snapshot setup to instrumentation sample#1145
runningcode wants to merge 5 commits intomainfrom
no/add-paparazzi-snapshot-example

Conversation

@runningcode
Copy link
Copy Markdown
Contributor

@runningcode runningcode commented Apr 13, 2026

Summary

  • Apply app.cash.paparazzi 2.0.0-alpha04 to the android-instrumentation-sample and enable sentry { snapshots { enabled.set(true) } }
  • Add @Preview composables (HomeTextPreview, DetailsTextPreview) so the snapshot scanner has something to discover
  • Add a CI step in the pre-merge workflow to record and upload snapshots when SENTRY_AUTH_TOKEN is available

#skip-changelog

🤖 Generated with Claude Code

Enable the Sentry snapshot integration in the android-instrumentation-sample
by applying the Paparazzi plugin and adding @Preview composables. The CI
pre-merge workflow now records and uploads snapshots when SENTRY_AUTH_TOKEN
is available.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 13, 2026

Semver Impact of This PR

🟡 Minor (new features)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


This PR will not appear in the changelog.


🤖 This preview updates automatically when you update the PR.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 13, 2026

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against aa263dc


- name: Record and upload snapshots
if: env.SENTRY_AUTH_TOKEN != ''
run: ./gradlew :examples:android-instrumentation-sample:sentryUploadSnapshotsStagingDebug
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Snapshot upload runs redundantly on all three OS matrices

Medium Severity

The new "Record and upload snapshots" step runs on all three matrix OSes (ubuntu-latest, macos-latest, windows-latest) since it only guards on SENTRY_AUTH_TOKEN. Paparazzi snapshot rendering can produce platform-dependent output (e.g., font rendering differences), so uploading from all three OSes can result in non-deterministic snapshots overwriting each other in Sentry. This likely needs a runner.os condition (similar to the existing preMerge step) to restrict it to a single OS.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c0d0a21. Configure here.

Keep the original composable signatures non-nullable by passing a
dummy NavController from rememberNavController() in the preview
functions instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +66 to +68
@Preview
@Composable
fun HomeTextPreview() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: Calling rememberNavController() inside @Preview composables will crash Paparazzi snapshot tests because a ViewModelStoreOwner is not available in the test environment.
Severity: HIGH

Suggested Fix

To prevent the crash, do not call rememberNavController() directly within @Preview functions. Instead, create and pass a mock NavController to the composable under test. For example: HomeText(navController = NavController(LocalContext.current), ...). Alternatively, you can wrap the preview composable with a CompositionLocalProvider to supply a fake ViewModelStoreOwner for the test environment.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location:
examples/android-instrumentation-sample/src/main/java/io/sentry/samples/instrumentation/ui/ComposeActivity.kt#L66-L68

Potential issue: The `@Preview` composables `HomeTextPreview` and `DetailsTextPreview`
directly invoke `rememberNavController()`. This function internally depends on
`LocalViewModelStoreOwner.current` to get a `ViewModelStoreOwner`. The Paparazzi
snapshot testing environment, which runs on a JVM, does not provide this context by
default. As a result, attempting to generate snapshots for these previews will cause a
runtime crash, likely an `IllegalStateException`. This crash will cause the
`recordPaparazziStagingDebug` Gradle task to fail, which in turn will block the CI
workflow step `sentryUploadSnapshotsStagingDebug` from completing.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 951e483. Configure here.

@Composable
fun HomeTextPreview() {
HomeText(rememberNavController(), RoundedCornerShape(50))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Preview composables may crash in Paparazzi rendering context

Medium Severity

HomeTextPreview and DetailsTextPreview call rememberNavController(), which internally uses checkNotNull(LocalViewModelStoreOwner.current). Paparazzi's rendering context may not provide LocalViewModelStoreOwner, causing an IllegalStateException at snapshot recording time. This is a known class of issues with navigation components in Paparazzi (cashapp/paparazzi#635). Simpler preview-safe composables that don't require NavController would avoid this risk.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 951e483. Configure here.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +49 to +52

- name: Record and upload snapshots
if: env.SENTRY_AUTH_TOKEN != ''
run: ./gradlew :examples:android-instrumentation-sample:sentryUploadSnapshotsStagingDebug
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The use of .first() to find the Paparazzi snapshots directory is unsafe and will throw an exception if the directory is not found in the test task's outputs.
Severity: MEDIUM

Suggested Fix

Replace the unsafe .first() call with .firstOrNull(). This allows for checking if the directory exists and throwing a more informative GradleException if it is not found, preventing unexpected build failures.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: .github/workflows/pre-merge.yaml#L49-L52

Potential issue: The code uses `.first { file -> file.name == "snapshots" }` to find a
snapshots directory within a test task's output files. This will throw a
`NoSuchElementException` if no file with that name is found, causing the build to fail.
Standard test tasks do not typically produce a "snapshots" directory in their output,
and while the Paparazzi library might configure this, it's an undocumented behavior.
This makes the code fragile and reliant on a specific, unconfirmed output structure of
an alpha version of a library.

runningcode and others added 2 commits April 13, 2026 17:13
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants