8 мин

Какие проверки pull request агента должны блокировать слияние?

Используйте семь измеримых проверок pull request агентов, чтобы остановить небезопасный код: тесты, CodeQL, зависимости, секреты, авторизацию, миграции и откат.

Какие проверки pull request агента должны блокировать слияние?

Агент может подготовить аккуратный дифф, убедительное описание и код, который проходит быстрое ревью, но при этом оставить приложение уязвимым или невосстановимым. Поэтому решение о слиянии должно опираться на измеримые в репозитории подтверждения, а не на уверенность агента или размер патча.

Я использую семь блокирующих проверок: тесты, CodeQL, проверку зависимостей, сканирование секретов, проверки авторизации, репетицию миграции и проверку отката. Каждая отвечает на свой вопрос о сбое. Зеленый набор тестов не доказывает безопасность нового пакета, а чистый результат статического анализа ничего не говорит о том, заблокирует ли миграция базы данных самую загруженную таблицу.

Эти проверки одинаково применимы к изменениям людей и агентов. Авторство агента меняет объем, скорость и характер ошибок, но не оправдывает отдельный, более слабый путь. Если предложенное изменение не может предоставить те же подтверждения, что и любой другой pull request, оно не готово к слиянию.

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

Проверка слияния должна возвращать воспроизводимый результат «успешно» или «ошибка» для точного коммита, который попадет в защищенную ветку. Комментарий «пожалуйста, проверьте эту зависимость» - это совет. Обязательная проверка, которая указывает пакет, версию, предупреждение и порог серьезности, - это подтверждение.

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

  • Она запускается для текущего head-коммита pull request.
  • Защита ветки требует ее результат с указанным именем.
  • Пропущенная, превысившая тайм-аут или аварийно завершившаяся задача не засчитывается как успех.
  • В результате достаточно деталей, чтобы воспроизвести решение.

Храните политику в репозитории. Небольшой манифест упрощает ревью по сравнению с набором настроек, известных только администраторам:

merge_gates:
  tests: required
  codeql: required
  dependency_review: required
  secret_scan: required
  authorization: required
  migration_rehearsal: required_when_changed
  rollback_verification: required

Значение required_when_changed не создает лазейку. Оно означает, что проверка сначала определяет подходящие файлы, а затем либо проводит репетицию, либо фиксирует чистый результат «неприменимо». Не позволяйте фильтрам по путям оставлять обязательную проверку в состоянии постоянного ожидания и не позволяйте агенту самому решать, что его рискованное изменение освобождено от проверки.

Ограничивайте разрешения workflow минимумом, необходимым каждой задаче. Код pull request - недоверенный ввод, даже если ветка принадлежит вашей организации. Проверка, которая предоставляет проверяемому коду токен с правами записи или секрет production, может создать проблему серьезнее той, которую должна была обнаружить.

Защищайте идентичность проверки так же тщательно, как ее логику. Правила ветки обычно требуют имя статуса, поэтому два workflow, способные сообщать одно и то же имя, могут позволить более слабой задаче выполнить правило. Дайте задаче политики уникальное имя, ограничьте круг тех, кто может менять ее workflow, и требуйте ревью от владельцев этого файла. Когда очередь слияния создает новый коммит слияния, запускайте проверки снова для этого коммита или используйте функцию платформы, которая привязывает результаты к поставленной в очередь ревизии. Подтверждение для вчерашнего head-коммита не подтверждает сегодняшнее слияние.

Относитесь к конфигурации проверок как к чувствительному коду. Pull request, который меняет порог, убирает путь, понижает набор запросов или добавляет исключение, меняет смысл каждого последующего зеленого результата. Явно показывайте диффы политики и требуйте ревью от сопровождающего, который понимает затронутый контроль. Агент может предложить такое изменение, но не должен получать более легкий проход только потому, что редактирует механизм, который его оценивает.

Тесты блокируют заметные регрессии

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

Агенты особенно хорошо умеют удовлетворять ближайшее утверждение. Они могут добавить запасной вариант, который делает один тест зеленым, но ломает обработку ошибок, разбиение на страницы, конкурентность или соседний контракт API. Требуйте, чтобы pull request добавлял или менял тесты, когда меняет поведение, но не измеряйте качество числом новых строк тестов. Проверьте, упал бы тест, если удалить или откатить реализацию.

