示例#1
0
    def publish(self,
                application_package_path_patterns: Sequence[pathlib.Path],
                apple_id: Optional[str] = None,
                app_specific_password: Optional[
                    Types.AppSpecificPassword] = None,
                submit_to_testflight: Optional[bool] = None) -> None:
        """
        Publish application packages to App Store and submit them to Testflight
        """

        if not (apple_id and app_specific_password):
            self._assert_api_client_credentials(
                'Either Apple ID and app specific password or App Store Connect API key information is required.'
            )
        elif submit_to_testflight:
            self._assert_api_client_credentials(
                'It is required for submitting an app to Testflight.')

        application_packages = self._get_publishing_application_packages(
            application_package_path_patterns)
        try:
            altool = Altool(
                username=apple_id,
                password=app_specific_password.value
                if app_specific_password else None,
                key_identifier=self._key_identifier,
                issuer_id=self._issuer_id,
                private_key=self._private_key,
            )
        except ValueError as ve:
            raise AppStoreConnectError(str(ve))

        failed_packages: List[str] = []
        for application_package in application_packages:
            try:
                build, pre_release_version = self._publish_application_package(
                    altool, application_package)
                if submit_to_testflight:
                    self.create_beta_app_review_submission(build.id)
            except IOError as error:
                # TODO: Should we fail the whole action on first publishing failure?
                failed_packages.append(str(application_package.path))
                self.logger.error(Colors.RED(error.args[0]))

        if failed_packages:
            raise AppStoreConnectError(
                f'Failed to publish {", ".join(failed_packages)}')
示例#2
0
    def run_test(self,
                 xcode_project_path: Optional[pathlib.Path] = None,
                 xcode_workspace_path: Optional[pathlib.Path] = None,
                 target_name: Optional[str] = None,
                 configuration_name: Optional[str] = None,
                 scheme_name: Optional[str] = None,
                 clean: bool = False,
                 devices: Optional[List[str]] = None,
                 disable_code_coverage: bool = False,
                 max_concurrent_devices: Optional[int] = TestArgument.MAX_CONCURRENT_DEVICES.get_default(),
                 max_concurrent_simulators: Optional[int] = TestArgument.MAX_CONCURRENT_SIMULATORS.get_default(),
                 test_only: Optional[str] = TestArgument.TEST_ONLY.get_default(),
                 test_sdk: str = TestArgument.TEST_SDK.get_default(),
                 test_xcargs: Optional[str] = XcodeArgument.TEST_XCARGS.get_default(),
                 test_flags: Optional[str] = XcodeArgument.TEST_FLAGS.get_default(),
                 disable_xcpretty: bool = False,
                 xcpretty_options: str = XcprettyArgument.OPTIONS.get_default(),
                 output_dir: pathlib.Path = TestResultArgument.OUTPUT_DIRECTORY.get_default(),
                 output_extension: str = TestResultArgument.OUTPUT_EXTENSION.get_default(),
                 graceful_exit: bool = False):
        """
        Run unit or UI tests for given Xcode project or workspace
        """
        self._ensure_project_or_workspace(xcode_project_path, xcode_workspace_path)
        simulators = self._get_test_destinations(devices)
        xcodebuild = self._get_xcodebuild(**locals())
        clean and self._clean(xcodebuild)

        self.echo(Colors.BLUE(f'Run tests for {(xcodebuild.workspace or xcodebuild.xcode_project).name}\n'))
        xcresult_collector = XcResultCollector()
        xcresult_collector.ignore_results(Xcode.DERIVED_DATA_PATH)
        try:
            xcodebuild.test(
                test_sdk,
                simulators,
                enable_code_coverage=not disable_code_coverage,
                only_testing=test_only,
                xcargs=test_xcargs,
                custom_flags=test_flags,
                max_concurrent_devices=max_concurrent_devices,
                max_concurrent_simulators=max_concurrent_simulators,
            )
        except IOError:
            testing_failed = True
            self.echo(Colors.RED('\nTest run failed\n'))
        else:
            testing_failed = False
            self.echo(Colors.GREEN('\nTest run completed successfully\n'))
        xcresult_collector.gather_results(Xcode.DERIVED_DATA_PATH)

        output_dir.mkdir(parents=True, exist_ok=True)
        self._copy_simulator_logs(simulators, output_dir)

        if not xcresult_collector.get_collected_results():
            raise XcodeProjectException('Did not find any test results')

        test_suites, xcresult = self._get_test_suites(
            xcresult_collector, show_found_result=True, save_xcresult_dir=output_dir)

        message = (
            f'Executed {test_suites.tests} tests with '
            f'{test_suites.failures} failures and '
            f'{test_suites.errors} errors in '
            f'{test_suites.time:.2f} seconds.\n'
        )
        self.echo(Colors.BLUE(message))
        TestSuitePrinter(self.echo).print_test_suites(test_suites)
        self._save_test_suite(xcresult, test_suites, output_dir, output_extension)

        if not graceful_exit:
            has_failing_tests = test_suites and (test_suites.failures or test_suites.errors)
            if testing_failed or has_failing_tests:
                raise XcodeProjectException('Tests failed')