本日核心價值 (Core Focus): 在 Pull Request 上先跑 pytest 當硬閘門,再用 read-only 的 Codex 產出檢視摘要與 artifact;金鑰只走 repo secrets,權限最小,CI 不開
danger-full-access。
概念說明與實戰情境 (Overview)
Day 16 的 Self-Correction Loop 適合本機或受控 runner;一進 CI,問題變成「誰能寫檔、誰能看到 API key」。正確切法是兩段:測試必須過(pytest),AI 檢視可選且預設唯讀。官方已提供 Codex GitHub Action(openai/codex-action@v1),會安裝 CLI、必要時啟動 Responses API proxy,再以你指定的 sandbox 跑 codex exec。CI 預設用 --sandbox read-only(或 Action 的 sandbox: read-only),除非你明確需要寫入工作區。不要在 GitHub Actions 使用 danger-full-access。Windows runner 的 sandbox 較弱,Codex Action 在 Windows 還必須設 safety-strategy: unsafe,不適合作為預設。
關鍵操作與範例 (Implementation & Example)
建議拆成兩個 job:test 不碰 AI 金鑰;codex_review 只在測試通過後以 read-only 跑,並把摘要上傳為 artifact。權限採 least privilege:contents: read 足夠 checkout 與讀 diff;只有要留言到 PR 時才給 pull-requests: write,而且最好放在另一個 job。
Secrets 設定:
| Secret 名稱 | 用途 | 注意 |
|---|---|---|
OPENAI_API_KEY |
Codex GitHub Action 的 openai-api-key |
官方文件以此為例;勿 echo |
CODEX_API_KEY |
自行呼叫 codex exec 時的單次金鑰 |
只支援 codex exec;不要設成 job 層 env |
官方安全要求:不要把 OPENAI_API_KEY 或 CODEX_API_KEY 設成整個 job 的環境變數。checkout 後的測試、hook、被 PR 改過的腳本都可能讀到環境。Action 路徑會用 proxy 降低金鑰暴露;若你堅持用 shell 呼叫 CLI,金鑰只准出現在那一行 CODEX_API_KEY=... codex exec ...。
Sandbox 在 CI 的對照(與 Day 16 相同旗標,只是預設更嚴):
| 目的 | 旗標 / Action input | 適用 |
|---|---|---|
| PR 程式碼檢視 | --sandbox read-only 或 sandbox: read-only |
今天的預設 |
| 受控修補(另 workflow) | --sandbox workspace-write |
只要寫工作區、不要碰 runner 其他路徑 |
| 關閉 sandbox | danger-full-access |
CI 禁用 |
Prompt 檔放進 repo,例如 .github/codex/prompts/review.md:
Review this pull request as a senior engineer.
Focus on correctness, test gaps, and security.
Do not modify files. Do not run commands that write the workspace.
Summarize findings in Traditional Chinese with severity: blocker / warning / note.
完整 workflow(pytest + 可選 read-only 檢視 + artifact):
name: CI with Codex review
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install and test
run: |
python -m pip install -U pip
pip install -r requirements.txt
pytest -q
codex_review:
needs: test
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge
fetch-depth: 0
persist-credentials: false
# Official Codex GitHub Action: installs CLI and runs codex exec.
# Keep sandbox read-only in CI unless you explicitly need writes.
- name: Codex read-only review
id: run_codex
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
prompt-file: .github/codex/prompts/review.md
output-file: codex-review.md
sandbox: read-only
safety-strategy: drop-sudo
- name: Upload review summary artifact
uses: actions/upload-artifact@v4
with:
name: codex-review-summary
path: codex-review.md
if-no-files-found: error
若尚未導入 Action、只想用 CLI 做同等唯讀檢視,等價指令是:
codex exec --sandbox read-only --ask-for-approval never \
"Review the current git diff. Do not modify files. Write a short review in Traditional Chinese."
這條指令適合受控 runner。官方建議 GitHub Actions 優先用 openai/codex-action@v1,而不是自己在 step 裡安裝 CLI 再把 key 丟進 shell。Action 的 sandbox 對應 codex exec 的 --sandbox:read-only、workspace-write、danger-full-access。第三種不要出現在 PR CI。
Runner 選擇:
ubuntu-latest(預設):Linux runner + safety-strategy: drop-sudo,符合官方安全模型;pytest 與 Codex 都放這裡。safety-strategy: unsafe,sandbox 隔離較弱。Windows 專案的測試可另開 runs-on: windows-latest 只跑 pytest;不要在 Windows runner 上對 fork PR 跑 Codex。Artifact 與 PR 留言要分開看。把 codex-review.md 上傳成 artifact,優點是權限只需 contents: read、fork PR 也不會在討論串刷機器人留言;缺點是人要進 Actions 頁面才看得到。若要 createComment,官方範例是第二個 job 才給 pull-requests: write,用 job output 傳 final-message,持有 API key 的 job 仍然不要有寫入權限。對 fork 進來的 PR,預設不要跑會讀 secrets 的 Codex job(GitHub 對 fork 本來就不會把 repo secrets 傳給 workflow);內部 repo 也應把 Prompt 固定成 prompt-file,不要把 PR 標題、issue 內文原封不動餵給模型,以免 Prompt Injection。
若要自動修 CI 失敗,官方模式是:失敗後另開 workflow,Codex 產出 patch artifact,另一個 job 才用 contents: write 開 PR。修補 job 與持有 OPENAI_API_KEY 的 job 分開。那是 Day 16 迴圈的 CI 版,不是今天 PR 檢視的預設路徑。今天預設:測試硬失敗、檢視軟輸出、不在 PR 來源分支上讓模型直接 commit。pytest 不過就讓 CI 紅;Codex 審查意見最多當 warning,不要用「模型覺得有問題」去 exit 1 擋合併,除非你已把規則寫成決定性的 linter 或測試。
CI 的價值是可重複,不是每次 PR 都強制花一次模型額度。可以先只跑 pytest,等測試穩定再打開 codex_review;也可以用路徑過濾,只在後端或安全相關檔變更時才呼叫 Action。output-file 寫成 Markdown 方便人讀,也方便對照 Day 12 的 REVIEW.md 嚴重度。若要把摘要貼到 PR,第二個 job 不要繼承 openai-api-key。fork PR 的檢視改成 maintainer 手動 workflow_dispatch,避免把內部 Prompt 暴露給外部貢獻者。Windows 專案請把「能編譯」和「能給 Codex 讀」拆開:前者用 windows-latest 跑原生測試,後者仍用 ubuntu-latest 做唯讀審查。Action 的 safety-strategy: drop-sudo 只在 Linux/macOS 有效;這也是 Codex job 不要放 Windows runner 的原因。
注意事項與常見失敗 (Pitfalls)
echo $OPENAI_API_KEY 或把它印進 artifact:GitHub 的 mask 不是萬能,log 與 fork PR 都可能外洩。修法:secrets 只出現在 Action input;禁止 debug 輸出環境。env:同 job 的 pip install、測試、惡意 pre-commit 都能讀。修法:Action 用 openai-api-key:;CLI 則單行 CODEX_API_KEY=... codex exec ...。workspace-write 或 danger-full-access:fork PR 等於讓外人的 Prompt 改你的 checkout。修法:檢視用 read-only;寫檔修補改走獨立、受控 workflow。contents: write + pull-requests: write + AI 同 job,事故面最大。修法:test / review 只 contents: read;留言或開 PR 另 job。unsafe。修法:Codex job 固定 ubuntu-latest。openai/codex-action@v1(或 commit SHA),Prompt 用 repo 內 prompt-file,不要直接餵 issue / PR 原文。本日總結 (Takeaways)
codex exec --sandbox read-only;需要寫檔才顯式開 workspace-write,不要用 danger-full-access。openai/codex-action@v1 是 GitHub Actions 上跑 Codex 的首選,可少暴露 API key。OPENAI_API_KEY / CODEX_API_KEY 只放 repo secrets,永不 echo,也不要當 job 層環境變數。ubuntu-latest;Windows runner 只跑你真正需要的原生測試,不拿來做預設 AI 檢視。明日預告 (Next)
明天離開 CI,把 Function Calling 接到真實通路:用 Line Chatbot + AI Agent 做企業級 ERP 查詢助手,重點是 webhook 驗簽、工具白名單與唯讀查詢。