From 6bcfcdcd5a11d47d4a85e785b3bd4a91b6ff48a9 Mon Sep 17 00:00:00 2001 From: VeArnold Date: Fri, 26 Aug 2022 17:21:20 +0300 Subject: [PATCH 1/6] Require device for development and ad hoc profiles --- CHANGELOG.md | 6 +++ pyproject.toml | 2 +- .../provisioning/profiles.py | 15 +++++++ src/codemagic/apple/resources/enums.py | 8 +++- src/codemagic/tools/app_store_connect.py | 2 +- .../provisioning/test_profiles.py | 39 +++++++++++++++++++ .../resources/enums/test_profile_type.py | 4 +- 7 files changed, 70 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99f89547..aff60f67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version 0.31.3 +------------- + +**Development**: +- Show error message when no matching test device is found in the Apple Developer Portal when creating an Ad Hoc or development provisioning profile. + Version 0.31.2 ------------- diff --git a/pyproject.toml b/pyproject.toml index 3e36d1e9..421e882c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "codemagic-cli-tools" -version = "0.31.2" +version = "0.31.3" description = "CLI tools used in Codemagic builds" readme = "README.md" authors = [ diff --git a/src/codemagic/apple/app_store_connect/provisioning/profiles.py b/src/codemagic/apple/app_store_connect/provisioning/profiles.py index 4017ee4a..8cd42306 100644 --- a/src/codemagic/apple/app_store_connect/provisioning/profiles.py +++ b/src/codemagic/apple/app_store_connect/provisioning/profiles.py @@ -57,6 +57,21 @@ def create(self, """ if profile_type.devices_not_allowed() and devices: raise ValueError(f'Cannot assign devices to profile with type {profile_type}') + elif profile_type.devices_required() and not devices: + if profile_type.is_tvos_profile: + device_type = 'tvOS' + elif profile_type.is_macos_profile: + device_type = 'macOS' + elif profile_type.is_ios_profile: + device_type = 'iOS' + else: + raise ValueError(f'Device type for profile type {profile_type} is unknown') + + raise ValueError( + f'Cannot create profile: Apple requires that you register at least one {device_type} ' + f'testing device on the Apple Developer Portal to create a {profile_type} profile' + ) + if devices is None: devices = [] attributes = { diff --git a/src/codemagic/apple/resources/enums.py b/src/codemagic/apple/resources/enums.py index ee790bdf..4242d8c9 100644 --- a/src/codemagic/apple/resources/enums.py +++ b/src/codemagic/apple/resources/enums.py @@ -205,6 +205,10 @@ def is_ad_hoc_type(self) -> bool: def is_development_type(self) -> bool: return self.value.endswith('_DEVELOPMENT') + @property + def is_ios_profile(self) -> bool: + return self.value.startswith('IOS_') + @property def is_macos_profile(self) -> bool: return self.value.startswith('MAC_') @@ -214,9 +218,9 @@ def is_tvos_profile(self) -> bool: return self.value.startswith('TVOS_') def devices_not_allowed(self) -> bool: - return not self.devices_allowed() + return not self.devices_required() - def devices_allowed(self) -> bool: + def devices_required(self) -> bool: return self.is_development_type or self.is_ad_hoc_type diff --git a/src/codemagic/tools/app_store_connect.py b/src/codemagic/tools/app_store_connect.py index fb1f0080..174d8582 100755 --- a/src/codemagic/tools/app_store_connect.py +++ b/src/codemagic/tools/app_store_connect.py @@ -682,7 +682,7 @@ def create_profile( devices=[], omit_keys=['devices'], ) - if profile_type.devices_allowed(): + if profile_type.devices_required(): create_params['devices'] = device_resource_ids profile = self._create_resource(self.api_client.profiles, should_print, **create_params) diff --git a/tests/apple/app_store_connect/provisioning/test_profiles.py b/tests/apple/app_store_connect/provisioning/test_profiles.py index 8ec50640..2caaf9b8 100644 --- a/tests/apple/app_store_connect/provisioning/test_profiles.py +++ b/tests/apple/app_store_connect/provisioning/test_profiles.py @@ -39,6 +39,28 @@ def test_create_profile_success_with_devices(profile_type, profile_response, app app_store_api_client.session.post.assert_called_once() +@pytest.mark.parametrize('profile_type, device_type', [ + (ProfileType.IOS_APP_DEVELOPMENT, 'iOS'), + (ProfileType.IOS_APP_ADHOC, 'iOS'), + (ProfileType.MAC_APP_DEVELOPMENT, 'macOS'), + (ProfileType.MAC_CATALYST_APP_DEVELOPMENT, 'macOS'), + (ProfileType.TVOS_APP_DEVELOPMENT, 'tvOS'), + (ProfileType.TVOS_APP_ADHOC, 'tvOS'), +]) +def test_create_profile_failure_without_devices(profile_type, device_type, app_store_api_client): + with pytest.raises(ValueError) as error_info: + app_store_api_client.profiles.create( + name='test profile', + profile_type=profile_type, + bundle_id=ResourceId('bundle_id_resource_id'), + certificates=[ResourceId('certificate_resource_id')], + devices=None, + ) + expected_error_msg = f'Cannot create profile: Apple requires that you register at least one {device_type} ' \ + f'testing device on the Apple Developer Portal to create a {profile_type} profile' + assert str(error_info.value) == expected_error_msg + + @pytest.mark.skipif(not os.environ.get('RUN_LIVE_API_TESTS'), reason='Live App Store Connect API access') class ProfilesTest(ResourceManagerTestsBase): @@ -59,6 +81,23 @@ def test_create(self): assert profile.attributes.name == name assert profile.attributes.profileType is profile_type + def test_create_fail_if_no_devices_but_devices_are_required(self): + name = 'test profile' + profile_type = ProfileType.IOS_APP_DEVELOPMENT + bundle_id_resource_id = ResourceId('F88J43FA9J') + certificate_id = ResourceId('29NU422CRF') + device_ids = None + + with pytest.raises(ValueError) as error_info: + self.api_client.profiles.create( + name=name, + profile_type=profile_type, + bundle_id=bundle_id_resource_id, + certificates=[certificate_id], + devices=device_ids, + ) + assert str(error_info.value) == 'gaga' + def test_delete(self): profile_id = ResourceId('ZK3RZ4B465') self.api_client.profiles.delete(profile_id) diff --git a/tests/apple/resources/enums/test_profile_type.py b/tests/apple/resources/enums/test_profile_type.py index 96cd52bc..fe22c762 100644 --- a/tests/apple/resources/enums/test_profile_type.py +++ b/tests/apple/resources/enums/test_profile_type.py @@ -19,5 +19,5 @@ (ProfileType.TVOS_APP_INHOUSE, False), (ProfileType.TVOS_APP_STORE, False), ]) -def test_devices_allowed(profile_type, should_be_allowed): - assert profile_type.devices_allowed() is should_be_allowed +def test_devices_required(profile_type, should_be_required): + assert profile_type.devices_required() is should_be_required From 3eab206180ef4d36736d9672cceae27263d1ea87 Mon Sep 17 00:00:00 2001 From: VeArnold Date: Fri, 26 Aug 2022 17:33:19 +0300 Subject: [PATCH 2/6] Add trailing comma --- src/codemagic/apple/app_store_connect/provisioning/profiles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codemagic/apple/app_store_connect/provisioning/profiles.py b/src/codemagic/apple/app_store_connect/provisioning/profiles.py index 8cd42306..2882998b 100644 --- a/src/codemagic/apple/app_store_connect/provisioning/profiles.py +++ b/src/codemagic/apple/app_store_connect/provisioning/profiles.py @@ -69,7 +69,7 @@ def create(self, raise ValueError( f'Cannot create profile: Apple requires that you register at least one {device_type} ' - f'testing device on the Apple Developer Portal to create a {profile_type} profile' + f'testing device on the Apple Developer Portal to create a {profile_type} profile', ) if devices is None: From a888ceab6ac6a49971111490fb0eeba304e10d8a Mon Sep 17 00:00:00 2001 From: VeArnold Date: Fri, 26 Aug 2022 17:37:04 +0300 Subject: [PATCH 3/6] Amend tests --- tests/apple/resources/enums/test_profile_type.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/apple/resources/enums/test_profile_type.py b/tests/apple/resources/enums/test_profile_type.py index fe22c762..560c62e2 100644 --- a/tests/apple/resources/enums/test_profile_type.py +++ b/tests/apple/resources/enums/test_profile_type.py @@ -3,7 +3,7 @@ from codemagic.apple.resources import ProfileType -@pytest.mark.parametrize('profile_type, should_be_allowed', [ +@pytest.mark.parametrize('profile_type, should_be_required', [ (ProfileType.IOS_APP_ADHOC, True), (ProfileType.IOS_APP_DEVELOPMENT, True), (ProfileType.IOS_APP_INHOUSE, False), From f27f729ae282ca77f5ad7d6a6cb9d6b5ce2e8108 Mon Sep 17 00:00:00 2001 From: VeArnold Date: Fri, 26 Aug 2022 17:41:09 +0300 Subject: [PATCH 4/6] Remove reduntant test --- .../provisioning/test_profiles.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tests/apple/app_store_connect/provisioning/test_profiles.py b/tests/apple/app_store_connect/provisioning/test_profiles.py index 2caaf9b8..95e6fc77 100644 --- a/tests/apple/app_store_connect/provisioning/test_profiles.py +++ b/tests/apple/app_store_connect/provisioning/test_profiles.py @@ -81,23 +81,6 @@ def test_create(self): assert profile.attributes.name == name assert profile.attributes.profileType is profile_type - def test_create_fail_if_no_devices_but_devices_are_required(self): - name = 'test profile' - profile_type = ProfileType.IOS_APP_DEVELOPMENT - bundle_id_resource_id = ResourceId('F88J43FA9J') - certificate_id = ResourceId('29NU422CRF') - device_ids = None - - with pytest.raises(ValueError) as error_info: - self.api_client.profiles.create( - name=name, - profile_type=profile_type, - bundle_id=bundle_id_resource_id, - certificates=[certificate_id], - devices=device_ids, - ) - assert str(error_info.value) == 'gaga' - def test_delete(self): profile_id = ResourceId('ZK3RZ4B465') self.api_client.profiles.delete(profile_id) From fa065b62f2bf5238585ccd0ccdc488bf02212c02 Mon Sep 17 00:00:00 2001 From: VeArnold Date: Mon, 29 Aug 2022 12:17:20 +0300 Subject: [PATCH 5/6] Add deprecation notice and improve error message --- CHANGELOG.md | 4 ++-- .../apple/app_store_connect/provisioning/profiles.py | 5 +++-- src/codemagic/apple/resources/enums.py | 11 +++++++++++ .../app_store_connect/provisioning/test_profiles.py | 7 +++++-- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aff60f67..82c6db80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ Version 0.31.3 ------------- -**Development**: -- Show error message when no matching test device is found in the Apple Developer Portal when creating an Ad Hoc or development provisioning profile. +**Bugfixes** +- Show error message when no matching test device is found in the Apple Developer Portal when creating an Ad Hoc or development provisioning profile. [PR #256](https://github.com/codemagic-ci-cd/cli-tools/pull/256) Version 0.31.2 ------------- diff --git a/src/codemagic/apple/app_store_connect/provisioning/profiles.py b/src/codemagic/apple/app_store_connect/provisioning/profiles.py index 2882998b..bf7e03d8 100644 --- a/src/codemagic/apple/app_store_connect/provisioning/profiles.py +++ b/src/codemagic/apple/app_store_connect/provisioning/profiles.py @@ -68,8 +68,9 @@ def create(self, raise ValueError(f'Device type for profile type {profile_type} is unknown') raise ValueError( - f'Cannot create profile: Apple requires that you register at least one {device_type} ' - f'testing device on the Apple Developer Portal to create a {profile_type} profile', + f'Cannot create profile: the request does not include any {device_type} testing devices ' + f'while they are required for creating a {profile_type} profile. If the profile creation is automatic, ' + 'ensure that at least one suitable testing device is registered on the Apple Developer Portal.' ) if devices is None: diff --git a/src/codemagic/apple/resources/enums.py b/src/codemagic/apple/resources/enums.py index 4242d8c9..a8509e94 100644 --- a/src/codemagic/apple/resources/enums.py +++ b/src/codemagic/apple/resources/enums.py @@ -2,7 +2,9 @@ from typing import Tuple +from codemagic.cli import Colors from codemagic.models.enums import ResourceEnum +from codemagic.utilities import log class AppStoreState(ResourceEnum): @@ -220,6 +222,15 @@ def is_tvos_profile(self) -> bool: def devices_not_allowed(self) -> bool: return not self.devices_required() + def devices_allowed(self) -> bool: + warning = ( + 'Deprecation warning! Method ' + '"devices_allowed" is deprecated in favor of "devices_required" in version 0.31.3 ' + 'and is subject for removal in future releases.' + ) + log.get_logger(self.__class__).warning(Colors.RED(warning)) + return self.devices_required() + def devices_required(self) -> bool: return self.is_development_type or self.is_ad_hoc_type diff --git a/tests/apple/app_store_connect/provisioning/test_profiles.py b/tests/apple/app_store_connect/provisioning/test_profiles.py index 95e6fc77..d3f9059e 100644 --- a/tests/apple/app_store_connect/provisioning/test_profiles.py +++ b/tests/apple/app_store_connect/provisioning/test_profiles.py @@ -56,8 +56,11 @@ def test_create_profile_failure_without_devices(profile_type, device_type, app_s certificates=[ResourceId('certificate_resource_id')], devices=None, ) - expected_error_msg = f'Cannot create profile: Apple requires that you register at least one {device_type} ' \ - f'testing device on the Apple Developer Portal to create a {profile_type} profile' + expected_error_msg = ( + f'Cannot create profile: the request does not include any {device_type} testing devices ' + f'while they are required for creating a {profile_type} profile. If the profile creation is automatic, ' + 'ensure that at least one suitable testing device is registered on the Apple Developer Portal.' + ) assert str(error_info.value) == expected_error_msg From 31c068a463b4af1482ffbdacdcfdcb62253698d8 Mon Sep 17 00:00:00 2001 From: VeArnold Date: Mon, 29 Aug 2022 12:26:50 +0300 Subject: [PATCH 6/6] Fix trailing comma and warning color --- src/codemagic/apple/app_store_connect/provisioning/profiles.py | 2 +- src/codemagic/apple/resources/enums.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codemagic/apple/app_store_connect/provisioning/profiles.py b/src/codemagic/apple/app_store_connect/provisioning/profiles.py index bf7e03d8..009af86d 100644 --- a/src/codemagic/apple/app_store_connect/provisioning/profiles.py +++ b/src/codemagic/apple/app_store_connect/provisioning/profiles.py @@ -70,7 +70,7 @@ def create(self, raise ValueError( f'Cannot create profile: the request does not include any {device_type} testing devices ' f'while they are required for creating a {profile_type} profile. If the profile creation is automatic, ' - 'ensure that at least one suitable testing device is registered on the Apple Developer Portal.' + 'ensure that at least one suitable testing device is registered on the Apple Developer Portal.', ) if devices is None: diff --git a/src/codemagic/apple/resources/enums.py b/src/codemagic/apple/resources/enums.py index a8509e94..b7326690 100644 --- a/src/codemagic/apple/resources/enums.py +++ b/src/codemagic/apple/resources/enums.py @@ -228,7 +228,7 @@ def devices_allowed(self) -> bool: '"devices_allowed" is deprecated in favor of "devices_required" in version 0.31.3 ' 'and is subject for removal in future releases.' ) - log.get_logger(self.__class__).warning(Colors.RED(warning)) + log.get_logger(self.__class__).warning(Colors.YELLOW(warning)) return self.devices_required() def devices_required(self) -> bool: