安安~我是ChiYu~
鐵人賽要連續寫 30 天。文章明明都準備好了,某一天卻忘記發,連載還是會中斷。
每天還得核對日期、Day、標題、Markdown、草稿和公開結果。重複 30 次,最忙的那天很容易漏掉其中一項。
我曾經因為漏掉發文而中斷連載。這次,我乾脆把自己的流程整理成一個開源專案: iThome Ironman AutoPost 。
我用 TypeScript、Playwright 和 GitHub Actions,把文章檢查一路接到草稿預覽、儲存、發布和公開結果驗證;每一段都能停下來確認。
下載範本後,它不會立刻替你發文。我刻意把「先驗證、再預覽、最後才發布」寫進流程,正式發布前一定要走完前面的檢查。
文章寫完,還有每天不能漏掉的發布檢查
文章內容和圖片準備好後,連載期還有一批很機械、又不能漏的事情:
- 今天到底是 Day 幾?
- 這篇文章屬於哪個系列?
- Day 1 要沿用哪一份草稿?
- Day 2 之後應該從哪個系列入口建立文章?
- 標題、內文與圖片連結是否完整?
- workflow 成功後,文章真的公開了嗎?
少檢查一項,可能只是多花幾分鐘修正;在連續 30 天的規則下,也可能直接中斷整場挑戰。
所以這個專案只接手發布流程。文章內容還是由你準備,每一步發布操作則交給能驗證結果的自動化。
按下 Publish 前,先過五個檢查站
我把 Preview、Save draft 和 Publish 拆開,每個階段使用不同權限,也有各自的停止條件。
| 階段 | 會做什麼 | 不會做什麼 |
|---|---|---|
| 文章驗證 | 檢查 Day 檔名、H1、標題、正文、篇數與圖片網址 | 不開啟瀏覽器、不登入 iThome |
| Plan | 算出指定日期對應的 Day、系列、文章與草稿入口 | 不讀取 Session、不連線 iThome |
| Preview | 開啟既有 Day 1 草稿並填入標題與 Markdown | 不按儲存、不按發布 |
| Save draft | 儲存草稿,再重新開啟並比對標題與 Markdown | 不把文章公開 |
| Publish | 先儲存與讀回,再發布並驗證公開文章頁 | 不保證能自動 rollback |
Save draft 後的讀回驗證,是我最不想省的一關。畫面顯示「儲存成功」還不算,程式會重新開啟草稿,比對標題與 Markdown。正式發布後,它還會確認公開網址、文章標題和系列連結。
這些步驟都能在 自動化主流程 與 草稿讀回驗證 中直接看到。
templateMode:我故意留下的總電源鎖
公開範本預設使用虛構 ID,templateMode 也維持 true。測試、型別檢查、文章驗證與 --plan 都能跑;一旦操作需要登入狀態、瀏覽器或連線 iThome,程式就會停止。
這道閘門會直接阻擋執行。你可以在 assertLiveOperationAllowed
看到實作。
要進入真實操作流程,使用者必須先完成這些事情:
- 換掉公開範例的活動與系列資料。
- 確認每個系列的
signupId、day1DraftId與完整題目。 - 放入所有 Markdown 文章並通過完整驗證。
- 分別確認 Preview、Save draft 與 Publish 的 plan。
- 人工完成三階段 UAT。
- 最後才建立
ITHOME_PUBLISH_ENABLED=true。
有一說一,自動化敢按下發布還不夠,它也得知道什麼時候必須停手。
多系列與補償排程,先處理「不要重複發」
同一屆鐵人賽可能同時準備兩個以上的系列,天數也不一定相同。專案依 publishOrder 逐一處理;短系列跑完最後一天就略過。前一個系列如果發生重大錯誤,後續系列會直接停止。
範本同時保留主排程和補償排程。補償排程啟動時,會先查系列 RSS、個人文章列表和既有 receipt。只要同一 Day 已公開,就回報 already-published 並停止,不會再發一次。
GitHub Actions 顯示 Success,只代表 workflow 跑完。要確認文章真的發布,還得看到公開文章頁,並在個人文章列表或系列 RSS 找到它。
把 storage state 當成憑證保管
Playwright 需要已登入的瀏覽器狀態才能操作 iThome。使用者會在 Playwright 開啟的 Chromium 中人工登入,再把 storage state 存進 GitHub Secret;整個流程不會收集帳號密碼。
storage state 內含 Cookie 與網站儲存空間,拿到它的人可能在 Session 有效期間使用你的登入狀態。因此 README 對這件事寫得很直接:
- 不要 commit storage state。
- 不要貼到 Issue、聊天或 Actions log。
- 沒有明確需求時,不要把未發布文章與執行畫面上傳成 artifact。
- Session 洩漏時,立刻在 iThome 登出所有工作階段並重新產生登入狀態。
如果文章內容還沒公開,我也建議把實際連載資料放在自己的 Private Repo,公開 Repo 只保留範本與虛構資料。
圖片怎麼辦?它只接受公開 HTTPS 網址
iThome 無法讀取你電腦裡的相對圖片路徑,所以文章驗證會阻擋本機相對圖片。圖片需要先放到公開圖床,再使用 https:// 網址。
圖片可以搭配我之前整理的 Cloud-Assets-Template :先轉成 WebP,再產生 jsDelivr CDN 網址。撰寫與預覽時可以暫用 branch 路徑;正式發布前,改成固定的 Git tag 或 commit SHA,之後換圖才不會連舊文章一起變動。
發布前,我重新跑了這些檢查
截至 2026 年 9 月 2 日,我在專案目前的 3eed2d2 commit 重新執行完整檢查:
- 42 項自動化測試全部通過。
- TypeScript 型別檢查通過。
- 公開範例的 30 篇文章完整驗證通過。
- 本機工作樹與
origin/main沒有差異。
測試涵蓋 templateMode、唯讀 Preview、確認字串、發布時間窗、文章驗證、儲存後讀回、公開頁與 RSS 判定,也包含補償排程避免重複發布的情境。
測試原始碼
全部放在 repo 裡,可以直接查看。
它適合誰?又不適合誰?
如果你已經用 Markdown 準備文章,也願意設定 GitHub Actions,這個範本適合拿來把每天的發布操作整理成可檢查的流程。
如果你希望 Fork 後零設定就能跑,或期待網站改版後腳本照樣穩定,這個專案不適合。它操作的是 iThome 網頁 UI,目前沒有官方發文 API。DOM、表單或登入流程改動,Playwright 腳本就可能得跟著調整。GitHub Actions 排程也可能延遲;文章公開後仍得人工修改,沒有可靠的自動 rollback。
這些限制我都寫在 README。使用前先確認自己能接受,再決定要不要啟用排程。
想開始使用,先從 README 的安全順序走一次
完整設定會碰到系列 ID、Day 1 草稿、文章資料夾、登入狀態、GitHub Secret 與三階段 UAT。硬縮成三行指令只會把停止條件一起省掉,所以我把完整順序和常見問題留在 README:
專案採用 MIT License。你可以直接 Fork,但先別急著開排程。照 README 完成設定與三階段 UAT,確認每一道停止條件都符合自己的系列,再決定是否建立 ITHOME_PUBLISH_ENABLED=true。