以前免費的 GitHub 不支援 private repo,所以我把部落格的 source code 放在 Bitbucket。現在 GitHub 也支援 private repo,我就決定把部落格搬到 GitHub,順便將自動建置和發布流程從 Bitbucket Pipelines 改成 GitHub Actions。
因此這次除了搬文章和設定,還要處理兩個 repo 之間的發布權限。
搬移 repo
這次不需要保留舊 repo 的 Git 歷史,只把已追蹤的檔案複製到新的 repo,並保留新 repo 原本的 Git 歷史。
搬移時決定部落格的主題 stirring 和網站輸出 output 都繼續使用 Git submodule。output 指向 hansliu.github.io,Pelican 建置完成後,生成檔案會更新在這個 submodule 裡。
Bitbucket 原本怎麼發布
原本的 bitbucket pipelines 使用 Python 3.7.2,流程大致如下:
- 安裝
requirements.txt的依賴。 - 初始化 submodule,並從各自的
main更新到最新版本。 - 執行
make DEBUG=1 publish產生網站。 - 將
output的生成結果提交,再強制推送到hansliu.github.io的main。
最後的 --force 會以新生成的網站內容覆寫遠端分支。這是原本的發布方式,遷移後先沿用,之後需要留意 output/main 上不要放置必須保留的手動提交。
改成 GitHub Actions
新的 workflow 放在 .github/workflows/publish.yml,只在 main 分支有 push 時執行,merge 到 main 也會以 push 事件觸發。沒有設定其他分支或手動觸發。
建置環境改用 Python 3.14。安裝依賴後,workflow 會初始化 submodule,並沿用原流程更新 submodule 的 main,接著執行 make DEBUG=1 publish。publish 會清理 output 的生成檔、使用 publishconf.py 建置,最後把 CNAME 和 ads.txt 一起複製到輸出目錄。
發布時,workflow 會設定提交者資訊,將生成檔提交到 output,再推送到 hansliu.github.io 的 main。同一時間只允許一個發布工作執行,避免兩次 workflow 同時更新網站。
跨 repo 的部署憑證
GitHub Actions 預設的 GITHUB_TOKEN 主要授權目前執行 workflow 的 repo,不能直接假設它可以推送到另一個 repo。即使部落格 source code 和 hansliu.github.io 都在同一個 GitHub account 底下,跨 repo 權限仍需要另外設定。
這次建立一個 fine-grained personal access token,僅授權 hansliu.github.io,並開啟 Contents: Read and write。Token 存在主要 source code repo 的 Actions Secret,名稱是 DEPLOY_TOKEN;token 本身不放進 repo 檔案。
發布命令使用臨時的 Git HTTP header 提供 token,避免把憑證寫入 submodule 的 remote URL 設定。若 Secret 尚未設定,workflow 會在發布步驟報錯停止。
透過 Codex 協助遷移
這次遷移是透過 Codex 規劃並實作完成的。先請 Codex 唯讀比較新舊 repo,列出檔案範圍、Git 歷史、submodule 和部署流程的差異,再逐項確認搬遷決策,不保留舊 Git 歷史,不納入未追蹤文章和大型文件檔,並繼續使用 stirring 和 output submodule。
接著把 Bitbucket pipeline 的步驟整理成待辦清單,逐步確認 GitHub Actions 的觸發條件、Python 版本和跨 repo 憑證方式。決策確認後,再由 Codex 建立 workflow,並檢查 token 是否會被寫進 Git remote 設定。
把問題拆成一個個可以 review 的決定很方便:先理解現況,再決定怎麼搬,最後才實作。尤其部署憑證和 --force 這類會影響發布安全的設定,可以先看清楚流程,再選擇是否沿用。
本機測試與發布
本機可以先用相同的 Python 版本安裝依賴並執行建置,確認 Pelican、主題和外掛能正常產生網站。至於 GitHub Secret、Actions 權限和跨 repo push 仍要透過 GitHub Actions 實際確認。
結語
這次遷移最花心思的部分,不是把 YAML 換個格式,而是釐清 repo 的分工,以及 GitHub Actions 如何安全地跨 repo 發布。透過 Codex 協助盤點和拆解步驟,讓整個搬遷過程更容易。