# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""The `osx_sdk` module provides safe functions to access a semi-hermetic
XCode installation.

Available only to Google-run bots."""

import os

from contextlib import contextmanager

from recipe_engine import recipe_api

# Rationalized from https://en.wikipedia.org/wiki/Xcode.
#
# Maps from OS version to the maximum supported version of Xcode for that OS.
#
# Keep this sorted by OS version.
_DEFAULT_VERSION_MAP = [('10.12.6', '9c40b'), ('10.13.2', '9f2000'),
                        ('10.13.6', '10b61'), ('10.14.3', '10g8'),
                        ('10.14.4', '11b52'), ('10.15.4', '12a7209')]

_RUNTIMESPATH = [
    'Contents', 'Developer', 'Platforms', 'iPhoneOS.platform', 'Library',
    'Developer', 'CoreSimulator', 'Profiles', 'Runtimes'
]

_XCODE_CACHE_PATH = 'osx_sdk'

# This CIPD source contains Xcode and iOS runtimes create and maintained by the
# Flutter team.
_FLUTTER_XCODE_CIPD = 'flutter_internal/ios/xcode'

# This CIPD source contains Xcode and iOS runtimes created and maintained by the
# Chrome team.
_INFRA_XCODE_CIPD = 'infra_internal/ios/xcode'


class OSXSDKApi(recipe_api.RecipeApi):
  """API for using OS X SDK distributed via CIPD."""

  def __init__(self, sdk_properties, *args, **kwargs):
    super(OSXSDKApi, self).__init__(*args, **kwargs)
    self._sdk_properties = sdk_properties
    self._sdk_version = None
    self._runtime_versions = None
    self._tool_pkg = 'infra/tools/mac_toolchain/${platform}'
    self._tool_ver = 'latest'
    self._cleanup_cache = False
    self.macos_13_or_later = False
    self._xcode_cipd_package_source = None

  def initialize(self):
    """Initializes xcode, and ios versions.

    Versions are usually passed as recipe properties but if not then defaults
    are used.
    """
    if not self.m.platform.is_mac:
      return

    if 'cleanup_cache' in self._sdk_properties:
      self._cleanup_cache = self._sdk_properties['cleanup_cache']

    if 'arm' in self.m.platform.arch and 'toolchain_ver_arm' in self._sdk_properties:
      self._tool_ver = self._sdk_properties['toolchain_ver_arm']
    elif 'intel' in self.m.platform.arch and 'toolchain_ver_intel' in self._sdk_properties:
      self._tool_ver = self._sdk_properties['toolchain_ver_intel']

    if 'runtime_versions' in self._sdk_properties:
      # Sorts the runtime versions to make xcode cache path deterministic, without
      # being affected by how user orders the runtime versions.
      runtime_versions = self._sdk_properties['runtime_versions']
      runtime_versions.sort(reverse=True)
      self._runtime_versions = runtime_versions

    current_os = self.m.platform.mac_release
    if 'sdk_version' in self._sdk_properties:
      self._sdk_version = self._sdk_properties['sdk_version'].lower()
    else:
      for target_os, xcode in reversed(_DEFAULT_VERSION_MAP):
        if current_os >= self.m.version.parse(target_os):
          self._sdk_version = xcode
          break
      else:
        self._sdk_version = _DEFAULT_VERSION_MAP[0][-1]

    self.macos_13_or_later = current_os >= self.m.version.parse('13.0.0')

    if 'xcode_cipd_package_source' in self._sdk_properties:
      self._xcode_cipd_package_source = self._sdk_properties[
          'xcode_cipd_package_source']
    else:
      # TODO(vashworth): Once all bots are on macOS 13, we can remove this
      # check and always default to _INFRA_XCODE_CIPD.
      if self.macos_13_or_later:
        # Starting with macOS 13, Xcode packages that have been altered are
        # considered "damaged" and will not be usable. Since Xcode CIPD packages
        # from flutter_internal have been altered up to Xcode 15 beta 6 (15a5219j),
        # use infra_internal Xcode CIPD packages as the default on macOS 13.
        self._xcode_cipd_package_source = _INFRA_XCODE_CIPD
      else:
        self._xcode_cipd_package_source = _FLUTTER_XCODE_CIPD

  @contextmanager
  def __call__(self, kind, devicelab=False):
    """Sets up the XCode SDK environment.

    Is a no-op on non-mac platforms.

    This will deploy the helper tool and the XCode.app bundle at
    `[START_DIR]/cache/osx_sdk`.

    To avoid machines rebuilding these on every run, set up a named cache in
    your cr-buildbucket.cfg file like:

        caches: [
          {
            name: "flutter_xcode"
            path: "osx_sdk"
          }
        ]

    The Xcode app will be installed under:
        osx_sdk/xcode_<xcode-version>

    If any iOS runtime is needed, the corresponding path will be:
        osx_sdk/xcode_<xcode-version>_runtime_<runtime-version>

    These cached packages will be shared across builds/bots.

    Usage:
      with api.osx_sdk('mac'):
        # sdk with mac build bits

      with api.osx_sdk('ios'):
        # sdk with mac+iOS build bits

    Args:
      kind ('mac'|'ios'): How the SDK should be configured. iOS includes the
        base XCode distribution, as well as the iOS simulators (which can be
        quite large).
      devicelab (bool): whether this is a devicelab tasks. The xcode for devicelab
        is installed in a fixed location `/opt/flutter/xcode`.

    Raises:
        StepFailure or InfraFailure.
    """
    assert kind in ('mac', 'ios'), 'Invalid kind %r' % (kind,)
    if not self.m.platform.is_mac:
      yield
      return

    try:
      with self.m.context(infra_steps=True):
        self._show_xcode_cache()
        self._setup_osx_sdk(kind, devicelab)
        runtime_simulators = self.m.step(
            'list runtimes', ['xcrun', 'simctl', 'list', 'runtimes'],
            stdout=self.m.raw_io.output_text()
        ).stdout.splitlines()
        if self._missing_runtime(runtime_simulators[1:]):
          self._cleanup_cache = True
          self._setup_osx_sdk(kind, devicelab)
      yield
    finally:
      self.reset_xcode()

  def reset_xcode(self):
    '''Unset manually defined Xcode path for Xcode command line tools on macOS.'''
    if not self.m.platform.is_mac:
      return
    with self.m.context(infra_steps=True):
      self.m.step('reset XCode', ['sudo', 'xcode-select', '--reset'])

  def _missing_runtime(self, runtime_simulators):
    """Check if there is any missing runtime.

    If no explicit `_runtime_versions` is specified, we assume `runtime_simulators`
    at least has the default runtime and should not be empty.

    If there is explicit `_runtime_versions` defined, we need to check if the number
    of installed runtime matches the number of required.

    The runtime_simulators follows:
    [
      "iOS 16.2 (16.2 - 20C52) - com.apple.CoreSimulator.SimRuntime.iOS-16-2",
      "iOS 16.4 (16.4 - 20E247) - com.apple.CoreSimulator.SimRuntime.iOS-16-4"
    ]

    The property `_runtime_versions` follows:
    [
      "ios-16-4_14e300c",
      "ios-16-2_14c18"
    ]
    """
    if not self._runtime_versions:
      return not runtime_simulators
    return len(self._runtime_versions) != len(runtime_simulators)

  def _setup_osx_sdk(self, kind, devicelab):
    app = None
    self._clean_xcode_cache(devicelab)
    self._micro_manage_cache(devicelab)
    app = self._ensure_sdk(kind, devicelab)
    self.m.os_utils.kill_simulators()
    self._select_xcode(app)
    self.m.step('list simulators', ['xcrun', 'simctl', 'list'])

  def _clean_xcode_cache(self, devicelab):
    """Cleans up cache when specified or polluted.

    Cleans up only corresponding versioned xcode instead of the whole `osx_sdk`.

    If on macOS 13 or later, deletes all mounted runtimes and deletes
    corresponding cached runtime dmgs.
    """
    if not self._cleanup_cache:
      return
    if devicelab or not self.macos_13_or_later:
      self.m.file.rmtree('Cleaning up Xcode cache', self._xcode_dir(devicelab))
    else:
      # Clean up with `file.rmtree` fails on macOS 13 non-devicelab bots with an
      # "Operation not permitted" error when deleting XCode.app/Contents/_CodeSignature.
      # Use `rm -rf` instead.
      self.m.step(
          'Cleaning up Xcode cache',
          ['rm', '-rf', self._xcode_dir(devicelab)]
      )

  def _ensure_mac_toolchain(self, tool_dir):
    ef = self.m.cipd.EnsureFile()
    ef.add_package(self._tool_pkg, self._tool_ver)
    self.m.cipd.ensure(tool_dir, ef)

  def _select_xcode(self, sdk_app):
    self.m.step('select xcode', ['sudo', 'xcode-select', '--switch', sdk_app])

  def _verify_xcode(self, sdk_app):
    '''If Xcode is already downloaded, verify that it's not damaged.

    Args:
    sdk_app: (Path) Path to installed Xcode app bundle.
    '''
    if not self.m.path.exists(sdk_app):
      return

    with self.m.step.nest('verify xcode %s' % sdk_app):
      version_check_failed = False
      try:
        self._select_xcode(sdk_app)

        # This step is expected to timeout if Xcode is damaged.
        self.m.step(
            'check xcode version',
            [
                'xcrun',
                'xcodebuild',
                '-version',
            ],
            timeout=60 * 5,  # 5 minutes
        )
      except self.m.step.StepFailure:
        version_check_failed = True
        raise
      finally:
        self.reset_xcode()
        self._dimiss_damaged_notification()

        if version_check_failed:
          self._diagnose_codesign_failure(sdk_app)

  def _diagnose_codesign_failure(self, sdk_app):
    '''Check if Xcode verification may have failed due to code not matching
    original signed code. Used to help debug issues.
    '''
    self.m.step(
        'verify codesign',
        [
            'codesign',
            '-vv',
            sdk_app,
        ],
        ok_ret='any',
    )

  def _dimiss_damaged_notification(self):
    '''If Xcode is damaged, it may show a notification that can cause
    Xcode processes to hang until it's closed. Kill `CoreServicesUIAgent`
    to close it.
    '''
    self.m.step(
        'dismiss damaged notification',
        ['killall', '-9', 'CoreServicesUIAgent'],
        ok_ret='any',
    )

  def _try_install_xcode(self, tool_dir, kind, app_dir, sdk_app, devicelab):
    """Installs xcode using mac_toolchain. If install fails, clear the cache and try again.

    Args:
      devicelab: (bool) Whether this is a devicelab tasks. Don't install
        explicit runtimes for devicelab tasks.
      app_dir: (Path) Path to Xcode cache directory.
      tool_dir: (Path) Path to mac_toolchain cache directory.
      sdk_app: (Path) Path to installed Xcode app bundle.
      kind ('mac'|'ios'): How the SDK should be configured.
    """
    with self.m.step.nest('install xcode'):
      try:
        self._install_xcode(tool_dir, kind, app_dir, sdk_app, devicelab)
      except self.m.step.StepFailure:
        self._install_xcode(tool_dir, kind, app_dir, sdk_app, devicelab, True)

  def _install_xcode(
      self, tool_dir, kind, app_dir, sdk_app, devicelab, retry=False
  ):
    """Installs xcode using mac_toolchain.

    Args:
      devicelab: (bool) Whether this is a devicelab tasks. Don't install
        explicit runtimes for devicelab tasks.
      app_dir: (Path) Path to Xcode cache directory.
      tool_dir: (Path) Path to mac_toolchain cache directory.
      sdk_app: (Path) Path to installed Xcode app bundle.
      kind ('mac'|'ios'): How the SDK should be configured.
      retry: (bool) Whether this is the second attempt to install Xcode.
    """

    install_path = sdk_app

    # On retry, install Xcode to a different path and later move it to the
    # original path. Although unproven, there is a theory that re-installing
    # Xcode to the same path as a previously damaged version may cause the new
    # version to also be considered damaged.
    if retry:
      uuid = self.m.uuid.random()
      install_path = self.m.path.join(app_dir, 'temp_%s_xcode.app' % uuid)

    try:
      # Verify that existing Xcode is not damaged. If it's damaged, the
      # 'install xcode from cipd' step may get stuck until it times out.
      self._verify_xcode(install_path)
    except self.m.step.StepFailure:
      self._cleanup_cache = True
      self._clean_xcode_cache(devicelab)

    try:
      self._ensure_mac_toolchain(tool_dir)
      if self.macos_13_or_later:
        # TODO(vashworth): Remove macOS 13 specific install steps once
        # https://github.com/flutter/flutter/issues/138238 is resolved.
        self.m.step('Show tool_dir cache', ['ls', '-al', tool_dir])
      self.m.step(
          'install xcode from cipd',
          [
              tool_dir.join('mac_toolchain'), 'install', '-kind', kind,
              '-xcode-version', self._sdk_version, '-output-dir', install_path,
              '-cipd-package-prefix', self._xcode_cipd_package_source,
              '-with-runtime=%s' % (not bool(self._runtime_versions)),
              '-verbose',
          ],
          timeout=60 * 30  # 30 minutes
      )
      if retry:
        self.m.step(
            'move to final destination',
            [
                'mv',
                install_path,
                sdk_app,
            ],
        )
    except self.m.step.StepFailure:
      if self.macos_13_or_later:
        # TODO(vashworth): Remove macOS 13 specific install steps once
        # https://github.com/flutter/flutter/issues/138238 is resolved.
        self.m.step('Show tool_dir cache', ['ls', '-al', tool_dir])
        self.m.step('Show app_dir cache', ['ls', '-al', app_dir], ok_ret='any')
      self._dimiss_damaged_notification()
      self._diagnose_codesign_failure(sdk_app)
      self._cleanup_cache = True
      self._clean_xcode_cache(devicelab)
      self.m.step.empty(
          'Failed to install Xcode',
          status=self.m.step.INFRA_FAILURE,
      )
    finally:
      if retry:
        self.m.step(
            'clean temporary install path',
            [
                'rm',
                '-rf',
                install_path,
            ],
            ok_ret='any',
        )

  def _ensure_sdk(self, kind, devicelab):
    """Ensures the mac_toolchain tool and OSX SDK packages are installed.

    Returns Path to the installed sdk app bundle."""
    app_dir = self._xcode_dir(devicelab)
    tool_dir = self.m.path.mkdtemp().join('osx_sdk') if devicelab else app_dir
    sdk_app = self.m.path.join(app_dir, 'XCode.app')
    self._try_install_xcode(tool_dir, kind, app_dir, sdk_app, devicelab)

    self._cleanup_runtimes_cache(sdk_app)

    self._install_runtimes(devicelab, app_dir, tool_dir, sdk_app, kind)

    return sdk_app
  
  def _micro_manage_cache(self, devicelab):
    app_dir = self._xcode_dir(devicelab)
    self.m.step("show app_dir", ['echo', app_dir])
    self._show_xcode_cache()
    self.m.cache_micro_manager.run(self.m.path['cache'].join(_XCODE_CACHE_PATH), [app_dir])
    self._show_xcode_cache()

  def _show_xcode_cache(self):
    self.m.step(
        'Show xcode cache',
        ['ls', '-al', self.m.path['cache'].join(_XCODE_CACHE_PATH)],
        ok_ret='any',
    )

  def _install_runtimes(self, devicelab, app_dir, tool_dir, sdk_app, kind):
    '''Ensure runtimes are installed.

    For macOS lower than 13, this involves downloading the runtime and copying
    it into the Xcode app bundle.

    For macOS 13 and higher, this involved downloading the runtime dmg and
    running a `simctl` command to verify and mount it. This is required because
    copying files into Xcode on macOS 13 may damage it and prevent it from
    being usable.

    Args:
      devicelab: (bool) Whether this is a devicelab tasks. Don't install
        explicit runtimes for devicelab tasks.
      app_dir: (Path) Path to Xcode cache directory.
      tool_dir: (Path) Path to mac_toolchain cache directory.
      sdk_app: (Path) Path to installed Xcode app bundle.
      kind ('mac'|'ios'): How the SDK should be configured.
    '''
    if not self._runtime_versions:
      # On macOS 13, when cleanup_cache is True, we first clear the Xcode cache,
      # install Xcode, and then clean up the runtimes cache. It happens in this
      # order because removing runtimes requires Xcode developer tools so Xcode
      # must be installed first. However, when no explicit runtimes are defined,
      # the runtime is also installed in the `_try_install_xcode` function. So after
      # cleaning the runtimes, the runtime that was installed may have been
      # removed. So re-call `_try_install_xcode` to reinstall the removed runtime.
      if self.macos_13_or_later and self._cleanup_cache:
        with self.m.step.nest('install runtimes'):
          self._try_install_xcode(tool_dir, kind, app_dir, sdk_app, devicelab)
      return

    if devicelab:
      return

    with self.m.step.nest('install runtimes'):
      if self.macos_13_or_later:
        self._select_xcode(sdk_app)
        runtime_simulators = self.m.step(
            'list runtimes', ['xcrun', 'simctl', 'list', 'runtimes'],
            stdout=self.m.raw_io.output_text(add_output_log=True)
        ).stdout.splitlines()

        for version in self._runtime_versions:
          runtime_version_parts = version.split('_')
          if len(runtime_version_parts) != 2:
            self.m.step.empty(
                'Invalid runtime version %s' % version,
                status=self.m.step.INFRA_FAILURE,
            )
          runtime_version = runtime_version_parts[0]
          xcode_version = runtime_version_parts[1]
          runtime_dmg_cache_dir = self._runtime_dmg_dir_cache_path(version)

          self.m.step(
              'install xcode runtime %s' % version.lower(),
              [
                  app_dir.join('mac_toolchain'),
                  'install-runtime-dmg',
                  '-cipd-package-prefix',
                  self._xcode_cipd_package_source,
                  '-runtime-version',
                  runtime_version,
                  '-xcode-version',
                  xcode_version,
                  '-output-dir',
                  runtime_dmg_cache_dir,
              ],
          )
          downloaded_runtime_files = self.m.file.listdir(
              'list xcode runtime dmg %s' % version.lower(),
              runtime_dmg_cache_dir
          )

          # The runtime dmg may not be named consistently so search for the dmg file.
          runtime_dmg_path = None
          for file_path in downloaded_runtime_files:
            if '.dmg' in str(file_path):
              runtime_dmg_path = str(file_path)

          if runtime_dmg_path is None:
            self.m.step.empty(
                'Failed to find runtime dmg',
                status=self.m.step.INFRA_FAILURE,
            )

          # Skip adding the runtime if it's already mounted
          if not self._is_runtime_mounted(runtime_version, xcode_version,
                                          runtime_simulators):
            self.m.step(
                'verify and mount runtime %s' % version.lower(),
                [
                    'xcrun',
                    'simctl',
                    'runtime',
                    'add',
                    runtime_dmg_path,
                ],
            )

      else:
        # Skips runtime installation if it already exists. Otherwise,
        # installs each runtime version under `osx_sdk` for cache sharing,
        # and then copies over to the destination.

        self.m.file.ensure_directory(
            'Ensuring runtimes directory',
            self.m.path.join(sdk_app, *_RUNTIMESPATH)
        )
        for version in self._runtime_versions:
          runtime_name = 'iOS %s.simruntime' % version.lower(
          ).replace('ios-', '').replace('-', '.')
          dest = self.m.path.join(sdk_app, *_RUNTIMESPATH, runtime_name)
          if not self.m.path.exists(dest):
            runtime_cache_dir = self.m.path['cache'].join(_XCODE_CACHE_PATH
                                                         ).join(
                                                             'xcode_runtime_%s'
                                                             % version.lower()
                                                         )
            self.m.step(
                'install xcode runtime %s' % version.lower(),
                [
                    app_dir.join('mac_toolchain'),
                    'install-runtime',
                    '-cipd-package-prefix',
                    _FLUTTER_XCODE_CIPD,
                    '-runtime-version',
                    version.lower(),
                    '-output-dir',
                    runtime_cache_dir,
                ],
            )
            # Move the runtimes
            path_with_version = runtime_cache_dir.join(runtime_name)
            # If the runtime was the default for xcode the cipd bundle contains a directory called iOS.simruntime otherwise
            # it contains a folder called "iOS <version>.simruntime".
            source = path_with_version if self.m.path.exists(
                path_with_version
            ) else runtime_cache_dir.join('iOS.simruntime')
            self.m.file.copytree(
                'Copy runtime to %s' % dest, source, dest, symlinks=True
            )

  def _xcode_dir(self, devicelab):
    """Returns xcode cache dir.

    For a devicelab task, the path is prefixed at `/opt/flutter/xcode`.

    For a host only task without runtime, the path looks like
            xcode_<xcode-version>

    a host only task with runtimes, the path looks like
        xcode_<xcode-version>_runtime1_<runtime1-version>_..._runtimeN_<runtimeN-version>
    """
    if devicelab:
      return '/opt/flutter/xcode/%s' % self._sdk_version
    runtime_version = None
    sdk_version = 'xcode_' + self._sdk_version
    if not self.macos_13_or_later and self._runtime_versions:
      runtime_version = "_".join(self._runtime_versions)
      sdk_version = sdk_version + '_runtime_' + runtime_version
    return self.m.path['cache'].join(_XCODE_CACHE_PATH).join(sdk_version)

  def _runtime_dmg_dir_cache_path(self, version):
    return self.m.path['cache'].join(_XCODE_CACHE_PATH).join(
        'xcode_runtime_dmg_%s' % version.lower()
    )

  def _cleanup_runtimes_cache(self, sdk_app):
    '''Deletes all mounted runtimes and deletes corresponding cached runtime dmgs.

    This is only used for macOS 13+ since runtimes are installed and mounted separately.
    '''

    if not self._cleanup_cache or not self.macos_13_or_later:
      return

    with self.m.step.nest('Cleaning up runtimes cache'):
      self._select_xcode(sdk_app)

      simulator_cleanup_result = self.m.step(
          'Cleaning up mounted simulator runtimes',
          [
              'xcrun',
              'simctl',
              'runtime',
              'delete',
              'all',
          ],
          raise_on_failure=False,
          ok_ret='any',
          stdout=self.m.raw_io.output_text(add_output_log=True),
          stderr=self.m.raw_io.output_text(add_output_log=True),
      )

      simulator_cleanup_stdout = simulator_cleanup_result.stdout.rstrip()
      simulator_cleanup_stderr = simulator_cleanup_result.stderr.rstrip()
      if simulator_cleanup_stdout and 'No matching images found to delete' not in simulator_cleanup_stdout:
        self.m.step.empty(
            'Failed to delete runtimes',
            status=self.m.step.INFRA_FAILURE,
            step_text=simulator_cleanup_stdout,
        )
      if simulator_cleanup_stderr and 'No matching images found to delete' not in simulator_cleanup_stderr:
        self.m.step.empty(
            'Failed to delete runtimes',
            status=self.m.step.INFRA_FAILURE,
            step_text=simulator_cleanup_stderr,
        )

      # Wait up to ~5 minutes until runtimes are unmounted.
      self.m.retry.basic_wrap(
          self._is_runtimes_unmounted,
          step_name='Wait for runtimes to unmount',
          sleep=5.0,
          backoff_factor=2,
          max_attempts=7
      )

      if not self._runtime_versions:
        return

      for version in self._runtime_versions:
        runtime_dmg_cache_dir = self._runtime_dmg_dir_cache_path(version)

        self.m.file.rmtree(
            'Cleaning up runtime cache %s' % version.lower(),
            runtime_dmg_cache_dir
        )

  # pylint: disable=unused-argument
  def _is_runtimes_unmounted(self, timeout=None):
    '''Check if more than one runtime is currently mounted. If more than one
    is mounted, raise a `StepFailure`.
    '''
    runtime_simulators = self.m.step(
        'list runtimes', ['xcrun', 'simctl', 'list', 'runtimes'],
        stdout=self.m.raw_io.output_text(add_output_log=True)
    ).stdout.splitlines()

    # There should not be more than one runtime after deleting all. There may
    # be one if the runtime is included within Xcode, which means it won't be
    # unmounted.
    if len(runtime_simulators[1:]) > 1:
      raise self.m.step.StepFailure('Runtimes not unmounted yet')

  def _is_runtime_mounted(
      self, runtime_version, xcode_version, runtime_simulators
  ):
    '''Determine if iOS runtime version is already mounted.

    Args:
      runtime_version: (string) The iOS version (e.g. "ios-16-4").
      xcode_version: (string) The Xcode version (e.g. "14e300c").
      runtime_simulators: (list) A list of strings of runtime versions.
    Returns:
      A boolean for whether or not the runtime is already mounted.
    '''

    with self.m.step.nest('cipd describe %s_%s' %
                          (runtime_version, xcode_version)) as display_step:
      # First try to get the iOS runtime build version by the Xcode version
      ios_runtime_build_version = self._get_ios_runtime_build_version(
          runtime_version, xcode_version
      )

      # If unable to get from the Xcode version, try again by using the iOS runtime version
      if ios_runtime_build_version is None:
        ios_runtime_build_version = self._get_ios_runtime_build_version(
            runtime_version
        )

      if ios_runtime_build_version is None:
        self.m.step.empty(
            'Failed to get runtime build version',
            status=self.m.step.INFRA_FAILURE,
        )
      else:
        self.m.step.empty(
            'runtime build version', step_text=ios_runtime_build_version
        )
        display_step.presentation.status = self.m.step.SUCCESS

    # Check if runtime is already mounted
    for runtime in runtime_simulators:
      # Example runtime: `iOS 14.3 (14.3 - 18C61) - com.apple.CoreSimulator.SimRuntime.iOS-14-3`
      if ios_runtime_build_version.lower() in runtime.lower():
        return True

    return False

  def _get_ios_runtime_build_version(self, runtime_version, xcode_version=None):
    '''Gets the iOS runtime build version from CIPD.

    If `xcode_version` is provided, it will use it to search for the CIPD package.
    If not provided, the `runtime_version` will be used. In both cases, it ensures
    the found package matches the `runtime_version`.

    Args:
      runtime_version: (string) An iOS version used to find and match the CIPD package (e.g. "ios-16-4")
      xcode_version: (string) A version of Xcode to use to find CIPD package (e.g. "14e300c").
    Returns:
      A string of the build version or None if unable to get the build version.
    '''

    search_ref = runtime_version
    if xcode_version is not None:
      search_ref = xcode_version

    try:
      description = self.m.cipd.describe(
          '%s/ios_runtime_dmg' % self._xcode_cipd_package_source,
          search_ref,
      )
      runtime_tag = None
      build_tag = None
      for tag in description.tags:
        if 'ios_runtime_version' in tag.tag:
          runtime_tag = self._parse_cipd_description_tag(tag.tag)
        if 'ios_runtime_build' in tag.tag:
          build_tag = self._parse_cipd_description_tag(tag.tag)

      if runtime_tag == runtime_version:
        return build_tag

      self.m.step.empty(
          'mismatching runtimes',
          step_text='Found %s, expected %s' % (runtime_tag, runtime_version),
          status=self.m.step.INFRA_FAILURE,
      )

    except self.m.step.StepFailure:
      pass

    return None

  def _parse_cipd_description_tag(self, tag):
    '''Parse a colon separated CIPD description tag.

    Args:
      tag: (string) A colon separated string describing a CIPD tag.
        (e.g "ios_runtime_build:21A5303d" or "ios_runtime_version:ios-17-0")
    Returns:
      A string of the value following the colon or None if unable to parse.
    '''
    tag_parts = tag.split(':')
    if len(tag_parts) == 2:
      return tag_parts[1]
    return None