Полезная проверка тестов состоит из слоев с отдельными именами:

  • Модульные тесты для локальной логики и граничных случаев.
  • Интеграционные тесты для контрактов базы данных, очереди, кэша и внешних сервисов.
  • Контрактные тесты для публичных форм запросов и ответов.
  • Небольшой smoke-тест для собранного артефакта.

Доводите нестабильные тесты до исправления, а не выдавайте автоматические повторы, пока они не позеленеют. Один повтор может собрать диагностические данные, но итоговый статус должен показывать первоначальный сбой. Иначе агент сможет слить код, единственное доказанное свойство которого - иногда он работает.

Smoke-тест должен запустить артефакт, проверить endpoint состояния и один значимый путь записи, затем корректно остановить его. Тестирование исходного кода без запуска упакованного приложения не выявляет отсутствующие файлы, неверные значения окружения по умолчанию, сломанные миграции и панику при запуске. Для веб-сервиса результат можно записать в компактном виде:

{"commit":"abc123","build":"pass","startup_ms":842,"health":200,"write_read_cycle":"pass"}

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

Защищайте тесты от реализации, которую они оценивают. Если pull request одновременно меняет правило и переписывает утверждения, чтобы принять новый результат, набор может пройти, пока контракт незаметно смещается. Потребуйте, чтобы ревьюер сравнил измененные тесты с публичным API, задачей или правилом приемки. Для парсеров, валидаторов, логики биллинга и проверок доступа добавьте мутационное тестирование или небольшой набор заведомо неверных входных данных. Важный вопрос в том, отвергает ли набор правдоподобную неверную реализацию, а не в том, может ли агент заставить собственную реализацию пройти утверждения, которые он тоже написал.

Сохраняйте артефакты, когда проверка тестов завершается ошибкой. Храните seed, вызвавший ошибку в рандомизированных тестах, точный образ базы данных, логи сервиса без секретов и команду для воспроизведения запуска. Статус без данных для воспроизведения заставляет следующего агента или инженера снова гадать. Ограничивайте срок хранения артефактов правилами работы с данными в репозитории и никогда не выгружайте снимок production только потому, что с ним легко воспроизвести сбой.

CodeQL блокирует известные пути к уязвимостям

Проверка CodeQL должна блокировать новые находки с высокой достоверностью в языках и сгенерированных артефактах, которые CodeQL действительно анализирует. Она не должна создавать впечатление, что чистый результат доказывает безопасность всего приложения.

GitHub описывает CodeQL как преобразование кода в базу данных для запросов и запуск запросов по ней. Эта модель полезна, потому что отслеживает данные в коде, а не ищет только подозрительный текст. Ее охват ограничен поддержкой языков, успешной сборкой, выбором запросов и кодом, доступным во время анализа. Если сборка базы данных молча исключает сервис, зеленый результат охватывает меньше, чем считают ревьюеры.

Используйте workflow с явно указанными языками и фиксированной политикой запросов:

name: codeql
on: [pull_request]
permissions:
  contents: read
  security-events: write
jobs:
  analyze:
    strategy:
      matrix:
        language: [javascript-typescript, go]
    steps:
      - uses: actions/checkout@v4
      - uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}
          queries: security-extended
      - uses: github/codeql-action/autobuild@v3
      - uses: github/codeql-action/analyze@v3

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

Решите, что блокирует слияние, до появления первого предупреждения. Обычно я блокирую новые находки на согласованном в репозитории пороге серьезности и точности, а существующий долг оставляю видимым в базовой линии. Блокировка всех исторических результатов в первый день поощряет массовое отклонение. Вечное игнорирование всех существующих результатов создает постоянную слепую зону. Вместо этого назначьте владельцев и сроки для базовой линии.

Проверяйте набор проанализированных файлов, когда меняются сервисы, языки или команды сборки. Pull request, добавляющий новый мобильный клиент, сгенерированный resolver или отдельный backend, может потребовать еще один анализатор или шаг сборки. Фраза «CodeQL прошел» имеет смысл, только когда ревьюеры могут сказать, что именно проверил CodeQL.

Отделяйте сбои анализа от чистого анализа. Если autobuild не может скомпилировать пакет, задача должна сообщить об ошибке инфраструктуры или конфигурации, а не о нуле находок. Сохраняйте журнал создания базы данных и количество проанализированных исходных файлов по языкам. Сравнивайте эти значения с базовой веткой и отмечайте большое необъяснимое падение. Это выявляет обычный сбой: изменение сборки исключает уязвимый модуль, анализ ускоряется, а проверка безопасности становится зеленой, потому что увидела меньше кода.

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

