Модуль 2 · CI/CD · урок 6 из 14
GitHub Action для Codex
Основной код агентства в GitLab, но часть клиентских проектов живёт на GitHub. Там у Codex есть готовая обёртка — openai/codex-action@v1. Она ставит CLI, поднимает прокси для ключа API и запускает codex exec с заданными правами. В уроке — как её подключить, какие входы важны и какие настройки безопасности нельзя оставлять по умолчанию без понимания.
Что делает action
Action решает три задачи, которые в GitLab мы решали руками:
- Устанавливает Codex CLI нужной версии.
- Запускает прокси Responses API, если передан ключ. Ключ не выставляется переменной окружения для всего job.
- Запускает
codex execс вашим промптом и выбранной стратегией безопасности.
Требования: раннер на Linux или macOS (для Windows обязателен safety-strategy: unsafe), ключ в секретах репозитория (например, OPENAI_API_KEY), код уже получен через actions/checkout.
Минимальный workflow: ревью PR
Пример по мотивам документации. Codex читает PR, а отдельный job публикует итог комментарием.
name: Codex pull request review
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
codex:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
final_message: ${{ steps.run_codex.outputs.final-message }}
steps:
- uses: actions/checkout@v5
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge
fetch-depth: 0
persist-credentials: false
- name: Run Codex
id: run_codex
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/review.md
codex-version: "0.163.0"
sandbox: read-only
output-file: codex-output.md
post_feedback:
runs-on: ubuntu-latest
needs: codex
if: needs.codex.outputs.final_message != ''
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/github-script@v7
env:
CODEX_FINAL_MESSAGE: ${{ needs.codex.outputs.final_message }}
with:
github-token: ${{ github.token }}
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: process.env.CODEX_FINAL_MESSAGE,
});Главное в этой схеме — разделение прав. Job с Codex может только читать репозиторий (contents: read) и не хранит учётные данные Git (persist-credentials: false). Job, который пишет комментарий, получает права на запись, но не получает ключ OpenAI и не запускает агента.
Входы action
| Вход | Зачем |
|---|---|
prompt / prompt-file |
Задача: текст прямо в workflow или файл в репозитории. Только одно из двух. Промпты удобно хранить в .github/codex/prompts/ |
codex-args |
Дополнительные флаги codex exec: JSON-массив (["--ephemeral"]) или строка в стиле shell. Аргументы, ослабляющие защиту (альтернативный профиль конфигурации, дополнительные каталоги для записи, обход песочницы), action отклоняет |
model, effort |
Модель и уровень рассуждений. Пусто — значения по умолчанию |
sandbox |
read-only, workspace-write, danger-full-access |
output-file |
Записать итоговое сообщение в файл для артефактов |
codex-version |
Закрепить версию CLI. Пусто — последняя опубликованная |
codex-home |
Каталог конфигурации Codex. Считается доверенным: не указывайте каталог из проверяемой ветки |
safety-strategy |
Привилегии самого процесса Codex (ниже) |
allow-users, allow-bots, allow-bot-users |
Кто может запускать action |
Выход action — final-message, последнее сообщение Codex.
В актуальном action.yml репозитория openai/codex-action есть входы, которых пока нет на странице документации: permission-profile (профиль прав, например :workspace, вместо устаревающего sandbox), output-schema и output-schema-file для ответа по схеме, working-directory. Перед использованием сверьтесь с action.yml той версии, которую закрепили. Если нужна структура ответа, а нового входа в вашей версии нет, передайте --output-schema через codex-args.
Стратегии безопасности
Вход safety-strategy управляет тем, с какими привилегиями работает процесс Codex на раннере.
drop-sudo(по умолчанию) — перед запуском у пользователя отбираетсяsudo, необратимо для всего job. Это защищает секреты в памяти.unprivileged-userвместе сcodex-user— Codex работает от отдельного пользователя. Ему нужны права на чтение и запись рабочей копии.read-only— Codex не меняет файлы и не ходит в сеть, но работает от пользователя по умолчанию, у которого на раннере, скорее всего, естьsudo. Документация прямо предупреждает: одногоread-onlyдля защиты секретов недостаточно.unsafe— без ограничений. Обязателен на Windows, недопустим на раннерах, которые делят несколько команд.
Почему это важно. На раннерах GitHub по умолчанию работает sudo без пароля. В документации action разобран пример: даже при доступе только на чтение и без сети пользователь с sudo может достать ключ через файловую систему procfs. Поэтому не трогайте drop-sudo без веской причины.
safety-strategy и sandbox — разные уровни. Первый ограничивает процесс Codex целиком, второй — команды, которые запускает агент. Нужны оба.
Кто может запускать
По умолчанию action запускается только пользователями с правом записи в репозиторий. Расширить список можно через allow-users, разрешить бота github-actions[bot] — через allow-bots, другие доверенные боты перечисляются явно в allow-bot-users (звёздочка там не поддерживается). Делайте это осторожно. Значение allow-users: "*" открывает ваш ключ всему интернету: документация action описывает злоупотребления, когда посторонние заводят issue, чтобы заставить Codex работать на них за ваш счёт.
Недоверенный ввод
Промпт часто собирают из контекста PR: заголовок, описание, коммиты. Всё это — потенциальный канал prompt injection. Документация action перечисляет типичные места:
- описание PR: инструкции прячут в HTML-комментарий, который не виден в интерфейсе, но виден модели;
- сообщения отдельных коммитов, которые никто не читает;
- файлы инструкций из ветки PR —
AGENTS.md,AGENTS.override.md: если Codex работает с содержимым PR, эти файлы тоже недоверенные; - скриншоты и другие медиа.
Отдельная ловушка — shell-инъекция в самом workflow. GitHub подставляет выражения ${{ ... }} в скрипт до запуска shell. Если вставить так название ветки или заголовок issue, специально составленное значение выполнится как команда. Передавайте такие значения через env и используйте в кавычках:
- name: Safe shell usage
env:
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
git fetch origin "$PR_BASE_REF"Ещё три правила из документации
- Codex — последний шаг job. После агента с широкими правами состояние раннера непредсказуемо: могли остаться процессы, измениться файлы других actions или Git-хуки. Результат передавайте в следующий job через outputs или артефакты.
- Закрепляйте
codex-version. Воспроизводимость важнее свежести. - Ротация ключа. Если есть подозрение, что ключ попал в логи или вывод, отзывайте его сразу.
Встроенное ревью без workflow
Для ревью PR на GitHub workflow не обязателен. У Codex есть встроенная интеграция: подключаете репозиторий, включаете Automatic review в настройках ревью или пишете в PR комментарий @codex review. Codex публикует обычное ревью GitHub и отмечает только проблемы приоритетов P0 и P1. Правила ревью берутся из раздела ## Code Review Rules в AGENTS.md. Подробно — в уроке про ревью и в документации.
Action нужен, когда вам важен контроль: свой промпт, своя схема ответа, своё место публикации или задача, отличная от ревью, — например, автопочинка упавшего CI из следующего урока.
Попробуйте сами
10–15 мин на рабочем месте- В тестовом репозитории на GitHub добавьте секрет
OPENAI_API_KEYи workflow из урока. Создайте файл.github/codex/prompts/review.mdс тремя-пятью пунктами, на что смотреть в ревью. - Откройте PR и убедитесь, что комментарий появился. Проверьте в логе job, что Codex работал с
drop-sudo. - Найдите в своих workflow места, где
${{ github.event... }}подставляется прямо вrun:, и перенесите эти значения вenv.
Коротко
openai/codex-action@v1ставит CLI, прячет ключ за прокси и запускаетcodex exec.- Job с Codex — только чтение. Публикация результата — отдельный job без ключа.
safety-strategy: drop-sudoне отключайте.read-onlyсекреты не защищает.- Запускать могут только пользователи с правом записи.
allow-users: "*"— открытый ключ. - Текст PR, коммиты и AGENTS.md из ветки PR — недоверенный ввод.