← Вернуться в дневник

Вы в Сингапуре, код в облаке: удалённая сборка Xcode для короткой командировки

Заметки о командировке · 2026.06.03 · ~9 мин

Ультрабук по SSH к облачному Mac mini M4 для сборки Xcode в командировке в Сингапур

Эта статья отвечает ровно на один вопрос: вы на несколько дней в Сингапуре с одним ультрабуком — успеете ли за 72 часа пройти цепочку правка кода → удалённая сборка → TestFlight без Mac Studio в багаже?

Допущение (всё ниже опирается на него): у вас уже есть постоянно доступный macOS build node с зафиксированной версией и предсказуемым egress — не Mac коллеги «на вечер» и не CI-runner с холодным стартом на каждый job. Runbook описывает, как запускать этот node в дороге; без стабильного build node рухнет даже идеальный SSH-чеклист.

Хронология — реальный hotfix команды 13–15 ноября 2025 (время Сингапура), зафиксированный на 3 июня 2026. Идентификаторы замаскированы; фрагменты логов — дословно из терминала и GitHub Actions, чтобы вы повторили те же проверки у себя.

Российские и СНГ-команды часто путают «я в Сингапуре» и «нужен локальный Mac в аренду». Для сборки iOS и XCTest город Mac в облаке не важен; на месте решают стабильный uplink и то, что App Store Connect видит egress build-машины, а не IP номера в отеле.

Перед вылетом согласуйте три пункта:

  • Сначала стабильный build node

    Фиксированный IP, закреплённый Xcode, match с единственным писателем; в поездке только триггер, не поднимать подпись в отельном Wi‑Fi.

    commit + run ID в тикете

  • Узел следует за egress артефактов

    Только APAC-бета — приоритет Сингапур; ASC Северной Америки и фиксированный egress — builder в Канаде.

    см. таблицу

  • Не кодить весь день по VNC

    Отель или транстихоокеанский канал делают screen sharing хрупким; VNC — только для связки ключей.

    сначала SSH

Вы в Сингапуре роуминг / Wi‑Fi отеля git · ssh ультрабук · без крупного SwiftUI Internet Облачный Mac mini M4 ЦОД SG или Канада xcodebuild · match тёплый Derived Data TestFlight ASC API Сборка не через NAT отеля; загрузка с фиксированного egress builder
В поездке — правки и триггер; тяжёлая сборка и upload на облачном Mac

Проверяемые якоря (фрагмент поездки, ноябрь 2025)

В день зелёного релиза мы зафиксировали в тикете те же поля — в вашем runbook должно быть так же, иначе потом не отличить медленную сеть от медленной компиляции:

В российских командах часто не архивируют hash коммита и URL run в Actions: помнят «долго», но не то, что archive занял 11 или 38 минут. Эти метаданные дешёвы и спасают post-mortem после Чанги.

Один полный цикл: ключевые поля (чувствительные значения скрыты)
Поле Записанное значение Как снять
Git commit7f2a91c (main)git rev-parse --short HEAD
GitHub ActionsRun #18472930156 · workflow ios-ship.ymlUI Actions → URL run
Xcode на builder16.2 (16C5032a) · SDK iphoneos18.2xcodebuild -version + заголовок лога
Xcode на ноутбуке16.2 (сверено с builder за T-48h)то же, до вылета
Длительность archive11m 34s (облачный M4 24 ГБ)разница времени до ** ARCHIVE SUCCEEDED **
Тот же commit, clean build на Air локально38m 12s (после одной неудачи)локальная база; объясняет offload
Обработка TestFlightupload 4m 08s · ASC «Processing» ~22maltool / API + письмо ASC
Egress builder203.0.xxx.xxx (хост Канада, без изменений)curl -4 ifconfig.me на builder
Фрагмент лога archive на builder (запуск 14.11.2025 23:41 SGT, сокращено)
Build description signature: 7f2a91c7e3b2…
ExecuteExternalTool …/Xcode.app/Contents/Developer/Toolchains/…
** CLEAN SUCCEEDED **
** ARCHIVE SUCCEEDED ** [684.123 sec]   ← ~11m 24s (с clean)
note: Using codesigning identity: Apple Distribution: Acme *** (TEAMID)