Проверка зависимостей останавливает риск до установки

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

Эта проверка отличается от предупреждения об уязвимости в репозитории. Предупреждение сообщает, что в ветке есть уязвимая зависимость. Проверка зависимостей спрашивает, ухудшает ли этот pull request граф зависимостей. Проверка зависимостей GitHub сравнивает манифесты и lock-файлы в pull request, поэтому решение принимается вовремя и его можно связать с конкретным изменением.

Требуйте согласованности lock-файла. Если агент меняет package.json, но не lock-файл, или меняет lock-файл без соответствующего изменения манифеста, задача должна завершаться ошибкой. Команды установки, разрешающие свежие версии во время CI, делают результат недетерминированным и могут проверять граф, отличный от того, который видели ревьюеры.

Компактная политика может выглядеть так:

dependency_policy:
  fail_on_severity: high
  deny_licenses:
    - AGPL-3.0
  allow_sources:
    - registry.npmjs.org
    - proxy.golang.org
  require_owner_for_direct_additions: true

Точный список лицензий - юридическое и продуктовое решение, а не значение, которое стоит слепо копировать. Главное, чтобы репозиторий его объявлял, а проверка печатала пакет, который сработал.

Не одобряйте пакет автоматически только потому, что его имя похоже на предложенную библиотеку. Агенты могут выдумывать имена пакетов, выбирать заброшенные форки или добавлять крупный клиент ради одной простой вспомогательной функции. Результат проверки должен показывать новые прямые и транзитивные пакеты, реестр-источник, разрешенную версию, лицензию и статус предупреждений. Тогда ревьюер сможет спросить, решает ли проблему уже существующий код или меньшая зависимость.

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

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

Вендорский код и образы контейнеров относятся к тому же решению, хотя обычная проверка манифеста может их не заметить. Сравнивайте дайджесты образов, имена базовых образов, Git submodules и добавленные в репозиторий архивы. Для входных данных релиза требуйте неизменяемые дайджесты. Удобный тег вроде latest делает pull request невоспроизводимым позднее, потому что байты могут измениться без нового диффа.

Сканирование секретов должно проверять дифф и историю

Сохраняйте заведомо рабочее состояние
Снимки Koder.ai дают проверке отката конкретную точку восстановления вместо обещания на словах.

Сканирование секретов должно блокировать pull request, когда он добавляет шаблон учетных данных или подтвержденный действующий секрет, даже если строка находится в тестовой фикстуре, удаленном файле, сгенерированном bundle или более раннем коммите pull request.

Защита при push и сканирование pull request решают связанные, но разные задачи. Защита при push может остановить распознанный секрет до того, как он попадет в удаленный репозиторий. Проверка pull request изучает то, что уже поступило, и может охватить участников или типы токенов, которые защита при push пропустила. Предупреждение без защиты ветки не блокирует слияние.

Сканируйте полный диапазон коммитов относительно базовой ветки, а не только итоговую файловую систему. Агент может добавить токен в одном коммите и удалить его в следующем, но токен останется в истории Git и уже мог попасть в логи или кэши. Считайте его раскрытым. Отзовите или смените учетные данные, удалите их из предлагаемой истории и заново запустите проверку.

Используйте синтетические фикстуры, которые не могут пройти аутентификацию. Фикстура должна ясно обозначать себя и соответствовать локально определенному шаблону теста, а не копировать форму настоящего облачного ключа. Широкие списки разрешений опасны, потому что злоумышленники и случайные ошибки в конце концов находят игнорируемый каталог. Держите исключения точными, проверенными и близко к конфигурации детектора.

Сочетайте детекторы шаблонов с проверками энтропии и, если провайдер поддерживает это безопасно, с проверкой учетных данных. Сопоставление шаблонов создает меньше рисков для сети и раскрытия данных, но пропускает нестандартные токены. Проверка может уменьшить неопределенность, однако она отправляет часть предполагаемого секрета в другой сервис и никогда не должна выполняться против недоверенного endpoint, указанного в pull request. Документируйте, какие детекторы проводят проверку, какие остаются локальными и какие данные покидают CI.

