使用Github Actions部署主题样例站

  1. 1. 准备密钥对
  2. 2. 构建Actions
    1. 2.1. 触发事件
    2. 2.2. 工作任务
      1. 2.2.1. 设置环境变量
      2. 2.2.2. 准备运行环境
      3. 2.2.3. 获取测试资源
      4. 2.2.4. 获取主题文件
      5. 2.2.5. 修改配置参数
      6. 2.2.6. 安装Hexo环境
      7. 2.2.7. 设置Git配置
      8. 2.2.8. 拉取站点文件
      9. 2.2.9. 生成新的文件
      10. 2.2.10. 推送部署

作为一名Hexo主题开发者,为了让用户能直观地体会到这个主题的默认样式,我总觉得需要部署一个用于测试的样例站点。但一些新加入的特性,由于种种兼容性的原因,有时并无法在博客里直观完整地表现出来,因而便萌生了一个使用Hexo主题组件测试进行测试样例生成的想法。

然而每次手动生成测试站未免有些太被动了一些,而且也显得相当不优雅,来回倒腾代码也可能出现意料之外的情况。在自动化大行其道的今天,既然是一套完整到已经确定了的规定动作,那就全部交给计算机来运行吧,让持续集成平台来自动构建我们的代码,并推送到相关的分支上去就可以啦~

本次我使用了Github Actions作为持续集成的构建平台,一来因为它对开源公共项目是免费使用的,二来它与Github的工作流(包括PR后的自动测试等)Github自家的生态有着完美的集成;因而虽然相关的资料还并不多见,但根据官方文档默认样例文件的指引,还是可以比较用户友好地构建出测试用的项目哒

准备密钥对

由于我在Actions里使用到了SSH的拉取推送构建方式(使用的并不是Hexo用于快速部署的git模块),因此事先需要准备一下用于部署和推送的SSH公私钥。为了安全起见,建议使用项目专属的 Deploy Key(在项目的 Settings - Deploy Key 里可以新建)进行认证,相比起账户密钥而言具有更高的安全性。而为了兼顾后期的站点推送需求,建议您同时勾选Allow Write Access以支持写入操作。但如果使用其他的方式进行身份验证,例如Github Tokens,则建议使用Actions构建过程中自动生成的GITHUB_TOKEN进行处理,这样就更加安全,而且一般不容易出事故。

密钥对可以使用OpenSSH生成,我选择的是4096位的RSA密钥对,由于我是在Windows环境下且常用PuTTY,因此使用了PuTTYgen来生成(这个软件讲道理其实并不是很友好,因为默认保存的是PuTTY私有的格式,需要在顶部菜单的Conversions里Export OpenSSH Key导出成OpenSSH格式的密钥才可以)

生成完毕后,将框里的ssh-rsa公钥复制,并在项目设置的 Deploy Key 下新建一个带有写入权限的公钥即可。

别忘了将导出的私钥保存到项目设置的 Secrets 里面,机密的数据要放在安全的位置呢。Secrets的命名比较有讲究,因为要作为环境变量传递到设置中去,建议使用全部大写的字母,使用下划线进行分割,以避免可能出现的问题。

准备完成之后,就可以正式开始构建Actions工作流啦。

构建Actions

可以从推荐的模板直接新建默认样例文件一样的工作流,或是选择自己创建一个工作流(”set up a workflow yourself”)。但相对于单纯的模板而言,我们的工作显得比较更加复杂,所以就还是根据操作提示,一步一步构建独属于我们的工作流吧。

Github Actions使用的是yml格式的配置文件,使用缩进之间的分别关系来定义不同行之间的层级,因此请严格遵守模板的缩进规则,以避免由于缩进设置错误导致的结构混乱。高亮显示时会将文首统一的缩进空格抹去,因此片段性的代码仅供参考,具体设置还请参见完整的工作流文件

触发事件

由于是对于这个版本主分支的提交事件才会进行样例站的构建,因此仅需在触发事件中留下如下的内容即可:

1
2
3
on:
push:
branches: [ master ]

工作任务

