После переименования публичного API локальный проект по-прежнему может успешно компилироваться, хотя ссылки на старые символы в документации уже не работают. Обычно проблема обнаруживается только при ручной проверке документации перед выпуском. Более надёжный подход — запускать сборку DocC при каждой проверке слияния на облачном Mac. Неразрешимые ссылки, дублирующиеся темы и предупреждения компилятора будут сразу приводить к сбою, а статический сайт и журналы диагностики сохранятся как артефакты.
Сначала определите границы проверки
Проверка DocC не должна отвечать за все аспекты качества документации. Лучше всего DocC проверяет символы Swift, каталоги статей, иерархию тем и внутренние ссылки. Доступность внешних URL и единообразие стиля текста лучше контролировать в отдельных заданиях. Иначе единичный временный сетевой тайм-аут может заблокировать слияние кода.
Для начала рекомендуется определить три категории результатов:
| Результат | Действие | Типичные случаи |
|---|---|---|
| Ошибка | Немедленная блокировка | Неразрешимый символ, недопустимая структура каталога |
| Предупреждение | Блокировка в основной ветке | Недействительная ссылка на тему, дублирующийся идентификатор |
| Рекомендация | Зарегистрировать и пропустить | Слишком краткое описание, пример можно дополнить |
Цель проверки документации — не добиться полного отсутствия сообщений, а получать одинаковый результат для одинаковых входных данных в зафиксированной среде. Все правила должны воспроизводиться одной и той же командой как на компьютере разработчика, так и на узле CI.
Структура каталогов также должна иметь единый источник истины. Документацию модуля следует хранить в каталоге .docc соответствующего target, а руководства для нескольких модулей — в target документации, который выполняет функцию агрегации. Не копируйте одну статью в несколько catalog: после правок легко обновить только одну из копий.
Зафиксируйте Xcode и входные данные сборки
На удалённых узлах чаще всего меняется путь к Xcode по умолчанию. В начале задания сначала выведите версию, а затем явно проверьте каталог разработчика. Если команда поддерживает несколько версий, полный путь можно передавать через переменную CI, не полагаясь на выбор, оставшийся от предыдущего интерактивного сеанса.
set -euo pipefail
: "${DEVELOPER_DIR:?set DEVELOPER_DIR}"
: "${SCHEME:?set SCHEME}"
test -x "$DEVELOPER_DIR/usr/bin/xcodebuild"
xcodebuild -version
swift --version
git status --short
Перед сборкой необходимо проверить и состояние репозитория. CI должен начинать работу с чистой копии, файлы разрешения зависимостей должны находиться под контролем версий, а ресурсы для генерации документации не должны зависеть от локальных копий в каталоге разработчика. Если скрипт генерирует Markdown, сначала создайте файлы во временном каталоге, а затем сравните результат. При обнаружении незакоммиченных изменений задание должно завершаться ошибкой.
Избегайте неявного состояния рабочей области
Не используйте один и тот же долговременный каталог DerivedData. Из-за старых графов символов удалённые типы могут продолжать отображаться в документации, а отсутствие ресурсов — оставаться незамеченным. Для каждого задания используйте отдельный каталог, а после завершения архивируйте только необходимые диагностические данные и артефакты DocC.
Запустите воспроизводимый docbuild
Следующий скрипт создаёт изолированный каталог для каждого задания, преобразует предупреждения DocC в ошибки и сохраняет полный журнал. generic/platform=iOS не зависит от конкретного запущенного симулятора и подходит для проверок, которым требуется только компиляция графов символов и документации.
set -euo pipefail
ROOT="$PWD/.build/docs"
DERIVED="$ROOT/DerivedData"
LOG="$ROOT/docc-build.log"
rm -rf "$ROOT"
mkdir -p "$ROOT"
set -o pipefail
xcodebuild docbuild \
-scheme "$SCHEME" \
-destination "generic/platform=iOS" \
-derivedDataPath "$DERIVED" \
OTHER_DOCC_FLAGS="--warnings-as-errors" \
2>&1 | tee "$LOG"
ARCHIVE="$(find "$DERIVED/Build/Products" -name '*.doccarchive' -print -quit)"
test -n "$ARCHIVE"
printf '%s
' "$ARCHIVE" > "$ROOT/archive-path.txt"
Если scheme также включает target, для которых документацию создавать не нужно, явно задайте область компиляции документации в настройках проекта, а не фильтруйте предупреждения в журнале. Фильтрация текста может скрыть и настоящую регрессию. При первом включении --warnings-as-errors можно сначала запустить проверку в неблокирующем задании, исправить существующие проблемы и только затем сделать её обязательным условием слияния.
Экспортируйте статический сайт и проверьте артефакты
Формат .doccarchive удобен для дальнейшей обработки, но рецензентам обычно нужны статические файлы, которые можно открыть напрямую. Найдя archive, создайте сайт с помощью встроенной команды преобразования DocC:
set -euo pipefail
ARCHIVE="$(cat .build/docs/archive-path.txt)"
OUTPUT="$PWD/.build/docs/site"
xcrun docc process-archive transform-for-static-hosting \
"$ARCHIVE" \
--output-path "$OUTPUT" \
--hosting-base-path docs
test -s "$OUTPUT/index.html"
find "$OUTPUT" -type f | sort > .build/docs/site-files.txt
Значение --hosting-base-path должно совпадать с конечным подпутём развёртывания. Если сайт фактически размещается в корне, не копируйте значение docs без изменений. При несовпадении путей главная страница может нормально открываться локально, тогда как после развёртывания запросы скриптов и стилей будут завершаться ошибками.
Следует архивировать как минимум журнал сборки, путь к archive, статический сайт и список файлов. Журнал нужен для поиска конкретных диагностических сообщений, а список файлов помогает обнаружить аномальное массовое удаление. Для статического сайта можно задать сравнительно короткий срок хранения, но журналы неудачных заданий следует сохранять до закрытия проблемы.
Выполняйте проверку внешних ссылок отдельно
Проверка внешних ссылок должна анализировать сгенерированный HTML, обращаться только к разрешённым адресам https и ограничивать число параллельных запросов. Для тайм-аутов и серверных ограничений частоты запросов предусмотрите ограниченное число повторных попыток. Блокировать сборку следует только при устойчивой ошибке. Ссылки с временными токенами, параметрами запроса или внутренними адресами не должны попадать ни в публичную документацию, ни в журнал проверки.
Разберите типичные сбои и составьте приёмочный список
У ситуации «символ существует, но DocC его не находит» обычно три причины: символ не входит в текущую scheme, его уровень доступа не включён в область документации либо в ссылке используется устаревшая полная сигнатура. Сначала проверьте target, а затем изучите символы-кандидаты в журнале генерации. Не пытайтесь решить проблему многократным изменением написания наугад.
Если ссылка на статью не работает, проверьте имя файла, идентификатор, сформированный из заголовка, и относительный уровень в каталоге. При ошибке загрузки ресурса проверьте регистр символов и target membership. Облачная файловая система точно соблюдает реальные пути. Не следует сохранять написание с неверным регистром только потому, что оно случайно работает в некоторых локальных средах.
Итоговая проверка должна давать ответы на следующие вопросы:
- Записаны ли версии Xcode и Swift;
- Началась ли работа с чистого состояния рабочей области;
- Обрабатываются ли предупреждения DocC согласованным способом;
- Найден ли ожидаемый archive и только ли он был обработан;
- Существует ли точка входа статического сайта;
- Архивируются ли журнал сборки и список файлов;
- Отделены ли ошибки внешних ссылок от ошибок компиляции DocC.
Когда все эти проверки выполняются одним скриптом, изменения документации получают такую же воспроизводимую картину сбоя, как и изменения кода. Сопровождающие могут находить проблемные ссылки по журналу, проверять структуру по статическим артефактам и явно сравнивать изменения поведения после обновления Xcode.
Часто задаваемые вопросы
Проверяет ли успешная сборка DocC все внешние ссылки?
Нет. DocC в основном проверяет ссылки на символы и темы внутри документации. Внешние URL следует проверять отдельной задачей с тайм-аутами, повторами и списком допустимых исключений.
Зачем фиксировать каталог разработчика Xcode в CI?
Разные версии Xcode включают разные версии компилятора и DocC. Явная проверка DEVELOPER_DIR не позволяет смене Xcode по умолчанию незаметно изменить результат сборки.
Развёртывание облачного Mac рабочего процесса в OpsVM
Выберите одну из трёх конфигураций Apple Silicon и 6 доступных узлов; актуальный статус доступности отображается в консоли в реальном времени.