搭建静态博客是很有意思的事情,它可以很简单(半自动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月推出正式版。

    网址:https://github.com/features/actions

目录结构

为了尽可能地解耦和模块化,我们将整个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)

  1. 子模块更新(push)触发Action
  2. 子模块Actions启动
    1. 发请求(repository_dispatch)触发主Repo的Action
  3. 主RepoActions启动
    1. 切换到master分支,加载子模块
    2. 升级子模块到最新的分支
    3. 主Repo commit并push改动
    4. 加载配置文件
    5. 调用ZEIT进行部署

具体实现

结构建立

  1. sourcetheme/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

    这里就记录着子模块的信息

  2. 提交并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

  1. 建立action文件,yml格式,名字随意

    md .github/workflows
    touch xxx.yml
  2. 编辑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

这里主要干了三件事

  1. 升级子模块

    git submodule update --remote

    为什么要升级子模块?是这样的,子模块的机制,跟踪的是commit,而不是branch,所以子模块更新,并不会更新到主模块,所以我们需要通过该命令手动将子模块升级到最新的commit上

  2. 提交更新

    我们用了非常好用的包来帮我们解决问题,这样保证了每次部署,主Repo跟踪的子模块commit的都是更新的。secrets.GITHUB_TOKEN 是GITHUB的自带Secret,不需要使用,直接使用即可。

  3. 把主题配置文件拷贝回正确的位置

ZEIT配置

  1. ZEIT是依靠 npm run build 来进行构建的,所以我们需要手动在 package.json 加入该script

    //......  
    "scripts": {
        "build": "hexo deploy"
     }
  2. 加入自定义域名,不是重点,自行研究

  3. 同样我们需要生成TOKEN,进入https://zeit.co/account/tokens

    点击create创建,参照前文的方式,复制token,并保存在主Repo的secrets(假定名称为ZEIT_TOKEN)中。

  4. 改动主Repo的action

    # ......
          - name: hexo build
            uses: "actions/zeit-now@1.0.0"
            with:
              args: "--prod"
            env:
              ZEIT_TOKEN: ${{ secrets.ZEIT_TOKEN }}

    这里需要注意的是传入 --prod ,保证构建使用自定义域名。

结语

写这篇博客之前,感觉自己做的好复杂,好牛逼。但写出来一看,感觉又平淡无奇,心理想的无法落实到笔头,技术文写不出什么干货,实在惭愧。



经验分享      Hexo 博客 CI/CD

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!