Той ночью в Сингапуре запускал по SSH через раздачу с телефона; логи сборки и загрузки только на builder. Ультрабук хранил ссылку на run Actions и commit. Для self-hosted runner вставляйте run ID в описание PR — как в статье про самостоятельные macOS runner на облачном Mac.

Какой build node предполагает runbook? (выбрать до вылета)

Худшая неделя спорить «арендуем Mac на три дня?». Мы записали отклонённое и оставшееся — названия продуктов только в последней колонке, не вывод:

Для iOS с Fastlane, match и whitelist ASC API build node — актив compliance. Менять его на неделе выставки — change event, не «быстро попробуем».

Короткая командировка, удалённая сборка iOS: четыре источника compute — почему остался только выделенный облачный Mac
Вариант Почему не на неделе поездки Что всё равно нужно было
Xcode CloudКлючи match, свой Fastlane, фиксированный egress трудно полностью контролировать; непрозрачная диагностикаPR-checks ок; hotfix-подпись — свой node
AWS EC2 MacМинимум аренды 24h, квоты/регионы; egress часто плаваетНастоящий macOS; команды на AWS compliance
Общий / ротируемый Mac cloudОстатки Keychain и Derived Data; риск перепутать сертификатыДёшево, только unsigned compile
Mac mini в офисеКоллега выключил, обновления ОС, никто не меняет диск в 2 ночиПолный контроль, но не 7×24 в поездке
Выделенный облачный Mac (наш выбор)Нужно заранее включить, закрепить версию, whitelist IPSSH + фиксированный egress + Keychain на одной машине; SG/Канада

Днём SSH из APAC на M4 в Сингапуре (спеки на странице узла Сингапур), загрузка TestFlight по-прежнему из Канады — whitelist ASC API и приватные ключи match уже привязаны к egress Канады 203.0.xxx.xxx. Смена провайдера — в окне обслуживания; смена egress на неделе поездки — нет. Hashvps: при продлении IP не ротируется, bare-metal mini — как в одна машина — один IP. EC2 Mac или офисный mini с фиксированным IP и закреплённым Xcode — остальной runbook без изменений.

Разделить проблему: сеть и вычисления

Многие ищут «аренду Mac на месте» сразу после посадки. Если нужна только сборка iOS и XCTest, аренда облачного Mac не обязана быть в том же городе — SSH из Чанги ощущается как из Москвы. На месте решаете:

  • Стабильный uplink: eSIM в роуминге или надёжная точка доступа для непрерывного SSH (обзор GSMA про eSIM; dual-SIM — данные и голос раздельно).
  • Часовые пояса: стендапы и окна review с домашней командой — не влияют на время compile, но на момент push.
  • Compliance egress: App Store Connect и корпоративные прокси смотрят egress build-машины, не IP номера отеля.

По compute: до вылета repo клонирован, сертификаты импортированы, пути Derived Data зафиксированы. После прилёта — git pull и скрипты; не ставьте Xcode в аэропорту, иначе сожжёте окно 72 ч на загрузку компонентов.

Цепочка зависимостей упорядочена: (1) машина с предсказуемым egress и single-writer подписью; (2) workflows и Fastlane под этот хост; (3) ноутбук как пульт; (4) качество отеля/роуминга — ограничение для (3), не для throughput compile. Пропустить (1) и надеяться на (3) — archive на MacBook Air в переговорке и вопрос «почему upload упал, хотя демо-IPA встала».

Хронология 72 часов (реальные метки времени)

