Кому полезно: командам, которые гоняют Bazel на удалённом Mac и упираются в трансграничные загрузки при общих раннерах. В материале: карта узких мест WORKSPACE и MODULE.bazel, таблица порогов disk_cache / remote_cache, готовые флаги (--repository_cache, --disk_cache, --remote_cache, --jobs) и заметки по Git shallow clone. Без входа в аккаунт: список блога, трансграничные зеркала Git/npm/Homebrew в CI, FAQ пула: параллельные pull и диск.
  • Веер к реестру: Bzlmod тянет Bazel Central Registry и архивы с GitHub; один нестабильный hop валит анализ до первой компиляции.
  • Коллизия кешей: несколько job пишут в один --disk_cache и одновременно наполняют --repository_cache на одном SSD — в метриках это похоже на «медленный Bazel», хотя корень в очереди диска.
  • Глубина Git: git clone --depth 1 для монорепы не совместим с git_repository, если нужные теги или коммиты лежат вне shallow-окна.

① Bazel: внешние источники и registry на удалённом Mac — где узкое место

На Apple Silicon в CI дорогой этап редко бывает первым вызовом компилятора — чаще это разрешение репозиториев. Правила в духе http_archive, git_repository и кастомные макросы в WORKSPACE качают архивы и Git-объекты по HTTPS. Путь Bzlmod идёт через модульный реестр, но в конце всё равно упирается в tarball’ы и Git-хосты. Трансграничные линки добавляют разброс RTT, инспекцию TLS на периметре и кратковременные обрывы, которые в логе выглядят как repository failed, а не как ошибка компиляции.

Диск участвует дважды: repository cache хранит неизменяемые загрузки по содержимому, а распакованные деревья оказываются под $(bazel info output_base)/external. Если output_base делит том с горячим --disk_cache, параллельные анализы от разных job перемешивают случайные записи выходов действий с последовательными распаковками внешних правил. Рассматривайте сеть и IO как одну систему: при низкой задержке до registry, но джиттере сборки сначала смотрите пропускную способность тома, а не спешите поднимать --jobs.

См. также: ускорение Git и Docker pull — те же паттерны транспорта помогают HTTP-загрузкам Bazel; по SSH и релейным схемам — трансграничное ускорение Mac по SSH.

② Локальный disk_cache и remote_cache: таблица порогов выбора

Перед закупкой диска или включением общего endpoint сверьтесь с таблицей. --disk_cache кеширует выходы действий локально; --remote_cache (gRPC или HTTP) разделяет их между машинами. Третья опора — --repository_cache: дедуплицирует апстрим-загрузки и чаще всего даёт максимальный эффект при трансграничном CI.

Сигнал / метрика Склоняйтесь к --disk_cache Склоняйтесь к --remote_cache Заметки
Число параллельных CI job на одном хосте 1–2 job и предсказуемое окно повторного использования 3+ job или эфемерные workspace после каждого прогона Remote cache выносит повторное использование выходов с локального SSD; при дорогом egress --repository_cache всё равно держите рядом с раннером
Hit rate после холодного bazel clean --expunge Высокий, если один пул ежедневно собирает один и тот же монорепозиторий Высокий, если много реп делят toolchain и genrule-ы Разделяйте пространства имён по границам доверия; не смешивайте регулируемые артефакты с публичными без ревью политики
Стоимость egress / стабильность канала Ок, если зеркала физически близки к региону раннера Выигрыш, когда endpoint кеша соразмещён с раннерами Remote cache на другом континенте может съесть выигрыш — настраивайте --remote_timeout и режимы загрузки
Операционные затраты Низкие: путь и скрипт-уборщик Выше: TLS, заголовки авторизации, квоты Гибрид: локально --repository_cache + --disk_cache, в remote только action outputs

Рычаг параллелизма действий — --jobs=N. На сборках, тяжёлых по fetch, высокое N до прогрева repository cache увеличивает число одновременных распаковок и конкурирует с писателями disk cache: начинайте консервативно, смотрите IO wait, затем наращивайте.

③ WORKSPACE / MODULE: повторы при сбоях загрузки, таймауты и флаги кеша

Закрепите значения в проверяемом .bazelrc или генерируемом CI-фрагменте. Пути и секреты подставляйте из оркестратора; живые токены в публичный репозиторий не коммитьте — передавайте --remote_header из переменных окружения job.

Флаг / настройка Назначение Пример / стартовая точка
common --repository_cache=… Повторное использование скачанных внешних артефактов между workspace /usr/local/ci/bazel-repo-cache на NVMe
build --disk_cache=… Локальный кеш выходов действий /usr/local/ci/bazel-disk-cache на пул (отдельный подкаталог на tenant при необходимости)
build --remote_cache=… Общий кеш действий (gRPC/HTTP) grpcs://cache.example.internal:443
build --remote_header Авторизация remote cache / прокси Authorization=Bearer ${BAZEL_CACHE_TOKEN} в CI
build --remote_timeout Длинные аплоады на узком аплинке 600 с как первая проба для крупных blob’ов
common --experimental_repository_downloader_retries Повторы HTTP-загрузок repository rule 5 после проверки release notes вашей минорной версии Bazel
build --jobs Локальный параллелизм действий Около половины производительных ядер, если repository_cache, disk_cache и output_base на одном томе
Зеркала MODULE (enterprise) Переопределение URL реестра --registry=file:///… или внутреннее зеркало индекса — только после security review

