使用 Github Action,自动构建 Hugo 博客并部署至腾讯云 COS 静态存储,并触发 CDN 刷新。
hugo 和 hexo 都是静态博客,将最终构建生成的静态文件放置到 web 服务器即可访问。通过 Github Action 构建静态博客并发布到 GitHub Pages 十分简单,但是考虑到国内访问速度问题,还是选择了国内服务商来承载博客。
之前使用 hexo 时有插件可以比较方便的通过 hexo g && hexo d
自动部署到阿里云或腾讯云的对象存储,hugo 没有找到现成的轮子,看了下腾讯云对象存储的文档,发现借助 Github Action 自动上传挺简单的,记录一下。
自动构建
在博客仓库根目录下新建 .github/workflows
文件夹,新建一个 deploy.yaml
(文件名随意),指定触发条件:
1
2
3
4
5
6
7
| name: Build and deploy
on:
workflow_dispatch: # 触发方式 1: 手动触发
push: # 触发方式 2: push 到 master 分支时自动触发
branches:
- master
|
紧接着继续写自动构建工作流部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true # 下载子仓库,即主题仓库
fetch-depth: 0
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
extended: true # 启用 hugo extend
- name: Build
run: hugo --minify
|
整个工作流主要包括三个部分:
这样,即完成了触发工作流时自动构建静态页面的配置,当工作流被触发时,便会生成静态文件放置在 publish
目录下。
部署至对象存储
准备工作
部署到对象存储之前,首先要完成一些使用对象存储发布静态页面的基本配置。下面以我正在使用的腾讯云为例演示。
首先到 对象存储控制台 创建一个 bucket,访问权限设置为 公有读私有写(如果后面会套一层 CDN,建议使用私有读写,并且在回源时开启鉴权)。
创建成功后,到 基础配置 - 静态网站 中开启静态网站托管。
如果要使用 CDN 进行加速,到 域名与传输管理 - 默认 CDN 加速域名 - 自定义 CDN 加速域名 中添加你的域名,国内加速需要备案,海外加速可使用未备案的域名。
源站类型为 静态网站源站,如果前面选择的是私有读写,那么要开启回源鉴权,并且为 CDN 配置 HTTPS 证书(可使用腾讯云的证书控制台直接申请并配置)。
API 鉴权配置
在开始下一部分之前,我们还需要获取腾讯云的 access key,以使用命令行工具操作 COS 和 CDN。
首先,点击控制台右上角的头像,进入 访问管理,切换到 用户-用户列表,新建用户,自定义创建,选择类型 可访问资源并接收消息,填写一个用户名,仅启用编程访问。
在权限策略板块,搜索并添加 QcloudCOSDataFullControl
(对象存储数据读写删除权限) 和 QcloudCDNFullAccess
(内容分发网络全读写访问权限)。如果有更细粒度的权限控制要求,可以选择自定义策略,并详细控制权限和范围。
全部添加完成后,将生成的 SecretId
和 SecretKey
保存下来。
使用 Github Action 自动部署到 COS
继续书写我们前面的工作流,该部分要完成将构建好的静态文件自动上传至存储桶的工作,主要使用腾讯云官方的 cosmod 工具 来实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| - name: Setup Python #配置 python 环境,cosmod 基于 python 开发
uses: actions/setup-python@v4
with:
python-version: 3.9
- name: Setup coscmd # 安装 coscmd 工具
run: sudo pip install coscmd
- name: Configure coscmd # 配置存储桶参数和鉴权
env:
SECRET_ID: ${{ secrets.SecretId }} # SecretId
SECRET_KEY: ${{ secrets.SecretKey }} # SecretKey
BUCKET: ${{ secrets.Bucket }} # 存储桶名称,在存储桶基本信息中获取
REGION: ${{ secrets.Region }} # 存储桶地域,在存储桶基本信息中获取,如 ap-shanghai
run: coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION # 为 coscmd 工具配置存储桶信息
- name: Upload to COS
run: coscmd upload -rfs --delete public/ / #上传 public 中的文件 至 cos 存储桶根目录
|
本部分中,我们安装了 python 环境和 coscmd 工具,在最后一条命令中,
- -r
参数用于上传文件夹;
- -s
参数用于同步上传,即仅上传发生变化的文件;
- -f
参数用于强制同步文件;
- --delete
参数用于删除云端中本地已经删除的文件。
其中的 {{ secrets.xxxxxx }}
需要在 Github 仓库中进行配置,即不能将鉴权信息泄露。
在仓库的 Settings 界面,选择 Secrets - Actions,点击 New repository secret,分别配置 SecretId
SecretKey
Bucket
和 Region
。
到此为止,我们便完成了构建静态博客并自动上传至 COS 的工作流。
刷新 CDN
在上传完成后,需要刷新 CDN,否则访客看到的页面依然是 CDN 之前缓存的页面。
该部分有两种配置方式,一种是在存储桶页面,通过 函数计算 - CDN 缓存刷新函数
来自动触发刷新,该方法基于与你的存储桶同区域的腾讯云函数,当前腾讯云函数已经转为收费,因此如果没有购买资源包,不建议使用该付费方法。
第二种,使用腾讯云的 Python-SDK 实现,写一个 Python 脚本,在部署完成后执行脚本调用 API 完成缓存刷新。
缓存刷新脚本
在仓库根目录下创建文件 flush-dns.py
,文件内容如下,将其中的 https://blog.example.com/
修改为你的 CDN 加速域名。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| import json
import argparse
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import (
TencentCloudSDKException,
)
from tencentcloud.cdn.v20180606 import cdn_client, models
# 传入参数
parser = argparse.ArgumentParser(description='-i <secretId> -k <secretKey>')
parser.add_argument('-i', '--secretid', type=str, required=True, help='secretId')
parser.add_argument('-k', '--secretkey', type=str, required=True, help='secretKey')
args = parser.parse_args()
try:
cred = credential.Credential(args.secretid,args.secretkey)
httpProfile = HttpProfile()
httpProfile.endpoint = "cdn.tencentcloudapi.com"
clientProfile = ClientProfile()
clientProfile.httpProfile = httpProfile
client = cdn_client.CdnClient(cred, "", clientProfile)
req = models.PurgePathCacheRequest()
params = {"Paths": ["https://blog.example.com/"], "FlushType": "flush"}
req.from_json_string(json.dumps(params))
resp = client.PurgePathCache(req)
print(resp.to_json_string())
except TencentCloudSDKException as err:
print(err)
|
配置工作流
创建完脚本后,需要在工作流中调用,配置如下:
1
2
3
4
5
6
7
| - name: Flush CDN
env:
SECRET_ID: ${{ secrets.SecretId }} # 传入鉴权信息
SECRET_KEY: ${{ secrets.SecretKey }}
run: | # 安装 sdk 并运行刷新脚本
pip install --upgrade tencentcloud-sdk-python
python flush-dns.py -i $SECRET_ID -k $SECRET_KEY
|
这样,即完成了 撰写博客 - 上传 Github 仓库 - 自动构建、发布并刷新 DNS 的全部操作。
完整的 Action 工作流配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
name: Build and deploy
on:
workflow_dispatch:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.9
- name: Setup coscmd and sdk
run: sudo pip install coscmd
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
extended: true
- name: Build
run: hugo --minify
- name: Configure coscmd
env:
SECRET_ID: ${{ secrets.SecretId }}
SECRET_KEY: ${{ secrets.SecretKey }}
BUCKET: ${{ secrets.Bucket }}
REGION: ${{ secrets.Region }}
run: coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION
- name: Upload to COS
run: coscmd upload -rfs --delete public/ /
- name: Flush CDN
env:
SECRET_ID: ${{ secrets.SecretId }}
SECRET_KEY: ${{ secrets.SecretKey }}
run: |
pip install --upgrade tencentcloud-sdk-python
python flush-dns.py -i $SECRET_ID -k $SECRET_KEY
|