搭建静态博客是很有意思的事情,它可以很简单(半自动Github Page方案),也可以很复杂(自动拉取文章,自动部署)。在之前的文章中,有提到使用Webhook来拉取的方法,但实际实施起来,发现自己更喜欢直接SSH到服务器上来写作。所以这次介绍的方法将不使用自己的服务器,利用ZEIT来部署网页,子模块将不同功能分隔,再使用Github Actions串联起整个操作。
前置知识
子模块(submodule)
快速上手:https://juejin.im/post/5aa11f486fb9a028e0140e34
比较简单的讲就是Repo套Repo,我们利用此工具,将一个repo分拆成
源文件
和主题
这两个子模块。由此,用户可以分开进行写作/魔改。而无需下载所有的文件,降低了项目的耦合👏。ZEIT-now
一个用来部署静态网站的工具,无论你的源文件在哪里(Github/本地/etc),都可以进行部署。自带CDN加速,同时还可以支持自定义域名。
官网地址:https://zeit.co/
Github Action
其实就是CI/CD(持续集成/持续部署),持续集成(CI)可以帮助开发人员更加频繁地(有时甚至每天)将代码更改合并到共享分支或“主干”中。一旦开发人员对应用所做的更改被合并,系统就会通过自动构建应用并运行不同级别的自动化测试(通常是单元测试和集成测试)来验证这些更改,确保这些更改没有对应用造成破坏。持续部署可以自动将应用发布到生产环境。
相较于其他竞品,Github Action还有一个好,就是可以使用社区里的相关包来简化流程。
Github Action目前在公测,11月推出正式版。
目录结构
为了尽可能地解耦和模块化,我们将整个HEXO目录进行拆分。
├── _config.yml
├── db.json
├── error.log
├── package-lock.json
├── package.json
├── scaffolds
│ ├── draft.md
│ ├── page.md
│ └── post.md
├── source (子模块)
└── themes
└── xxx (子模块)
我们将文章代码和主题文件(假定主题名字就叫xxx)拆出来,是因为文章代码事最经常进行改动地,我们往往关注的也就是这个文件夹;而主题文件是为了对主题进行魔改的需要。
为了保持纯净,我们希望主题Repo不要存在个人的配置,所以我的选择是将主题配置 _config.yml
移到source的Repo下,在构建时,把主题配置文件拷贝到正确位置。
cp themes/xxx/_config.yml source/_data/_config.yml
整体流程图
我们用流程图来解释工作流程
![](https://gofun4-pic.oss-cn-hangzhou.aliyuncs.com/未命名文件 (2).png)
- 子模块更新(push)触发Action
- 子模块Actions启动
- 发请求(repository_dispatch)触发主Repo的Action
- 主RepoActions启动
- 切换到master分支,加载子模块
- 升级子模块到最新的分支
- 主Repo commit并push改动
- 加载配置文件
- 调用ZEIT进行部署
具体实现
结构建立
将
source
和theme/xxx
分别建一个Repo,然后在主Repo上加入这两个模块git submodule add your-source-repo-url source git submodule add your-theme-repo-url theme/xxx
会发现多了一个
.gitmodules
文件[submodule "source"] path = source url = your-source-repo-url [submodule "themes/xxx"] path = themes/xxx url = your-theme-repo-url
这里就记录着子模块的信息
提交并push
git add . git commit -m 'update' git push
Actions
生成TOKEN
由于我们需要通过请求的方式来手动触发主Repo的构建,所以需要设立token来作为凭证。
https://github.com/settings/tokens/new
点击该链接进行创建,名称随意,权限我不是很确定,把相关的全勾上吧,反正自己用(
复制生成的Token
建立Secrets
Secrets和Token是不同的,token是为了获取访问repo的权限,secrets则是为了防止token的泄露,避免明文写入workflow中。
在两个子模块的上图界面点击 Add a new secret
按钮,创建新的Secret,Name随意填写,这里假定为 TRIGGER_TOKEN
,Value填入刚刚复制的token。
子模块action
建立action文件,yml格式,名字随意
md .github/workflows touch xxx.yml
编辑action文件
name: trigger blog-src on: push jobs: build: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@master - name: trigger target env: TRIGGER_TOKEN: ${{ secrets.TRIGGER_TOKEN }} EVENT: trigger ORG: your-org REPO: your-repo run: | curl -d "{\"event_type\": \"${EVENT}\"}" -H "Content-Type: application/json" -H "Authorization: token ${TRIGGER_TOKEN}" -H "Accept: application/vnd.github.everest-preview+json" "https://api.github.com/repos/${ORG}/${REPO}/dispatches"
secrets.TRIGGER_TOKEN就是我们刚刚生成的token。
比较简单,核心就是发一个
curl
,触发主Repo的action即可。
主Repo action
第一步同子模块。
编辑action文件
name: Deploy on zeit
on:
repository_dispatch
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: "actions/checkout@master"
with:
submodules: true
- name: update submodule
uses: srt32/git-actions@v0.0.3
with:
args: "git submodule update --remote"
- name: commit and push
uses: github-actions-x/commit@v2.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
push-branch: 'master'
commit-message: 'publish'
force-add: 'true'
- name: copy config
run: |
cp ./source/_data/_config.yml ./themes/xxx/_config.yml
这里主要干了三件事
升级子模块
git submodule update --remote
为什么要升级子模块?是这样的,子模块的机制,跟踪的是commit,而不是branch,所以子模块更新,并不会更新到主模块,所以我们需要通过该命令手动将子模块升级到最新的commit上
提交更新
我们用了非常好用的包来帮我们解决问题,这样保证了每次部署,主Repo跟踪的子模块commit的都是更新的。
secrets.GITHUB_TOKEN
是GITHUB的自带Secret,不需要使用,直接使用即可。把主题配置文件拷贝回正确的位置
ZEIT配置
ZEIT是依靠
npm run build
来进行构建的,所以我们需要手动在package.json
加入该script//...... "scripts": { "build": "hexo deploy" }
加入自定义域名,不是重点,自行研究
同样我们需要生成TOKEN,进入https://zeit.co/account/tokens
点击create创建,参照前文的方式,复制token,并保存在主Repo的secrets(假定名称为ZEIT_TOKEN)中。
改动主Repo的action
# ...... - name: hexo build uses: "actions/zeit-now@1.0.0" with: args: "--prod" env: ZEIT_TOKEN: ${{ secrets.ZEIT_TOKEN }}
这里需要注意的是传入
--prod
,保证构建使用自定义域名。
结语
写这篇博客之前,感觉自己做的好复杂,好牛逼。但写出来一看,感觉又平淡无奇,心理想的无法落实到笔头,技术文写不出什么干货,实在惭愧。
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!