# 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'
]

# 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._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 _get_xcode_base_cache_path(self, devicelab: bool):
    """Returns the base cache path for xcode.

    Args:
      devicelab - Whether or not the machine this code is running is a devicelab
        machine.
    """
    if devicelab:
      return '/opt/flutter/xcode'
    return self.m.path['cache'].join('osx_sdk')

  def _setup_osx_sdk(self, kind, devicelab):
    app = None
    self._clean_xcode_cache(devicelab)
    self._micro_manage_cache(devicelab=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):
    cache_path = self._get_xcode_base_cache_path(devicelab)
    app_dir = self._xcode_dir(devicelab)
    self.m.step("show app_dir", ['echo', app_dir])
    self._show_xcode_cache(devicelab=devicelab)
    self.m.cache_micro_manager.run(cache_path, [app_dir])
    self._show_xcode_cache(devicelab=devicelab)

  def _show_xcode_cache(self, devicelab):
    cache_path = self._get_xcode_base_cache_path(devicelab)
    self.m.step(
        'Show xcode cache',
        ['ls', '-al', 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]
          # we can assume devicelab False and build this with base path.
          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):
            cache_base_path = self._get_xcode_base_cache_path(False)
            runtime_cache_dir = cache_base_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 the location of the xcode app in the 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>
    """

    xcode_cache_base_path = self._get_xcode_base_cache_path(devicelab)
    if devicelab:
      return f"{xcode_cache_base_path}/{self._sdk_version}"
    runtime_version = None
    sdk_version = f"xcode_{self._sdk_version}"
    if not self.macos_13_or_later and self._runtime_versions:
      runtime_version = "_".join(self._runtime_versions)
      sdk_version = f"{sdk_version}_runtime_{runtime_version}"
    return xcode_cache_base_path.join(sdk_version)

  def _runtime_dmg_dir_cache_path(self, version):
    cache_base_path = self._get_xcode_base_cache_path(False)
    # this method seems to be only used for non-devicelab cache path.
    return cache_base_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