由于不同的工作任务涉及到不同的环境配置,不知道是否会对文件进行相关的迁移,因此我选择仅保留一个运行在ubuntu-latest上的build任务,以避免不同环境对生成的文件结构的影响。

设置环境变量

首先是准备任务级的环境变量(我有事先把变量整合在一起的习惯,您也可以仅为需要的任务分别准备环境变量),因此我们在标示运行环境的runs-on下标注env环境变量,例如分别给出站点的地址和头像的链接:

1
2
3
env:
SITE_URL: kr-demo.candinya.com
AVATAR_LINK: https://cn.gravatar.com/avatar/a7f9e15fef26e0a540edc977e21cb3eb

环境变量定义完毕之后,就可以开始准备需要进行的步骤了。

准备运行环境

首先需要准备一个Node.js环境,我们可以直接使用已经预定义好的动作模板进行简化操作。由于Hexo目前与Node.JS v14的兼容性还存在些许的问题,因此现阶段并不推荐使用v14作为构,建的环境,根据模板的提示,我们可以这样构建获取:

1
2
3
4
# Setup Node.js env
- uses: actions/[email protected]
with:
node-version: '12.x'

获取测试资源

当node环境架构完成之后,是时候获取Hexo主题组件测试资源了。同样,为了简化操作流程,我们可以参照模板自带的样例,使用预定义的checkout来拉取所需要的组件代码:

1
2
3
4
# Get Hexo test utils
- uses: actions/checkout@v2
with:
repository: 'hexojs/hexo-theme-unit-test'

获取主题文件

之后,我们需要为需要测试的主题准备一个文件夹。我们可以:

1
2
3
# Make dirs for themes
- name: Make dirs for themes
run: mkdir themes

主题文件夹建立完成之后,我们就可以将我们的项目拉取到themes文件夹下的指定目录了;我们只需要拉取存放了主题文件那一枝的文件即可:

1
2
3
# Clone Kratos-Rebirth into themes dir
- name: Clone Kratos-Rebirth into themes dir
run: git clone --single-branch --branch master https://github.com/${GITHUB_REPOSITORY} ./themes/kratos-rebirth

修改配置参数

到这时,基本的生成环境已经准备完毕,我们可以开始修改相关的配置参数了:

1
2
3
4
5
6
7
8
9
10
11
# Edit hexo site settings
- name: Edit Hexo site settings
run: |
sed -i "s/title: Hexo/title: Kratos-Rebirth/" "_config.yml"
sed -i "s/subtitle:/subtitle: A demo site of theme Kratos Rebirth/" "_config.yml"
sed -i "s/description:/description: A demo site of theme Kratos Rebirth/" "_config.yml"
sed -i "s/author: John Doe/author: Candinya/" "_config.yml"
sed -i "s/language:/language: zh-CN/" "_config.yml"
sed -i "s|url: http://yoursite.com|url: https://${SITE_URL}|" "_config.yml"
sed -i "s|permalink: :year/:month/:day/:title/|permalink: posts/:title/|" "_config.yml"
sed -i "s/theme: landscape/theme: kratos-rebirth/" "_config.yml"

额外注意指令里的双引号,如果使用单引号,则里面的环境变量不会被转义,就会出现这样的尴尬情况:

如果我们的主题还有对于站点相关的附加选项的话,也不要忘记一并加入站点设置:

1
2
3
# Append more settings into site settings
- name: Append theme-specified settings into site configs
run: cat "themes/kratos-rebirth/_config.yml.site.example" >> "_config.yml"

之后,我们需要复制一份主题的设置样例成为正式的设置文件;之所以不使用直接设置的方式,是因为害怕我们的相关升级会对用户的配置造成不可逆转的损伤,因此出于安全起见,更推荐使用配置样例的方式,进而为用户提供更高的安全性与客制化程度:

1
2
3
# Copy theme settings
- name: Copy theme settings
run: cp "themes/kratos-rebirth/_config.yml.example" "themes/kratos-rebirth/_config.yml"

复制完成后,对配置文件进行一定的编辑吧:

