前言
網頁東東至今仍完全以本地為主,所有代碼、字體、圖片影片與文章內容都紀錄於單個 Git 倉庫當中,並透過 Git LFS 來管理大檔案。
這樣的決定有好有壞,其中一個問題便是內容與代碼的耦合高,任何一個想維護的人要把我撰寫的幾百篇文章連帶抓下來 😅,隨著專案成熟我決定要將兩者分離。
方法一:Git Submodule
Git Submodule 可以達成將倉庫嵌入到令一個倉庫當中,相當於設置一個指標指向另一個倉庫。GitHub Action checkout 也有貼心的 submodules
選項。不過並不是我最終選擇的方法。
單純需要額外了解 submodules
設定麻煩,且 時常要下 git 指令同步內容 因此不考慮。我期望一個方案是 完全分離兩個倉庫,但在建構時又能組裝在一起使用 。
方法二:Symbolic Link + 自動拉倉庫
Unix-like 系統有 Symbolic Link 的方式可以簡單的把一個資料夾指向另一個資料夾,如下:
ln -s Path_A Path_B
ln -s ~/Desktop/my-content/post ~/Desktop/web-dong-blog/src/content/post
我可以抓取兩個倉庫後將內容倉庫的內容藉由指向連結到開發倉庫中,未來內容有任何更動開發倉庫也會即時改變,之外要記得忽略連結指標檔案於 .gitignore
:
# Skip Symbolic link filesrc/content/shortpostsrc/content/toolbox
至於線上部屬的部份內容倉庫可以在推送 main
分支時設定替目標 Repo 發送 content-updated
事件來觸發開發倉庫的 CI/CD。
name: Update Content
on: push: branches: - main
jobs: trigger-blog: runs-on: ubuntu-latest steps: - name: Trigger Blog CI env: BLOG_TRIGGER_TOKEN: ${{ secrets.BLOG_TRIGGER_TOKEN }} run: | curl -X POST -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer $BLOG_TRIGGER_TOKEN" \ https://api.github.com/repos/riceball-tw/web-dong-blog/dispatches \ -d '{"event_type": "content-updated"}'
開發倉庫接收先前 content-updated
事件觸發,並且搭配 actions/checkout 抓取內容倉庫並手動用 rsync 移動整合檔案:
name: Deploy Pipeline
on: workflow_dispatch: repository_dispatch: types: [content-updated]
jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4
- name: Checkout external content uses: actions/checkout@v4 with: repository: riceball-tw/obsidian-sync ref: main path: src/content-temp/ token: ${{ secrets.CHECKOUT_GITHUB_CONTENT_PAT }} lfs: true
- name: Merge local and external content folder run: rsync -av --ignore-existing src/content-temp/ src/content/
總結
以上提供不同的可能性來解決多個倉庫需要開發時分離但建構時組裝在一起的方式,相同的概念搬到不同平台概念應是差距不大可以沿用的。
可能讀到這裡有人覺得奇怪,拿 Git 存放非開發資源是什麼意思?好好串個專門的 CMS 不好嗎?
的確這是經過取捨後的架構,為了降低花費與複雜度,不依賴第三方程式管理內容,至少可見的未來這套方式都還堪用。
延伸閱讀
- Symlink your content in Astro for better portability - ELIO STRUYF
- 让Astro的 content 目录支持符号链接 - JiPai Store