Skip to content

Commit 3dca1e6

Browse files
authored
feat(preprod): Save android_app_info to extras if present (#102454)
Save android_app_info to extras if present.
1 parent e106395 commit 3dca1e6

File tree

4 files changed

+81
-4
lines changed

4 files changed

+81
-4
lines changed

src/sentry/preprod/api/endpoints/project_preprod_artifact_update.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ def validate_preprod_artifact_update_schema(
6262
"missing_dsym_binaries": {"type": "array", "items": {"type": "string"}},
6363
},
6464
},
65+
"android_app_info": {
66+
"type": "object",
67+
"properties": {
68+
"has_proguard_mapping": {"type": "boolean"},
69+
},
70+
},
6571
"dequeued_at": {"type": "string"},
6672
"app_icon_id": {"type": "string", "maxLength": 255},
6773
},
@@ -84,6 +90,8 @@ def validate_preprod_artifact_update_schema(
8490
"apple_app_info.is_code_signature_valid": "The is_code_signature_valid field must be a boolean.",
8591
"apple_app_info.code_signature_errors": "The code_signature_errors field must be an array of strings.",
8692
"apple_app_info.missing_dsym_binaries": "The missing_dsym_binaries field must be an array of strings.",
93+
"android_app_info": "The android_app_info field must be an object.",
94+
"android_app_info.has_proguard_mapping": "The has_proguard_mapping field must be a boolean.",
8795
"dequeued_at": "The dequeued_at field must be a string.",
8896
"app_icon_id": "The app_icon_id field must be a string with a maximum length of 255 characters.",
8997
}
@@ -319,6 +327,12 @@ def put(
319327
if field in apple_info:
320328
extras_updates[field] = apple_info[field]
321329

330+
if "android_app_info" in data:
331+
android_info = data["android_app_info"]
332+
for field in ["has_proguard_mapping"]:
333+
if field in android_info:
334+
extras_updates[field] = android_info[field]
335+
322336
if "dequeued_at" in data:
323337
extras_updates["dequeued_at"] = data["dequeued_at"]
324338

src/sentry/preprod/api/models/project_preprod_build_details_models.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ class AppleAppInfo(BaseModel):
2222
missing_dsym_binaries: list[str] = []
2323

2424

25+
class AndroidAppInfo(BaseModel):
26+
has_proguard_mapping: bool = True
27+
28+
2529
class BuildDetailsAppInfo(BaseModel):
2630
app_id: str | None
2731
name: str | None
@@ -34,6 +38,7 @@ class BuildDetailsAppInfo(BaseModel):
3438
is_installable: bool
3539
build_configuration: str | None = None
3640
apple_app_info: AppleAppInfo | None = None
41+
android_app_info: AndroidAppInfo | None = None
3742

3843

3944
class BuildDetailsVcsInfo(BaseModel):
@@ -140,11 +145,26 @@ def transform_preprod_artifact_to_build_details(
140145

141146
size_info = to_size_info(size_metrics)
142147

143-
apple_app_info = AppleAppInfo(
144-
missing_dsym_binaries=(
145-
artifact.extras.get("missing_dsym_binaries", []) if artifact.extras else []
148+
platform = None
149+
# artifact_type can be null before preprocessing has completed
150+
if artifact.artifact_type is not None:
151+
platform = platform_from_artifact_type(artifact.artifact_type)
152+
153+
apple_app_info = None
154+
if platform == Platform.IOS or platform == Platform.MACOS:
155+
apple_app_info = AppleAppInfo(
156+
missing_dsym_binaries=(
157+
artifact.extras.get("missing_dsym_binaries", []) if artifact.extras else []
158+
)
159+
)
160+
161+
android_app_info = None
162+
if platform == Platform.ANDROID:
163+
android_app_info = AndroidAppInfo(
164+
has_proguard_mapping=(
165+
artifact.extras.get("has_proguard_mapping", True) if artifact.extras else True
166+
)
146167
)
147-
)
148168

149169
app_info = BuildDetailsAppInfo(
150170
app_id=artifact.app_id,
@@ -164,6 +184,7 @@ def transform_preprod_artifact_to_build_details(
164184
artifact.build_configuration.name if artifact.build_configuration else None
165185
),
166186
apple_app_info=apple_app_info,
187+
android_app_info=android_app_info,
167188
)
168189

169190
vcs_info = BuildDetailsVcsInfo(

tests/sentry/preprod/api/endpoints/test_project_preprod_artifact_update.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,30 @@ def test_update_preprod_artifact_with_apple_app_info(self) -> None:
179179
stored_apple_info = self.preprod_artifact.extras or {}
180180
assert stored_apple_info == apple_info
181181

182+
@override_settings(LAUNCHPAD_RPC_SHARED_SECRET=["test-secret-key"])
183+
def test_update_preprod_artifact_with_android_app_info(self) -> None:
184+
android_info = {
185+
"has_proguard_mapping": True,
186+
}
187+
data = {
188+
"date_built": "2024-01-01T00:00:00Z",
189+
"artifact_type": 2,
190+
"build_version": "1.2.3",
191+
"build_number": 123,
192+
"android_app_info": android_info,
193+
}
194+
response = self._make_request(data)
195+
196+
assert response.status_code == 200
197+
resp_data = response.json()
198+
assert resp_data["success"] is True
199+
assert "extras" in resp_data["updatedFields"]
200+
201+
self.preprod_artifact.refresh_from_db()
202+
stored_android_info = self.preprod_artifact.extras or {}
203+
assert stored_android_info == android_info
204+
assert stored_android_info["has_proguard_mapping"] is True
205+
182206
@override_settings(LAUNCHPAD_RPC_SHARED_SECRET=["test-secret-key"])
183207
def test_update_preprod_artifact_with_missing_dsym_binaries_truncation(self) -> None:
184208
"""Test that missing_dsym_binaries list is truncated if it exceeds 1024 chars."""

tests/sentry/preprod/api/endpoints/test_project_preprod_build_details.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ def test_size_info_none_when_no_metrics(self) -> None:
229229

230230
def test_get_build_details_with_missing_dsym_binaries(self) -> None:
231231
"""Test that missing_dsym_binaries is returned in apple_app_info."""
232+
self.preprod_artifact.artifact_type = PreprodArtifact.ArtifactType.XCARCHIVE
232233
self.preprod_artifact.extras = {
233234
"missing_dsym_binaries": ["libTest.dylib", "TestFramework.framework"]
234235
}
@@ -241,7 +242,24 @@ def test_get_build_details_with_missing_dsym_binaries(self) -> None:
241242

242243
assert response.status_code == 200
243244
resp_data = response.json()
245+
244246
assert resp_data["app_info"]["apple_app_info"]["missing_dsym_binaries"] == [
245247
"libTest.dylib",
246248
"TestFramework.framework",
247249
]
250+
assert resp_data["app_info"]["android_app_info"] is None
251+
252+
def test_get_build_details_with_missing_proguard_mapping(self) -> None:
253+
"""Test that has_proguard_mapping is returned in android_app_info."""
254+
self.preprod_artifact.extras = {"has_proguard_mapping": False}
255+
self.preprod_artifact.save()
256+
257+
url = self._get_url()
258+
response = self.client.get(
259+
url, format="json", HTTP_AUTHORIZATION=f"Bearer {self.api_token.token}"
260+
)
261+
262+
assert response.status_code == 200
263+
resp_data = response.json()
264+
assert resp_data["app_info"]["android_app_info"]["has_proguard_mapping"] is False
265+
assert resp_data["app_info"]["apple_app_info"] is None

0 commit comments

Comments
 (0)