Codex CLI 接入 CI/CD:GitHub Actions 与自动化实战

codex exec 是专为自动化设计的非交互入口——它接受任务指令、执行后退出,返回码可供脚本判断。把它接入 GitHub Actions 或 GitLab CI,可以实现 AI 驱动的代码审查、CHANGELOG 自动生成、测试用例补全等任务,无需人工干预。

codex exec 与交互模式的区别

在把 Codex 接入 CI 之前,理解两个入口的本质区别非常重要。交互模式(codex)是为人工使用设计的,而 codex exec 是为机器调用设计的。

特性 交互模式 (codex) 非交互模式 (codex exec)
启动方式 打开全屏终端 UI 接受参数后直接执行
审批对话框 会弹出需要人工确认的对话框 无任何交互提示,完全自动
退出方式 需要手动退出 任务完成后自动退出
退出码 不适用 成功返回 0,失败返回非零
斜杠命令 支持 /model/init 不支持,用 CLI 参数代替
适用场景 日常开发、探索代码库 CI/CD、脚本、定时任务
i

codex exec 的可靠退出码是接入 CI 的关键。任务成功时返回 0,配合 set -e 或 GitHub Actions 的默认失败检测,任何执行失败都能立即中止流水线。

前置条件

在 CI 环境中使用 Codex CLI 之前,确保以下条件已满足:

  1. Node.js 版本:Codex CLI 要求 Node.js 22 或更高版本。大多数 CI 镜像自带 Node.js,但需确认版本满足要求。
    检查 Node.js 版本
    $ node --version
    # 需要 v22.0.0 或更高
  2. API Key 设置为 CI Secrets:这是最重要的安全要求。绝对不要OPENAI_API_KEY 明文写在任何配置文件或代码中。
  3. 安装 @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:

.github/workflows/codex-task.yml
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 条目并追加到文件。

.github/workflows/changelog.yml
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 上。

.github/workflows/pr-review.yml
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 合并后或定期运行。

.github/workflows/test-completion.yml
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.yml
# 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
i

在 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 diffgit status 检查实际变更后再提交。

成本控制

CI/CD 中的 API 调用会累积成本,合理的配置可以显著降低费用:

选择合适的模型

模型 相对成本 推荐场景
gpt-4.1 复杂代码审查、需要深度理解的任务
gpt-4.1-mini 低(约为 gpt-4.1 的 1/20) CHANGELOG 生成、简单格式化、日常 PR 检查
gpt-4.1-nano 极低 简单文本处理、快速分类任务
在 CI 中使用低成本模型
# 对于简单的 CHANGELOG 生成,mini 模型已经足够
codex exec --model gpt-4.1-mini \
  "根据 git diff HEAD~1 生成简洁的 CHANGELOG 条目"

# 对于需要深度分析的安全审查,使用完整模型
codex exec --model gpt-4.1 \
  "详细分析这次 PR 中的安全漏洞,包括 SQL 注入、XSS 等"

优化触发条件

  • 按分支过滤:使用 branches 筛选只在重要分支(如 maindevelop)上运行。
  • 按文件路径过滤:使用 paths 限制只在特定目录有变更时才触发。
  • 手动触发:对于昂贵的任务(如完整测试生成),使用 workflow_dispatch 手动触发而非自动触发。
按文件路径过滤触发条件
on:
  push:
    branches: [main, develop]
    paths:
      - 'src/**'        # 只有 src/ 有变更才触发
      - '!src/**/*.md'  # 排除文档文件

常见报错与排查

401 Unauthorized — API Key 无效或未设置

最常见的错误。排查步骤:

  1. 确认 Secret 名称拼写正确(区分大小写),应为 OPENAI_API_KEY
  2. 在 YAML 的 env 块中确认已正确引用:OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
  3. 检查 Secret 是否设置在正确的层级(仓库级 vs 组织级)。
  4. 在 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 步骤同级,不是在 jobssteps 级别错误嵌套。
  • 添加调试步骤 run: echo "Key is set: ${{ secrets.OPENAI_API_KEY != '' }}" 验证 Secret 是否非空(不会泄露实际值)。
git diff 返回空 — 无法分析变更

在 CI 中默认 checkout 只拉取最近一次提交(fetch-depth: 1),导致 git diff HEAD~1 失败。解决方案:

设置 fetch-depth
- 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 明确指定版本:

指定 Node.js 版本
- uses: actions/setup-node@v4
  with:
    node-version: '22'  # 明确指定,不依赖默认版本
🌿 在本地也想用 AI 增强 Git 工作流? 查看 Codex CLI Git 工作流指南:自动生成 Commit Message、起草 PR 描述、Pre-commit hook 代码审查。