Иллюстративный фрагмент (в проде разбейте по профилям):

# Общий пролог CI (пути — пример)
common --repository_cache=/usr/local/ci/bazel-repo-cache
common --experimental_repository_downloader_retries=5
build --disk_cache=/usr/local/ci/bazel-disk-cache
build --remote_cache=grpcs://bazel-cache.internal.example:443
build --remote_timeout=600
# build --remote_header=Authorization=Bearer ${BAZEL_CACHE_TOKEN}

Проверка: один прогревочный job — bazel fetch //… или цель в режиме анализа, затем включайте матрицу. На первой неделе раската добавьте --verbose_failures в лог CI.

④ Параллельно с Git partial clone: каталоги, квоты IO — FAQ

Делать shallow clone приложения, пока Bazel тянет вложенные Git-зависимости?

Да, если SHA в shallow-истории полностью покрывают то, что объявлено в правилах. Внешние корни фиксируйте неизменяемыми коммитами в WORKSPACE или патчами модулей. Если правилу нужны теги вне shallow-набора, увеличьте глубину на этом шаге либо перейдите на http_archive с checksum.

Можно ли класть --repository_cache и --disk_cache на один том?

Физически да, но бюджетируйте IOPS. Два быстрых тома снижают хвостовую задержку, когда анализ, fetch и компиляция пересекаются. Держите на каждом кеш-томе запас свободного места порядка 15–20%, чтобы APFS не душил пики CI.

Что ломается, если пять workflow бьют в один общий --disk_cache?

Фазы чтения обычно терпимы; гонки с агрессивной очисткой или prune дают редкие сообщения о повреждении. На мультитенантных хостах предпочтительнее remote_cache или отдельные подкаталоги и окна обслуживания без параллельных писателей.

Как отделить сетевой флейк от насыщения диска?

Сверьте временную шкалу repository-логов Bazel с метриками диска. Высокая глубина очереди при нормальном пинге до registry намекает на диск; простой диска при зависании рукопожатий TLS — на egress или DNS. Для прокси и релея см. SSH-релей и эффективность трансграничной разработки.

⑤ Регион удалённого Mac-узла и параллельная компиляция: влияние на стабильность pull

Размещайте раннер ближе к реестрам и зеркалам, которые реально использует пайплайн. Удалённый Mac в регионе A с remote cache в регионе B может сократить время компиляции, но съесть выигрыш на аплоаде/скачивании крупных промежуточных артефактов. При нестабильном трансграничном канале соразмещайте endpoint кеша, хранилище артефактов и сам раннер.

Высокий --jobs усиливает нагрузку на CPU и диск, пока правила репозиториев могут продолжать потоковые загрузки. Сдвигайте ноги матрицы по времени, ограничивайте число одновременных инвокаций Bazel на хосте или выделите один «fetch»-job, который заполняет --repository_cache до fan-out. Эта логика совпадает с рекомендациями в FAQ по параллельным pull и диску: Bazel — ещё один тяжёлый потребитель того же IO-бюджета.

Чеклист внедрения: пять исполняемых шагов

1
Зафиксируйте Bazel и политику модулей. Запишите LTS-версию, включён ли Bzlmod, какие зеркала реестра одобрены безопасностью.
2
Создайте каталоги кешей. mkdir -p для repository и disk cache; владелец — пользователь CI; при необходимости исключите том из Time Machine.
3
Закоммитьте фрагменты rc. Строки common для --repository_cache и повторов; строки build для --disk_cache и при необходимости --remote_cache с таймаутами.
4
Подберите --jobs. Прогоните репрезентативную цель при N ≈ cores/2, повышайте, пока задержка диска не растёт.
5
Согласуйте скрипты checkout. Документируйте глубину для основного репозитория и для внешних корней Bazel; на свежем образе выполните префлайт bazel fetch.

Итог

Bazel на удалённом Mac в CI чаще всего ломается на слое загрузок: для трансграничной стабильности в первую очередь настройте --repository_cache, затем выбирайте --disk_cache или --remote_cache по числу хостов и политике повторного использования, и ограничивайте --jobs реальной пропускной способностью диска. Shallow clone сочетайте осознанно с неизменяемыми SHA, а endpoint кеша держите в одном регионе с раннерами, если узкое место — WAN.

Готовы вынести fetch-тяжёлые сборки на выделенный Apple Silicon: откройте главную, сравните тарифы и узлы, оформите покупку или аренду без лишних шагов. Вопросы по SSH и подключению — в центре помощи; больше сценариев CI — в техническом блоге.

Дополнительно для полиглотных репозиториев: матрица Gradle и Maven и Go modules и GOPROXY — та же логика зеркал и кешей в соседних стеках.

Удалённый Mac под Bazel и кеш-тяжёлый CI

Узлы Apple Silicon, раскладка SSD под repository и disk cache, отладка по SSH. Тарифы, покупка, помощь и блог доступны без обязательного входа.