После подключения xcodebuild analyze к облачному Mac команда обычно получает не нулевое число дефектов, а сразу несколько десятков накопившихся диагностик. Если считать условием ошибки общее количество предупреждений, конвейер надолго останется красным. Если же просто прикладывать журнал к артефактам, его никто не будет регулярно просматривать. Более практичный подход — сначала создать проверенную базовую линию, а затем при каждом слиянии блокировать только вновь появившиеся проблемы.
Зафиксируйте входные данные задачи анализа
Результаты статического анализа зависят от конфигурации проекта, условий компиляции и фактического набора исходных файлов, участвующих в сборке. Перед анализом необходимо зафиксировать версию Xcode, рабочую область, Scheme, конфигурацию и целевую платформу. Кроме того, CI должен использовать те же файлы блокировки зависимостей, что и задача архивирования. Не используйте личную Scheme разработчика и не выбирайте автоматически «новейшую» цепочку инструментов в скрипте.
Для анализа нужен отдельный каталог, чтобы задачи сборки и тестирования не изменяли DerivedData одновременно с ним:
set -o pipefail
ROOT="$PWD"
OUT="$ROOT/ci-artifacts/analyze"
DERIVED="$ROOT/.derived/analyze"
RESULT="$OUT/AppAnalyze.xcresult"
rm -rf "$OUT" "$DERIVED"
mkdir -p "$OUT" "$DERIVED"
xcodebuild analyze \
-workspace App.xcworkspace \
-scheme App \
-configuration Debug \
-destination 'generic/platform=iOS' \
-derivedDataPath "$DERIVED" \
-resultBundlePath "$RESULT" \
CODE_SIGNING_ALLOWED=NO \
| tee "$OUT/xcodebuild.log"
Параметр CODE_SIGNING_ALLOWED=NO подходит только для целей анализа, которым не требуется подпись. Если скрипты проекта явно читают связанные с подписью параметры сборки, сначала исправьте границы их входных данных, а не добавляйте вслепую дополнительные переопределения.
Базовая линия — это не список проблем, которые можно игнорировать, а снимок известных фактов на время переходного периода. Новые проблемы по-прежнему должны немедленно приводить к ошибке, а у старых должны быть ответственные и план устранения.
Сохраняйте полные результаты, а не только число warning
Прямой вызов grep -c warning: удобен, но не подходит для долговременного контроля качества. Пути, номера строк и формат сообщений в журнале могут меняться, а одна и та же диагностика иногда выводится несколько раз. CI должен сохранять полный файл .xcresult и исходный журнал, а затем формировать из структурированных результатов список диагностик для сравнения.
Подкоманды xcresulttool могут различаться между версиями Xcode. Поэтому сначала сохраните справочную информацию и повторно проверяйте скрипт разбора при обновлении образа узла:
xcrun xcresulttool help > "$OUT/xcresulttool-help.txt"
xcrun xcresulttool get \
--legacy \
--path "$RESULT" \
--format json > "$OUT/xcresult.json"
Если текущая цепочка инструментов не принимает --legacy, скорректируйте команду в соответствии со справкой для этой версии и включите изменение парсера и обновление цепочки инструментов в один запрос на слияние. При ошибке скрипта нельзя возвращаться к подсчёту строк журнала и пропускать задачу: иначе контроль качества незаметно перестанет работать.
Для каждой диагностики рекомендуется сохранять следующие поля:
| Поле | Назначение |
|---|---|
| Правило или тип проблемы | Позволяет различать нулевые указатели, утечки ресурсов и другие категории |
| Относительный путь в репозитории | Не допускает попадания рабочего каталога узла в базовую линию |
| Имя функции или символа | Помогает найти проблему после изменения номеров строк |
| Нормализованное сообщение | Исключает временные каталоги и нестабильные числа |
| Уровень серьёзности | Позволяет задавать стратегию обработки с учётом риска |
Создайте проверяемую базовую линию на основе стабильных отпечатков
Отпечаток диагностики не должен включать абсолютный путь, путь DerivedData или отдельно взятый номер строки. Более устойчивое сочетание — «тип проблемы + относительный путь в репозитории + имя символа + нормализованное сообщение». Номер строки можно сохранить для отображения, но не следует использовать в качестве первичного ключа. Иначе добавление одной строки в начале файла приведёт к тому, что все прежние проблемы будут распознаны как новые.
Не допускайте чрезмерного объединения при нормализации
Можно удалять префикс рабочего каталога, временные UUID и повторяющиеся пробелы, но нельзя удалять имена переменных, вызываемых функций или типы ресурсов. Если два разных дефекта в одном файле будут сведены к одному отпечатку, более поздняя проблема окажется скрыта старой записью базовой линии.
Для файла базовой линии рекомендуется использовать отсортированный формат JSON Lines с одной записью в строке и хранить его в системе контроля версий:
{"fingerprint":"sha256:…","type":"AnalyzeWarning","path":"Sources/Cache.swift","symbol":"load()","message":"Potential leak of an object"}
При первоначальном создании базовой линии владелец кода должен проверить каждую запись. Как минимум следует убедиться, что диагностика действительно получена из текущей основной ветки, её пока невозможно исправить немедленно, для неё уже создана задача отслеживания, а ошибки разбора и повторяющиеся записи не попали в базовую линию.
Сравнивайте в запросе на слияние только разность множеств
После создания current.jsonl в каждой задаче сравните множество его отпечатков с baseline.jsonl. Разность current - baseline содержит новые проблемы и должна приводить к ошибке задачи. Разность baseline - current содержит уже исчезнувшие проблемы: в этом случае сопровождающим нужно предложить удалить соответствующие записи базовой линии, а не сохранять неактуальные данные.
Вывод проверки должен быть кратким и пригодным для немедленных действий. Для каждой новой проблемы укажите тип, относительный путь, номер строки, символ и сообщение, а также расположение артефакта с полным xcresult. В консольном журнале показывайте только сводку, чтобы тысячи строк трассировки анализа не скрывали действительно важные различия.
Разделяйте три вида ошибок
Скрипт анализа должен различать как минимум следующие состояния:
- Ошибка самого
xcodebuild analyze, например из-за отсутствующих зависимостей или недоступной Scheme. - Ошибка разбора результатов, например после изменения структуры JSON при обновлении цепочки инструментов.
- Анализ завершился успешно, но обнаружил новые диагностики, отсутствующие в базовой линии.
Первые два состояния относятся к ошибкам инфраструктуры или конфигурации и не должны отображаться как «новых дефектов нет». Задача может завершиться успешно только тогда, когда анализ и разбор результатов прошли без ошибок, а разность множеств пуста.
Постоянно сокращайте базовую линию
Если базовая линия долго не меняется, со временем она превратится в ещё один никем не поддерживаемый список исключений. Можно назначить ответственных за отдельные модули и исправлять близлежащие диагностики при изменении соответствующих файлов. Другой вариант — устранять небольшое число проблем с высоким риском в каждой итерации. После исправления необходимо удалить запись из базовой линии, чтобы следующий запуск подтвердил фактическое исчезновение проблемы.
Повседневную проверку можно выполнять в следующем порядке:
- Убедиться, что цепочка инструментов, Scheme, конфигурация и целевая платформа не изменились.
- Убедиться, что каталог анализа изолирован от других задач.
- Убедиться, что xcresult, журнал и нормализованный список успешно созданы.
- Выборочно проверить, что отпечатки не содержат абсолютных путей или временных идентификаторов.
- Блокировать слияние при новых диагностиках и предлагать сократить базовую линию при исчезновении старых.
- При обновлении цепочки инструментов сначала пересоздать результаты в отдельной ветке и проверить различия.
При выполнении таких задач на OakVM важно не выбирать более агрессивный порог, а сохранять возможность отслеживать цепочку инструментов, скрипты и формат результатов на одном физическом узле. Если ошибка разбора никогда не считается успешным результатом, а изменения базовой линии обязательно проходят проверку, статический анализ превращается из длинного журнала, который легко проигнорировать, в стабильный инкрементальный шлюз качества.
Часто задаваемые вопросы
Почему не требовать нулевого числа предупреждений сразу?
В зрелом проекте могут оставаться известные старые замечания. Если сразу включить строгий порог, проверка будет постоянно падать. Лучше зафиксировать базу, блокировать новые дефекты и постепенно сокращать долг.
Какие артефакты нужно сохранять после анализа?
Сохраняйте полный пакет xcresult, журнал сборки, нормализованный список диагностик и использованную базовую линию. Этого достаточно для повторной проверки и разбора контекста ошибки.
Запустите следующую сборку на выделенном физическом узле
Выберите OakVM M4 или OakVM M4 Pro и арендуйте облачный Mac без виртуализации на день, неделю, месяц или квартал. Фактическая доступность узла отображается в консоли в режиме реального времени.