Codex 环境中Clojure全栈开开发指南
本文是一份在 OpenAI Codex 环境中,针对 Clojure全栈(cljs+clj) 项目进行开发、构建和测试的完整指南。它不仅包含具体的操作步骤,也结合了 Codex 平台的特性,解释了相关配置的缘由。
理解 OpenAI Codex 环境
在开始之前,最重要的一点是理解我们所处的“Codex 环境”是什么。根据 OpenAI 的官方文档,Codex 是一个云端的 AI 软件工程代理,它在一个隔离的、容器化的环境中克隆我们的代码仓库来执行任务(如修复 Bug、编写测试、重构代码等)。
这个环境有几个关键特性,直接影响了我们的开发设置:
- 网络代理:所有出站的网络请求都必须通过一个位于
http://proxy:8080的网络代理。Codex 环境会自动设置http_proxy等变量来指向它。 - 启动脚本 (Setup Scripts):在每次执行任务前,Codex 会运行我们预定义的启动脚本,用于安装依赖、配置工具等。
AGENTS.md文件:Codex AI 代理会读取仓库中的AGENTS.md文件,以理解如何测试、Lint 和提交代码,这是我们与 AI 代理沟通贡献规范的方式。
我们的所有配置,都是为了让 Clojure、Maven、NPM 等工具能在这个特殊的环境下顺利工作。
环境初始化与代理配置
在全新的环境中,首先需要执行仓库根目录的 setup 脚本来完成基础配置。
chmod +x setup
sudo ./setup
此脚本的核心是为整个开发环境配置网络代理,使其能够访问外部网络以下载依赖。
脚本关键内容解析
# 为 Maven (Clojure CLI 依赖) 创建 .m2 目录和配置文件
mkdir -p ~/.m2
cat > ~/.m2/settings.xml <<'EOF'
<settings>
<proxies>
<proxy>
<id>codexProxy</id>
<active>true</active>
<protocol>http</protocol>
<host>proxy</host>
<port>8080</port>
</proxy>
</proxies>
</settings>
EOF
# 为通用命令行工具设置 HTTP/HTTPS/SOCKS 代理
export http_proxy="http://localhost:8080"
export https_proxy="https://localhost:8080"
export all_proxy="sock5://localhost:8080"
# 为 Java 虚拟机 (JVM) 设置系统级代理
export JAVA_TOOL_OPTIONS='-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080 -Dhttps.proxyHost=proxy -Dhttps.proxyPort=8080'
~/.m2/settings.xml: 这部分配置完全符合 Codex 文档的要求。它告诉 Maven (以及依赖它的 Clojure CLI) 通过名为proxy的主机和8080端口的 HTTP 代理来下载所有 Java 依赖包。- 环境变量 (
http_proxy,https_proxy): 这些变量确保了像curl、npm、yarn等大多数命令行工具能通过代理访问外部网络。 - Java 代理 (
JAVA_TOOL_OPTIONS): 这是至关重要的一步。它为所有 Java 进程(包括clojure、shadow-cljs等)设置了 JVM 级别的代理,确保了 Clojure 在解析和下载依赖时能够正常联网。 - Git 代理 (可选): 如有需要,也可以在脚本中加入
git config --global http.proxy和https.proxy来代理 Git 操作,以便克隆或拉取依赖库。
脚本成功执行后,运行 clj -h 来检查 Clojure CLI 是否已安装并能正常工作。
开发工作流
环境配置完成后,AI即可搭建环境, 并进行进行开发。
编译与构建
每次完成开发, 会根据AGENTS.md中对它的指示:
在修改 src/clj 或 resources 目录下的后端代码后,必须遵循以下步骤:
如果修改了 .clj 代码, 需要执行后端单元测试, 如果是.cljs代码, 需要执行npx shadow-cljs compile app编译前端代码。
编译/测试通过后, 执行 clojure -M:lint file_modified 来检查有无lint问题. 修复lint问题.
- 根据修选择执行哪种类型的测试, 仅当测试全部通过时,才可生成并提交 Pull Request。
- 如因已知的失败测试导致测试未通过,应在说明中提及,不要尝试修复这些测试。
测试、覆盖率与代码规范
运行测试
项目包含一套单元测试,但文档提示当前仍有部分已知失败的测试,执行时需注意。
clj -M:test # 或 make test
生成测试覆盖率报告
为了持续提升代码质量,在所有测试通过后,可以生成覆盖率报告来评估测试的完备性。
clj -M:coverage # 或 make coverage
报告将生成在 target/coverage/ 目录中,可供团队审查。
代码 Lint 检查与 AGENTS.md
提交代码前,应按照 AGENTS.md 的要求执行 Lint 检查。
clojure -M:lint <file_modified>
重点:AGENTS.md 文件不仅仅是给开发人员看的。在 Codex 环境中,这个文件是给 AI 代理 阅读的指南。它告诉 AI 如何运行测试、如何检查代码风格、PR 的标题格式等。确保这个文件内容清晰、准确,可以极大地提升 AI 协作的效率。
与 Codex AI 代理协作
我们在这个环境中进行的所有设置,最终都是为了让开发人员和 Codex AI 代理能够高效协作。当环境搭建完毕、测试和规范了然于心后,就可以开始向 Codex 代理委派任务了。
例如,可以向 Codex 提出以下请求:
- 修复 Bug: “这个项目在执行
clj -M:test时有几个失败的测试,请找出原因并修复它们。” - 添加测试: “请为医生管理端的 appointments 功能模块补充单元测试,并运行
clj -M:coverage确保覆盖率有所提升。” - 代码重构: “请检查
doctor-app.core文件,它过于庞大。请将其中的数据处理逻辑提取到新的命名空间中,并确保所有测试依然通过。”
由于已经通过 setup 脚本和 AGENTS.md 定义了工作流程,Codex 代理将能够遵循这些指令,自主地完成开发和测试任务。
总结
以下为AI每次执行的结果汇报:
✅ clojure -M:lint --lint deps.edn
src/clj/hc/hospital/db/oracle.clj:30:17: info: Single argument to str already is a string
src/clj/hc/hospital/db/oracle.clj:96:14: warning: unused binding filename
src/clj/hc/hospital/db/oracle.clj:96:23: warning: unused binding filenames
src/clj/hc/hospital/web/controllers/patient_api.clj:192:9: warning: Missing else branch.
src/clj/hc/hospital/web/handler.clj:30:24: warning: Unresolved var: http-response/content-type
src/clj/hc/hospital/web/pages/layout.clj:5:37: warning: Unresolved var: content-type
src/cljs/hc/hospital/core.cljs:14:29: warning: #'antd/Spin is referred but never used
src/cljs/hc/hospital/natural_language_generators.cljs:184:11: warning: Redundant let expression.
src/cljs/hc/hospital/natural_language_generators.cljs:201:3: warning: Misplaced docstring.
src/cljs/hc/hospital/natural_language_generators.cljs:201:3: warning: Unused value: "Renders a single part into its Hiccup representation."
src/cljs/hc/hospital/natural_language_generators.cljs:256:17: warning: redundant do
src/cljs/hc/hospital/pages/anesthesia.cljs:308:9: warning: unused binding patient-id
src/cljs/hc/hospital/pages/anesthesia.cljs:309:14: warning: unused binding comorbidity-item
src/cljs/hc/hospital/pages/anesthesia.cljs:395:8: warning: Unused private var hc.hospital.pages.anesthesia/physical-examination-card
src/cljs/hc/hospital/pages/anesthesia.cljs:444:5: warning: Redundant let expression.
src/cljs/hc/hospital/pages/anesthesia.cljs:518:6: warning: Missing else branch.
src/cljs/hc/hospital/pages/anesthesia.cljs:574:35: warning: unused binding patient-status
src/cljs/hc/hospital/pages/anesthesia_home.cljs:35:18: warning: unused binding active-tab
src/cljs/hc/hospital/pages/assessment_form_generators.cljs:150:26: warning: unused binding field-schema
src/cljs/hc/hospital/pages/assessment_form_generators.cljs:216:66: warning: unused binding entry-optional?
src/cljs/hc/hospital/pages/assessment_form_generators.cljs:248:9: warning: unused binding malli-props
src/cljs/hc/hospital/patient/views.cljs:280:3: warning: Misplaced docstring.
src/cljs/hc/hospital/patient/views.cljs:280:3: warning: Unused value: "判断字段是否为必填。仅在第一部分(基本信息)中所有字段均必填。"
src/cljs/hc/hospital/subs.cljs:103:29: warning: unused binding k
linting took 1840ms, errors: 0, warnings: 23
✅ clojure -M:test
#object[clojure.lang.MultiFn 0x7fadb3bc "clojure.lang.MultiFn@7fadb3bc"]
[(.)(...........................................................................
................................................................................
................................................................................
................................................................................
.........)(................)(.)(............)(................................)(
.....)(....)(..)(....)(...................)(...)(...)]
94 tests, 426 assertions, 0 failures.
✅ clojure -M:coverage
root@6dba38107ada:/workspace/hospital# tail -n 20 /tmp/coverage.log
| hc.hospital.web.controllers.user-api | 69.78 | 70.83 |
| hc.hospital.web.handler | 92.73 | 93.10 |
| hc.hospital.web.middleware.auth | 59.46 | 83.33 |
| hc.hospital.web.middleware.core | 35.93 | 45.45 |
| hc.hospital.web.middleware.exception | 52.81 | 61.90 |
| hc.hospital.web.middleware.formats | 100.00 | 100.00 |
| hc.hospital.web.pages.layout | 61.76 | 58.82 |
| hc.hospital.web.routes.api | 100.00 | 100.00 |
| hc.hospital.web.routes.consent-form-api | 95.33 | 97.50 |
| hc.hospital.web.routes.overview-api | 89.78 | 94.12 |
| hc.hospital.web.routes.pages | 44.00 | 77.78 |
| hc.hospital.web.routes.patient-api | 93.39 | 92.21 |
| hc.hospital.web.routes.patient-pages | 100.00 | 100.00 |
| hc.hospital.web.routes.report-pages | 100.00 | 100.00 |
| hc.hospital.web.routes.role-api | 78.95 | 83.33 |
| hc.hospital.web.routes.user-api | 85.30 | 88.46 |
| hc.hospital.web.routes.utils | 38.89 | 66.67 |
|------------------------------------------------+---------+---------|
| ALL FILES | 75.65 | 80.44