Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -288,31 +288,10 @@ def put(
head_artifact.main_binary_identifier = apple_info["main_binary_uuid"]
updated_fields.append("main_binary_identifier")

# Truncate missing_dsym_binaries if total character count exceeds 1024
if "missing_dsym_binaries" in apple_info:
binaries = apple_info["missing_dsym_binaries"]
if isinstance(binaries, list):
total_chars = sum(len(str(b)) for b in binaries)
if total_chars > 1024:
truncated = []
char_count = 0
for binary in binaries:
binary_str = str(binary)
if char_count + len(binary_str) <= 1024:
truncated.append(binary_str)
char_count += len(binary_str)
else:
break
apple_info["missing_dsym_binaries"] = truncated
logger.warning(
"Truncated missing_dsym_binaries list to not exceed 1024 characters limit",
extra={
"artifact_id": artifact_id_int,
"original_count": len(binaries),
"truncated_count": len(truncated),
"total_chars": total_chars,
},
)
extras_updates["has_missing_dsym_binaries"] = len(binaries) > 0

for field in [
"is_simulator",
Expand All @@ -322,7 +301,6 @@ def put(
"certificate_expiration_date",
"is_code_signature_valid",
"code_signature_errors",
"missing_dsym_binaries",
]:
if field in apple_info:
extras_updates[field] = apple_info[field]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Platform(StrEnum):


class AppleAppInfo(BaseModel):
missing_dsym_binaries: list[str] = []
has_missing_dsym_binaries: bool = False


class AndroidAppInfo(BaseModel):
Expand Down Expand Up @@ -182,11 +182,16 @@ def transform_preprod_artifact_to_build_details(

apple_app_info = None
if platform == Platform.IOS or platform == Platform.MACOS:
apple_app_info = AppleAppInfo(
missing_dsym_binaries=(
artifact.extras.get("missing_dsym_binaries", []) if artifact.extras else []
)
legacy_missing_dsym_binaries = (
artifact.extras.get("missing_dsym_binaries", []) if artifact.extras else []
)
has_missing_dsym_binaries = (
artifact.extras.get("has_missing_dsym_binaries", False)
or len(legacy_missing_dsym_binaries) > 0
if artifact.extras
else False
)
apple_app_info = AppleAppInfo(has_missing_dsym_binaries=has_missing_dsym_binaries)

android_app_info = None
if platform == Platform.ANDROID:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,16 @@ def test_update_preprod_artifact_with_apple_app_info(self) -> None:

self.preprod_artifact.refresh_from_db()
stored_apple_info = self.preprod_artifact.extras or {}
assert stored_apple_info == apple_info
# Verify that missing_dsym_binaries array is converted to has_missing_dsym_binaries boolean
expected_extras = {
"is_simulator": True,
"codesigning_type": "development",
"profile_name": "Test Profile",
"is_code_signature_valid": False,
"code_signature_errors": ["Certificate expired", "Missing entitlements"],
"has_missing_dsym_binaries": True, # Converted from non-empty array
}
assert stored_apple_info == expected_extras

@override_settings(LAUNCHPAD_RPC_SHARED_SECRET=["test-secret-key"])
def test_update_preprod_artifact_with_android_app_info(self) -> None:
Expand All @@ -204,15 +213,9 @@ def test_update_preprod_artifact_with_android_app_info(self) -> None:
assert stored_android_info["has_proguard_mapping"] is True

@override_settings(LAUNCHPAD_RPC_SHARED_SECRET=["test-secret-key"])
def test_update_preprod_artifact_with_missing_dsym_binaries_truncation(self) -> None:
"""Test that missing_dsym_binaries list is truncated if it exceeds 1024 chars."""
# Create a list that exceeds 1024 chars total
# Each item is 30 chars, so 40 items = 1200 chars
large_list = [f"VeryLongLibraryName{i:04d}.dylib" for i in range(40)]
total_chars = sum(len(s) for s in large_list)
assert total_chars > 1024, "Test data should exceed 1024 chars"

apple_info = {"missing_dsym_binaries": large_list}
def test_update_preprod_artifact_with_missing_dsym_binaries_empty_array(self) -> None:
"""Test that empty missing_dsym_binaries array converts to has_missing_dsym_binaries=False."""
apple_info: dict[str, Any] = {"missing_dsym_binaries": []}
data = {
"artifact_type": 1,
"apple_app_info": apple_info,
Expand All @@ -225,13 +228,27 @@ def test_update_preprod_artifact_with_missing_dsym_binaries_truncation(self) ->

self.preprod_artifact.refresh_from_db()
stored_apple_info = self.preprod_artifact.extras or {}
stored_binaries = stored_apple_info.get("missing_dsym_binaries", [])
assert stored_apple_info.get("has_missing_dsym_binaries") is False

# Verify the list was truncated
assert len(stored_binaries) < len(large_list)
# Verify total chars is within limit
stored_total_chars = sum(len(s) for s in stored_binaries)
assert stored_total_chars <= 1024
@override_settings(LAUNCHPAD_RPC_SHARED_SECRET=["test-secret-key"])
def test_update_preprod_artifact_with_missing_dsym_binaries_non_empty_array(self) -> None:
"""Test that non-empty missing_dsym_binaries array converts to has_missing_dsym_binaries=True."""
# Even a large list should just convert to True
large_list = [f"VeryLongLibraryName{i:04d}.dylib" for i in range(40)]
apple_info: dict[str, Any] = {"missing_dsym_binaries": large_list}
data = {
"artifact_type": 1,
"apple_app_info": apple_info,
}
response = self._make_request(data)

assert response.status_code == 200
resp_data = response.json()
assert resp_data["success"] is True

self.preprod_artifact.refresh_from_db()
stored_apple_info = self.preprod_artifact.extras or {}
assert stored_apple_info.get("has_missing_dsym_binaries") is True

@override_settings(LAUNCHPAD_RPC_SHARED_SECRET=["test-secret-key"])
def test_update_preprod_artifact_with_partial_apple_app_info(self) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,11 +228,9 @@ def test_size_info_none_when_no_metrics(self) -> None:
assert resp_data["size_info"] is None

def test_get_build_details_with_missing_dsym_binaries(self) -> None:
"""Test that missing_dsym_binaries is returned in apple_app_info."""
"""Test that has_missing_dsym_binaries is returned in apple_app_info."""
self.preprod_artifact.artifact_type = PreprodArtifact.ArtifactType.XCARCHIVE
self.preprod_artifact.extras = {
"missing_dsym_binaries": ["libTest.dylib", "TestFramework.framework"]
}
self.preprod_artifact.extras = {"has_missing_dsym_binaries": True}
self.preprod_artifact.save()

url = self._get_url()
Expand All @@ -243,10 +241,24 @@ def test_get_build_details_with_missing_dsym_binaries(self) -> None:
assert response.status_code == 200
resp_data = response.json()

assert resp_data["app_info"]["apple_app_info"]["missing_dsym_binaries"] == [
"libTest.dylib",
"TestFramework.framework",
]
assert resp_data["app_info"]["apple_app_info"]["has_missing_dsym_binaries"] is True
assert resp_data["app_info"]["android_app_info"] is None

def test_get_build_details_without_missing_dsym_binaries(self) -> None:
"""Test that has_missing_dsym_binaries defaults to False when not set."""
self.preprod_artifact.artifact_type = PreprodArtifact.ArtifactType.XCARCHIVE
self.preprod_artifact.extras = {"has_missing_dsym_binaries": False}
self.preprod_artifact.save()

url = self._get_url()
response = self.client.get(
url, format="json", HTTP_AUTHORIZATION=f"Bearer {self.api_token.token}"
)

assert response.status_code == 200
resp_data = response.json()

assert resp_data["app_info"]["apple_app_info"]["has_missing_dsym_binaries"] is False
assert resp_data["app_info"]["android_app_info"] is None

def test_get_build_details_with_missing_proguard_mapping(self) -> None:
Expand Down
Loading