Как часто нам, iOS разработчикам, приходится собирать приложение для загрузки в iTunes Connect App Store Connect? В процессе этапа активного бета-тестирования приложения нужно оперативно фиксить баги и поставлять обновленную сборку для тестирования. А также необходимо скачивать сертификаты, Provision profiles, прокликивать много разных галочек и кнопочек при каждой выкладке нового билда.


К счастью, есть такой замечательный инструмент, как fastlane, который помогает нам автоматизировать ручные действия мобильного разработчика.


В этом посте я расскажу: что такое fastlane и как быстро начать его использовать в своих iOS проектах.


Введение


Что это? 


Fastlane ?-? это инструмент для автоматизации процессов сборки и выкладки мобильных iOS и Android приложений, которая включает в себя также генерирование скриншотов, запуск Unit/UI тестов, отправка сообщений в Slack, подключение к Crashlytics и многие другие полезные вещи, которые упрощают жизнь. 


Какой профит?


На первоначальную настройку базовых команд для автоматизации выкладки приложения, например, для публикации в App Store или на TestFlight, уйдет не более двух часов, однако в будущем это сэкономит уйму времени, т.к. весь процесс будет запускаться одним вызовом из командной строки.


ВНИМАНИЕ: Для выполнения всех шагов необходима подписка Apple Developer, так как доступ в App Store Connect отсутствует для бесплатных аккаунтов.


Установка


Устанавливаем сам fastlane


Для начала установим/обновим до последней версии Xcode Command Tools: 


$ xcode-select --install

Устанавливаем gem fastlane:


$ sudo gem install fastlane -NV 
# или через brew
$ brew cask install fastlane

Добавляем в проект 


В корневой директории проекта запускаем:


$ sudo fastlane init

Fastlane предложит нам варианты предустановленных скриптов в зависимости от того, что мы хотим:



Мы выберем 4 вариант, т.к. будем прописывать все необходимые команды под свою ситуацию:



Готово! Папка fastlane и файл gemfile успешно установлена к нам в проект.


Перед тем, как продолжим


Если в shell профайле locale не UTF-8, то будут возникать проблемы со сборкой и загрузкой билдов. Заходим в файл вашего shell profile (~/.bashrc, ~/.bash_profile, ~/.profile или ~/.zshrc) и добавляем следующие строчки:


export LC_ALL=en_US.UTF-8 
export LANG=en_US.UTF-8

Теперь все готово к написанию непосредственных шагов автоматизации сборки.


Как это работает


Для начала выясним, что делает fastlane: основные его команды и как мы описываем то, что нужно сделать.


Команды (Actions)


В fastlane входит много полезных команд, упрощающих жизнь разработчику:


  • cert: автоматически скачивает и устанавливает необходимые сертификаты (Distribution, Development) для подписи собираемых приложений;
  • increment_build_number: увеличивает номер билда на 1, либо изменяет на значение, заданное в параметре build_number
  • sigh: автоматически скачивает и устанавливает все необходимые provision profiles;
  • snapshot: запускает UI-тесты и делает скриншоты, которые можно использовать при отправке на review в App Store;
  • gym: собирает архив и, здесь же, конечный ipa вашего приложения;
  • scan: все просто? — ?запускает таргет тестов;
  • deliver: отправляет ipa, скриншоты, метаданные прямиком в App Store;
  • pilot: загружает свежий ipa на бета тест в TestFlight. Также с помощью этой команды можно управлять тестировщиками.
  • и многие другие

Fastfile


Папка fastlane содержит в себе Fastfile и Appfile. В Appfile мы будем прописывать необходимые для сборки и публикации значения: Bundle IDs, App ID, Team ID и другие. В Fastfile мы будем описывать наши скрипты. После первоначальной установки он выглядит так:


default_platform(:ios)

platform :ios do
  desc "Description of what the lane does"
  lane :custom_lane do
    # add actions here: https://docs.fastlane.tools/actions
  end
