Retry скрывает красные тесты: повторяем только сбой runner

В pipeline добавили retry: 2, чтобы пережить редкие сбои runner. Теперь любой упавший тест запускается до трёх раз. Иногда последний запуск проходит, и зелёный статус скрывает нестабильный тест. Команда получает медленный pipeline и меньше информации о качестве проверки. Повторять стоит конкретный класс отказов, для которого новая попытка действительно имеет смысл.

GitLab позволяет задавать retry с max и when. max ограничивает число дополнительных запусков, а when выбирает причины отказа. Для инфраструктурной ошибки runner есть runner_system_failure. Такой фильтр не обещает, что причина обязательно исчезнет, но не превращает каждый неуспешный script в кандидата на автоматический повтор.

Минимальный пример политики

В учебной job script намеренно возвращает 7. Этот отказ нужен, чтобы проверить отрицательный сценарий: при политике только для runner_system_failure обычная ошибка скрипта не должна автоматически повторяться.

verify-retry-policy:
  image: alpine:3.22
  script:
    - printf '%s\n' 'Намеренный отказ тестовой команды'
    - exit 7
  retry:
    max: 2
    when:
      - runner_system_failure

В отдельном тестовом проекте ожидается одна неуспешная попытка с кодом 7. Две дополнительные попытки разрешены только для указанной причины отказа, которую фиксирует GitLab. Не создавайте настоящий сбой runner ради проверки положительной ветки на общей рабочей инфраструктуре; её лучше проверять на выделенном стенде.

Причину отказа смотрите в деталях job и сообщениях runner. Одинаковое слово «failed» в конце лога не означает одинаковую категорию. Неуспешный exit приложения, невозможность подготовить среду и отменённая job имеют разные последствия для политики повторов.

Почему общий retry меняет смысл проверки

При max: 2 возможны три запуска: исходный и два повтора. Если тест зависит от времени или порядка, один удачный запуск после двух отказов не объясняет причину нестабильности. Для таких тестов сохраняйте историю попыток и разбирайте источник флуктуации отдельно, вместо расширения retry на весь pipeline.

Некоторые причины отказов меняются между версиями GitLab. Например, классификация ошибок настройки runner и отдельных timeout-состояний уточнялась в новых выпусках. Поэтому для self-managed сначала проверьте доступные значения when в документации вашей версии и выполните CI Lint. Не копируйте длинный список всех причин из чужого проекта: он быстро перестаёт выражать осмысленную политику.

Повтор job повторяет всю операцию

Если script уже опубликовал пакет или отправил уведомление, повтор может выполнить действие снова. Разделите подготовку и публикацию либо сделайте внешнее действие идемпотентным: повтор с тем же идентификатором должен приводить к известному результату. Ограничение причины runner_system_failure само по себе не доказывает, что до отказа ничего не успело произойти.

Для диагностики сохраняйте идентификатор pipeline, job и предметный идентификатор операции. Когда возникнет повтор, инженер сможет проверить, что было создано первой попыткой. Опираться только на финальный зелёный статус опасно для действий, которые изменяют внешнее состояние.

В случае постоянного инфраструктурного отказа дополнительные попытки лишь занимают очередь. Порог повторов должен быть небольшим, а повторяющаяся причина — видимой владельцу runner. Если все попытки заканчиваются одинаково, следующий шаг — исправить среду, а не увеличить число запусков.

Откройте программу GitLab CI/CD. В ней есть изоляция runners и диагностика нестабильных pipeline. Продолжите к процессу выпуска, где повторная попытка имеет конкретное основание, а красный тест остаётся сигналом для разбора кода.

Ещё по теме

Продолжить на практике

  • GitLab CI/CD: автоматизация сборки и деплоя ↗

    От первого .gitlab-ci.yml до pipeline, который тестирует код, собирает образ и выкладывает приложение. Runners, artifacts, cache, registry, окружения и безопасный откат — на одном практическом проекте.