迁移 Hexo 博客于 GitHub 并使用 GitHub Actions 进行编译及部署

前言

因为最近 4 个月都没有电脑用,而想写点博客也只能在公众号写,无法用自己的电脑部署,不够爽,加上之前有看到可以利用 GitHub Actions 功能进行云编译和部署,遂尝试一下。毕竟未来数月也没有电脑用,总要写点东西打发时间。

本文适用于在本地电脑已有 Hexo 文件夹的用户,目标是将源文件迁移到 GitHub 中,并使用 GitHub Actions 功能在提交新的文章后自动进行编译与部署,减少操作步骤,提升使用体验。在某种程度上,也避免了对于电脑的依赖。(当然你也可以本地安装了 Hexo 和主题后上传)

步骤

定义

首先做出本文定义,以为了表达明确:

  • 假设读者为位于大陆境内,熟练掌握通灵术的用户,且已有 GitHub 账户。

  • 在 GitHub 上,储存原始 Hexo 文件的 repository 为私有仓库 Blog, 例如 github.com/user/blog

  • 在 GitHub 上,部署公开文件的 repository 为公开仓库 Public, 例如 github.com/user/user.github.io

  • 对于一般(白嫖)用户,GitHub 私人仓库使用限制为 2000 分钟/月,每次执行编译时间不一,视文章数量及插件使用数量而定,约 2 分钟, 完全能够满足个人部署需求及试错学习。

  • 坚决抵制用 main 替代 master, 反正出 bug 了不可能手动去修的。

使用 GitHub Desktop 上传

由于 GitHub 网页上传有限制,体验不佳,建议下载 GitHub Desktop 来上传。

使用 Netch 全局通灵

为啥不使用路由或是一般的软件呢,因为他们功力不够强,无法通灵命令行。

Netch 发布页面在→这里

具体设置自行领会

建立 Blog

打开 GitHub Desktop

1.png

2.png

打开本地 Hexo 文件夹,除了public .depoloy_git node_modules 外,其他都复制到 Blog 文件夹

创建 commit

3.png

Push 到 GitHub

4.jpg

创建 SSH 密匙 (此部分引用 sanonz 的文章)

1
ssh-keygen -f github-deploy-key

当前目录下会有 github-deploy-keygithub-deploy-key.pub 两个文件。

添加 SSH 密匙到 repository (此部分引用 sanonz 的文章)

复制 github-deploy-key 文件内容,在 Blog 仓库 Settings -> Secrets -> Add a new secret 页面上添加。

  1. Name 输入框填写 HEXO_DEPLOY_PRI
  2. Value 输入框填写 github-deploy-key 文件内容。

add-secret

复制 github-deploy-key.pub 文件内容,在 your.github.io 仓库 Settings -> Deploy keys -> Add deploy key 页面上添加。

  1. Title 输入框填写 HEXO_DEPLOY_PUB
  2. Key 输入框填写 github-deploy-key.pub 文件内容。
  3. 勾选 Allow write access 选项。

add-key

创建 GitHub Actions (此部分引用 sanonz 的文章)

Workflow 模版

Blog 仓库根目录下创建 .github/workflows/deploy.yml 文件。

deploy.yml 文件中粘贴以下内容。

我修改之后的版本在后面,下面这个作为参考吧

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
name: CI

on:
push:
branches:
- master

env:
GIT_USER: Sanonz
GIT_EMAIL: sanonz@126.com
THEME_REPO: sanonz/hexo-theme-concise
THEME_BRANCH: master
DEPLOY_REPO: sanonz/sanonz.github.io
DEPLOY_BRANCH: master

jobs:
build:
name: Build on node ${{ matrix.node_version }} and ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest]
node_version: [12.x]

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Checkout theme repo
uses: actions/checkout@v2
with:
repository: ${{ env.THEME_REPO }}
ref: ${{ env.THEME_BRANCH }}
path: themes/concise

- name: Checkout deploy repo
uses: actions/checkout@v2
with:
repository: ${{ env.DEPLOY_REPO }}
ref: ${{ env.DEPLOY_BRANCH }}
path: .deploy_git

- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node_version }}

