从vercel到Github action

#Blog #CICD #Hugo

Table of Contents

很长时间没有更新自己的博客了,可能是人的经验是有限的,也可能是最近的东西都是零散的记录在 Obsidian上。但是看过一篇写PKM的文章,所有的知识有 输入 转化 和输出 三个步骤。写博客就是属于输出的过程。

知识没有体系则不是知识

这篇文章里面,把自己的hugo的博客换了主题。觉得之前的 Paper-mod 的主题layout并不是很喜欢。

并且配置太多,不符合我现在的minimal的主张了。所以找到了一个 texify3的主题,由于没有搜索功能,后面也进行了二次开发。加上一些自己喜欢的功能。后面可能会把这个主题从原来的 仓库中分离出来。

这篇看标题是记录把静态博客从 vercel 迁移到使用 Github action来进行部署。原因有

  1. vercel 在部署的时候 sass 有兼容性问题,导致css 无法完成编译。直接导致无法使用
  2. 显然 gtihub action 更是正规军,有完整的 CICD的流程。可以联系下新技能

在方案选型上使用:

  1. Hugo
  2. github Action
  3. Cloudflare R2

由于 Github Pages 只支持 Public 的仓库,但是博客的源文件不想open掉,所以这里使用 R2 来作为静态文件的托管。也遇上了一些问题。后面会讲。

正文

流水线

这里使用的是 Github Action。通过自己编写 yaml 文件来实现自动化的build和deploy。这里分两部分来介绍

Build

这里直贴出来pipeline 的文件,下面部份 是实现了 hugo 的安装,npm 安装依赖,以及Hugo 的编译。这里的 ShortID 是一个 博客的前缀路径,用于区分 对象存储里的文件版本。

build:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.126.1
    steps:
      - name: Install Hugo CLI
        run: |
          wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
          && sudo dpkg -i ${{ runner.temp }}/hugo.deb
      - name: Install Dart Sass
        run: sudo snap install dart-sass
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 18
      - name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: recursive
      - name: Install Node.js dependencies
        run: npm install
      - name: Install Node.js dependencies
        run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
      - name: Build with Hugo
        env:
          # For maximum backward compatibility with Hugo modules
          HUGO_ENVIRONMENT: production
          HUGO_ENV: production
        run: |
          hugo --minify --baseURL "${{ vars.BASE_URL }}/${{ env.SHORTID }}"

这里说一下ShortID,这里在流水线中生成了 ShortID, 在两个地方用到。

  1. 在Hugo 编译的时候配置在 baseURL中,用于访问不同的博客版本
  2. 写入临时文件,传递给下一个JOB(deploy)来使用
      - name: Generate shortid
        run: |
          npm install shortid
          SHORTID=$(node -e "console.log(require('shortid').generate())")
          echo "SHORTID=$SHORTID" >> $GITHUB_ENV

      -  name: Print shortid
         run: |
          echo ${{ env.SHORTID }}
          echo $SHORTID > ./public/shortid.txt

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: public-folder
          path: ./public

Deploy

Deploy主要实现的功能就是上传到 R2。代码如下,使用 download-artifact 来获取前面的 public 文件夹。之后使用 upload 模块来上传到R2 即可提供访问。

  # Deployment job
  deploy:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Download public folder artifact
        uses: actions/download-artifact@v4
        with:
          name: public-folder
          path: public/
      - name: Read shortid from file
        run: |
          SHORTID=$(cat public/shortid.txt)
          echo "SHORTID=$SHORTID" >> $GITHUB_ENV


      - uses: shallwefootball/s3-upload-action@master
        name: Upload public
        with:
          endpoint: ${{ vars.S3_ENDPOINT }}
          aws_key_id: ${{ vars.AWS_KEY_ID }}
          aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
          aws_bucket: ${{ vars.AWS_BUCKET }}
          source_dir: './public'
          destination_dir: ${{ env.SHORTID }}

但是在实际使用的时候遇到了问题:

  1. R2 的文件版本问题
  2. R2 不支持try index.html

Patch

部署

第一个问题,我们在前面引入了 ShortID。

每次静态文件都会上传到不同的ShortID 对应的目录下。来实现版本控制。

针对第二个问题,使用一个简单的index文件来实现自动跳转到ShortID 的路径

- name: Create index.html
  run: |
    echo "<html><head><meta http-equiv='refresh' content='0; url=/${{ env.SHORTID }}/index.html'></head><body></body></html>" > index.html

访问

在R2 时候还有一个访问的问题。例如下面的链接。会报404的问题,因为不会自动try index.html

https://blog3.12ms.xyz/52UkBhSCH/posts/

这里需要在 CF中添加重定向规则,这样就强制在非资源链接后面添加 index.html 的文件名,例如上面的链接就变成了下面的样子。 这样就可以解决掉404 问题。

https://blog3.12ms.xyz/52UkBhSCH/posts/index.html

#匹配
(not http.request.uri.path contains "." and http.request.uri.path ne "/" and http.host eq "blog3.12ms.xyz")
#重定向
concat(http.request.uri.path, "/index.html")

虽然整体的过程没有什么难以理解的概念。但是从 vercel 升级到 GA 来进行部署 更贴近正式的 CICD 的流程还是很开心的。

中间遇到了一些问题,也是用综合的知识来进行一一解决。这就是工程师的成长之路吧。