Гайд · TNWS AI

Как сохранить диагностику проваленного AI-теста как артефакт GitHub Actions

6 мин—

Собираем безопасный диагностический отчёт проваленного AI-контракта и загружаем его через upload-artifact без секретов.

Задача и границы применения

После падения проверки AI-промпта получить воспроизводимый файл с входом и ожидаемыми полями, не копируя сырой пользовательский текст в публичный лог. Работа с промптами часто требует сравнить ожидаемое и фактическое значение. Диагностический файл должен содержать только синтетическую фикстуру; если в нём есть PII или секрет, artifact тоже становится каналом утечки. Пример намеренно не обращается к API и пишет только заранее заданные значения. Ниже — сценарий для собственного репозитория, а не обещание универсальной точности генеративной модели. Для демонстрации используются вымышленные обращения, которые не содержат персональных данных.

Актуальность названий полей, событий и версий actions проверена 19.09.2026 по официальным материалам GitHub. Если у вашего проекта другая структура каталогов или другой протокол AI API, адаптируйте пути и прикладной клиент после проверки его документации. Пример не содержит утверждений о тарифах, ценах или скорости.

Что подготовить до изменения workflow

Нужен репозиторий GitHub, доступ к его Actions и возможность добавить файл в каталог .github/workflows. Подготовьте тестовую ветку и одно синтетическое обращение с известным ожидаемым результатом. Не берите production-заявки: даже если runner временный, ввод и диагностика оказываются в истории запуска. Для Python-части используйте unittest из стандартной библиотеки; если в вашем проекте есть дополнительные импорты, установите их отдельно из контролируемого файла зависимостей.

До коммита запишите контракт: какие поля обязательно должны быть в результате, какие значения разрешены и при каком несоответствии job получает ненулевой код выхода. Сначала выполните тот же скрипт локально. Это позволяет различить ошибку Python от ошибки описания workflow. Если проверка обращается к внешней модели, разделите транспортную ошибку, отсутствие ключа и несоответствие ответа: эти причины требуют разного исправления.

Пошаговая настройка

  1. Создайте нужные каталоги и файлы из блоков ниже; имена путей в YAML должны совпадать с именами файлов в репозитории. Файл workflow хранится внутри .github/workflows, а тестовый код — в tests или scripts согласно примеру.
  2. Проверьте три секции YAML: on задаёт событие, permissions ограничивает встроенный токен, jobs содержит runner и последовательность шагов. Не вставляйте ключи или закрытые тексты в YAML.
  3. Внесите два файла в PR. Скрипт сначала сохраняет reports/contract.json, потом завершает процесс с ошибкой. Условие if: failure() запускает upload-artifact при падении предыдущего шага; if-no-files-found: error превращает отсутствие файла в явную ошибку вместо тихого предупреждения. После тестового запуска откройте страницу failed run и скачайте артефакт с именем ai-fixture-diagnostics. Для успешного сценария замените демонстрационное actual на вычисленный результат приложения. Не выгружайте файлы .env, полные тела реальных обращений или необработанный ответ закрытого сервиса.
  4. Сначала воспроизведите успешный вход, затем намеренно измените одно ожидаемое значение и убедитесь, что job падает. Проверка без негативного сценария не доказывает, что тест вообще способен обнаружить регрессию. После этого верните правильное значение и повторите запуск.
  5. При сбое откройте конкретный job и шаг, а не ориентируйтесь только на общий статус workflow. Проверьте событие запуска, выбранную ветку, наличие файлов, код завершения скрипта и последние безопасные диагностические сообщения.

Готовый шаблон workflow

Скопируйте YAML; если в блоке указаны два имени файла, разделите его на два соответствующих файла. Ссылки на внешние actions и параметры проверены по их официальным README на 19.09.2026.

name: AI failure diagnostics
on:
  pull_request:
permissions:
  contents: read
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-python@v7
        with:
          python-version: '3.13'
      - name: Verify fixture
        run: python scripts/eval_fixture.py
      - name: Upload diagnostics
        if: failure()
        uses: actions/upload-artifact@v7
        with:
          name: ai-fixture-diagnostics
          path: reports/contract.json
          if-no-files-found: error

Код или тестовая фикстура для копирования

Этот блок даёт исходную контрольную точку. Встраивая его в приложение, заменяйте демонстрационный нормализатор на собственный импорт, сохраняя контракт и синтетические тестовые входы.