1
2
3
4
5
6
# Edit theme settings
- name: Edit theme settings
run: |
sed -i "s|site_logo:|site_logo: ${AVATAR_LINK}|" "themes/kratos-rebirth/_config.yml"
sed -i "s|comments: disqusjs|comments:|" "themes/kratos-rebirth/_config.yml"
sed -i "s|avatarUri: /images/avatar.webp|avatarUri: ${AVATAR_LINK}|" "themes/kratos-rebirth/_config.yml"

此时站点的主要设置就已经初步完成,为了生成后的站点中含有Pages正常工作所需的CNAME文件,我们手动生成一份并将其写入(当然也可以在站点生成完成之后直接写入public文件夹,这都没有问题):

1
2
3
4
5
# Set Pages CNAME file
- name: Set github pages CNAME file
run: |
touch "source/CNAME"
echo "${SITE_URL}" > source/CNAME

安装Hexo环境

当这一切都完成之后,我们就可以开始运行npm install来根据package.json自动安装Hexo正常运行所需的组件了:

1
2
3
# Install Hexo env
- name: Install Hexo environment
run: npm install

设置Git配置

组件完成安装后,我们需要同步旧的站点文件,以便于后续提交升级使用;但若直接使用HTTPS抓取,在生成之后的提交会报一个认证失败的问题导致构建的文件无法被提交(可以参见这个失败的Build),因此我们需要使用SSH的方式进行拉取与推送。利用之前存储到项目secrets里的私钥,我们可以这样来设置git相关的配置选项:

1
2
3
4
5
6
7
8
9
10
# Setup git configs
- name: Setup git configs
run: |
git config --global user.name "Github Actions"
git config --global user.email "[email protected]"
# Set private key for deployment
mkdir -p ~/.ssh/
echo "${{ secrets.DEPLOY_KEY }}" | tr -d '\r' > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts

拉取站点文件

这样就能将拉取和提交所需的SSH验证方法都配置完成了。之后,我们单独拉取gh-pages分枝的文件至public文件夹,以便继承之前的git文件结构:

1
2
3
# Get released page files
- name: Get released page files
run: git clone --single-branch --branch gh-pages [email protected]:${GITHUB_REPOSITORY} ./public

但是为了防止从并不存在的分支拉取文件,我们先要手动建立这个分支,并存入一些我们觉得有意义的文件,提交上去之后才能在Github上出现。因此可以使用如下的指令(使用之前别忘了备份哦):

1
2
3
4
5
6
git checkout --orphan gh-pages # 新建一个独立的分支
rm -rf ./ # 清理干净工作区
touch CNAME # 新建一个CNAME文件,至于是否需要写入信息就看个人喜好啦
git add -A
git commit -am "Github Pages branch init"
git push --set-upstream origin gh-pages

至于为什么一定要是gh-pages这条branch,因为Github Pages只能发布在mater branch、master branch的docs文件夹或是gh-pages branch下(可参阅GitHub Pages 站点的发布源配置文档),因此为了避免对master branch的损毁,或是可能会造成跨项目的配置困难,还是就放置在gh-pages branch下部署吧

生成新的文件

现在,是时候生成我们的站点文件了。为了防止已经存在的资源文件不会被替换,我们可以手动指定强制生成参数:

1
2
3
# Hexo build demo site
- name: Hexo build demo site
run: npx hexo generate --force

推送部署

终于到了最终部署的时刻,是时候将生成的站点部署上去啦;顺带使用一个git的小技巧,标记处我们这来之不易的站点的生成时间吧:

1
2
3
4
5
6
7
# Deploy demo site
- name: Deploy demo site
run: |
cd ./public
git add -A
git commit -m "Update Demo Site at `date +'%Y-%m-%d %H:%M:%S'`"
git push

终于写完了,是不是可以提交上去,之后撒花庆祝一下了呢~

顺带官方提供了一个小badge可用于管理最新构建的信息,可以按照这个格式把图片放入到项目说明里面去哦

1
https://github.com/<OWNER>/<REPOSITORY>/workflows/<WORKFLOW_NAME>/badge.svg

具体的完整代码可以参阅主题的部署工作流文件哦,任何问题欢迎在评论区提出,祝大家也都能构建顺利啦w