T-48h · 11.11.2025 Москва: builder в Канаде прогнал archive + TestFlight в зелёный (commit 9e0b44f, run #18451002201). На обоих хостах xcodebuild -version 16.2. SSH public key в authorized_keys; ServerAliveInterval 60 в ~/.ssh/config ноутбука.

T-24h · 12.11.2025: роуминг включён; mosh build-ca 10 минут без обрыва. Приватный ключ match только в Канаде (см. хост загрузки TestFlight).

T+0 · 13.11.2025 19:10 SGT Чанги: первый сбой SSH на Wi‑Fi отеля (инцидент ①); hotspot, git pull + инкрементальный build за 4m 02s (не archive).

T+24h · 14.11.2025: встречи с клиентом днём; 20:15 SGT push 7f2a91c. 23:41 SGT archive → 00:03 SGT upload в ASC → 00:25 SGT TestFlight готов к тесту. Меня не было у клавиатуры; builder и Actions закончили сами.

T+48h–72h: демо на площадке с уже обработанной сборкой TestFlight, без live archive на Wi‑Fi выставки. Upload через App Store Connect API с builder; роуминг ноутбука не важен.

Между T+0 и T+24h хост в Сингапуре — интерактивный builder: низкий RTT, логи «как локальные» — каждая минута compile в ЦОД. Между T+24h и upload Канада — compliance gate: match readonly, export, API — ASC уже знал этот egress. Скучно — хорошо: никто не открывает Keychain на телефоне в полночь.

Узел Сингапур vs Канада в короткой поездке

Региональный разбор: гид по удалённому Mac в пяти регионах. В поездке — два правила:

Куда ставить builder, если вы ненадолго в Сингапуре
Измерение Сингапур / ЦОД APAC редактируете на месте Канада / ЦОД Северной Америки артефакты с NA egress
Ощущение SSHНизкий RTT, логи идут с вами150–250 ms через океан; норм, compile удалённо
TestFlight / ASCРаботает, если egress в whitelistУ большинства match/API на NA IP
Подходит дляВнутренние беты, коллаб APAC, дневные итерацииРелиз в Store, нотаризация, deps с NA CDN
Мигрировать из-за перелёта?Нет; несколько ролей хоста в repoНет; SG compile + Canada upload — норма

Мы не переносили match, потому что человек оказался в Сингапуре: там собирали debug/internal; Канада продолжала upload. Миграция сертификатов — change event, на неделе поездки запрещена (то же разделение, что в медленная сборка Xcode на облачном Mac M4, география наоборот).

Чеклист связи: роуминг, Wi‑Fi отеля, SSH

В отелях часто режут UDP, рвут idle TCP через ~5 минут или сбрасывают SSH после ARP-странностей. Минимальный набор:

  • Ноутбук + телефон: SSH через hotspot, видеозвонки через Wi‑Fi отеля.
  • ServerAliveInterval 60 и ServerAliveCountMax 3 в ~/.ssh/config.
  • Длинные задачи в tmux или screen; после обрыва — tmux attach.
  • Никогда rsync DerivedData по нестабильному каналу — только Git.

Корпоративный VPN с полным туннелем: до поездки согласовать split — внутренние ресурсы через VPN, SSH к builder напрямую. Многие вешают Mac только в Tailscale. Mosh помогает при потерях; не заменяет firewall, убивающий UDP — держите обычный SSH запасным.

Не делать на неделе поездки
Менять egress IP builder, поднимать major Xcode, пересоздавать репозиторий match, править Storyboard по VNC. Каждое действие — отдельное окно обслуживания вне встреч с клиентом.

Инциденты дня 2 (с логами)

Все четыре ниже — 14.11.2025 в одном окне, по порядку, не гипотезы. Пути замаскированы.

① Wi‑Fi отеля: обрыв idle SSH

Терминал ноутбука · вечер T+0
$ ssh build-sg 'cd ~/workspace/MyApp && git pull'
client_loop: send disconnect: Broken pipe
Connection to build-sg.xxx port 22: Broken pipe

Причина: NAT отеля оборвал idle TCP ~через 300 с. Исправление: hotspot + ServerAliveInterval 60; длинные задачи в tmux. Повтора не было.

② Archive упал: нет сертификата Distribution в Keychain

Builder Канада · первый неудачный archive
error: No signing certificate "iOS Distribution" found
error: No profiles for 'com.acme.myapp' were found
** ARCHIVE FAILED **

Причина: коллега установил сертификаты через VNC login, но не импортировал Distribution в login keychain облака; ноутбук прошёл из‑за Automatic Signing в Xcode. Исправление: bundle exec fastlane match appstore --readonly в Канаде, проверить security find-identity -p codesigning -v на Apple Distribution, повторить archive (11m 34s выше).

③ Параллельные тесты: runtime Simulator vs патч Xcode

Ночной XCTest · лог ошибки
xcodebuild: error: Unable to find a destination matching the provided destination specifier:
		{ platform:iOS Simulator, OS:18.1, name:iPhone 16 }
	Ineligible destinations: … missing matching iOS Simulator runtime

Причина: builder на Xcode 16.2 (runtime 18.2), workflow всё ещё OS:18.1. Исправление: destination в ios-ship.yml на 18.2, закоммитить .xcode-version — не проблема удаления Derived Data.

④ Derived Data «битый»: диск полон

Более ранний инкрементальный build того же дня
error: unable to attach DB: error: accessing build database
  "/Users/builder/Cache/DerivedData/…/build.db": database or disk is full

Исправление: df -h показал 6,2 ГБ свободно на /; удалили старые .xcarchive и Derived Data ветки. При «cache corrupt» сначала уровень диска, потом rm -rf DerivedData.

Матрица режимов сбоя

Удалённая сборка iOS в короткой поездке: симптом → сцена → причина в облаке → действие
Симптом Сцена Причина cloud / remote Действие
Обрыв SSHWi‑Fi отеляNAT idle timeouthotspot + ServerAlive + tmux/mosh
build OK, upload failASC / корп. proxyegress не в whitelistфиксированный IP builder; не менять хост
локально OK / удалённо failarchive / подписьдрейф Keychain vs matchmatch readonly + find-identity
нет Simulatorночные CI-тестыSDK/runtime не залочены.xcode-version + destination
build.db / cacheпараллельные веткиполный диск как corruptdf -h → archives / DerivedData
подпись истекларелиз в конце кварталаистёк Distributionротация за 14 дней; на неделе поездки только readonly match

Минимальный удалённый цикл Xcode (команды)

Первая ночь на месте — доказать цикл 72 ч; параметры по TN2339; commit 7f2a91c:

Разовый pull и compile на builder (фрагмент)
ssh build-sg 'set -e
  cd ~/workspace/MyApp
  git fetch origin && git checkout 7f2a91c && git pull --ff-only
  xcodebuild -scheme MyApp -configuration Release \
    -derivedDataPath ~/Cache/DerivedData \
    -destination "generic/platform=iOS" \
    build 2>&1 | tee /tmp/build-7f2a91c.log'

Archive и upload — в Fastlane lanes; в Сингапуре только make ship COMMIT=7f2a91c, Actions Run #18472930156 как аудит. Builder также self-hosted runner.

Спеки и диск: не урезать на неделе поездки

Уровни builder M4 для недели поездки
Уровень Память Диск Рекомендация
16 ГБ / 256 ГБпараллельные тесты легко уходят в swapможет заполниться за неделютолько hotfix одного repo
24 ГБ / 512 ГБбольшинству iOS repo хватаетеженедельная чистка archivesдефолт для поездок
24 ГБ / 1 ТБкомфортный запаскэш нескольких веток OKmonorepo + много симуляторов

Уменьшить диск в неделю вылета — путь к инциденту ④: archives и runtime Simulator съедают десятки ГБ быстрее интуиции. Финансам лучше урезать параллельные тесты, чем диск на хосте подписи.

Что ещё положить в чемодан

Сознательно легче: без MacBook Pro 16", с ноутбуком с Terminal, тестовым Lightning/USB-C, запасными зарядками, бумажной или офлайн PDF-копией QR активированной eSIM в роуминге. Аккаунты builder, API keys, пароли match — в командном 1Password, но в офлайн-аварийке — IP builder, порт SSH, телефон дежурного — чтобы «роуминг мёртв + SMS 2FA не пришла» не заблокировали вдвойне.

Демо клиенту — TestFlight или Ad Hoc уже на устройстве, не live archive на Wi‑Fi выставки. Демо и релиз — разные пути: демо через потребительскую сеть, релиз через фиксированный egress builder — иначе «демо встало, значит upload должен пройти».

Физические тестовые устройства нужны для Bluetooth/NFC, которым не доверяете Simulator. Облачный Mac заменяет throughput compile/sign, не лабораторию девайсов.

Скрытая стоимость недели (для того, кто утверждает бюджет)

Купить или отправить Mac mini, или арендовать на месте: таможня, адаптеры, переустановка ОС, импорт сертификатов, новое доверие отпечатку устройства. Выделенный build node с понедельной оплатой покупает готовую среду — Derived Data, match, фиксированный IP не пересобирают в неделю поездки. Тот же TCO-рамка, что недорогой Mac-офис для стартапа: CapEx → OpEx без сертификатов на личных ноутбуках.

Упущенная выгода чувствуется руководством: час compile в отеле — час меньше с клиентом. Push в коридоре, логи в номере. При трёх–четырёх перелётах в ЮВА в год предсказуемый builder надёжнее «купить Mac в аэропорту».

Последняя практическая заметка из Чанги: в тикете фиксируйте не только «build зелёный», но и какой node делал archive и какой заливал — если поменять роли в неделю командировки, ночью отлаживаете с половиной контекста. Run ID в описании PR дешевле страховки, чем лишний пакет роуминга.

FAQ

Нужен ли Mac с собой? Достаточно машины с Git и SSH (Windows — в наших статьях про облачный Mac). Тестовые девайсы — если обязателен device debug; compile остаётся в облаке.

Новый builder за три дня до вылета? Да — сертификаты и первый полный compile до полёта; на месте только инкремент.

ЦОД Сингапура должен совпадать с городом? Нет. Co-location снижает RTT SSH; релиз в североамериканский Store — builder в Канаде.

Хватит ли роуминга для IPA? Не должно понадобиться. IPA с builder в ASC; ноутбук передаёт только мелкие Git-объекты.

Чем отличается от статьи про медленную сборку? Та — про перегрев ноутбука; эта — про географический сдвиг и нестабильные сети с runbook и размещением узлов.

Переносить gateway OpenClaw / agent? Нет. Может остаться в Канаде; Сингапур — только SSH-триггер сборок.

Корпоративный VPN 24/7? По политике. Полный туннель ломает SSH → split или Tailscale только к builder.

Часовые пояса и окна релиза? Сингапур UTC+8, запад США ~15–16 ч разницы. Archive днём в Сингапуре, upload ночью в Канаде — совместимо с ночными североамериканскими batch «следом за солнцем»; не нужно смотреть upload в 3 ночи.

Проверить ваш commit / run ID? Цифры из внутреннего repo, домены/IP скрыты; копируйте формат полей в тикеты, не наши числа.

Зачем два дата-центра? Латентность для ежедневной работы vs compliance upload — одна машина покрывает оба, если ASC и match уже на одном IP; мы сознательно разделили.

Итог: цепочка зависимостей → наша реализация

Порядок: стабильный build node → фиксированный egress и match → в поездке только SSH/CI → логи с commit/run ID. В ноябре 2025 — два выделенных M4 (Сингапур компилирует, Канада заливает). При эквивалентной среде менять провайдера не обязательно.

При сборке с нуля: bare-metal macOS, IP при продлении не меняется, ЦОД SG/Канада — узел Сингапур и цены; whitelist egress до покупки билета.

Hashvps · Mac Cloud

Собрать iOS build node с нуля?

M4 bare metal, выделенный IP, SSH сразу — постоянная машина сборки, а не аренда на неделю командировки.

Смотреть тарифы
Спецпредложение