Яблочный CI

Введение


Мы — команда Platform в Playrix, у нас большая и сложная билд-ферма, использующая возможности всех платформ и облачных решений и успешно применяющая их на практике. В этой статье я бы хотел поделиться с вами особенностью работы с платформой MacOS.

image-loader.svg


Проблемы и их решение


Глава 1. Таков путь


Для успешного CI в современных реалиях необходимо использовать все доступные платформы и средства, уметь их масштабировать и автоматизировать. И разные платформы имеют разную степень сложности реализации данного требования. Для Win-платформ достаточно общих знаний и доступно очень много информации в интернете. Также эту платформу, как самую распространенную, поддерживают все облачные провайдеры, включая такие гиганты, как AWS и Azure. Для нее существует очень много решений по автоматизации и настройке. Linux-like, да-да, именно Linux. Так вот, всеми нами любимые «Убунточки» имеют еще больше возможностей по автоматизации всего и вся. 

Славься, о великий Bash!


И вроде бы все хорошо в прекрасном мире CI… Но тут появляется еще одна потребность — MacOS, обладающая низкой масштабируемостью, ведь на текущий момент нет хороших облачных решений. Да, есть подвижки в этом направлении у AWS с их мак-инстансами, есть другие решения разной степени успешности. 

Кроме низкой масштабируемости эта система обладает сложностями автоматизации. Те, кто пытались использовать MDM-решения, думаю, согласятся с этим утверждением. Но что делать, если работать эффективно надо здесь и сейчас? Верно — нужно искать обходные пути. 

image-loader.svg


Глава 2. Big Surrealism


Команда из Купертино, глядя на то, что постепенно люди научились бороться с логикой их системы и достаточно хорошо все автоматизировать, решает сделать мир «безопасней» и выпускает BigSur. Где меняет логику защиты системы, чем осложняет жизнь разработчикам. Например, выдача системных разрешений на system events и screen recording требует вашего участия. tccutil больше не может управлять этими правами. Тут опытные камрады могут возразить, что есть MDM. Так-то оно так, но разворачивать всю структуру MDM только ради того, чтоб решить пару вопросов с настройкой — дорогое оверкилл решение, обладающее достаточно скромным функционалом в области системного администрирования. 

Одновременно с этим все старые системы стали непригодными для современной разработки, ведь XCODE 12.5 + есть только на BigSur. Ну что ж, современные проблемы требуют современного подхода и решений. Как говорится, challenge accepted!

MWn9tiyO05E2h08Y-y3NzrHbN1efjzSbj0sC0HPQ


Глава 3. Fusion


Итак, начнем решать некоторые особенности MacOS BigSur, а именно попробуем немного улучшить ситуацию с масштабируемостью. Стоит подумать о виртуализации сборочных мак-агентов — это позволит лучше утилизировать ресурсы хостовой машины, а также сократить время развертывания и подготовки новых агентов. 

Единственным легальным способом решить это является связка из оригинального оборудования Apple + VMWARE Fusion в роли гипервизора. В качестве хостов отлично подходят Mac PRO в стоечном исполнении. Да, дорого, иногда очень. А вы ожидали чего-то другого от этого производителя?  

Описывать установку гипервизора и установку macos в качестве гостевой системы я не буду. Официальная документация от vmware достаточно проста и подробна. Я опишу некоторые особенности, связанные с использованием MacOS BigSur и необходимостью отключать System Integrity Protection (SIP) (зачем это нужно — я напишу ниже).

Итак. Установка BigSur на Fusion не отличается от установки других MacOS, не будем заострять на этом внимание. Проблемы начинаются, когда вы решите отключить SIP, так как классический вариант с загрузкой в рековери мод не работает. На виртуалке вы в него просто не попадете. Возможно, в будущем эта проблема будет решена, но как поступить сейчас? Решение есть. 

Для того, чтобы отключить SIP на MacOS BigSur внутри VMWARE Fusion, надо проделать следующее:

  • Грузимся в гостевую систему → sudo nvram Asr-active-config=%7f%00%00%00;
  • Выключаем VM, выбираем Restart to Firmware…;
  • Грузимся в BIOS — выбираем EFI Internal Shell, грузимся, подтверждаем запуск start.sh;
  • Теперь нужно найти EFI раздел. Пробуем команду fs0:, затем vol, если в выводе видим EFI — переходим к следующему шагу, если нет — то пробуем fs1:, fs2:, fs3: и т.д.;
  • Сохраняем дамп переменных в файл dmpstore Asr-active-config -s csr.bin;
  • Правим получившийся файл HEX редактором hexedit csr.bin;
  • Нужно заменить в первой строке 41 на 63, сохраняемся;
  • Записываем конфиг в NVRAM dmpstore -l csr.bin;
  • Вводим exit и грузимся нормально, система загрузится с отключенным SIP.


