codex exec 与交互模式的区别
在把 Codex 接入 CI 之前,理解两个入口的本质区别非常重要。交互模式(codex)是为人工使用设计的,而 codex exec 是为机器调用设计的。
| 特性 | 交互模式 (codex) |
非交互模式 (codex exec) |
|---|---|---|
| 启动方式 | 打开全屏终端 UI | 接受参数后直接执行 |
| 审批对话框 | 会弹出需要人工确认的对话框 | 无任何交互提示,完全自动 |
| 退出方式 | 需要手动退出 | 任务完成后自动退出 |
| 退出码 | 不适用 | 成功返回 0,失败返回非零 |
| 斜杠命令 | 支持 /model、/init 等 |
不支持,用 CLI 参数代替 |
| 适用场景 | 日常开发、探索代码库 | CI/CD、脚本、定时任务 |
codex exec 的可靠退出码是接入 CI 的关键。任务成功时返回 0,配合 set -e 或 GitHub Actions 的默认失败检测,任何执行失败都能立即中止流水线。
前置条件
在 CI 环境中使用 Codex CLI 之前,确保以下条件已满足:
-
Node.js 版本:Codex CLI 要求 Node.js 22 或更高版本。大多数 CI 镜像自带 Node.js,但需确认版本满足要求。
$ node --version # 需要 v22.0.0 或更高 -
API Key 设置为 CI Secrets:这是最重要的安全要求。绝对不要把
OPENAI_API_KEY明文写在任何配置文件或代码中。 -
安装 @openai/codex:在 CI 步骤中通过
npm install -g @openai/codex安装,或在package.json中作为 devDependency 引入。
正确设置 API Key 为 Secrets
在 GitHub 仓库中设置 Secret 的路径:仓库 → Settings → Secrets and variables → Actions → New repository secret。
| 平台 | 设置入口 | 引用方式 |
|---|---|---|
| GitHub Actions | Settings → Secrets and variables → Actions | ${{ secrets.OPENAI_API_KEY }} |
| GitLab CI | Settings → CI/CD → Variables(勾选 Masked) | $OPENAI_API_KEY |
| CircleCI | Project Settings → Environment Variables | $OPENAI_API_KEY |
API Key 一旦泄露到日志或代码仓库,应立即在 OpenAI 控制台吊销并生成新 Key。建议为 CI/CD 场景单独创建一个 API Key,方便独立追踪用量和撤销。
GitHub Actions 基础配置
下面是一个完整的 GitHub Actions Workflow 文件,演示如何在 CI 中安装并运行 Codex CLI:
name: Codex Automation Task
on:
pull_request:
types: [opened, synchronize]
jobs:
codex-task:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 2 # 获取足够的提交历史
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Codex CLI
run: npm install -g @openai/codex
- name: Run Codex Task
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
codex exec --model gpt-4.1-mini \
"分析本次 PR 中的代码变更,列出潜在的 Bug、性能问题和代码风格问题"
几个关键点说明:
fetch-depth: 2:确保 CI 能拉取到足够的提交历史,让 Codex 可以使用git diff分析变更。permissions: contents: write:如果任务需要写入文件(如更新 CHANGELOG),需要赋予写权限。env块:这是注入 API Key 的正确位置,Key 来自 Secrets,不会出现在日志中。
3 个实战任务 YAML 示例
任务一:自动生成 CHANGELOG
每次合并到 main 分支时,自动分析本次提交的变更,生成 CHANGELOG 条目并追加到文件。
name: Auto Generate CHANGELOG
on:
push:
branches: [main]
jobs:
changelog:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install -g @openai/codex
- name: Generate CHANGELOG entry
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
codex exec --model gpt-4.1-mini "读取 git diff HEAD~1 的内容,用中文生成一条简洁的 CHANGELOG 条目(格式:## vX.X.X - YYYY-MM-DD 开头,后跟变更列表),追加到 CHANGELOG.md 末尾,不要删除已有内容"
- name: Commit CHANGELOG update
run: |
git config --global user.email "[email protected]"
git config --global user.name "Codex CI Bot"
git add CHANGELOG.md
git diff --staged --quiet || git commit -m "chore: auto-update CHANGELOG [skip ci]"
git push
注意提交信息末尾加了 [skip ci],防止 CHANGELOG 更新本身再次触发 CI,形成无限循环。
任务二:PR 自动代码审查
每次新开或更新 PR 时,Codex 自动分析变更并将审查意见以评论形式发布到 PR 上。
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
ai-review:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install -g @openai/codex
- name: Run AI code review
id: review
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
# 获取 PR 变更内容并存入临时文件
git diff origin/${{ github.base_ref }}...HEAD > /tmp/pr_diff.txt
# 让 Codex 审查变更,结果写入文件
codex exec --model gpt-4.1 \
"读取 /tmp/pr_diff.txt 文件内容(这是一个 PR 的 git diff),以中文撰写代码审查报告,关注:1) 潜在 Bug 和边界情况,2) 安全漏洞,3) 性能问题,4) 代码可读性建议。将报告写入 /tmp/review_result.txt"
# 将报告内容存为环境变量
REVIEW_CONTENT=$(cat /tmp/review_result.txt)
echo "REVIEW_CONTENT<> $GITHUB_ENV
echo "$REVIEW_CONTENT" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Post review comment
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 🤖 AI 代码审查\n\n${process.env.REVIEW_CONTENT}`
})
任务三:单元测试补全
识别项目中缺少测试的函数,自动生成测试用例。此任务适合在 PR 合并后或定期运行。
name: Auto Complete Unit Tests
on:
workflow_dispatch: # 手动触发,也可改为 schedule
schedule:
- cron: '0 2 * * 1' # 每周一凌晨 2 点运行
jobs:
test-completion:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm install -g @openai/codex
- name: Generate missing unit tests
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
codex exec --model gpt-4.1 \
"扫描 src/ 目录下所有 .js 和 .ts 文件,找出其中导出的函数或类,检查 __tests__ 或 *.test.* 文件中是否已有对应的测试用例。对于缺少测试的导出函数,生成对应的 Jest 单元测试,测试文件放在与源文件同级的 __tests__ 目录下,命名为 [原文件名].test.js。每个测试至少包含正常路径和边界情况各一个用例。"
- name: Create PR with new tests
run: |
git config --global user.email "[email protected]"
git config --global user.name "Codex CI Bot"
git checkout -b feat/auto-tests-$(date +%Y%m%d)
git add '**/__tests__/*.test.*'
git diff --staged --quiet || \
git commit -m "test: auto-generate missing unit tests" && \
git push origin HEAD && \
gh pr create --title "test: auto-generated unit tests" \
--body "由 Codex CI Bot 自动生成的单元测试,请审查后合并。"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GitLab CI 适配
GitLab CI 与 GitHub Actions 的核心逻辑完全相同,主要差异在于配置文件格式和 Secrets 注入方式。
# GitLab CI — Codex 自动代码审查
stages:
- ai-review
variables:
NODE_VERSION: "22"
codex-code-review:
stage: ai-review
image: node:22-slim
only:
- merge_requests
before_script:
- npm install -g @openai/codex
- git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
script:
- git diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME...HEAD > /tmp/mr_diff.txt
- codex exec --model gpt-4.1-mini
"读取 /tmp/mr_diff.txt 的 git diff 内容,识别潜在 Bug、安全问题和性能瓶颈,用中文生成审查报告写入 /tmp/review.txt"
- cat /tmp/review.txt
variables:
OPENAI_API_KEY: $OPENAI_API_KEY # 从 CI/CD Variables 读取
artifacts:
paths:
- /tmp/review.txt
expire_in: 1 week
codex-changelog:
stage: ai-review
image: node:22-slim
only:
- main
before_script:
- npm install -g @openai/codex
- git config --global user.email "[email protected]"
- git config --global user.name "Codex CI"
script:
- codex exec --model gpt-4.1-mini
"根据 git diff HEAD~1 生成 CHANGELOG 条目并追加到 CHANGELOG.md"
- git add CHANGELOG.md
- git diff --staged --quiet || git commit -m "chore: update CHANGELOG [skip ci]"
- git push https://ci-token:$CI_JOB_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git HEAD:main
variables:
OPENAI_API_KEY: $OPENAI_API_KEY
| 差异点 | GitHub Actions | GitLab CI |
|---|---|---|
| 配置文件 | .github/workflows/*.yml |
.gitlab-ci.yml(根目录) |
| Secrets 引用 | ${{ secrets.KEY }} |
$KEY(需在 Variables 中设置) |
| PR/MR 事件 | on: pull_request |
only: - merge_requests |
| 内置 Token | secrets.GITHUB_TOKEN |
$CI_JOB_TOKEN |
| 仓库信息 | github.repository |
$CI_PROJECT_PATH |
在 GitLab CI 的 Variables 设置中,建议勾选 Masked 选项,确保 OPENAI_API_KEY 的值不会出现在 Job 日志中。同时勾选 Protected 可限制该变量只在受保护分支(如 main)上可用。
安全注意事项
将 AI 工具接入 CI/CD 需要特别注意安全性,以下是最重要的几点:
API Key 管理
- 使用 Secrets 存储:永远不要把 API Key 写在代码、配置文件或 YAML 中。
- CI 专用 Key:为 CI/CD 创建独立的 API Key,便于独立监控用量和一键吊销。
- 最小权限原则:在 OpenAI 控制台检查是否可以为 Key 设置用量上限,防止意外超支。
- 定期轮换:建议每 90 天轮换一次 CI/CD 使用的 API Key。
CI 中的沙箱模式设置
在 CI 环境中,Codex 的默认沙箱模式是 workspace-write,这意味着它只能读写工作区内的文件,不能修改系统文件。对于大多数 CI 任务,这个默认设置已经足够安全。
# 只读模式:Codex 只能读取文件,不能做任何修改
# 适合纯审查任务,确保 CI 不会意外修改任何代码
codex exec --sandbox-mode read-only \
"分析 src/ 目录下所有文件,识别可能的安全漏洞"
避免意外修改
- 明确任务边界:在 Prompt 中清楚说明允许修改哪些文件,如 "只修改 CHANGELOG.md,不要修改其他文件"。
- 审查提交内容:在 Commit 步骤前加入
git diff --staged输出,让 CI 日志记录实际变更内容。 - PR 而非直推:对于测试生成等任务,让 Codex 创建 PR 而非直接推送到主分支,人工审查后再合并。
在 CI 中运行 codex exec 时,任务的 Prompt 越具体越好。模糊的指令可能导致 Codex 修改超出预期范围的文件。始终通过 git diff 或 git status 检查实际变更后再提交。
成本控制
CI/CD 中的 API 调用会累积成本,合理的配置可以显著降低费用:
选择合适的模型
| 模型 | 相对成本 | 推荐场景 |
|---|---|---|
gpt-4.1 |
高 | 复杂代码审查、需要深度理解的任务 |
gpt-4.1-mini |
低(约为 gpt-4.1 的 1/20) | CHANGELOG 生成、简单格式化、日常 PR 检查 |
gpt-4.1-nano |
极低 | 简单文本处理、快速分类任务 |
# 对于简单的 CHANGELOG 生成,mini 模型已经足够
codex exec --model gpt-4.1-mini \
"根据 git diff HEAD~1 生成简洁的 CHANGELOG 条目"
# 对于需要深度分析的安全审查,使用完整模型
codex exec --model gpt-4.1 \
"详细分析这次 PR 中的安全漏洞,包括 SQL 注入、XSS 等"
优化触发条件
- 按分支过滤:使用
branches筛选只在重要分支(如main、develop)上运行。 - 按文件路径过滤:使用
paths限制只在特定目录有变更时才触发。 - 手动触发:对于昂贵的任务(如完整测试生成),使用
workflow_dispatch手动触发而非自动触发。
on:
push:
branches: [main, develop]
paths:
- 'src/**' # 只有 src/ 有变更才触发
- '!src/**/*.md' # 排除文档文件
常见报错与排查
401 Unauthorized — API Key 无效或未设置
最常见的错误。排查步骤:
- 确认 Secret 名称拼写正确(区分大小写),应为
OPENAI_API_KEY。 - 在 YAML 的
env块中确认已正确引用:OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}。 - 检查 Secret 是否设置在正确的层级(仓库级 vs 组织级)。
- 在 OpenAI 控制台验证 Key 是否仍有效,未过期,余额充足。
执行超时 — CI Job 长时间未完成
Codex 执行复杂任务可能耗时较长。解决方案:
- 在 GitHub Actions 中设置
timeout-minutes: 10限制单个 Step 时间。 - 简化任务 Prompt,将大任务拆分为多个小任务分步执行。
- 使用
--model gpt-4.1-mini提升响应速度。
环境变量未设置 — codex 找不到 API Key
Codex 会自动从环境变量 OPENAI_API_KEY 读取 Key。如果报告找不到 Key:
- 确认
env块在run步骤同级,不是在jobs或steps级别错误嵌套。 - 添加调试步骤
run: echo "Key is set: ${{ secrets.OPENAI_API_KEY != '' }}"验证 Secret 是否非空(不会泄露实际值)。
git diff 返回空 — 无法分析变更
在 CI 中默认 checkout 只拉取最近一次提交(fetch-depth: 1),导致 git diff HEAD~1 失败。解决方案:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # 拉取最近 2 个提交,支持 HEAD~1
# 或者 fetch-depth: 0 拉取全部历史
Node.js 版本过低 — 安装失败
Codex CLI 需要 Node.js 22+。使用 actions/setup-node@v4 明确指定版本:
- uses: actions/setup-node@v4
with:
node-version: '22' # 明确指定,不依赖默认版本