Сканируйте распространенные закодированные формы и сгенерированные результаты, но не считайте каждую случайную строку учетными данными. Base64, URL-кодирование и минифицированные bundle могут скрыть секрет, который на шаге исходного кода был виден открыто. Настраивайте порог блокировки по проверенным фикстурам, затем рассматривайте обновления детекторов как другие изменения политики. Шумный сканер приучает сопровождающих отклонять результаты, а молчащий создает ложную уверенность.

Результат проверки должен содержать местоположение без раскрытия:

{"result":"fail","detector":"generic-api-token","commit":"abc123","path":"config/dev.env","line":7,"fingerprint":"sha256:8f2c..."}

Никогда не печатайте полное совпадение в логах CI или комментарии pull request. Маскирование после вывода сканера может оказаться слишком поздним, потому что системы логов, уведомления и артефакты задач могут его скопировать.

Сканирование секретов не заменяет проверку разрешений репозитория. Workflow может читать учетные данные production, не помещая их в дифф, а агент может изменить задачу развертывания, чтобы вывести их наружу. Не передавайте секреты задачам pull request, ограничивайте разрешения workflow и требуйте ревью человеком для изменений определений CI.

Проверки авторизации доказывают, что запрещенные действия остаются запрещенными

Проверка авторизации должна доказать, что каждая защищенная операция отклоняет неправильного субъекта и разрешает действие нужному субъекту на границе сервиса. Одни только тесты входа не проверяют авторизацию.

Команды регулярно смешивают аутентификацию, авторизацию и видимость в интерфейсе. Аутентификация устанавливает, кто отправил запрос. Авторизация решает, может ли эта личность выполнить действие с этим объектом. Скрытие кнопки администратора в React не меняет ни одно из этих решений в Go API. Если backend принимает запрос, приложение остается уязвимым.

Создайте матрицу разрешений для измененных endpoint и бизнес-действий. Она должна быть достаточно небольшой для ревью, но включать границы владения и арендаторов:

read_private_project:
  anonymous: deny
  member: deny
  other_tenant: deny
  owner: allow
  admin: allow
update_project:
  anonymous: deny
  other_tenant: deny
  owner: allow

Генерируйте тесты из этой матрицы или закодируйте эквивалентные табличные случаи на языке сервиса. Каждый случай отказа должен вызывать настоящий обработчик с реалистичными идентификаторами. Моки, заменяющие middleware авторизации, могут доказать работу маршрута, пропуская проверяемый контроль.

Тестируйте доступ на уровне объекта, а не только роли. У двух пользователей может быть роль member, хотя они принадлежат разным организациям. Независимо меняйте идентификатор ресурса и идентификатор арендатора, чтобы выявить небезопасный прямой доступ к объекту. Также проверяйте массовые endpoint, экспорты, фоновые задачи и GraphQL resolvers, которые часто обходят проверки, написанные для обычных REST-обработчиков.

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

Агенты часто повторно используют соседний обработчик и сохраняют его успешный путь, но теряют проверку владельца. Матрица разрешений делает это упущение видимым. Она также дает ревьюерам устойчивый контракт, когда позднее меняются роли или правила арендаторов.

Проверяйте авторизацию после нормализации входных данных. Приведение регистра, альтернативные форматы идентификаторов, повторяющиеся параметры запроса и вложенные ссылки на объекты могут направлять эквивалентные запросы по разным путям кода. Тестируйте прямой endpoint и любые маршруты пакетного импорта, которые выполняют ту же операцию. Если окончательную запись делает фоновый worker, передавайте в задачу контекст субъекта и арендатора, а не считайте worker всемогущим доверенным пользователем.

Фиксируйте ожидаемое решение и правило политики, которое его выдало, но не раскрывайте в логах приватные данные объектов. Полезный сбой называет класс субъекта, действие, класс объекта и ожидаемый статус. Он не выгружает токен доступа или полную запись. Такие подтверждения помогают ревьюеру отличить сломанную тестовую фикстуру от настоящего изменения привилегий.

Репетиция миграции измеряет блокировки и обратимость

Пусть политика ветки остается главной
Экспортируйте сгенерированный код в репозиторий, где существующая политика слияния примет окончательное решение.

Проверка миграции должна применить каждое предложенное изменение схемы к копии, похожей на production, запустить проверки совместимости и до слияния зафиксировать длительность, блокировки и поведение отката. Миграция, успешная на пустой тестовой базе данных, доказывает очень мало.

