工作室只有我一個人的時候,我覺得「流程」是大公司的東西。
要發新版本,我就打開編輯器,把 views.py 裡那行
"1.0.2" 改成 "1.0.3",前端 .env 也跟著改一次,
然後 build、push、重啟容器。整套動作我閉著眼睛都會做。
問題是,我不是每次都閉著眼睛做對。
版本號手改的日子裡,我踩過的坑大概可以分成三類。
第一類是忘記。前端改了,後端忘了改,線上兩個服務回報不同版本號, 追 bug 時完全不知道自己在看哪一版。
第二類是順序。Next.js 的版本號是 build 時被寫死進 bundle 的,
Django 的是 runtime 讀環境變數。這件事我知道,但我只有在「剛好想起來」的時候才知道。
有幾次前端 build 完,footer 上還是印著 dev。
第三類最麻煩:無法轉述。如果現在有人要接手發版,我得跟他講半小時,
而且一定會漏掉某個「喔對了,那個要先……」。這種知識沒有存在任何地方,
它存在我的肌肉記憶裡,而肌肉記憶不能 git clone。
這三類坑有一個共同點:它們都不是技術問題。技術上,每一步我都會做。 它們是知識存放位置的問題——這些知識存在我腦袋裡,而不是存在工具裡。
後來我做了 fleet-console,一個自己的發版後台。做的過程中我才發現, 「把流程寫進工具」有深淺不同的三個層次,而大部分人只做到第一層。
第一層是自動化:把手動步驟變成一顆按鈕。 這是最直覺的一層,也是效果最有限的一層。因為按鈕只是把動作變快, 沒有阻止你做錯的動作。
第二層是預設值:讓正確的做法變成最省力的做法。 版本號現在由後端讀 git tag 自動加一。我不必記得上一版是幾號, 因為系統比我記得清楚。
第三層——我認為這層才是文化——是移除選項。 fleet-console 的發版畫面上,沒有一個讓你手動輸入版本號的欄位。 你只能在三顆按鈕裡選一顆:修補、小改版、大改版。
這不是技術限制。做一個輸入框比做三顆按鈕還簡單。這是一個決定。
語意化版本號(semver)的規則寫在文件裡,沒有人會去讀。 但當畫面上只有三顆按鈕,而且每顆按鈕旁邊直接顯示它會產生的版本號時, 規則就變成你按下去之前一定會看見的東西:
1.0.31.1.02.0.0這裡的關鍵是括號裡的說明文字。它們不是 UI 裝飾,是規範本身。 一個新來的人不需要知道 semver 是什麼,他只需要問自己「我這次改的東西會不會弄壞別人」, 然後按對應的那顆按鈕。判斷的成本從「記得規則」降到「回答一個問題」。
而且因為前端根本沒有版本號的輸入框,那個「先手動填一個暫時的版本號,之後再改回來」的 誘惑,從一開始就不存在。工具沒有給你做錯的入口。
發版的 request body 只有兩個欄位,其中一個是 by——是誰按的。
body: JSON.stringify({ bump, by: me?.name })
工作室只有我一個人的時候,這個欄位看起來很荒謬。永遠都是我。
但我還是留著它,理由有兩個。第一,我希望這套系統從第一天起就假設「不只一個人」, 這樣哪天真的多一個人,不必回頭改資料結構。第二,也是更重要的: 記錄「誰做的」和「怪罪誰」是兩件事。 當發版紀錄上寫著誰在什麼時間發了哪一版,出事時第一個問題會是「那次發版改了什麼」, 而不是「到底是誰動的」。前者能查,後者只會讓人下次不敢按按鈕。
一個人的工作室最容易養成的壞習慣,就是覺得「反正只有我,記不記錄都一樣」。 但你未來的自己,其實是一個完全不同的人。他不記得你今天為什麼這樣做。
我不想把這件事寫得太美好,所以講一次工具沒能救我的例子。
有一次線上前端完全連不到 API,瀏覽器報 CORS 錯誤。我花了很久檢查 Django 的 CORS 設定,
middleware 順序、允許的來源,全都是對的。最後 curl 一打才發現,
根本不是 CORS——那是一個 502,而 502 的錯誤頁不帶 CORS header,
所以瀏覽器誤報成跨域問題。
真正的兇手是 nginx 設定裡的一個字:我寫了 clelereve-blog-backend(連字號),
實際的容器名是 clelereve_blog_backend(底線)。一個字元,兩個小時。
這種錯,發版按鈕救不了。但它讓我學到工具化的邊界在哪裡: 工具能固化「你已經想清楚的事」,不能替你想清楚還沒想過的事。 版本號的規則我想清楚了,所以能寫成三顆按鈕。容器命名的規則我沒想清楚, 所以它到現在還是靠人眼對照。
知道哪些事還在腦袋裡,本身就是有價值的資訊。
寫到這裡,我對「團隊文化」這個詞的理解跟以前不太一樣了。
我沒有員工,但我確實在跟人協作。三個月後的我,是一個記不得今天所有決定的協作者。 幫我寫程式的 AI,是一個只能讀到我留下的文字的協作者。 未來某天可能接手這套系統的人,是一個從來沒跟我說過話的協作者。
這些協作者有一個共同點:他們都無法問我問題。 他們只能讀我留在 repo 裡的東西——commit message、Dockerfile 裡的註解、 按鈕上的那句「新增功能,相容」。
所以文化不是一群人形成的氛圍。文化是「當我不在場時,這個專案還會不會被正確地對待」。 對一人工作室來說,這個問題不但成立,而且比大公司更迫切——因為沒有同事會在你出錯時提醒你。
每次我發現自己在腦中默念一串步驟,我就知道那裡有一段還沒被固化的文化。 它現在活在我的記憶裡,隨時會蒸發。
把它寫進工具,不是為了偷懶。是為了讓一個不認識我的人——包括三個月後的我—— 也能把事情做對。
如果你想看這三顆按鈕背後實際發生什麼事, 我在另一篇文章裡拆開了那條跨越三個 repo 的路徑:誰算版本號、誰 build image、誰只是被動接收。




