用GitHub Actions部署静态站点到OSS

   瞎折腾  Hexo  GitHub Actions 

前言

寻思了好几天,还是决定继续用 Hexo(没信用卡买不了 AWS lightsail),在线编辑的需求一时半会是解决不了了,就先考虑解决速度的问题,把文件托管到东南亚节点的对象存储上。考虑了七牛云和阿里云 OSS,但是,七牛云即便是海外的对象存储节点也需要绑定备案域名,提工单问了一下,客服说是因为绑定 CDN 需要。缓缓打出一个问号,为啥要把对象存储跟 CDN 绑在一起,为啥 CDN 一定要开国内的节点。首选七牛有一个原因,在网上搜关于把静态站点部署到对象存储的文章都是说 OSS 要求绝对地址,也就是 /archive/index.html 这种格式,而 /archive/ 会跳转到预定的首页,网上的解决办法都是改 Hexo 的代码给链接上加 index.html。看这些资料的时候我就觉得不太对,阿里不至于这么憨吧,于是找到文档看了看,果然,OSS 早就支持子目录首页了。

这还选啥选,就 OSS 了。下面结合 GitHub Actions 自动推送 Hexo 编译的结果推送到 OSS。

流程图

OSS 相关配置

开通 OSS、绑域名、设置防盗链等等就省略不说了。

为了能够正常访问 https://test.com/archive/ 这种链接,需要开启「子目录首页」。指路:Bucket 控制台 => 基础设置 => 静态页面。

子目录

配置结果如图

子目录配置

Actions 推送文件到 OSS 是通过 ossutil 实现的,推送过程中需要一个 RAM 子账户的 AccessKeyId 和 AccessKeySecret,这一步也不多说了,谷歌一搜多的是教程。注意:添加权限的时候只需要选择 AliyunOSSFullAccess。当然也可以继续细化权限,具体的 Bucket 设置中可以通过 Bucket Policy 将权限限制到某一个 Bucket,某一个目录下等等,阿里云的权限控制还是很给力的。

Actions 相关配置

进入存放博客文件的仓库,将上一步获取的 AccessKeyId 和 AccessKeySecret 存放到仓库的 Secrets 中。

仓库配置

有两种上传方案:

  1. 先清空 Bucket,再上传(外网流入流量免费)
  2. 覆盖式上传,根据修改时间判断是否覆盖文件

个人倾向于第一种,因为 Actions 的虚拟机环境中使用 UTC 时间,所以如果手动修改过 Bucket 中的文件再在 8 小时内覆盖式上传,因文件修改时间晚于 Actions 中的时间导致无法覆盖。

以下配置的值根据自己的情况修改(为了醒目把需要改的地方用@@包围起来了,修改的时候直接搜索下面列出的条目替换掉即可):

  1. @@Barnch@@:Hexo 源文件存放的分支,不是生成的 Public 的分支
  2. @@OSSEndPoint@@:Bucket 所在地域的域名信息,比如新加坡是 oss-ap-southeast-1.aliyuncs.com
  3. @@HexoPath@@:Hexo 编译结果的目录,没在 _config.yml 里改过的话,默认是 ./public
  4. @@Bucket@@:Bucket 名
name: CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Download Source file
        uses: actions/checkout@v2
        with:
          ref: @@Barnch@@

      - name: Prepare Node env
        uses: actions/setup-node@v1
        with:
          node-version: "10.x"

      - name: Hexo
        run: |
          npm install -g yarn
          export PATH="$PATH:`yarn global bin`"
          yarn global add hexo-cli
          yarn
          hexo clean && hexo g && hexo d

      - name: Upload to OSS
        env:
          OSS_AccessKeyID: ${{ secrets.OSS_AccessKeyID }}
          OSS_AccessKeySecret: ${{ secrets.OSS_AccessKeySecret }}
        run: |
          wget -q http://gosspublic.alicdn.com/ossutil/1.6.10/ossutil64
          chmod +x ./ossutil64
          ./ossutil64 config -e @@OSSEndPoint@@ -i $OSS_AccessKeyID -k $OSS_AccessKeySecret -L CH
          echo y | ./ossutil64 rm oss://@@Bucket@@/ -r
          ./ossutil64 cp -r @@HexoPath@@ oss://@@Bucket@@

一丢丢遗憾

因为我用的 Let’s Encrypt 的证书每 90 天需要 renew 一次,可以通过 Actions 的 cron 任务定时执行 acme.sh,但是没有现成的上传 OSS 域名证书的脚本,如何将证书推送到阿里云的 CDN? #1461 中讨论过这个问题,希望 acme.sh 有计划增加这个功能,或者回学校后有时间研究文档写个脚本。

套了一层阿里云 CDN,就免费提供了证书且自动 renew。

2333