前言
网页东东至今仍完全以本地为主,所有代码、字体、图片影片与文章内容都记录于单个 Git 仓库当中,并通过 Git LFS 来管理大文件。
这样的决定有好有坏,其中一个问题便是内容与代码的耦合高,任何一个想维护的人要把我撰写的几百篇文章连带抓下来 😅,随着项目成熟我决定要将两者分离。
方法一:Git 子模块
Git 子模块可以达到将仓库嵌入到另一个仓库当中,相当于设置一个指针指向另一个仓库。GitHub Action checkout 也有贴心的 submodules
选项。不过并不是我最终选择的方法。
单纯需要额外了解 submodules
设置麻烦,且 时常要下 git 指令同步内容 因此不考虑。我期望一个方案是 完全分离两个仓库,但在构建时又能组装在一起使用 。
方法二:符号链接 + 自动拉仓库
Unix-like 系统有符号链接的方式可以简单的把一个文件夹指向另一个文件夹,如下:
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