end

  • default_platform(:ios)? -? задаем платформу по умолчанию, чтобы не указывать ее из командной строки.
  • platform :ios do … end ?-? здесь описываются "lanes" для платформы iOS.
  • desc "Description of what the lane does" ?-? краткое описание "lane". Список всех "lanes" с описаниями можно посмотреть с помощью команды $ fastlane lanes.
  • lane :custom_lane do … end: Lane (путь, полоса) — это, проще говоря, метод. У него есть имя, параметры и тело. В теле мы будем вызывать необходимые нам команды для сборки, выкладки, запуска тестов и др. Lanes вызываются из командной строки вызовом $ fastlane [lane_name] [parameters] . Именно с вызова одной из lanes начинается выполнение автоматизированных шагов.

Автоматизируем выгрузку на TestFlight


Начнем с задания понятного имени нашему lane'у. Переименуем custom_lane в testflight_lane. Теперь понятно, что результатом выполнения этого скрипта будет загруженная свежая сборка в TestFlight.


default_platform(:ios)

platform :ios do
  desc "Builds, achieves and uploads ipa to TestFlight"
  lane :testflight_lane do
    # Actions
  end
end

Конфигурируем Appfile


Для того, чтобы каждый раз при запуске скрипта не вводить bundle приложения и Apple ID, выпишем их в Appfile:


app_identifier "ru.ee.shishko.TheHatGame"
apple_id "ee.shishko@gmail.com"

Сертификаты и Provision Profiles


Добавим команды cert и sigh для установки сертификатов и provision profiles соответственно:
(Внимание: если вашего приложения нет в App Store Connect, то необходимо добавить команду produce с параметром app_name)


default_platform(:ios)

platform :ios do
  desc "Builds, achieves and uploads ipa to TestFlight"
  lane :testflight_lane do
      # Если приложение не создавалось в App Store Connect: 
      # produce (
      #     app_name: "MyAppName"
      # )

      cert
      sigh
  end
end

Запустим наш скрипт с помощью команды $ fastlane testflight_lane 


При запуске Fastlane попросит у нас ввести пароль от аккаунта, вводим его. Потребуется это только один раз ?- ?fastlane его запомнит и при следующих запусках вводить ничего не потребуется.
Вот так выглядит вывод, когда fastlane успешно завершает выполнение скрипта:




Теперь сертификат и provision profiles скачены и установлены. Осталось проставить во вкладе General нужного таргета:




Сборка приложения


Добавим команду increment_build_number для увеличения номера билда. Если у вас главный .xcodeproj файл лежит не в корневой папке, то указываем для него путь в параметре xcodeproj:


default_platform(:ios)

platform :ios do
  desc "Builds, achieves and uploads ipa to TestFlight"
  lane :testflight_lane do
      cert
      sigh
      increment_build_number

      # Если главный .xcodeproj не в корневой директории проекта, то:
      #
      # increment_build_number(
      #   xcodeproj: "./path/to/MyApp.xcodeproj" 
      # )
  end
end

Для работы увеличения номера билда, необходимо зайти в Build Settings/Versioning и выставить Versioning System в Apple Generic и Current Project Version в 1:




Добавим команду gym, которая собирает ipa файл нашего приложения:




Среди параметров можно указать, куда будет положен ipa (output_directory), имя ipa (output_name), scheme (scheme), делать ли Clean (clean) и некоторые другие. Мы ничего не будем указывать в параметрах? — ?fastlane выставит параметры по-умолчанию, соберет и подпишет ipa, но опять же: при желании и необходимости всё можно указать подробно:


default_platform(:ios)

platform :ios do
  desc "Builds, achieves and uploads ipa to TestFlight"
  lane :testflight_lane do
      cert
      sigh
      increment_build_number
      gym
      # С заданием конкретных параметров:
      #
      # gym(
      #  workspace: "TheHatGame.xcworkspace",
      #  scheme: "TheHatGame",
      #  configuration: "Release",
      #  clean: true,
      #  output_directory: "./build",
      #  output_name: "TheHatGame.ipa",
      #  codesigning_identity: "iPhone Distribution: Evgeny Shishko"
      # )
  end