# scripts/eval_fixture.py
import json, pathlib
expected = {"priority":"high", "summary":"Срочно: платеж не прошёл"}
actual = {"priority":"normal", "summary":"Срочно: платеж не прошёл"}  # демо-сбой
path = pathlib.Path("reports/contract.json")
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps({"fixture":"urgent-payment", "expected":expected,
    "actual":actual}, ensure_ascii=False, indent=2), encoding="utf-8")
if actual != expected:
    raise SystemExit("Contract mismatch; see reports/contract.json")

Реалистичный вход и ожидаемый результат

Вход-фигура urgent-payment ожидает high, пример actual равен normal; job падает, но contract.json доступен как artifact и содержит оба значения. После исправления actual на high тест проходит, а шаг загрузки пропускается. Перед тем как трактовать красный job как баг модели, убедитесь, что сравниваются значения одной и той же ревизии кода и одной и той же фикстуры. Не подменяйте ожидаемое значение фактически полученным: такое «исправление» отключит сигнал регрессии.

Разбор ошибок и ограничения

Если workflow не появляется в Actions, сперва проверьте расположение YAML и событие on; затем проверьте ограничения по путям и веткам. Если job есть, но падает на checkout или setup-python, отличайте инфраструктурную ошибку от провала прикладного утверждения. Если Python завершился с ошибкой импорта, проверьте реальные пути и зависимости. Если проблема только в содержании ответа, сохраните минимальный безопасный вход и точное различие ожидаемого и фактического полей.

В CI тестируется выбранный контракт, а не «качество ИИ вообще». Он не доказывает отсутствие галлюцинаций, безопасность всех возможных промптов или корректность каждой интеграции. Добавляйте отдельные фикстуры для отрицательных кейсов, пустого ввода, Unicode и граничных форматов, когда эти ситуации есть в вашем продукте. Для live API ограничивайте доступ к секрету и используйте отдельные тестовые данные. Не выводите заголовки Authorization, тело закрытого ответа или переменные окружения целиком.

Чек-лист перед слиянием

  • Workflow лежит в .github/workflows, а событие запуска соответствует задаче.
  • Скрипт работает локально на синтетическом входе и падает при намеренно нарушенном контракте.
  • Имена файлов, переменные окружения и пути в YAML совпадают с репозиторием.
  • Секреты не записаны в код, входные параметры, summary или диагностический файл.
  • Проверен успешный запуск и понятный неуспешный запуск; просмотрен конкретный job.
  • Код и тесты соответствуют ограничениям доверия для внешнего PR и правам токена.
  • Результат относится к актуальному коммиту, а не к предыдущей ревизии.

FAQ

Почему artifact не появился?

Проверьте, был ли предыдущий шаг действительно неуспешен, совпадает ли путь reports/contract.json и не прерван ли job до создания файла.

Можно ли загружать один artifact из нескольких jobs?

Имена artifact должны быть уникальны для отдельных загрузок; добавьте суффикс по элементу матрицы, если jobs несколько.

Безопасно ли хранить персональные данные в отчёте?

Нет. Используйте синтетические фикстуры и удаляйте чувствительные поля до сохранения файла.

Зачем if-no-files-found: error?

Без этой опции отсутствие файла может остаться предупреждением; в диагностике отсутствие ожидаемого отчёта само является ошибкой.

Как зафиксировать проверенный результат

После успешного запуска сохраните ссылку на конкретный run рядом с pull request: так ревьюер увидит проверенную ревизию. При следующем сбое сравнивайте не только цвет check, но и фикстуру, входные параметры, изменённые файлы и точный шаг ошибки. Если ослабили утверждение теста, объясните в PR, какой риск остался непокрытым, и добавьте отдельный сценарий. При переносе шаблона в другой репозиторий повторно проверьте структуру каталогов и разрешения: одинаковый YAML сам по себе не гарантирует одинаковую модель доверия. Не называйте демонстрационные результаты измерением качества или производительности AI-системы.

Официальные первоисточники

Проверено 19.09.2026. Описание синтаксиса и поведения: 1, 2, 3, 4. Читайте первоисточники при переносе шаблона в другой репозиторий: доступность версии action или поддерживаемый синтаксис могут измениться.

Читайте также

Комментарии

Пока тихо. Скажите первое слово