iT邦幫忙

2025 iThome 鐵人賽

DAY 29
0
Software Development

30 天 Python 專案工坊:環境、結構、測試到部署全打通系列 第 29

ChatGPT 說: Day 29 - Vibe Coding × AI 協作:自動化腳本與守門規則

  • 分享至 

  • xImage
  •  

這天把「人類+AI」接進你已經成形的開發骨架:用一鍵化腳本把 AI 能做的事變成可靠重複的流程,用守門規則擋住 AI 產出的各種翻車現場。所有東西都要能在本地、CI、容器裡跑出同樣結果,這是前 28 天的共同語言。Hatch/Nox 一鍵化、鎖檔與可重現建置、型別與契約測、安全掃描與授權治理、觀測指標與追蹤都會被串起來。


一、你要的不是「AI 魔法」,而是「可重演流程」

AI 參與的開發活動大致分三類:

  1. 產出類:產生程式碼、測試、變更說明
  2. 協作類:審查 PR、摘要設計討論、對齊風格
  3. 維運類:產出變更日誌、生成 SBOM 註解、撰寫儀表板查詢描述

原則只有一條:把這些行為變成「可被腳本呼叫」的任務,塞進 Hatch/Nox 的單一入口,讓所有人用同一顆按鈕啟動它。


二、Hatch × Nox:把 AI 變成團隊指令

pyproject.toml 增加 AI 助攻的腳本群組,遵循我們既有的「一鍵多工」寫法【】:

[tool.hatch.envs.dev]
features = ["dev"]  # 你既有的開發 extra:pytest/ruff/black/mypy...

[tool.hatch.envs.dev.scripts]
check = [
  "ruff check .",
  "black --check .",
  "mypy src/",
  "pytest -q"
]

# --- AI 協作:全部「可選、可重演、可審計」 ---
ai:review = "python -m scripts.ai_review --diff HEAD"
ai:doc     = "python -m scripts.ai_doc    --paths src/"
ai:changelog = "python -m scripts.ai_changelog --since-tag $(git describe --tags --abbrev=0)"

noxfile.py 保持跨版本驗證,讓 AI 產物也走同一條 CI 流程路徑【】:

import nox

@nox.session(python=["3.10","3.11","3.12"])
def ai(session):
    session.install(".[dev]")  # 用你既有的 dev extra
    session.run("python","-m","scripts.ai_review","--sample")

重點:AI 腳本必須是純 Python/CLI,輸入固定、輸出可重演,避免「每次跑都長不一樣」的玄學。


三、守門規則(Gatekeeping):在「提交前」「CI」「容器建置」三段攔截

A) pre-commit:先在你按下 commit 的那一秒就把坑擋掉

延續 Day 10 的型別守門【】,再加三把刀:

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      # 1) 禁止把 AI 產生的 Placeholder 混進 PR
      - id: forbid-ai-placeholders
        name: forbid ai placeholders
        entry: python scripts/gates/forbid_ai_placeholders.py
        language: system
        pass_filenames: true

      # 2) 文字/程式碼都要有規範格式
      - id: ruff
        name: ruff
        entry: ruff check .
        language: system
        pass_filenames: false
      - id: black
        name: black
        entry: black --check .
        language: system
        pass_filenames: false

      # 3) 型別守門(Day 10)
      - id: pyright
        name: pyright
        entry: pyright
        language: system
        pass_filenames: false
      - id: mypy
        name: mypy
        entry: mypy
        language: system
        pass_filenames: false

forbid_ai_placeholders.py 的檢查邏輯很無情也很有效:擋住 TODO/???/FIXME、「Generated by」「LLM」「示意用」等關鍵字與可疑檔頭,避免把未審核的自動產物直接合進主幹。

B) CI:讓 AI 產物服從和其他檢查一樣的單一入口

在的 hatch run ci 維持統一入口,於 CI job 增加「AI 結果一致性」與「安全治理」步驟,與掃描並排:

# ci.yml 片段
- name: AI review (idempotent)
  run: |
    uv run hatch run dev:ai:review --diff HEAD~1..HEAD --save .reports/ai_review.json
    test -s .reports/ai_review.json  # 有輸出才算過

- name: Security & license
  run: |
    uv run hatch run sec:check-all   # 延續 Day 26 的腳本組合

C) 容器建置:AI 產物不應該靠平台祈禱

保持多階段建置,把「鎖檔」「非 root」「stdout JSON log」原則不變。AI 腳本若在 build 階段需要跑,務必使用 uv.lock--frozen 同步依賴,避免不同鏡像生成不同結果。


四、三支 AI 腳本樣板:小而剛好

