-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
feat(preprod): Add support for Apple insight types on Compare #106967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(preprod): Add support for Apple insight types on Compare #106967
Conversation
|
🚨 Warning: This pull request contains Frontend and Backend changes! It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently. Have questions? Please ask in the |
| insights: ( | ||
| Annotated[AndroidInsightResults | AppleInsightResults, Field(discriminator="platform")] | ||
| | None | ||
| ) = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: The SizeAnalysisResults model now requires a platform field. Parsing old analysis data lacking this field via parse_raw() will raise an unhandled ValidationError, crashing the task.
Severity: HIGH
Suggested Fix
To ensure backward compatibility, add try/except ValidationError blocks around the parse_raw() calls to gracefully handle parsing failures for old data. The exception handler could attempt to re-parse the data with a default platform or log the failure without crashing the entire task. Alternatively, adjust the Pydantic model to handle the absence of the platform field in old data.
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: src/sentry/preprod/size_analysis/models.py#L140-L143
Potential issue: The introduction of a Pydantic discriminated union on the `insights`
field in `SizeAnalysisResults` makes the `platform` field a required discriminator.
However, historical size analysis data stored in the database lacks this field. When a
size comparison task is run against an old baseline, the call to
`SizeAnalysisResults.parse_raw()` will fail with a `ValidationError`. Since these calls
are not wrapped in error handling blocks, the task will crash, leading to failed
analysis comparisons and incomplete results.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a valid issue. The platform field has a default value on both models:
class AndroidInsightResults(BaseModel):
platform: Literal["android"] = "android"
class AppleInsightResults(BaseModel):
platform: Literal["apple"] = "apple"When the discriminator field is missing from historical data, Pydantic does not raise a ValidationError. Instead, it falls back to left-to-right union validation and uses the default value.
Verified in Django shell:
>>> old_data = '{"analysis_duration": 0.5, "insights": {"image_optimization": {"total_savings": 1200, "optimizable_files": []}}}'
>>> result = SizeAnalysisResults.parse_raw(old_data)
>>> result.insights
AndroidInsightResults(platform='android', ...) # Parses successfully, no crashThe behavior is:
- Old data (no platform field): Parses successfully, maps to AndroidInsightResults, iOS-specific fields silently dropped (existing behavior)
- New data (with platform field): Parses successfully, correctly maps to the right model type
This is the intended backwards-compatible behavior documented in the PR.
There was a problem hiding this 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.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| 'multiple_native_library_archs', | ||
| 'video_compression', | ||
| 'image_optimization', | ||
| 'strip_binary', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing frontend entry for alternate_icons_optimization insight
Medium Severity
The backend now generates file-level diffs for ImageOptimizationInsightResult, which is used by both image_optimization and alternate_icons_optimization fields in AppleInsightResults. However, only 'strip_binary' was added to FILE_DIFF_INSIGHT_TYPES in the frontend - 'alternate_icons_optimization' is missing. When comparison data for alternate icons optimization exists, the frontend will silently drop it (returning null in the map), and users won't see the insight despite the backend generating valid comparison data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ticket only talks to LocalizedStringInsightResult, ImageOptimizationInsightResult and StripBinaryInsightResult
| base_files = base_insight.files if isinstance(base_insight, FilesInsightResult) else [] | ||
| head_groups = head_insight.groups if isinstance(head_insight, GroupsInsightResult) else [] | ||
| base_groups = base_insight.groups if isinstance(base_insight, GroupsInsightResult) else [] | ||
| head_optimizable_images = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be better as a follow up, but all these assignments might be better suited if we instead just check the instance type of the overall insight where our current file/group checks are (line 761). So something more like
if isinstance(head_insight, FilesInsightResults) and isinstance(base_insight, FilesInsightResults):
# Handle files insight
elif isinstance(head_insight, GroupsInsightsResults) ... :
...
elif ...
I know you're just following existing patterns here, so no worries, but could be a nice cleanup now that there's more branching logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I saw that the existing pattern wasn't scaling well. Good call.
| def _compare_optimizable_images( | ||
| head_files: list[OptimizableImageFile], base_files: list[OptimizableImageFile] | ||
| ) -> list[DiffItem]: | ||
| """Compare optimizable image files between head and base builds.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Would recommend removing these type of comments, usually they're not adding anything since the function is pretty self-explanatory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point.
Add comparison support for insights: - `ImageOptimizationInsightResult` - `StripBinaryInsightResult` Fixes bug that prevented `LocalizedStringInsightResult` results from showing. These Apple-specific insights now display file-level diffs on the Compare page, showing which optimizable images or strippable binaries were added, removed, or changed between builds. **Changes:** - Add `_compare_optimizable_images` and `_compare_strip_binary_files` functions to handle the different file structures of these insight types - Update `_compare_insights` to route these insight types to their specialized comparison functions - Add `platform` discriminator field to `AndroidInsightResults` and `AppleInsightResults` to fix union type parsing - without this, Pydantic uses left-to-right validation order which caused iOS insights to be incorrectly parsed as `AndroidInsightResults`, silently dropping iOS-specific fields like `strip_binary` and `image_optimization` - Add `image_optimization` to the frontend insight type union Requires: getsentry/launchpad#544 ## Backwards Compatibility These changes are backwards compatible with existing cached comparison results. When the `platform` discriminator field is missing from cached data (generated before the launchpad service changes), Pydantic falls back to the default value on each model. Since both `AndroidInsightResults` and `AppleInsightResults` have defaults for their `platform` field, Pydantic reverts to left-to-right union validation - preserving the existing (buggy) behavior where iOS results map to `AndroidInsightResults`. This means iOS-only insights (`image_optimization`, `strip_binary`, 'minify_localized_strings`) will only appear for new comparisons processed after getsentry/launchpad#544 is deployed. ## Before <img width="917" height="683" alt="Screenshot 2026-01-26 at 15 06 28" src="https://github.com/user-attachments/assets/69d680d8-0b6a-4d61-a059-8e0bfbc57252" /> ## After <img width="895" height="801" alt="Screenshot 2026-01-26 at 15 06 40" src="https://github.com/user-attachments/assets/9f7a2f89-0327-42e7-9ca5-d36a58db7b12" /> Refs EME-678
Add comparison support for insights: - `ImageOptimizationInsightResult` - `StripBinaryInsightResult` Fixes bug that prevented `LocalizedStringInsightResult` results from showing. These Apple-specific insights now display file-level diffs on the Compare page, showing which optimizable images or strippable binaries were added, removed, or changed between builds. **Changes:** - Add `_compare_optimizable_images` and `_compare_strip_binary_files` functions to handle the different file structures of these insight types - Update `_compare_insights` to route these insight types to their specialized comparison functions - Add `platform` discriminator field to `AndroidInsightResults` and `AppleInsightResults` to fix union type parsing - without this, Pydantic uses left-to-right validation order which caused iOS insights to be incorrectly parsed as `AndroidInsightResults`, silently dropping iOS-specific fields like `strip_binary` and `image_optimization` - Add `image_optimization` to the frontend insight type union Requires: getsentry/launchpad#544 ## Backwards Compatibility These changes are backwards compatible with existing cached comparison results. When the `platform` discriminator field is missing from cached data (generated before the launchpad service changes), Pydantic falls back to the default value on each model. Since both `AndroidInsightResults` and `AppleInsightResults` have defaults for their `platform` field, Pydantic reverts to left-to-right union validation - preserving the existing (buggy) behavior where iOS results map to `AndroidInsightResults`. This means iOS-only insights (`image_optimization`, `strip_binary`, 'minify_localized_strings`) will only appear for new comparisons processed after getsentry/launchpad#544 is deployed. ## Before <img width="917" height="683" alt="Screenshot 2026-01-26 at 15 06 28" src="https://github.com/user-attachments/assets/69d680d8-0b6a-4d61-a059-8e0bfbc57252" /> ## After <img width="895" height="801" alt="Screenshot 2026-01-26 at 15 06 40" src="https://github.com/user-attachments/assets/9f7a2f89-0327-42e7-9ca5-d36a58db7b12" /> Refs EME-678
Add comparison support for insights:
ImageOptimizationInsightResultStripBinaryInsightResultFixes bug that prevented
LocalizedStringInsightResultresults from showing.These Apple-specific insights now display file-level diffs on the Compare page, showing which optimizable images or strippable binaries were added, removed, or changed between builds.
Changes:
_compare_optimizable_imagesand_compare_strip_binary_filesfunctions to handle the different file structures of these insight types_compare_insightsto route these insight types to their specialized comparison functionsplatformdiscriminator field toAndroidInsightResultsandAppleInsightResultsto fix union type parsing - without this, Pydantic uses left-to-right validation order which caused iOS insights to be incorrectly parsed asAndroidInsightResults, silently dropping iOS-specific fields likestrip_binaryandimage_optimizationimage_optimizationto the frontend insight type unionRequires: getsentry/launchpad#544
Backwards Compatibility
These changes are backwards compatible with existing cached comparison results. When the
platformdiscriminator field is missing from cached data (generated before the launchpad service changes), Pydantic falls back to the default value on each model. Since bothAndroidInsightResultsandAppleInsightResultshave defaults for theirplatformfield, Pydantic reverts to left-to-right union validation - preserving the existing (buggy) behavior where iOS results map toAndroidInsightResults.This means iOS-only insights (
image_optimization,strip_binary, 'minify_localized_strings`) will only appear for new comparisons processed after getsentry/launchpad#544 is deployed.Before
After
Refs EME-678