Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix: tvOS ipas are validated and uploaded as iOS apps with altool #173

Merged
merged 3 commits into from
Dec 17, 2021
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
Version 0.13.2
-------------

**Fixes**

- Use correct package type for `altool` commands when publishing tvOS apps using `app-store-connect publish`. [PR #173](https://github.com/codemagic-ci-cd/cli-tools/pull/173)

Version 0.13.1
-------------

Expand Down
2 changes: 1 addition & 1 deletion src/codemagic/__version__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__title__ = 'codemagic-cli-tools'
__description__ = 'CLI tools used in Codemagic builds'
__version__ = '0.13.1'
__version__ = '0.13.2'
__url__ = 'https://github.com/codemagic-ci-cd/cli-tools'
__licence__ = 'GNU General Public License v3.0'
3 changes: 3 additions & 0 deletions src/codemagic/models/altool/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from typing import Union

from codemagic.mixins import StringConverterMixin
from codemagic.models.application_package import Ipa


class AuthenticationMethod(enum.Enum):
Expand All @@ -27,6 +28,8 @@ def from_path(cls, artifact_path: Union[pathlib.Path, AnyStr]) -> PlatformType:
if artifact_path.suffix == '.pkg':
return PlatformType.MAC_OS
elif artifact_path.suffix == '.ipa':
if Ipa(artifact_path).is_for_tvos():
return PlatformType.APPLE_TV_OS
return PlatformType.IOS
else:
raise ValueError(f'Unknown artifact type from path {artifact_path}')
3 changes: 3 additions & 0 deletions src/codemagic/models/application_package/ipa.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,6 @@ def get_summary(self) -> Dict[str, Union[bool, Optional[str], List[str]]]:
'version': self.version,
'version_code': self.version_code,
}

def is_for_tvos(self) -> bool:
return any('tv' in platform_name.lower() for platform_name in self.supported_platforms)
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def _get_app_store_connect_submit_options(
add_beta_test_info_options = None

if not platform:
if any('tv' in platform_name.lower() for platform_name in ipa.supported_platforms):
if ipa.is_for_tvos():
platform = Platform.TV_OS
else:
platform = Platform.IOS
Expand Down
6 changes: 6 additions & 0 deletions tests/models/altool/test_altool_retrying.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from codemagic.models import Altool
from codemagic.models.altool import AltoolResult
from codemagic.models.altool.altool import AltoolCommandError
from codemagic.models.altool.altool import PlatformType


@pytest.fixture
Expand Down Expand Up @@ -49,6 +50,7 @@ def mock_success_stdout() -> str:
return mock_path.read_text()


@mock.patch.object(PlatformType, 'from_path', lambda _artifact_path: PlatformType.IOS)
@pytest.mark.parametrize('retries, error_message', [
(2, 'error'),
(5, 'another error'),
Expand All @@ -66,6 +68,7 @@ def test_retrying_command_exhaustion(mock_altool, mock_auth_error_stdout, retrie
assert final_echo_call[0][0] == json.dumps(json.loads(mock_auth_error_stdout), indent=4)


@mock.patch.object(PlatformType, 'from_path', lambda _artifact_path: PlatformType.IOS)
def test_no_retries(mock_altool, mock_auth_error_stdout):
raise_error = mock.Mock(side_effect=AltoolCommandError('my error', mock_auth_error_stdout))
with mock.patch.object(mock_altool, '_run_command', side_effect=raise_error):
Expand All @@ -78,6 +81,7 @@ def test_no_retries(mock_altool, mock_auth_error_stdout):
assert final_echo_call[0][0] == json.dumps(json.loads(mock_auth_error_stdout), indent=4)


@mock.patch.object(PlatformType, 'from_path', lambda _artifact_path: PlatformType.IOS)
def test_retrying_command_failure(mock_altool, mock_auth_error_stdout, mock_other_error_stdout):
raise_errors = mock.Mock(side_effect=(
AltoolCommandError('my error', mock_auth_error_stdout),
Expand All @@ -100,6 +104,7 @@ def test_retrying_command_failure(mock_altool, mock_auth_error_stdout, mock_othe
assert call[0][0] == expected_output


@mock.patch.object(PlatformType, 'from_path', lambda _artifact_path: PlatformType.IOS)
def test_retrying_command_success(mock_altool, mock_auth_error_stdout, mock_success_result):
raise_errors = mock.Mock(side_effect=(
AltoolCommandError('my error', mock_auth_error_stdout),
Expand All @@ -120,6 +125,7 @@ def test_retrying_command_success(mock_altool, mock_auth_error_stdout, mock_succ
assert call[0][0] == expected_output


@mock.patch.object(PlatformType, 'from_path', lambda _artifact_path: PlatformType.IOS)
def test_retrying_command_immediate_success(mock_altool, mock_success_stdout, mock_success_result):
with mock.patch.object(mock_altool, '_run_command', side_effect=[mock_success_result]):
result = mock_altool.upload_app(pathlib.Path('app.ipa'), retries=100, retry_wait_seconds=0)
Expand Down
4 changes: 3 additions & 1 deletion tests/tools/app_store_connect/test_publish_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ def test_publish_action_app_store_submit(publishing_namespace_kwargs):
mock.patch.object(AppStoreConnect, 'add_beta_test_info') as mock_add_beta_test_info:
ipa_path = pathlib.Path('app.ipa')
mock_find_paths.return_value = [ipa_path]
mock_get_packages.return_value = [mock.create_autospec(Ipa, instance=True, path=ipa_path, version='1.2.3')]
mock_ipa = mock.create_autospec(Ipa, instance=True, path=ipa_path, version='1.2.3')
mock_ipa.is_for_tvos = lambda: False
mock_get_packages.return_value = [mock_ipa]
build = mock.Mock(id='1525e3c9-3015-407a-9ba5-9addd2558224')
mock_get_app.return_value = mock.Mock(id='1525e3c9-3015-407a-9ba5-9addd2558224')
mock_get_build.return_value = build
Expand Down