Dmitriy Azarov

Автоматизируем сборку iOS проектов используя XCode и скрипт на Ruby

Сегодняшний день требует быстрой реакции на пожелания пользователей и такую же быструю реализацию всех фич в приложении. Для того, чтобы не быть отстающим и быть впереди всех необходимо уметь быстро реагировать на изменения. Процесс сборки приложений и отправки их на тестирование может занимать несколько минут. Это не страшно, если это требуется раз в неделю. Но если это необходимо делать несколько раз в день не хочется как отвлекаться на эту рутиную задачу, так и более автоматизировать процесс сборки и тестов.

Первым шагом следует внедрить и отправку приложения на тестирование через инструмент командной строки fastlane. Ниже приведен простейший скрипт автоматизации сборки и отправки на fastlane.

lane :buildtocrashlytics do
  gym(
    clean: true,
    silent: true,
    configuration: "Debug",
    scheme: "app",
    export_method: "development",
    include_bitcode: false, 
    verbose: true,
    export_team_id: "ENTER_YOUR_TEAM_ID",
    output_directory: "build",
    output_name: "app.ipa",
    xcargs: "ARCHIVE=YES" # Used to tell the Fabric run script to upload dSYM file
  )

  # Distribute via Crashlytics
  crashlytics(
    ipa_path: "build/app.ipa",
    api_token: "ENTER_YOUR_CRASHLYTICS_API_TOKEN",
    build_secret: "ENTER_YOUR_CRASHLYTICS_API_SECRET",
    groups: ['main'], # Группа тестировщиков в crashlytics
    notes: "ENTER_YOUR_RELEASE_NOTES"
  )

  version = `/usr/libexec/plistbuddy -c Print:CFBundleShortVersionString '../Application/Info.plist'`.strip
  build = `/usr/libexec/plistbuddy -c Print:CFBundleVersion '../Application/Info.plist'`.strip
end

Эту сборку нужно запускать вручную на той машине, где будет производиться сборка. На ней должен быть установлен XCode. Во время сборки в Crashlytics работать с XCode нельзя, потому что он билдит приложение и другие процессы сборки будут ждать его окончания. Для этого необходимо найти отдельную машину для сборки. Мне повезло, такая нашлась. Осталось как-то удаленно запускать сборку. Первым делом я попробовал XCode bots. Честно все выглядит красиво, но копнув глужбе столкнулся с кучей ограничений на дополнительные обработки и ухищрения. Например, чтобы выполнить команду pod install необходимо уже писать костыли. Не хочется.

Пока нет полноценного CI сервера решено было реализовать триггер старта сборки через бота Telegram. Использовать будем Ruby, как близкий к macOS и iOS по духу. Сначала пробовал реализовать скрипт на Python, но возникли трудности с чтением xcodeproj файла и его парсинга, на Ruby есть актуальная библиотека, которая это делает. В рамках этой статьи нет различий на чем реализовывать.

Наш бот должен собирать приложение в 3 этапа:

  1. Скачать последние изменения в git
  2. Установить pods
  3. Выполнить fastlane по сборке и отправке приложения

Первые 2 пункта также можно реализовать в fastlane.

lane :pull do
  sh "git pull"
end

Скрипт по выполнению pull. И Установка подов ниже:

lane :pods do 
  cocoapods
end

Далее устанавливаем gem telegram-bot-ruby.

$ gem install telegram-bot-ruby

Теперь все готово для написания логики бота.

require 'telegram/bot'

token = 'ENTER_YOUR_BOT_TOKEN'

def build (bot, chatId)
    bot.api.send_message(chat_id: chatId, text: "Thank you. Starting build.")

    cmd = 'fastlane pull'
    %x[#{cmd}]
    bot.api.send_message(chat_id: chatId, text: "Pull OK")

    cmd = 'fastlane pods'
    %x[#{cmd}]
    bot.api.send_message(chat_id: chatId, text: "Pods OK")
    
    cmd = 'fastlane buildtocrashlytics'
    %x[#{cmd}]
    bot.api.send_message(chat_id: chatId, text: "Build done")
end

Telegram::Bot::Client.run(token) do |bot|
  bot.listen do |message|    
    case message.text
    when '/start'
        bot.api.send_message(chat_id: message.chat.id, text: "Hello, #{message.from.first_name}")
        kb = [
            Telegram::Bot::Types::KeyboardButton.new(text: 'Build application')
        ]
        markup = Telegram::Bot::Types::ReplyKeyboardMarkup.new(keyboard: kb)
        bot.api.send_message(chat_id: message.chat.id, text: 'Select action', reply_markup: markup)
    when 'Build application'
        Thread.start { build(bot, message.chat.id) }
    end
  end
end
  • 08 янв 2017
  • iOS, xcode
0 комментариев
Ваш комментарий
адрес не будет опубликован
Текст