這些腳本只做「提案」,不做「修改」。最後的決策仍由人類與傳統檢查來判定,與我們既有的型別/測試/安全守門一起工作,而不是互相取代。

1) scripts/ai_review.py:針對 diff 產生審查意見

  • 輸入:git diff
  • 輸出:JSON 建議清單
  • 守門:不自動改檔,只輸出「建議」
# 簡化版骨架:讀 diff -> 分段 -> 產 JSON 建議
# 真正的「模型調用」細節留白,確保可替換性(本地/雲端/代理皆可)
import json, subprocess, sys, re
def get_diff(spec="HEAD"):
    return subprocess.check_output(["git","diff",spec]).decode()

def review_hints(patch:str)->list[dict]:
    hints=[]
    if re.search(r"except Exception:", patch):
        hints.append({"severity":"warn","rule":"broad-except",
                      "msg":"避免捕太廣,改成具體例外並記錄 trace_id。"})
    if "print(" in patch:
        hints.append({"severity":"info","rule":"logging",
                      "msg":"用 structlog 打 JSON,攜帶 trace_id/span_id。【觀測 Day28】"})
    return hints

if __name__=="__main__":
    diff = get_diff(sys.argv[sys.argv.index("--diff")+1] if "--diff" in sys.argv else "HEAD")
    out = review_hints(diff)
    print(json.dumps(out,ensure_ascii=False,indent=2))

提示裡刻意提醒用 JSON log 並攜帶 trace_id/span_id,對應整合做法。

2) scripts/ai_doc.py:為模組與公開 API 產出 Docstring 草案

  • 檢查公開 API 來自你的 src/ 公開介面
  • 輸出到 docs/_drafts/*.md,不直接覆蓋原檔

3) scripts/ai_changelog.py:生成變更日誌初稿

  • 將 commit 訊息對應到 Keep a Changelog 類別,產出 CHANGELOG.md 草稿
  • 真正發佈仍走版本流與人工檢核節奏

五、AI 守門規則清單(建議預設開啟)

  1. 不得有 Placeholder:禁止含 TODO/???/FIXME/Generated by 的變更合併
  2. 邊界先於內部:外部 I/O 契約用 Pydantic v2,內部維持 typing,避免把全部資料都塞進模型
  3. 型別通過才談智慧:pyright/mypy 必過,否則 AI 產物當垃圾處理
  4. 測試覆蓋率門檻:沿用 Day 11 的 coverage 門檻與結構(此處承接你既有設定)
  5. 安全與授權:pip-audit、Safety、pip-licenses、CycloneDX 必跑,結果附在 PR artifact
  6. 觀測就緒:程式碼中的日誌呼叫必走 JSON,並附 trace_id/span_id,方便拉回整條追蹤
  7. 可重現:所有 AI 腳本都只能用鎖定的環境執行,與容器建置相同依賴樹
  8. 單一入口:本地與 CI 一律用 hatch runnox 觸發,不接受人肉命令差異

六、落地範例:PR 由機器先掃一遍,人類做最後裁決

  1. 開發者本地:hatch run dev:checkhatch run dev:ai:review
  2. pre-commit 擋掉 placeholder 與風格/型別違規(見上)
  3. CI 以 hatch run ci 跑完整檢查矩陣與 AI 建議輸出,附 artifact
  4. 審查者專注在:
    • AI 建議是否合理、有沒有錯殺
    • 觀測欄位是否到位(RED/USE 指標是否可得
    • 安全/授權報表是否乾淨

七、疑難排解速查

症狀 可能原因 修法
每次 AI 輸出結果都不一樣 腳本內隨機種子或非鎖定環境 固定 random seed,依賴走 uv.lock --frozen,輸出成 JSON 並上傳 artifact 以比對
本地過、CI 不過 入口不一致或依賴不同 一律 hatch run/nox,CI 先 uv sync --locked 再跑檢查
AI 建議忽略觀測欄位 程式碼沒帶追蹤上下文 先 setup OTel,再 setup logging,把 trace_id/span_id 注入 JSON log

八、結語

Vibe coding 的重點不是「讓 AI 幫你寫」,而是「讓團隊在同一條可重演的軌道上寫」。把 AI 收編進你既有的工程化骨架:單一入口、一致環境、嚴格守門、全程可觀測。當流程站穩,AI 只是多了一個聰明又會犯錯的實習生,出手快,但每次都要留下證據和紀錄。這就是 Day 29 要你帶走的節奏。


上一篇
Day 28 -監控與追蹤:OpenTelemetry 指標/追蹤
系列文
30 天 Python 專案工坊:環境、結構、測試到部署全打通29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言