Skip to main content
Glama
provisioning_profile_diagnostics.py9.87 kB
# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under both the MIT license found in the # LICENSE-MIT file in the root directory of this source tree and the Apache # License, Version 2.0 found in the LICENSE-APACHE file in the root directory # of this source tree. # pyre-strict from abc import ABCMeta, abstractmethod from pathlib import Path from typing import List, Optional, Type, TypeVar from .apple_platform import ApplePlatform from .identity import CodeSigningIdentity from .provisioning_profile_metadata import ProvisioningProfileMetadata META_IOS_DEVELOPER_CERTIFICATE_LINK: str = "https://www.internalfb.com/intern/qa/5198/how-do-i-get-the-fb-ios-developer-certificate" META_IOS_PROVISIONING_PROFILES_LINK: str = ( "https://www.internalfb.com/intern/apple/download-provisioning-profile/" ) META_IOS_PROVISIONING_PROFILES_COMMAND: str = ( "arc ios-certs --download-provisioning-profiles" ) META_IOS_CERTS_ALL_COMMAND: str = "arc ios-certs --all" # TODO(T197258387): Remove references to `arc download-provisioning-profile` in this wiki page. META_IOS_BUILD_AND_RUN_ON_DEVICE_LINK: str = "https://www.internalfb.com/intern/wiki/Ios-first-steps/running-on-device/#2-register-your-device-i" class IProvisioningProfileDiagnostics(metaclass=ABCMeta): profile: ProvisioningProfileMetadata def __init__(self, profile: ProvisioningProfileMetadata) -> None: self.profile = profile @abstractmethod def log_message(self) -> str: raise NotImplementedError class TeamIdMismatch(IProvisioningProfileDiagnostics): team_id: str team_id_constraint: str def __init__( self, profile: ProvisioningProfileMetadata, team_id: str, team_id_constraint: str, ) -> None: super().__init__(profile) self.team_id = team_id self.team_id_constraint = team_id_constraint def log_message(self) -> str: return f"Profile team ID `{self.team_id}` is not matching constraint `{self.team_id_constraint}`" class BundleIdMismatch(IProvisioningProfileDiagnostics): bundle_id: str bundle_id_constraint: str def __init__( self, profile: ProvisioningProfileMetadata, bundle_id: str, bundle_id_constraint: str, ) -> None: super().__init__(profile) self.bundle_id = bundle_id self.bundle_id_constraint = bundle_id_constraint def log_message(self) -> str: return f"Bundle ID `{self.bundle_id}` is not matching constraint `{self.bundle_id_constraint}`" class ProfileExpired(IProvisioningProfileDiagnostics): bundle_id_match_length: int def __init__( self, profile: ProvisioningProfileMetadata, bundle_id_match_length: int, ) -> None: super().__init__(profile) self.bundle_id_match_length = bundle_id_match_length def log_message(self) -> str: return "Provisioning profile expired." class UnsupportedPlatform(IProvisioningProfileDiagnostics): bundle_id_match_length: int platform_constraint: str def __init__( self, profile: ProvisioningProfileMetadata, bundle_id_match_length: int, platform_constraint: ApplePlatform, ) -> None: super().__init__(profile) self.bundle_id_match_length = bundle_id_match_length self.platform_constraint = platform_constraint def log_message(self) -> str: supported_profile_platforms = ", ".join(self.profile.platforms) return f"Requested platform `{self.platform_constraint}` is not in provisioning profile's supported platforms `{supported_profile_platforms}`." class EntitlementsMismatch(IProvisioningProfileDiagnostics): bundle_id_match_length: int mismatched_key: str mismatched_value: str def __init__( self, profile: ProvisioningProfileMetadata, bundle_id_match_length: int, mismatched_key: str, mismatched_value: str, ) -> None: super().__init__(profile) self.bundle_id_match_length = bundle_id_match_length self.mismatched_key = mismatched_key self.mismatched_value = mismatched_value def log_message(self) -> str: return f"Expected entitlement item key `{self.mismatched_key}` with value `{self.mismatched_value}` not found in provisioning profile." class DeveloperCertificateMismatch(IProvisioningProfileDiagnostics): bundle_id_match_length: int def __init__( self, profile: ProvisioningProfileMetadata, bundle_id_match_length: int, ) -> None: super().__init__(profile) self.bundle_id_match_length = bundle_id_match_length def log_message(self) -> str: certificate_fingerprints = ", ".join( self.profile.developer_certificate_fingerprints ) return f"Expected identity fingerprint not found in profile's certificate fingerprints `{certificate_fingerprints}`." _T = TypeVar("T") def interpret_provisioning_profile_diagnostics( diagnostics: List[IProvisioningProfileDiagnostics], bundle_id: str, provisioning_profiles_dir: Path, identities: List[CodeSigningIdentity], log_file_path: Optional[Path] = None, ) -> str: if not diagnostics: raise RuntimeError( "Expected diagnostics information for at least one mismatching provisioning profile." ) header = f"Failed to find provisioning profile in directory `{provisioning_profiles_dir}` that is suitable for code signing. Here is the best guess for how to fix it:\n\n⚠️ " footer = f"\n\nFor more info about running on an iOS device read {META_IOS_BUILD_AND_RUN_ON_DEVICE_LINK}." if log_file_path: footer += ( f" Full list of mismatched profiles can be found at `{log_file_path}`.\n" ) else: provisioning_profile_errors = "\n\n".join( [ f"`{mismatch.profile.file_path.name}`: {mismatch.log_message()}" for mismatch in diagnostics ] ) footer += f" Full list of mismatched profiles:{provisioning_profile_errors}\n" def find_mismatch(class_type: Type[_T]) -> Optional[_T]: return next( iter( sorted( filter(lambda d: isinstance(d, class_type), diagnostics), key=lambda d: d.bundle_id_match_length, reverse=True, ) ), None, ) if mismatch := find_mismatch(DeveloperCertificateMismatch): identities_description = ( "WARNING: NO SIGNING IDENTITIES FOUND!" if len(identities) == 0 else f"List of signing identities: `{identities}`." ) return "\n".join( [ header, f"The provisioning profile `{mismatch.profile.file_path.name}` satisfies all constraints, but no matching certificates were found in your keychain. ", identities_description, f"Execute `{META_IOS_CERTS_ALL_COMMAND}` or download and install the latest certificate from {META_IOS_DEVELOPER_CERTIFICATE_LINK}.", footer, ] ) if mismatch := find_mismatch(EntitlementsMismatch): return "".join( [ header, f"The provisioning profile `{mismatch.profile.file_path.name}` is the best match, but it doesn't contain all the needed entitlements. ", f"Expected entitlement item with key `{mismatch.mismatched_key}` and value `{mismatch.mismatched_value}` is missing. ", f"Usually that means the application entitlements were changed recently, provisioning profile was updated and you need to download & install the latest version of provisioning profile for Bundle ID `{bundle_id}`.", f"Execute `{META_IOS_PROVISIONING_PROFILES_COMMAND}` or download from from {META_IOS_PROVISIONING_PROFILES_LINK}", footer, ] ) if mismatch := find_mismatch(UnsupportedPlatform): supported_platforms = ", ".join([f"`{p}`" for p in mismatch.profile.platforms]) return "".join( [ header, f"The provisioning profile `{mismatch.profile.file_path.name}` is the best match, but it only supports the following platforms: {supported_platforms}. Unfortunately, it doesn't include the requested platform, `{mismatch.platform_constraint}`. ", f"This could indicate two possibilities: either the provisioning profile was recently updated to include the needed platform, or there is a separate profile supporting the required platform that you are missing. In the latter case, you would need to download and install it from {META_IOS_PROVISIONING_PROFILES_LINK}", footer, ] ) if mismatch := find_mismatch(ProfileExpired): return "".join( [ header, f"The provisioning profile `{mismatch.profile.file_path.name}` is the the best match; however, it has expired", f"Execute `{META_IOS_PROVISIONING_PROFILES_COMMAND}` to get the latest provisioning profiles.", f"Alternatively, please download and install a valid profile from {META_IOS_PROVISIONING_PROFILES_LINK}", footer, ] ) return "".join( [ header, f"No provisioning profile matching the Bundle ID `{bundle_id}` was found. ", f"Execute `{META_IOS_PROVISIONING_PROFILES_COMMAND}` to get the latest provisioning profiles.", f"Alternatively, please download and install the appropriate profile from {META_IOS_PROVISIONING_PROFILES_LINK}", footer, ] )

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server