- name: Configuration environment
env:
HEXO_DEPLOY_PRI: ${{secrets.HEXO_DEPLOY_PRI}}
run: |
sudo timedatectl set-timezone "Asia/Shanghai"
mkdir -p ~/.ssh/
echo "$HEXO_DEPLOY_PRI" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts
git config --global user.name $GIT_USER
git config --global user.email $GIT_EMAIL
cp _config.theme.yml themes/concise/_config.yml

- name: Install dependencies
run: |
npm install

- name: Deploy hexo
run: |
npm run deploy

执行任务

在此仓库 Actions 页面查看当前 task。

run

当任务完成后查看你的博客 https://your.github.io,如果不出意外的话已经可以看到新添加的文章了。

效果

pros.

✔️ 利用 GitHub Desktop, 可以实现在电脑写作好了,一键 push 到部署。

✔️ Git 的版本控制可实现文字基本不会丢,当然还是建议和 Dropbox 一同使用以增加安全感。

✔️ 安卓大概可以用纯纯写作来写一下了?(也太麻烦了吧,目前还没找到一个无缝对接 GitHub 的 安卓 Markdown 编辑器)

✔️ 自动化操作,幸福感 max.

✔️ 白嫖,幸福感 max plus.

cons.

🔴 abbrlink 插件无法针对原文件进行修改,即 header 里不会出现 abbrlink: XXXXX, 对于强迫症不能忍。实际多次 push 后新文章 link 不会变,勉强能接受。 已于下文解决。

🔴 如果开启了 “更新于” 功能,所有文章更新时间全都是最新一次 push 的时间了。 于下文有解决方式。

🔴 如果不特意保存 .git 文件夹,则所有 git 历史均被清空,以上模板就会导致如此。于下文有解决方式。

针对遇到的问题及作出的尝试

遇到的问题

1 Git 历史丢失

描述:user.github.io 中 commits 历史记录消失,就真的找不回来了。(这就是我陈年文章都变成最近更新的原因了。)

原因:GitHub Actions 相当于在一台新电脑里执行 push 操作,自然是不存在以前的 .git 文件的。

解决方式:已经丢失的找不回来了。还没丢失的,先备份一个吧。Workflow 里添加几个步骤,将 user.github.io 的 git 记录搬运回来,再执行 push,就可以把新的 commits 加到旧的里面了。

2 旧文章更新日期被替换为更新日期

描述:访问文章,可见 “更新于” 的时间为 push 的时间

原因:Hexo 将 mtime 即文件修改时间,作为了文件的 updated 时间。如果在个人电脑上,这个逻辑说得过去,但于 CI 这样的云端,每个文件都是新鲜下载的,时间当然会变。而 git 本身是不保存文件修改时间的。原因:在这里。看到了几篇可以参考的文章,都说可以用命令行把文件修改时间改为上次 git 时间,达到近似修改时间的作用,对于博客来说,时间精确度要求确实没那么高。而在多次测试后,才发现原来是 checkout 步骤里,默认的 clone 深度只有 1, 意味着位于子文件夹内的文章 md 文件的记录并没有被下载到。所以多看看 wiki 是多么重要。尬。

不完全解决方式:5.0.0 Hexo 的配置文件 _config.yml 里面的 updated_option: 'mtime' 将 mtime 更改为 date, 这样就更新时间就和发布时间一致了。如果特别需要更新时间,则在文章的 header 部分,添加 updated: 2020-10-07 12:54:21 这样就可以了。

解决方式: 在 Workflow 里,添加 checkout 的深度参数 fetch-depth: 0, 之后再添加一个恢复修改时间的命令。

描述:位于私有仓库的新文章,执行 Actions 之后并没有在文章的 header 处增加 abbrlink, 而在公开仓库的新文章多次部署的 abbrlink 均唯一(更改标题后会改变,大概是按标题来运算的),基本不影响访客体验。

原因:当然是没有 push 到 私人仓库呀。但是如果这样做,又会触发一个 Actions, 陷入无限循环。我的设想是:在 Workflow 开头设定筛选,只有用户的 push 才能触发,GitHub Actions BOT 则不能,最后加上由 GitHub Actions BOT 执行 push, 把修改后的文件 push 回私人仓库。