После этого остается настроить виртуальный мак-агент, как обычный. Почти :)

Чтобы, например, изменить разрешение экрана (предположим, на FullHD) виртуального мака, следует выполнить команду:

sudo /Library/Application\ Support/VMware\ Tools/vmware-resolutionSet 1920 1080


image-loader.svg


Глава 4. System Events


Часто при работе возникает потребность управлять разрешением доступов системы. Например, при написании автотестов или тестировании приложений.

Основные разрешения, которые могут при этом понадобиться, — это Screen Recording и, главное, System Events. До эры BS для установки разрешений можно было использовать утилиту tccutil, но этот способ больше не работает. Однако нас это не должно останавливать.

Давайте разбираться.

Установка разрешений в MacOS делится на пользовательскую и системную. Оба вида этих настроек отображаются в одном и том же меню — это System Preferences — Security and Privacy. Настройки пользователя — это те настройки, которые можно менять без ввода пароля, например, System Events. Тогда как для изменения Screen Recording необходим уже ввод пароля, что говорит нам о том, что это системная настройка.

Данные о настройках безопасности хранятся в sql базах TCC.db.

Системная база находится по пути «/Library/Application Support/com.apple.TCC/TCC.db», для удобства запишем этот путь в переменную SYS_DB_PATH.

Пользовательская база же находится по пути «/Users/[username]/Library/Application Support/com.apple.TCC/TCC.db», ее мы занесем в USR_DB_PATH.

Вот эти базы мы и будем редактировать, чтобы изменить разрешения безопасности. Это возможно сделать только при отключенном SIP.

Можно легко получить текущие записи в этих базах данных, используя sqlite3. Читаем:  

sqlite3 "$SYS(USR)_DB_PATH" 'SELECT * FROM access;'


Итак, выдадим права на захват экрана и управление системными событиями для нашего приложения. 

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

TARGET_BIN="/opt/myapp/bin/myapp".


Выдача прав на захват экрана будет простой и выглядит так:

sqlite3 "$SYS_DB_PATH" "insert into access values ('kTCCServiceScreenCapture', '"$TARGET_BIN"', 1, 2, 4, 1, '', '', 0, 'UNUSED', '', 0,1623954785)"


TimeStamp можно ставить любой, он ни на что не влияет, но если вы перфекционист, вы всегда можете сгенерировать настоящий штамп командой date +%s.

Для записи прав на System Events порядок действий несколько сложнее:

  • Получим requirement string из codesign 
    REQ_STR=$(codesign -d -r- $TARGET_BIN 2>&1 | awk -F ' => ' '/designated/{print $2}');
  • Конвертируем результат в бинарный вид
    $REQ_STR" | csreq -r- -b /tmp/csreq.bin;
  • Теперь из бинарного в HEX и отформатируем вывод:
    REQ_HEX="X'$(xxd -p /tmp/csreq.bin | tr -d '\n')'";
  • Наконец запишем результат в базу:
    sqlite3 "$USR_DB_PATH" "insert into access values ('kTCCServiceAppleEvents', '"$TARGET_BIN"', 1, 2, 3, 1, "$REQ_HEX", '', 0, 'com.apple.systemevents', "$REQ_HEX", 0,1623954785)".


Примечание: не бойтесь ошибиться, удалить записи можно 

sqlite3 "$USR_DB_PATH" 'delete from "access" where service=="kTCCServiceAppleEvents"'.


Даже если база данных станет по каким-либо причинам неработоспособной, просто удалите базу целиком и перезагрузитесь. Система вернет ее в значение по умолчанию.

image-loader.svg


Заключение


С помощью классических средств, таких как виртуализация и bash-скриптинг, можно сильно облегчить себе жизнь при использовании MacOS в CI пайплайне. 

Это были только общие примеры. На самом деле CI намного сложнее и интереснее, каждый день нам приносит новый челендж, с которым наша команда успешно справляется. Всем удачной интеграции и котиков. Котиков же все любят :)

© Habrahabr.ru