
1. 为什么开通 Plus / Pro 后CI 还是跑不起来很多人开通 ChatGPT Plus 或 Pro、在网页里用上 Codex 之后第一反应是「我是不是可以全自动写代码了」。结果真把 Codex 生成的 TypeScript 代码推到 GitHubCI 直接红一片npm ci找不到 lock 文件、tsc报类型错误、测试在本地过、在 Actions 里挂。问题不在 Codex而在于你只把 Codex 当聊天工具没把它接进「可复现的流水线」。这篇要解决的就是这件事把 ChatGPT Plus / Pro 里的 Codex 能力落到一个真实 TypeScript 项目的 CI 与 GitHub Actions 里。核心检索词先摆出来——Codex 接入 GitHub Actions 的 TypeScript CI 实战它是什么就是让 Codex 帮你生成 workflow、调用脚本、修 CI 报错同时用一条统一的 Key/API 通道完成鉴权避免每个环节各配一套密钥。适合谁已经开通 Plus / Pro、手上有 TypeScript 仓库、想让 AI 参与持续集成而不是只写片段的开发者。我试过最省事的路径是本地用 Codex 生成代码和 workflow把模型调用统一走 TaoToken 的 API 通道再让 GitHub Actions 用同一个 Key 去跑校验脚本。这样本地和 CI 的鉴权行为一致出问题好定位。下面从环境准备一路写到一次真实流水线跑绿。先明确 Plus 与 Pro 在 Codex 上的差异避免你按 Pro 的预期去用 Plus能力项ChatGPT PlusChatGPT ProCodex 云任务额度基础额度更高额度与优先级并行会话有限更多并行会话长上下文处理标准增强大型重构任务适合小步提交适合长时间运行日常小步提交、单模块 CI 修复Plus 完全够用整仓重构、长时间 Agent 任务Pro 更稳。这个判断会直接影响你后面 workflow 里怎么切分任务。2. 前置准备TaoToken 统一 Key 与 Codex 调用通道在把 Codex 接进 CI 之前先把「鉴权」这件事收敛掉。否则你会在本地配一个 Key、在 Actions secrets 里再配一个、脚本里又硬编码一个最后 401 报错都不知道是哪一层。TaoToken 在这里的角色是统一 Key/API 通道本地脚本、Codex 调用、CI 校验都走同一个 Base URL 和同一把 Key。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址是 https://taotoken.net/api 这个不加 UTM。你需要去控制台生成 Key路径是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。本地环境先确认三件套node -v # 建议 18本文用 20 git --version npm -v然后安装 Codex CLI用于脚本化调用npm install -g openai/codex codex --version能输出版本号就说明 CLI 就绪。接下来配置统一通道。Codex CLI 支持通过环境变量指定 Base URL 和 Key我习惯写进项目根目录的.env.local记得加进.gitignore# .env.local —— 本地开发用不要提交 TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的Key CODEX_MODELgpt-5-codex注意这里三件套必须齐全Base URL Key Model ID。少任何一个Codex CLI 都会在请求阶段失败。Model ID 按你账号实际可用的填本文示例统一用gpt-5-codex占位你替换成控制台里列出的真实模型名即可。如果你用的是 Claude Code 这类工具做代码润色同样把 Base URL 指向https://taotoken.net/apiKey 用同一把模型 ID 换成对应 Claude 模型。这样本地所有 AI 调用都走一条通道CI 里只需要注入一个 secret。验证通道是否通curl -s https://taotoken.net/api/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY | head -c 300返回模型列表 JSON 就说明 Key 和 Base URL 都对。这一步别跳过后面 CI 报 401 十有八九是这里没通。3. 可复制配置Codex 调用脚本 GitHub Actions workflow这一节是全文的核心给你能直接抄的配置。分三块Codex 调用脚本、TypeScript 项目配置、GitHub Actions workflow。3.1 Codex 调用脚本scripts/codex-review.mjs这个脚本的作用是在 CI 里对改动的 TypeScript 文件做一次模型审查把结果输出到日志。它读取环境变量里的 Base URL 和 Key不硬编码。// scripts/codex-review.mjs import { readFileSync } from node:fs; import { execSync } from node:child_process; const BASE_URL process.env.TAOTOKEN_BASE_URL; const API_KEY process.env.TAOTOKEN_API_KEY; const MODEL process.env.CODEX_MODEL || gpt-5-codex; if (!BASE_URL || !API_KEY) { console.error(缺少 TAOTOKEN_BASE_URL 或 TAOTOKEN_API_KEY); process.exit(1); } // 取本次改动涉及的 ts 文件 const changed execSync(git diff --name-only HEAD~1 HEAD, { encoding: utf8 }) .split(\n) .filter((f) f.endsWith(.ts) || f.endsWith(.tsx)); if (changed.length 0) { console.log(没有 TypeScript 改动跳过审查); process.exit(0); } const snippets changed .map((f) // 文件: ${f}\n${readFileSync(f, utf8).slice(0, 4000)}) .join(\n\n); const body { model: MODEL, messages: [ { role: system, content: 你是 TypeScript 代码审查员只输出问题清单按严重程度排序。 }, { role: user, content: 审查以下改动\n\n${snippets} }, ], }; const res await fetch(${BASE_URL}/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${API_KEY}, }, body: JSON.stringify(body), }); if (!res.ok) { console.error(请求失败: ${res.status} ${await res.text()}); process.exit(1); } const data await res.json(); console.log( Codex 审查结果 ); console.log(data.choices?.[0]?.message?.content ?? 无返回内容);这个脚本的关键点Base URL 和 Key 全部来自环境变量本地和 CI 用同一套逻辑。git diff HEAD~1 HEAD在 Actions 里需要fetch-depth: 0才能拿到上一个 commit后面 workflow 会配。3.2 TypeScript 项目配置package.json里加几个脚本让 CI 和本地命令一致{ name: ts-ci-demo, type: module, scripts: { lint: tsc --noEmit, test: node --test test/, check: npm run lint npm test, codex:review: node scripts/codex-review.mjs }, devDependencies: { typescript: ^5.6.0, types/node: ^22.0.0 } }tsconfig.json开严格模式让 CI 能真正拦住类型问题{ compilerOptions: { target: ES2022, module: NodeNext, moduleResolution: NodeNext, strict: true, noUnusedLocals: true, noUnusedParameters: true, outDir: dist }, include: [src, test, scripts] }3.3 GitHub Actions workflow.github/workflows/ci.yml这是把上面所有东西串起来的文件name: TypeScript CI with Codex on: push: branches: [main] pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 with: fetch-depth: 0 - name: Setup Node.js uses: actions/setup-nodev4 with: node-version: 20 cache: npm - name: Install dependencies run: npm ci - name: Type check run: npm run lint - name: Run tests run: npm test - name: Codex review env: TAOTOKEN_BASE_URL: ${{ secrets.TAOTOKEN_BASE_URL }} TAOTOKEN_API_KEY: ${{ secrets.TAOTOKEN_API_KEY }} CODEX_MODEL: ${{ secrets.CODEX_MODEL }} run: npm run codex:review三个 secret 在仓库 Settings → Secrets and variables → Actions 里配TAOTOKEN_BASE_URL填https://taotoken.net/apiTAOTOKEN_API_KEY填你的 KeyCODEX_MODEL填模型 ID。这样 CI 里的鉴权和本地完全一致出问题只需要查一处。如果你用的是 Cline MCP 或 Codex 的auth.json方式同样把 Base URL、Key、Model ID 三件套写全不要只填 Key 漏掉 Base URL否则会走到默认端点导致鉴权失败。4. 验证请求本地跑通再到流水线跑绿配置写完别急着 push先在本地把整条链路走一遍。第一步装依赖并跑类型检查和测试npm ci npm run lint npm testnpm run lint走的是tsc --noEmit有类型错误会直接报文件和行号。npm test用 Node 内置测试运行器不需要额外框架。第二步本地跑 Codex 审查脚本。先确保.env.local已加载可以用node --env-file.env.localnode --env-file.env.local scripts/codex-review.mjs如果改动里有.ts文件你会看到类似输出 Codex 审查结果 1. [高] src/routes/todos.ts:42 未处理 id 非数字的情况Number() 会返回 NaN 2. [中] src/types.ts:8 createdAt 用 Date 类型序列化后是字符串建议统一看到这个就说明 Base URL、Key、Model ID 三件套都通了请求路径正确。第三步提交并触发 Actionsgit add . git commit -m ci: add codex review workflow git push origin main打开仓库的 Actions 页面你会看到TypeScript CI with Codex这个 workflow 依次执行checkout带完整历史→ setup-node → npm ci → tsc → test → codex review。全部打绿勾说明流水线跑通。一次真实运行里我遇到npm ci失败原因是本地用了npm install生成了 lock 文件但没提交。补上package-lock.json后重跑就过了。这也是为什么 workflow 里坚持用npm ci而不是npm install——它强制要求 lock 文件存在且一致能提前暴露依赖漂移。5. 本篇常见报错排查这一节按真实报错来你对照日志找。401 Unauthorized / invalid api key九成是 Key 没注入或 Base URL 写错。检查 Actions 里 secret 名字是否和 workflow 里${{ secrets.XXX }}完全一致大小写敏感。再确认TAOTOKEN_BASE_URL是https://taotoken.net/api不要多写/v1路径拼接由脚本负责。本地报 401 就echo $TAOTOKEN_API_KEY看变量是否为空。local proxy failed / connection refused脚本请求的地址不通。先curl一下 Base URL 确认网络可达再检查是不是把 Base URL 写成了带尾斜杠的形式导致//v1双斜杠。统一去掉尾斜杠。reading choices of undefineddata.choices取不到说明返回体结构和你预期不一致。通常是请求失败但没检查res.ok或者模型名写错返回了错误对象。脚本里已经先判断res.ok如果还报这个打印完整data看实际返回。OAuth / token expired如果你混用了 OAuth 登录态和 API Key会出现鉴权方式冲突。CI 环境统一用 API Key不要依赖交互式登录。Codex CLI 在 CI 里也应通过环境变量传 Key而不是走浏览器授权。tsc 报 noUnusedLocalsCodex 生成的代码常带未使用导入。这是好事说明严格模式在起作用。让 Codex 修「删除 src 下所有未使用的导入保持 noUnusedLocals 通过」然后本地npm run lint复验。Actions 里 git diff 拿不到改动fetch-depth: 0没配。默认浅克隆只有一个 commitHEAD~1不存在。workflow 里已经加了别删。npm ci 报 lock 文件不同步本地npm install后忘了提交package-lock.json。提交它或者用npm ci前先npm install重新生成再提交。排查顺序建议固定先看 secret 是否注入 → 再 curl Base URL → 再看脚本res.ok→ 最后看模型名。按这个顺序绝大多数报错五分钟内能定位。6. 把 Codex 用进日常CTA 与长期编码流水线跑绿只是起点。真正提升效率的是把 Codex 变成日常协作的一部分本地写代码时让它生成测试、审查改动CI 里让它做增量审查大型重构时用 Pro 的长上下文整仓分析。如果你主要做排障和接入建议从 API Keys 和接入文档入手把统一通道先配稳API Keys 在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。想先验证模型返回是否符合预期可以直接在模型对话页试https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。如果你要把 Codex 长期用在编码和 Agent 任务上Coding Plan 更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。最后给一个我踩过的坑别让 Codex 一次性生成整个仓库的 CI 配置。分四步走——先生成项目结构和类型定义再实现路由再补测试最后生成 workflow。每步本地验证通过再进下一步。这样即使某一步出错回滚范围小定位也快。把 Codex 当协作伙伴而不是全自动代码机明确约束、分步推进、持续验证CI 才会真正稳。