Матрица версий в CI: как читать цифры и делать выводы
Матрица из восьми CI-запусков не обязательно делает проверку в восемь раз дольше, но почти всегда увеличивает расход ресурсов. Разберём, как считать ячейки, сравнивать время и находить несовместимость, а не просто собирать зелёные галочки.

В матрице CI одна проверка превращается в несколько запусков: например, четыре версии Python на двух операционных системах дают восемь ячеек. Это не означает, что разработчики будут ждать результат в восемь раз дольше, но счётчик занятых минут раннера может вырасти примерно настолько — и именно эту разницу легко не заметить, глядя только на время до зелёной галочки.
Что именно умножает матрица
Матрица — это набор значений параметров, для которых CI повторяет одну и ту же задачу. В GitHub Actions такими параметрами могут быть версии Python и операционные системы. Если заданы четыре версии языка и две ОС, получится 4 × 2 = 8 комбинаций. Добавьте ещё две версии базы данных — и потенциально получите 16 ячеек.
В этой статье речь о матричных заданиях GitHub Actions и примере с Python 3.10–3.13. Это иллюстрация расчёта, а не рекомендация поддерживать все четыре версии: проверьте, какие версии нужны вашему продукту, и сверьте их статус с официальным графиком Python. Синтаксис и поведение GitHub Actions могут меняться, поэтому перед настройкой смотрите актуальную документацию.
Сноска. Ячейка матрицы — отдельный запуск задания для одной комбинации значений, например Python 3.12 на Linux. Она может выполняться параллельно с другими ячейками, если CI располагает свободными раннерами и не упирается в лимиты.
Время ожидания — не то же самое, что цена проверки
Для оценки нагрузки разделяйте два показателя:
- Wall-clock time — сколько проходит от старта workflow до результата. На него влияют параллельность и очередь.
- Суммарное время раннеров — сколько минут все ячейки вместе выполнялись. Этот показатель лучше показывает расход вычислительных ресурсов.
Представим условный тестовый набор, который занимает шесть минут в каждой ячейке. Одна ячейка потребует около шести раннеро-минут. Восемь ячеек — около 48. Если все стартуют одновременно и длительность у них сопоставима, ожидание может остаться около шести минут; если параллельность ограничена двумя раннерами, тестовая часть займёт примерно 24 минуты. В реальном workflow добавятся установка зависимостей, сборка, очередь и различия между средами.
Это арифметический пример, не замер GitHub Actions и не обещание времени. Чтобы получить свои цифры, зафиксируйте длительность каждой ячейки и число запусков за неделю. Например, если восемь ячеек выполняются по шесть минут на каждом из 50 запусков, получится примерно 400 раннеро-часов? Нет: 8 × 6 × 50 = 2400 раннеро-минут, то есть 40 раннеро-часов. Переводите минуты аккуратно: ошибка в единицах быстро искажает бюджет.
Хорошая матрица отвечает на вопрос «какие комбинации мы обязаны поддерживать?». Плохая — просто размножает одну и ту же проверку, пока CI не начинает казаться дорогим и медленным.
Какие цифры собирать, прежде чем расширять матрицу
Одного времени всего workflow недостаточно. Если запуск стал длиннее, причина может быть не в новых версиях, а в очереди, медленной установке зависимостей или нестабильном тесте. Для каждой ячейки полезно смотреть длительность, статус, версию среды и повторяемость отказа.
- Длительность по ячейкам. Выясните, есть ли версия языка или ОС, которая стабильно медленнее остальных.
- Доля отказов. Разделите реальные несовместимости, ошибки тестов и случайные сбои инфраструктуры.
- Суммарные минуты. Сравните расход до и после изменения матрицы за одинаковое число запусков.
- Очередь и параллельность. Отдельно измеряйте ожидание свободного раннера и собственно выполнение.
- Ценность ячейки. Записывайте, какую поддерживаемую комбинацию она проверяет и какие дефекты помогла поймать.
Сравнивайте периоды одинаковой длины и похожую нагрузку: например, две недели до изменения и две после. Учитывайте изменения кода и объёма тестов. Если матрица запустилась одновременно с крупной миграцией зависимостей, разница в длительности сама по себе не докажет, что виноваты новые ячейки.
Полная матрица или выборочные комбинации
Не все параметры обязаны перемножаться. Иногда проекту важно прогонять весь набор тестов на одной основной среде, а крайние версии проверять сокращённым набором. Это уменьшает расход, но требует осознанно выбрать, какие комбинации можно не проверять полностью.
| Подход | Что проверяет | Цена и риск |
|---|---|---|
| Полный перебор | Каждую комбинацию версий и сред | Максимальный охват; число запусков быстро растёт как произведение параметров |
| Основная среда плюс крайние версии | Полный набор тестов на основной версии, совместимость на минимальной и максимальной | Меньше запусков; можно пропустить дефект, возникающий только в промежуточной версии |
| Разделение на быстрые и полные проверки | Быстрые тесты на широком наборе, полный набор на ограниченном | Экономит время обратной связи; сложнее поддерживать и объяснять, что именно блокирует релиз |
Для GitHub Actions важно учитывать и поведение отказов. По умолчанию сбой одной ячейки может привести к отмене ещё выполняющихся или ожидающих запусков матрицы. Это быстрее показывает красный статус, но оставляет меньше данных о других комбинациях. Если вам нужна диагностика всех версий, настройте стратегию так, чтобы остальные ячейки завершили работу; точные параметры проверьте в документации GitHub Actions для актуального синтаксиса.
Где матрица даёт ложную уверенность
Успех на версиях языка не означает совместимость со всеми зависимостями
Если зависимости устанавливаются заново без фиксации версий, два запуска могут получить разные наборы пакетов. Тогда матрица проверяет не только Python, но и меняющийся граф зависимостей. Для воспроизводимой диагностики фиксируйте зависимости подходящим для проекта способом и сохраняйте сведения о среде.
Соседние версии не всегда выявляют границу
Тесты на минимальной и максимальной версиях полезны, но библиотека или системный пакет может вести себя иначе посередине. Если проект обещает поддержку всех версий, выборочная проверка — компромисс, а не доказательство полной совместимости. При добавлении версии смотрите, где меняются зависимости, синтаксис, системные библиотеки и поведение платформы.
Параллельный запуск может ухудшить время ответа
Матрица способна породить много задач одновременно. При ограниченном числе доступных раннеров часть запусков ждёт в очереди; при перегруженной инфраструктуре быстрее становится не всегда. Следите за временем очереди отдельно от времени выполнения и не оценивайте оптимизацию только по суммарным минутам.
Как понять, окупилась ли новая ячейка
Перед расширением сформулируйте гипотезу: какую поддерживаемую комбинацию вы добавляете и какой риск хотите обнаружить. Затем сравните результаты за сопоставимый период. Полезный вывод выглядит не как «CI стал на 12% дольше», а как «добавили проверку минимальной версии, она выявляет несовместимость в конкретной зависимости; дополнительные 240 раннеро-минут в неделю приемлемы» — если эти цифры действительно получены из ваших запусков.
Если новую ячейку не удаётся связать ни с обещанной поддержкой, ни с типом дефектов, который важно ловить, это повод пересмотреть набор, а не автоматически оставлять все комбинации. И наоборот: редкая версия может быть критична, если её использует часть клиентов. Решение зависит от контракта поддержки, последствий сбоя и стоимости проверки.
Что делать дальше
Сначала выпишите версии языка и ОС, которые проект официально поддерживает. Посчитайте число комбинаций умножением параметров, затем измерьте для каждой ячейки длительность, очередь и частоту отказов в обычных запусках. После этого добавляйте или убирайте комбинации по конкретному риску и снова сравнивайте данные. Инвалидация кеша и ускорение установки зависимостей — отдельные темы: здесь важно не смешивать их эффект с ценой самой матрицы.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: GitHub Actions: Running variations of jobs in a workflow, Python Developer’s Guide: Status of Python versions
Частые вопросы
Матрица из восьми ячеек в восемь раз увеличит время CI?
Нужно ли прогонять полный набор тестов на каждой версии Python?
Как выбрать версии Python для матрицы?
Что делать, если время CI выросло после расширения матрицы?
Можно ли отключить остальные проверки после первого сбоя?
Что учитывать в проде, кроме минут раннера?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.