Гайд · TNWS AI
Как вывести результат AI-регрессионных тестов в GitHub Actions Job Summary
Создаём читаемую сводку контрактного AI-теста в GitHub Actions через GITHUB_STEP_SUMMARY: сценарии, статус и ограничения вывода.
Задача и границы применения
Показать ревьюеру результат проверки AI-маршрутизации прямо на странице workflow, без чтения всего лога. Сводка должна объяснять, что проверялось и где найти ошибку, но не должна публиковать входы реальных клиентов. GitHub поддерживает Markdown-файл GITHUB_STEP_SUMMARY; безопаснее записывать фиксированные имена синтетических кейсов и вычисленный статус. Ниже — сценарий для собственного репозитория, а не обещание универсальной точности генеративной модели. Для демонстрации используются вымышленные обращения, которые не содержат персональных данных.
Актуальность названий полей, событий и версий actions проверена 19.09.2026 по официальным материалам GitHub. Если у вашего проекта другая структура каталогов или другой протокол AI API, адаптируйте пути и прикладной клиент после проверки его документации. Пример не содержит утверждений о тарифах, ценах или скорости.
Что подготовить до изменения workflow
Нужен репозиторий GitHub, доступ к его Actions и возможность добавить файл в каталог .github/workflows. Подготовьте тестовую ветку и одно синтетическое обращение с известным ожидаемым результатом. Не берите production-заявки: даже если runner временный, ввод и диагностика оказываются в истории запуска. Для Python-части используйте unittest из стандартной библиотеки; если в вашем проекте есть дополнительные импорты, установите их отдельно из контролируемого файла зависимостей.
До коммита запишите контракт: какие поля обязательно должны быть в результате, какие значения разрешены и при каком несоответствии job получает ненулевой код выхода. Сначала выполните тот же скрипт локально. Это позволяет различить ошибку Python от ошибки описания workflow. Если проверка обращается к внешней модели, разделите транспортную ошибку, отсутствие ключа и несоответствие ответа: эти причины требуют разного исправления.
Пошаговая настройка
- Создайте нужные каталоги и файлы из блоков ниже; имена путей в YAML должны совпадать с именами файлов в репозитории. Файл workflow хранится внутри
.github/workflows, а тестовый код — вtestsилиscriptsсогласно примеру. - Проверьте три секции YAML:
onзадаёт событие,permissionsограничивает встроенный токен,jobsсодержит runner и последовательность шагов. Не вставляйте ключи или закрытые тексты в YAML. - Создайте YAML и скрипт, затем измените вычисление actual так, чтобы оно вызывало ваш нормализатор. Переменную
GITHUB_STEP_SUMMARYGitHub предоставляет шагу; Python добавляет Markdown в этот файл. Статус шага определяется ненулевым exit code, а не красивой таблицей: при mismatch скрипт обязан завершиться ошибкой. Откройте страницу запуска и блок Summary; проверьте, что видны две строки с именами фикстур. Не записывайте туда неочищенный текст клиента, ключи или прямую ссылку на закрытый ответ модели. При нескольких шагах их summary собираются на странице job, но файл каждого шага отдельный. - Сначала воспроизведите успешный вход, затем намеренно измените одно ожидаемое значение и убедитесь, что job падает. Проверка без негативного сценария не доказывает, что тест вообще способен обнаружить регрессию. После этого верните правильное значение и повторите запуск.
- При сбое откройте конкретный job и шаг, а не ориентируйтесь только на общий статус workflow. Проверьте событие запуска, выбранную ветку, наличие файлов, код завершения скрипта и последние безопасные диагностические сообщения.
Готовый шаблон workflow
Скопируйте YAML; если в блоке указаны два имени файла, разделите его на два соответствующих файла. Ссылки на внешние actions и параметры проверены по их официальным README на 19.09.2026.
name: AI contract summary
on:
pull_request:
permissions:
contents: read
jobs:
summary:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: '3.13'
- name: Evaluate and write summary
run: python scripts/summary_eval.py
Код или тестовая фикстура для копирования
Этот блок даёт исходную контрольную точку. Встраивая его в приложение, заменяйте демонстрационный нормализатор на собственный импорт, сохраняя контракт и синтетические тестовые входы.
# scripts/summary_eval.py
import os, pathlib
cases = [("urgent-payment", "Срочно: платеж не прошёл", "high"),
("ordinary-question", "Когда придёт чек?", "normal")]
rows, failures = [], []
for name, text, expected in cases:
actual = "high" if text.startswith("Срочно:") else "normal"
ok = actual == expected
rows.append(f"| {name} | {expected} | {actual} | {'OK' if ok else 'FAIL'} |")
if not ok: failures.append(name)
summary = "## Контракт маршрутизации
| Кейс | Ожидается | Факт | Статус |
|---|---|---|---|
" + "
".join(rows) + "
"
path = pathlib.Path(os.environ["GITHUB_STEP_SUMMARY"])
with path.open("a", encoding="utf-8") as f: f.write(summary)
if failures: raise SystemExit("Failed cases: " + ", ".join(failures))
Реалистичный вход и ожидаемый результат
Для кейса urgent-payment ожидается и получается high; для ordinary-question — normal. Сводка содержит обе строки OK. Если нормализатор ошибочно помечает обычный вопрос как high, соответствующая строка показывает FAIL, а job краснеет. Перед тем как трактовать красный job как баг модели, убедитесь, что сравниваются значения одной и той же ревизии кода и одной и той же фикстуры. Не подменяйте ожидаемое значение фактически полученным: такое «исправление» отключит сигнал регрессии.
Разбор ошибок и ограничения
Если workflow не появляется в Actions, сперва проверьте расположение YAML и событие on; затем проверьте ограничения по путям и веткам. Если job есть, но падает на checkout или setup-python, отличайте инфраструктурную ошибку от провала прикладного утверждения. Если Python завершился с ошибкой импорта, проверьте реальные пути и зависимости. Если проблема только в содержании ответа, сохраните минимальный безопасный вход и точное различие ожидаемого и фактического полей.
В CI тестируется выбранный контракт, а не «качество ИИ вообще». Он не доказывает отсутствие галлюцинаций, безопасность всех возможных промптов или корректность каждой интеграции. Добавляйте отдельные фикстуры для отрицательных кейсов, пустого ввода, Unicode и граничных форматов, когда эти ситуации есть в вашем продукте. Для live API ограничивайте доступ к секрету и используйте отдельные тестовые данные. Не выводите заголовки Authorization, тело закрытого ответа или переменные окружения целиком.
Чек-лист перед слиянием
- Workflow лежит в
.github/workflows, а событие запуска соответствует задаче. - Скрипт работает локально на синтетическом входе и падает при намеренно нарушенном контракте.
- Имена файлов, переменные окружения и пути в YAML совпадают с репозиторием.
- Секреты не записаны в код, входные параметры, summary или диагностический файл.
- Проверен успешный запуск и понятный неуспешный запуск; просмотрен конкретный job.
- Код и тесты соответствуют ограничениям доверия для внешнего PR и правам токена.
- Результат относится к актуальному коммиту, а не к предыдущей ревизии.
FAQ
Почему таблица есть, но workflow зелёный при ошибке?
Сводка не влияет на exit status. Поднимите исключение или завершите процесс ненулевым кодом при обнаруженном расхождении.
Можно ли использовать echo?
Да, документация показывает echo ... >> $GITHUB_STEP_SUMMARY; Python удобнее для формируемой программой таблицы.
Куда делась сводка после другого шага?
Файл summary уникален для каждого шага; поздний шаг не редактирует уже загруженную сводку предыдущего.
Что делать с чувствительными входами?
Пишите только идентификатор безопасной фикстуры и агрегированный статус; не публикуйте тело реального обращения.
Как зафиксировать проверенный результат
После успешного запуска сохраните ссылку на конкретный run рядом с pull request: так ревьюер увидит проверенную ревизию. При следующем сбое сравнивайте не только цвет check, но и фикстуру, входные параметры, изменённые файлы и точный шаг ошибки. Если ослабили утверждение теста, объясните в PR, какой риск остался непокрытым, и добавьте отдельный сценарий. При переносе шаблона в другой репозиторий повторно проверьте структуру каталогов и разрешения: одинаковый YAML сам по себе не гарантирует одинаковую модель доверия. Не называйте демонстрационные результаты измерением качества или производительности AI-системы.
Официальные первоисточники
Проверено 19.09.2026. Описание синтаксиса и поведения: 1, 2, 3, 4. Читайте первоисточники при переносе шаблона в другой репозиторий: доступность версии action или поддерживаемый синтаксис могут измениться.
Читайте также
Как исключить bias из weight decay через Optax
Optax 0.2.6: маска add_decayed_weights применяет decay к kernel и оставляет bias без изменения.
Как использовать Huber loss в Optax для регрессии с выбросами
Optax 0.2.6: Huber loss квадратичен около нуля и линеен после delta; проверяем ошибки 0,5 и 2.
Как использовать sigmoid focal loss в Optax
Optax 0.2.6: focal loss для logits 0 и labels 0/1 при gamma=2; проверка симметричного базового значения.
Комментарии
Пока тихо. Скажите первое слово