Аудитория и контекст
Материал рассчитан на команды из пяти–тридцати человек, где один или несколько удалённых Mac выполняют ночные и дневные сборки, а артефакты должны одновременно быть доступны тестировщикам, внутренним зеркалам и иногда внешним потребителям. В такой конфигурации ошибка не в «медленном диске», а в несогласованной модели данных: половина пайплайна считает каталог локальным, другая — сетевым; третья смешивает персональные UID с сервисными. Явное разделение эфемерного, общего кэша и опубликованного артефакта снижает число необъяснимых инцидентов.
Согласуйте этот гайд с политикой маршрутизации CI: матрица self-hosted runner и очередей на общем Mac и с изоляцией рабочих деревьев: Git worktree, lock-файлы и параллельные сборки.
Типовые боли общих путей артефактов
- Невидимые гонки. Две job завершаются одновременно и обе пишут в
latest/или в общее деревоexport; потребители видят обрезанные файлы или смесь POSIX ACL. - Дрейф прав. Один пайплайн под личной учёткой с umask
077, другой — под сервисным пользователем с022; downstream на том же томе перестаёт читать каталог без ручногоchmod. - Иллюзия сети. NFS ощущается «как локальный диск», пока не проявятся блокировки, устаревший кэш атрибутов или джиттер Wi‑Fi. rsync кажется медленным, пока не измерить стоимость контрольных сумм против повторных полных копий.
Базовая гигиена изоляции прав на общей сборке описана в материале про общую сборку, SSH/VNC и разграничение доступа.
Три подхода: rsync напрямую, инкрементальный rsync и NFS-кэш
Это разные модели согласованности, а не взаимозаменяемые команды копирования. Выбор определяется тем, кто читает артефакт, как часто меняется дерево и нужны ли явные удаления и журналы передачи.
| Подход | Когда уместен | Риски |
|---|---|---|
| rsync напрямую | Промоушен на объектное хранилище, Linux-runner, второй сайт или bastion; нужны явные delete и понятный лог передачи. | Контрольные суммы грузят CPU; на доверенной ЛВС политика может разрешить отказ от -c внутри цикла разработки. |
| Инкрементальный rsync | Много мелких файлов, частые дельты; неизменяемые префиксы на build id и зеркала с дельта-обновлением. | --delete на общих деревьях опасен; версионируйте назначения и индексы релизов. |
| NFS (кэш / read-mostly) | Несколько Mac читают одни и те же тяжёлые слои; запись редкая и управляемая. | Семантика блокировок отличается от APFS; при «шторме» stat проверьте кэш атрибутов и сегментацию сети. |
Для распределённой коллаборации на нескольких узлах см. мультиузловую коллаборацию OpenClaw на Mac-сетке — там же полезно согласовать единый каталог политик и наблюдаемость.
Матрица решений: сигнал → склонность → стартовый параметр
Используйте таблицу как эвристику на ретро инфраструктуры: если два сигнала спорят, побеждает тот, что связан с требованиями безопасности и воспроизводимости релиза.
| Сигнал | Склоняйтесь к | Стартовый параметр / правило |
|---|---|---|
| Потребители вне Mac или в нескольких регионах | rsync напрямую на объектное хранилище или через bastion | Один путь назначения на build id; latest обновлять двухфазно (staging → rename/symlink) |
| Повторные чтения одних и тех же слоёв 50–200 ГБ | NFS read-mostly + локальный эфемерный build dir на NVMe | Выделенная подсеть; ревью опций монтирования под кэш атрибутов |
| Комплаенс требует доказуемую передачу байтов | Инкрементальный rsync с checksum на границе релиза | Ворота checksum на тегах релиза; во внутренних циклах — без -c, если политика позволяет |
| Более двух параллельных издателей в один индекс | Каталоги в масштабе job + файл блокировки | Сериализовать запись в общие индексы; параллелить только изолированные префиксы |
Гибрид встречается чаще, чем «чистый» выбор: типичный контур — тяжёлые read-mostly слои на NFS или внутреннем filer’е, а финальный пакет релиза уходит rsync’ом в объектное хранилище с неизменяемым ключом версии. Так вы не смешиваете семантику кэша с семантикой поставки: кэш допускает инвалидацию и задержку согласованности, а артефакт релиза — нет. При смешении ролей на одном mount-point документируйте, какие каталоги допускают задержку атрибутов, а какие требуют немедленной видимости после закрытия файла; иначе отладка сводится к «иногда работает» без воспроизводимого триггера. Наконец, помните про стоимость операций: на гигабайтных деревьях с мелкими файлами rsync сравнение по размеру и mtime часто достаточно для внутренних циклов, а полный checksum оставьте для границы, где ошибка дороже лишних минут CPU.
Параллельные сборки: блокировки каталогов, umask и SSH-сертификаты по ролям
Блокировки. На APFS удобны flock на пуловом lock-файле или отдельные lock на префикс публикации. На NFS не полагайтесь на тонкую семантику блокировок для критичных инвариантов: собирайте в локальный staging на SSD, затем атомарно mv в шару. Для обновления симлинка latest держите один глобальный мьютекс на короткое окно «переключения указателя».
umask. Унифицируйте сервисные учётки с 027: файлы читает группа сборки, прочие пользователи хоста — нет. Это базовая изоляция прав при общем UNIX-групповом томе. 022 оставьте для осознанно публичных выгрузок и задокументируйте исключение.
SSH и роли. Разнесите principal’ы: ci-sync — только чтение для выгрузки зеркал; builder — запись под /artifacts/<job-id>/; админский контур — отдельный CA и более короткий TTL. Пошаговая модель ротации и матрица TTL — в руководстве по Jump Host и SSH-сертификатам; разметка узла — в гайде по общему build-узлу Mac.
Параметры rsync, снижающие конфликты и «рваные» чтения
- Избегайте
--inplace, если потребители опрашивают дерево во время копирования; пишите во временные имена и завершайте атомарным переименованием. --delay-updatesи--delete-delayуменьшают окно, в которое видна смесь старых и новых файлов.--timeout,--partial-dir,--link-destзакрывают зависания, обрывы и сценарии промоушена от снапшота с жёсткими ссылками.
Флаги согласуйте с политикой хранения: агрессивный --delete на общем префиксе без версионирования почти всегда ошибка в малых командах с общим пулом.
Пошаговое внедрение
- Инвентаризируйте каждый путь, куда CI пишет после компиляции; пометьте как эфемерный, общий кэш или опубликованный артефакт.
- Выберите rsync или NFS по строке матрицы, соответствующей расположению потребителей и комплаенсу.
- Создайте сервисные учётки с фиксированной первичной группой,
umask 027и домашними каталогами вне интерактивных пользователей. - Выпустите пользовательские SSH-сертификаты по ролям; ограничьте rsync-модули и forced command списками путей.
- Добавьте
flockили мьютекс вокруг любых обновлений общего симлинкаlatest; публикуйте build id как неизменяемые префиксы. - Задокументируйте откат: удалить плохой префикс, переключить symlink, повторить checksum-rsync из заведомо хорошего снапшота.
FAQ
- Можно ли монтировать NFS прямо в Xcode DerivedData?
- Обычно нет из соображений интерактивной производительности; держите DerivedData на локальном NVMe. NFS оставьте для общих кэшей (CocoaPods, SPM-зеркала, слои контейнеров) с явной политикой инвалидации.
- Можно ли нескольким параллельным job писать в один каталог rsync?
- Нет — см. блок про уникальные staging-префиксы и двухфазную публикацию в матрице и в блоке про конкурентность.
- Артефакт «есть», но checksum не сходится — с чего начать?
- Проверьте umask, расширенные атрибуты macOS и флаги rsync; выполните повторную передачу только checksum из изолированного staging.
- Минимальный набор мониторинга?
- Коды выхода rsync, p95 длительности, таймауты RPC NFS, свободное место на Mac и СХД; оповещение, если глобальная блокировка публикации держится дольше порогового интервала (см. блок ниже).
Цифры для runbook (можно вставить в соглашение команды)
- Публикация: удержание глобальной блокировки дольше пяти минут — сигнал к эскалации.
- umask сервисных учёток: по умолчанию 027; 022 — только как явное исключение.
- TTL SSH-сертификатов (ориентир): до 24 часов для builder, до 8 часов для ci-sync-читателей.
- NFS: пересматривайте кэш атрибутов, если инструменты выполняют свыше примерно тысячи stat в минуту на шаре.
Полный список материалов — на странице блога; главная для обзора тарифов — здесь.
Масштабируйте вывод артефактов отдельными узлами Mac
Когда трафик rsync или NFS упирается в один хост, разделите роли: отдельные builder-уровни и политики публикации. Откройте главную, чтобы сравнить конфигурации; оформление и выбор узлов без входа — на странице покупки. Справка по SSH, VNC и безопасности — в центре помощи; оглавление статей — в списке блога.