解决方式:看了 GitHub 的指南,没有这个选择。但是忽然想到之前玩云编译 OpenWrt 时候,可以设定对点星星的用户 id 进行判定,如果是本人,则执行 Workflow, 如果是其他人,则不执行。所以得出:在 push 到公开仓库后,更改 git 用户为机器人,创建 commit 和进行 push, 这样就不会触发了。

最终的 Workflow 文件

复制粘贴后记得删除#后面的内容呀,出错了我可不负责!

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
name: HEXO CI

on:
push:
branches:
- master #目前 GitHub 已使用 main 来替代 master 分支,自行注意
watch:
types: started #此处设置点星星可以执行文件,方便进行向搜索引擎推送或测试

env:
TZ: Asia/Shanghai #时区:上海
GIT_USER: user #你的 GitHub 用户名,自行替换
GIT_EMAIL: user@hotmail.com #你的 GitHub 用户邮箱,自行替换
HEXO_DEPLOY_PRI: ${{secrets.HEXO_DEPLOY_PRI}} #密匙
GITHUB_REPO: github.com/user/user.github.io #你的 GitHub 公共仓库地址,自行替换

jobs:
build:
if: github.event.repository.owner.id == github.event.sender.id
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest] #选择运行系统
node_version: [12.x] #选择 Node 版本
steps:
- name: Set Timezone to UTC+8 #设置时区
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo timedatectl set-timezone "$TZ"

- name: Checkout codes #克隆私有仓库代码
uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Last Modify Time Revert #恢复上次修改时间
run: |
git ls-files -z | while read -d '' path; do touch -d "$(git log -1 --format="@%ct" "$path")" "$path"; done

- name: Use Node.js ${{ matrix.node_version }} #运行 Node
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node_version }}

- name: Cache node modules #缓存 Node 模块
uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

- name: Configuration environment #设置 SSH 及 Git
run: |
mkdir -p ~/.ssh/
echo "$HEXO_DEPLOY_PRI" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts
git config --global user.name $GIT_USER
git config --global user.email $GIT_EMAIL

- name: Install dependencies #安装 Hexo 及依赖包
run: |
npm i -g hexo-cli
npm i

- name: Genarate hexo
run: |
git clone "https://$GITHUB_REPO" public #克隆公开仓库
git clone "https://$GITHUB_REPO" .deploy_git #克隆公开仓库
hexo clean
hexo g

- name: Deploy hexo blog #部署 Hexo
run: |
hexo d

- name: Reset Git config #重置 git 用户为 BOT
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .
git diff --quiet && git diff --staged --quiet || git commit -am '回传更新'

- name: Re-upload to Private Repository #回传回私有仓库
uses: ad-m/github-push-action@v0.5.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}

此外,你还可以自行修改,增加运行成功的信息推送到微信或者 Telegram. 顺带,如果要添加第三方的插件,可直接在 package.json 里定义就行了,简单。运行成功后,相关的包的版本会自动回传到 package-lock.json 以用于下次 Node 模块缓存,无需在意了。

1
2
3
4
5
6
7
推荐使用的插件:
hexo-abbrlink
hexo-deployer-git
hexo-generator-sitemap
hexo-lazyload-image
hexo-submit-urls-to-search-engine
添加之后,参考他们的官方指南,在 _config.yml 或者主题的配置文件中做好修改。

参考文章

https://github.com/marketplace/actions/hexo-action

https://hdj.me/github-actions-hexo-cicd/

https://juejin.im/post/6854573218779381773

https://sanonz.github.io/2020/deploy-a-hexo-blog-from-github-actions/

https://xirikm.net/2020/313-1

https://cjh0613.com/20200603HexoSubmitUrlsToSearchEngine.html

https://hexo.io/zh-cn/docs/configuration.html

https://stackoverflow.com/a/40255467

https://github.com/actions/checkout

迁移 Hexo 博客于 GitHub 并使用 GitHub Actions 进行编译及部署

https://soacg.pp.ua/posts/61081/

作者

左吉士

发布于

2020-10-05

更新于

2020-10-11

许可协议

评论