# Сборка на удалённом сервере Android Маркет

С целью ускорить сборку и разгрузить локальные машины, а также, чтобы не чувствовать себя, как на взлетной полосе при сборке, было решено настроить на проекте маркета [мейнфреймер](https://github.com/gojuno/mainframer).
Это такая тулза, с помощью которой сборка осуществляется на удаленной машине.

## История

Пошерстил по инету, поискал инфу, что нужно и как настраивать. Наткнулся на [статью](https://wiki.yandex-team.ru/users/tagakov/setup-mainframer/ ), где описан процесс настройки и даже скрипт предоставлен для легкой и непринужденной настройке удаленной и локальной машины. Там же есть рекомендации по мощности удаленной машины.
Выпросил по рекомендации виртуалку с `16` ядрами и `60`-тью ГБ оперативки.
Запустил скрипт и воаля. Заработало. Немного подправил скрипт под наши нужды и все отлично.

## Инструкция

1. Проверь, что у тебя раскатан ключ на стаффе. Иначе тебя не пустит на машинку. Если не делал, то вот [инструкция](https://wiki.yandex-team.ru/diy/macos/ssh). Если все равно не пускает (а на [паблик](public.market.yandex.net) например пускает), то попроси доступ через [IDM](https://idm.yandex-team.ru/). Запроси на себя роль в системе `CAuth`, назначение - `mobile-build01hd.market.yandex.net`, роль - `ssh`.
2. Попробуй зайти на удаленную машинку через `ssh`. Если не получается, то смотри пункт 1
3. В репе уже лежит скрипт. Называется `mainframer-init.sh`. Открой его. Установи плагин `Bash-Script`, который студия предложит сверху в файле. Перезапусти студию.
4. В консоли (А лучше терминале НЕ студиевском) запусти `./mainframer-init.sh`
5. Скрипт несколько раз спросит пароль к ключу, который на стаффе и для доступа по `ssh`
6. По идее - готово.

## Нюансы

1. Скрипт создал несколько вариантов сборок (`Remote build`, `Remote Build API 21` и др)

Это слева от кнопки запуска. Нажми на спиннер, который там и выбери `Edit Configurations`. Раскрой `Android App`. Открой сборку `Remote build`. Внизу в табличке `Before launch`, удали из списка `Gradle-aware Make`. Сделай так же для всех удаленных сборок. Эта строчка означает локальный билд - а он нам не нужен, т.к. все удаленно уже собралось

{% note alert %}

Студия при каждом перезапуске будет возвращать этот локальный билд (благо она прямо об этом пишет). Чтобы убрать его навсегда Help -> Edit Custom VM Options, добавь строку %%-Dgradle.ide.gradle.run.configuration.fix.enabled=false%%

{% endnote %}

2. В корне проекта появилась папка `.mainframer`

Там несколько файлов:
- `config`
  - В `remote_machine` нужно указать адрес удаленной машины.
  - Если в настройках `ssh` у тебя алиас для мейнфреймера, то укажи в этом файле алиас, а не реальный адрес.
  - Еще есть `local_compression_level` - уровень сжатия исходников
  - `remote_compression_level` - уровень сжатия сбилженных файлов
  - Исходники сживать нет смысла, т.к. отправляется только дельта, а она всегда маленькая. Сбилженные файлы есть смысл сжимать, если ты на `WiFi`, а не проводе. Хотя иногда и на проводе иногда долго синкается. Нормальное время синка на момент написания статьи - 4-6 секунд. Если дольше, играйся с `remote_compression_level`. Значения от 0 до 9

- остальные файлы настраивают игнорируемые файлы. Там все норм и менять ничего не нужно.

## Полезности

Я не смог запихнуть это в скрипт, поэтому придется тебе самому делать.

1. Можешь сделать `Remote rebuild`, чтобы не делать `clean` и сборку отдельно.
- Зайди в `Edit Configarations`, добавь в `Android App` новую сборку типа `Android App`
- Назови `Remote rebuild`
- выбери модуль `market`
- удали из блока `Before launch` локальную сборку
- добавь в `Before launch` `Run Another Configuration` -> `Remote clean` (которая запускает Bash)
- добавь в `Before Launch` `Run Another Configuration` -> `Remote`

2. Можно собирать тесты на удаленной машинке.
Для этого выбери `Defaults` в сборках -> `Android JUnit` и там удали локальную сборку и добавть запуск `Bash` `Remote tests build`

3. Для ui тестов то же самое, только нужно исправить сборку `Android Instrumented Tests` и туда нужно вставить `Remote assemble debug` и `Remote ui tests build`

4. Если не хочешь постоянно вводить пароль к `ssh` для сборки на удаленной машине, то можешь добавить файл в `~/.ssh/config`. В нем можно указывать алиасы к серверам и все такое. У меня для мейнфреймера прописано [следующее](https://paste.yandex-team.ru/524256). И не забудь поменять в конфиге мейнфреймера адрес на алиас `%%папка_проекта/.mainframer/config%%`. Также нужно добавить ключ в список используемых `%%ssh-add -K ~/.ssh/id_rsa%%`

5. Чтобы студия не возвращала `Gradle-aware make` после каждого перезапуска - [фикс](https://github.com/elpassion/mainframer-intellij-plugin/issues/185)

6. Если запускаешь на эмуляторе, то запускай сборку `x86`. Там прописан флаг, чтобы `apk` включало so-шники только для `x86`. По-умолчанию стоит arm, т.е. для реальных устройств. Если запускаешь ui-тесты, то поправь конфигурацию.

## Возможные проблемы

- Если сборка пишет `%%Permission denied: public key%%` или что-то в этом роде, то попробуй зайти по `ssh` через НЕ студиовский терминал. У студии проблемы с запросом пароля для `ssh`. Она просто кидает ошибку.

- Если долго синк происходит, то добавь в метод `syncBeforeRemoteCommand` (находится в скрипте mainfraimer.sh) в переменную `COMMAND` флаг `-P`. Во время билда увидишь, что происходит. Если синк зависает на одном файле, то проверь его размер. Если просто долго синк длится, то поиграйся с настройками сжатия в конфиге

- Если после перезапуска студия возвращает локальную сборку в `remote`-конфигурации, https://github.com/elpassion/mainframer-intellij-plugin/issues/185

- Если не находится `ANDROID_HOME`, то зайди на мейнфреймер и пропиши в ручную `%%export ANDROID_HOME=/home/{имя юзера}/android-sdk-linux%%`

- Если лицензия скинулась на мейнфреймер, но всё равно не заводится, обнови у себя локально `SDK` и снова скинь лицензию командой `%%scp -r ~/Library/Android/sdk/licenses/ mainframer:\android-sdk-linux%%`

- При проблемах с машинкой писать [Алексею Дубровину](https://staff.yandex-team.ru/adubrovin)
