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
1 change: 1 addition & 0 deletions src/launchpad/api/update_api_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class AppleAppInfo(BaseModel):
profile_name: Optional[str] = None
is_code_signature_valid: Optional[bool] = None
code_signature_errors: Optional[List[str]] = None
main_binary_uuid: Optional[str] = None
# TODO: add "date_built" field once exposed in 'AppleAppInfo'


Expand Down
13 changes: 12 additions & 1 deletion src/launchpad/artifacts/apple/zipped_xcarchive.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ def get_app_bundle_path(self) -> Path:

raise FileNotFoundError(f"No .app bundle found in {self._extract_dir}")

def get_main_binary_uuid(self) -> str | None:
main_binary_path = self._get_main_binary_path()
return self._extract_binary_uuid(main_binary_path)

def get_all_binary_paths(self) -> List[BinaryInfo]:
"""Find all binaries in the app bundle and their corresponding dSYM files.

Expand All @@ -176,7 +180,7 @@ def get_all_binary_paths(self) -> List[BinaryInfo]:
main_executable = self.get_plist().get("CFBundleExecutable")
if main_executable is None:
raise RuntimeError("CFBundleExecutable not found in Info.plist")
main_binary_path = Path(os.path.join(str(app_bundle_path), main_executable))
main_binary_path = self._get_main_binary_path()

# Find corresponding dSYM for main executable
main_uuid = self._extract_binary_uuid(main_binary_path)
Expand Down Expand Up @@ -284,6 +288,13 @@ def get_asset_catalog_details(self, relative_path: Path) -> List[AssetCatalogEle
logger.error(f"Failed to get asset catalog details for {relative_path}: {e}")
return []

def _get_main_binary_path(self) -> Path:
app_bundle_path = self.get_app_bundle_path()
main_executable = self.get_plist().get("CFBundleExecutable")
if main_executable is None:
raise RuntimeError("CFBundleExecutable not found in Info.plist")
return Path(os.path.join(str(app_bundle_path), main_executable))

def _parse_asset_element(self, item: dict[str, Any], parent_path: Path) -> AssetCatalogElement:
"""Parse a dictionary item into an AssetCatalogElement."""
name = item.get("name", "")
Expand Down
5 changes: 2 additions & 3 deletions src/launchpad/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@

from arroyo.backends.kafka import KafkaPayload
from arroyo.processing.processor import StreamProcessor
from sentry_kafka_schemas.schema_types.preprod_artifact_events_v1 import (
PreprodArtifactEvents,
)
from sentry_kafka_schemas.schema_types.preprod_artifact_events_v1 import PreprodArtifactEvents

from launchpad.api.update_api_models import AppleAppInfo as AppleAppInfoModel
from launchpad.api.update_api_models import UpdateData
Expand Down Expand Up @@ -437,6 +435,7 @@ def _get_artifact_type(artifact: Artifact) -> ArtifactType:
profile_name=app_info.profile_name,
is_code_signature_valid=app_info.is_code_signature_valid,
code_signature_errors=app_info.code_signature_errors,
main_binary_uuid=app_info.main_binary_uuid,
)
# TODO: add "date_built" and custom android fields

Expand Down
9 changes: 5 additions & 4 deletions src/launchpad/size/analyzers/apple.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
from launchpad.size.insights.apple.image_optimization import ImageOptimizationInsight
from launchpad.size.insights.apple.localized_strings import LocalizedStringsInsight
from launchpad.size.insights.apple.loose_images import LooseImagesInsight
from launchpad.size.insights.apple.main_binary_export_metadata import MainBinaryExportMetadataInsight
from launchpad.size.insights.apple.main_binary_export_metadata import (
MainBinaryExportMetadataInsight,
)
from launchpad.size.insights.apple.small_files import SmallFilesInsight
from launchpad.size.insights.apple.strip_symbols import StripSymbolsInsight
from launchpad.size.insights.apple.unnecessary_files import UnnecessaryFilesInsight
from launchpad.size.insights.common.duplicate_files import DuplicateFilesInsight
from launchpad.size.insights.common.hermes_debug_info import (
HermesDebugInfoInsight,
)
from launchpad.size.insights.common.hermes_debug_info import HermesDebugInfoInsight
from launchpad.size.insights.common.large_audios import LargeAudioFileInsight
from launchpad.size.insights.common.large_images import LargeImageFileInsight
from launchpad.size.insights.common.large_videos import LargeVideoFileInsight
Expand Down Expand Up @@ -243,6 +243,7 @@ def _extract_app_info(self, xcarchive: ZippedXCArchive) -> AppleAppInfo:
profile_name=profile_name,
is_code_signature_valid=is_code_signature_valid,
code_signature_errors=code_signature_errors,
main_binary_uuid=xcarchive.get_main_binary_uuid(),
)

def _get_profile_type(self, profile_data: dict[str, Any]) -> Tuple[str, str]:
Expand Down
1 change: 1 addition & 0 deletions src/launchpad/size/models/apple.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ class AppleAppInfo(BaseAppInfo):
code_signature_errors: List[str] = Field(
default_factory=list, description="List of code signature validation errors"
)
main_binary_uuid: str | None = Field(None, description="UUID of the main binary")


class MachOBinaryAnalysis(BaseBinaryAnalysis):
Expand Down
1 change: 1 addition & 0 deletions tests/unit/test_apple_basic_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ def test_basic_info(self) -> None:
assert basic_info.codesigning_type == "development"
assert basic_info.is_code_signature_valid is True
assert basic_info.code_signature_errors == []
assert basic_info.main_binary_uuid == "BEB3C0D6-2518-343D-BB6F-FF5581C544E8"