Используйте обезличенный снимок или сгенерированный набор данных с похожими размерами таблиц, индексами, ограничениями и перекосом распределения. Точные данные production не должны попадать в инфраструктуру pull request. Цель - воссоздать рабочую нагрузку без копирования персональных или конфиденциальных записей.

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

Записывайте подтверждения в машиночитаемом результате:

{"migration":"20260727_add_project_state","apply_ms":18420,"max_lock_ms":310,"old_app_probe":"pass","new_app_probe":"pass","down":"pass"}

Задавайте пороги для каждой базы данных и класса таблиц. Блокировка на 300 миллисекунд может быть безвредна для одной таблицы и разрушительна для другой. Ревьюеры должны видеть выбранный лимит рядом с измеренным результатом, а также версию базы данных, использованную в репетиции.

Для PostgreSQL проверяйте операции, которые переписывают таблицу, валидируют ограничение или строят индекс с блокировкой записей. Предпочитайте изменения по схеме expand and contract: добавьте новую форму, разверните код, который умеет работать с обеими формами, выполните backfill контролируемыми пакетами, переключите чтения, затем удалите старую форму в следующем изменении. Дополнительный pull request дешевле импровизации во время сбоя.

Не для каждой миграции возможна безопасная операция down. Удаление столбца теряет данные, а обращение преобразования может быть неоднозначным. В таких случаях проверка должна требовать процедуру восстановления вперед и проверенную точку восстановления из резервной копии. Называть необратимую миграцию «безопасной для отката» только потому, что есть down-файл, нечестно.

Проверяйте повторы и частичный сбой. Развертывание может остановиться после создания индекса, но до записи миграции как завершенной, и следующая попытка не должна портить состояние или навсегда завершаться ошибкой. Прервите репетицию на контролируемой границе, запустите ее снова и убедитесь, что схема и журнал миграций согласованы. Для долгого backfill докажите, что пакеты продолжаются с сохраненного курсора и что повторный запуск пакета не дублирует и не стирает данные.

Проверяйте влияние на диск и репликацию наряду с затраченным временем. Переписывание таблицы может потреблять временное место, увеличивать журналы предзаписи и задерживать реплики после того, как основная операция выглядит завершенной. Проверке не нужен идеальный прогноз production, но она должна записывать эти величины для набора данных репетиции и сравнивать их с лимитами, выбранными владельцем базы данных. Без таких подтверждений быстрая локальная миграция все равно может исчерпать том production.

Проверка отката должна запускать путь восстановления

Дайте ревьюерам настоящий дифф
Koder.ai экспортирует исходный код, чтобы ваш репозиторий мог запускать обязательные проверки перед слиянием.

Проверка отката должна развернуть кандидата в изолированной среде, создать репрезентативное состояние, запустить поддерживаемый способ отката и доказать, что предыдущая версия по-прежнему правильно обслуживает чтения и записи. Написанный план отката не равен проверке.

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

Практичная последовательность:

  1. Разверните текущий коммит main и создайте репрезентативные записи.
  2. Обновите приложение до артефакта pull request и пройдите измененные пути.
  3. Создайте новые записи в обновленном состоянии.
  4. Восстановите предыдущий артефакт или снимок через задокументированный инструмент управления.
  5. Запустите проверки чтения, записи, очереди и фоновых задач.

Проверка должна сохранять идентификаторы артефактов, идентификаторы снимков, временные метки и результаты проверок. Она не должна сохранять учетные данные или скопированные данные клиентов. Измеряйте время восстановления как подтверждение для собственной операционной цели, а не как универсальное обещание.

Снимки помогают только тогда, когда кто-то доказывает, что в них есть все необходимое приложению. Файлы, объектное хранилище, состояние очереди, изменения схемы и внешние побочные эффекты могут находиться вне снимка сервера. Перечислите эти границы в результате. Уже отправленный платеж, электронное письмо или webhook нельзя вернуть восстановлением базы данных.

Сделайте проверку отката сильнее, чем проверка состояния. Прочитайте запись, созданную до обновления, прочитайте запись, созданную после него, обновите обе, где совместимость это допускает, и обработайте задачу очереди, созданную каждой версией приложения. Сравнивайте видимый пользователю результат, а не только коды статуса. Сервер, который возвращает 200, но отбрасывает новое поле или неверно читает enum, не восстановился.

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

Koder.ai поддерживает экспорт исходного кода, развертывание и хостинг, снимки и откат, поэтому приложения, созданные там, могут использовать эти конкретные артефакты в данной проверке вместо того, чтобы считать восстановление абзацем в pull request. То же правило действует на любой платформе: запустите инструмент восстановления и проверьте восстановленное приложение.

