feat(snapshots): Restructure sidecar JSON to match ingestion schema#1162
feat(snapshots): Restructure sidecar JSON to match ingestion schema#1162runningcode wants to merge 2 commits intomainfrom
Conversation
Bucket appearance inputs (locale, device, font_scale, api_level, width_dp, height_dp, show_system_ui, show_background, preview_name) under `tags`; move preview identity (class_name, method_name, image_file_name) under `context`; replace the `night_mode` boolean with a `color_mode` enum that is emitted only when `uiMode` explicitly sets `UI_MODE_NIGHT_YES` or `UI_MODE_NIGHT_NO`. The serializer is extended with a small recursive `renderJson` helper so the template can emit nested objects without pulling in a JSON library. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Instructions and example for changelogPlease add an entry to Example: ## Unreleased
### Features
- Restructure sidecar JSON to match ingestion schema ([#1162](https://github.com/getsentry/sentry-android-gradle-plugin/pull/1162))If none of the above apply, you can opt out of this check by adding |
| if (info.showBackground) metadata["show_background"] = true | ||
|
|
||
| when (info.uiMode and UI_MODE_NIGHT_MASK) { | ||
| UI_MODE_NIGHT_YES -> metadata["color_mode"] = "dark" |
There was a problem hiding this comment.
Make sure to pass this through as uiMode in context
Relocate the uiMode → light/dark mapping from the top-level metadata field `color_mode` into the `tags` map, keyed as `ui_mode`. This aligns the field with the other appearance inputs (locale, device, font_scale, etc.) and matches the ingestion schema's expectation that preview configuration travels as tags rather than first-class metadata. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6acdeab. Configure here.
| when (info.uiMode and UI_MODE_NIGHT_MASK) { | ||
| UI_MODE_NIGHT_YES -> tags["ui_mode"] = "dark" | ||
| UI_MODE_NIGHT_NO -> tags["ui_mode"] = "light" | ||
| } |
There was a problem hiding this comment.
Night mode field has wrong name and wrong placement
High Severity
The dark/light value is placed in tags under the key ui_mode, but the PR description and example JSON clearly define it as color_mode at the top level of the metadata (alongside display_name, group, diff_threshold). Additionally, the reviewer asks for the raw uiMode to be passed through in the context block, which is also not done. Both the field name and its location contradict the ingestion schema this PR is designed to match.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 6acdeab. Configure here.


Summary
Aligns the per-snapshot sidecar JSON with the ingestion JSON Schema by organizing fields into the defined buckets:
display_name,group,diff_threshold,color_modetags(appearance / render inputs):preview_name,locale,device,font_scale,api_level,width_dp,height_dp,show_system_ui,show_backgroundcontext(preview identity / location):image_file_name,class_name,method_nameNotable behavior changes:
night_modeboolean is replaced by acolor_modeenum. It is emitted only when the@Preview(uiMode = …)bits explicitly setUI_MODE_NIGHT_YES→"dark"orUI_MODE_NIGHT_NO→"light". The commonUI_MODE_NIGHT_UNDEFINEDcase (which is the default for unannotated previews) now yields nocolor_modekey.preview_name(the@Preview(name = …)label) moves from top level intotags.tagsis omitted when empty;contextis always present.Implementation notes:
GenerateSnapshotTestsTask.kt), so the change lives in that template.renderJson(value, indentLevel)that handlesString,Number,Boolean, andMap<*,*>— no new dependencies.Example output:
{ "display_name": "FooPreview", "group": "main", "color_mode": "dark", "tags": { "preview_name": "Dark", "locale": "en", "font_scale": 1.5 }, "context": { "image_file_name": "com.example.FooPreview", "class_name": "com.example.Foo", "method_name": "FooPreview" } }#skip-changelog