end

Выгрузка на TestFlight


Для загрузки ipa в TestFlight будем использовать Pilot:



С помощью Pilot можно:


  • выгружать и распространять сборки;
  • добавлять и удалять бета тестеров;
  • получать информацию о тестировщиках и используемых ими устройств;
  • экспортировать информацию о тестировщиках в .csv для того, чтобы импортировать их в другой проект.

Мы будем использовать основную его функцию: отправка сборок в Apple Store Connect.


Добавим в testflight_lane вызов upload_to_testflight с параметрами skip_submission (будем использовать только для загрузки ipa файла) и skip_waiting_for_build_processing (не дожидаемся окончания processing'a):


default_platform(:ios)

platform :ios do
  desc "Builds, achieves and uploads ipa to TestFlight"
  lane :testflight_lane do
      cert
      sigh
      increment_build_number
      gym
      upload_to_testflight(
           skip_submission: true,
           skip_waiting_for_build_processing: true
      )
  end
end

Запускаем итоговый скрипт


Сохраняем наши изменения и запускаем из консоли:


$ fastlane testflight_lane

На этапе отправки в testflight в консоли потребуется ввести app-specific пароль (который требуется для авторизации в Application Loader). Найти его можно в личном кабинете Apple ID, сгенерировав его по нажатию на "Generate Password":



После ввода пароля свежая сборка будет успешно загружена в TestFlight и выполнение fastlane на этом закончится:




Статус новой версии можно посмотреть в App Store Connect:




Заключение


На этом всё! Хотел бы обратить внимание, что в данной статье мы в самом общем случае попробовали возможности fastlane. В связи c этим прикрепляю опрос: будут ли интересны вам, хабровчане, посты про подробное использование упомянутых и других полезных команд в fastlane и продвинутых фишек в настройке скриптов?


Приложение с представленной настройкой fastlane можно найти здесь.

Комментарии (8)


  1. rumyancevpavel
    25.09.2018 18:44

    Исходя из своего опыта могу сказать что вместо связки sigh+cert лучше использовать match. В добавок к функциям sigh и cert, match позволяет содержать в порядке certificates и provisioning profiles дев центре


    1. deimous Автор
      25.09.2018 19:54

      Согласен. Благодаря тому, что match работает со всеми сертификатами и provision profiles в отдельном git репозитории, можно предоставить всем разработчикам нужные права к нему и тогда изменения в code sign identities будут сразу доступны всем. Однако для более быстрой настройки, в посте были указаны команды cert+sigh по причине простоты их использования


  1. osigida
    25.09.2018 18:51

    Запуск на локальной машине решает мало проблем. А вот как все это вертеть в контейнере на абстрактном CI/CD?


    1. deimous Автор
      25.09.2018 20:04

      Да, для эффективного fastlane конечно же нужно использовать его с CI контейнерами. А интегрировать в контейнер его довольно просто — достаточно добавить как шаг CI вызов команды fastlane из shell с указанием lane’а: также как мы запускаем его с локальной машины. А вот как настроить у себя, например Jenkins или Travis — тема уже для отдельной статьи :)


      Подробнее можно посмотреть тут


      1. osigida
        25.09.2018 20:20

        Если-б, вы когда нибудь пытались запустить сборку iOS приложения в контейнере?
        Экосистема настолько закрыта и отстала, что это требует неимоверных танцев с бубном, по крайне мере так было, когда я смотрел в последний раз. Правда, может все изменилось?


        1. andrew8712
          25.09.2018 21:17

          CircleCI поддерживает iOS без (ну или почти) танцев с бубном


        1. tokarev
          27.09.2018 10:36

          попробуйте nevercode.io Определяет Fastfile и настраивается автоматически (если не используется match, то надо только сертификаты загрузить) скорость сборки обычно больше по сравнению с остальными CI

          ps: являюсь разработчиком сервиса, могу ответить на любые вопросы


          1. osigida
            27.09.2018 10:46

            спасибо! буду смотреть