Одна обязательная проверка должна сводить все семь

Окончательное решение о слиянии должно требовать одну стабильную проверку политики, которая подтверждает семь базовых результатов для точного head-коммита. Имена отдельных задач меняются, задачи матрицы множатся, а необязательные пути пропускают работу. Небольшой агрегатор не дает защите ветки разойтись с политикой.

Пусть каждая проверка выдает подписанный или подтвержденный платформой результат с коммитом, версией политики, исходом и расположением подтверждений. Агрегатор отклоняет отсутствующие, устаревшие, нейтральные и отмененные результаты. Он никогда не должен делать вывод об успехе из задачи, которая не сообщила результат.

{
  "commit": "abc123",
  "policy": "merge-gates-v3",
  "results": {
    "tests": "pass",
    "codeql": "pass",
    "dependency_review": "pass",
    "secret_scan": "pass",
    "authorization": "pass",
    "migration_rehearsal": "not_applicable",
    "rollback_verification": "pass"
  },
  "decision": "allow"
}

Определите узкий путь исключений, потому что случаются экстренные ситуации. Требуйте названного сопровождающего, второго одобряющего, письменную причину, срок действия и задачу для последующих действий. Не позволяйте агенту запрашивать или одобрять собственное исключение. Сообщайте об исключениях там же, где публикуются обычные результаты проверок, чтобы они оставались видимыми после завершения инцидента.

Эти проверки добавят минуты к некоторым pull request и гораздо больше времени к изменениям миграций. Это приемлемо, когда время покупает конкретные подтверждения. Запускайте быстрые проверки раньше, отменяйте замененные коммиты, кэшируйте доверенные входные данные сборки и резервируйте полную репетицию среды для подходящих путей. Не ослабляйте проверку лишь для того, чтобы быстрее сделать панель зеленой.

Начните с наблюдаемости текущего поведения. Поместите все семь имен в один файл политики, свяжите каждое с обязательным результатом и заставьте пропущенную работу объяснять себя. Первый pull request от агента, который не сможет выдать такую запись, обнаружит дыру в системе поставки раньше, чем в production.

FAQ

Нужны ли для pull request от агентов более строгие правила, чем для pull request от людей?

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

Может ли ревьюер вручную обойти не пройденную проверку слияния?

Да, но только через узкое, зафиксированное исключение с двумя ответственными людьми, причиной и сроком действия. Агент, создавший изменение, никогда не должен одобрять собственное исключение.

Означает ли успешная проверка CodeQL, что pull request безопасен?

Нет. Это означает, что выбранные запросы не нашли блокирующих результатов в коде, который CodeQL успешно проанализировал. Для зависимостей, авторизации во время выполнения, секретов, конфигурации и операционного восстановления нужны отдельные подтверждения.

Что делать, если обязательный сканер недоступен?

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

Должно ли сканирование секретов проверять удаленные коммиты?

Нужно проверить весь диапазон коммитов pull request. Секрет, который добавили и затем удалили, все равно остается в истории, поэтому его следует отозвать или сменить до принятия очищенного изменения.

Как тестировать авторизацию в pull request?

Вызывайте реальные обработчики сервиса с матрицей идентичностей, ролей, арендаторов, объектов и действий. Добавьте случаи отказа и смену владельца объекта: успешный вход и скрытые элементы интерфейса не доказывают авторизацию на сервере.

Нужен ли сценарий down для каждой миграции базы данных?

Нет. Некоторые разрушительные изменения нельзя честно отменить. Вместо этого потребуйте проверенную процедуру восстановления вперед или восстановления из резервной копии и пометьте изменение как необратимое.

Чем план отката отличается от проверки отката?

Планирование описывает предполагаемые шаги восстановления. Проверка запускает эти шаги для артефакта-кандидата и репрезентативного состояния, затем фиксирует, может ли предыдущая версия по-прежнему правильно читать и записывать данные.

Как не дать семи проверкам замедлить каждый pull request?

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

Какой результат должна требовать защита ветки?

Требуйте один стабильный результат политики, который объединяет все семь проверок для точного head-коммита. Он должен отклонять отсутствующие, устаревшие, пропущенные, отмененные и нейтральные результаты, а не считать их успешными по предположению.

Похожие статьи