一、前置知识

CI\CD 即:持续集成(Continuous Integration)、持续交付(Continuous Delivery)、持续部署(Continuous Deployment)。GitHub Actions 是一个持续集成和持续交付 (CI/CD) 平台,可用于自动执行构建、测试和部署管道,换句话说就是通过Actions帮助我们去执行hexo s & hexo g & hexo d的操作并推到xxx.github.io仓库中

二、参考教程

最近看了店长的自动化部署方案,感觉真不错,本地hexo g渲染比较慢,通过git push触发Github Actions执行渲染并推送到站点中,以下是看到过的一些教程,我主要借鉴了黑石的方案来实现我自己的需求,大家可以选择适合自己需求的方案

常量 解释
[Blogroot] 本地存放博客源码的文件夹路径
[SourceRepo] 存放博客源码的私有仓库名
[SiteBlogRepo] 存放编译好的博客页面的公有仓库名
Site指站点,例如xxx.github.io仓库
[Github Actions执行自动化部署] 执行hexo clean & hexo g & hexo d

三、解决方案

方案二是方案一的补充,方案一的所有设置都要做一遍

4.1、方案一

首先明确我的需求:本地[Blogroot]push到[SourceRepo]触发Github Ations执行自动化部署[GithubBlogRepo][服务器站点]

申请令牌

工作流也相当于一个虚拟机,token作用是在虚拟机上执行push操作,类似于通过给电脑和GitHub配置公私钥实现每次push时不需要输入密码

Settings->Developer->Personal access tokens->Generate new token

hexo自动化部署01

生成的令牌只会显示一次,记住令牌,如果忘记保存就删了重弄

hexo自动化部署02

更改博客配置文件

  deploy:
- - type: git
- repository:
- github: https://github.com/xxx/xxx.xxx.io.git,main
- tecent: xxxu@xxx.xx.xxx.xxx:/xxx/hexo.git,master
- #branch: main

deploy:
+ - type: git
+ repository: https://填写自己的token@github.com/GC-ZF/GC-ZF.github.io.git
+ branch: main

新建私有仓库

新建一个私有仓库(必须私有,如果公有,上传仓库后,会触发GitHub规则token自动失效)

在博客根路径下,找到主题文件[Blogroot]\themes\butterfly,将**.git**移出来

在博客根路径下的.gitignore加入忽略规则

.DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/
.vscode/
/.idea/
.deploy_git*/
.idea
themes/butterfly/.git

在博客根路径下执行

git init
git add .
git commit -m "init"
git branch -M main
git remote add origin https://github.com/用户名/私有仓库名.git
git push -u origin main

之后就可以在仓库中看到博客源码

可能出现的错误:查看仓库中themes\butterfly中是否有文件,如果没有将电脑端themes整个文件夹移走,再次执行push,然后将themes文件夹移回来,再次push,仓库就有主题文件了,如果以后更新主题文件重复操作移走+push+移回来+push(具体原理无解,可能是hexo的机制)

git add .
git commit -m "init"
git push

配置Github Actions

创建[Blogroot]\.github\workflows\autodeploy.yml文件并写入,如果没有移除主题文件的.git第39行为主题文件地址,如果移除了.git,则删除39~42行

name: Deploy # 部署

on: # 触发条件
push:
branches:
- main # 推送到 main 分支(这里的分支名很重要,不要弄错了)

release:
types:
- published # 推送新版本号

workflow_dispatch: # 手动触发

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout # Checkout 仓库
uses: actions/checkout@v2
with:
ref: main

- name: Setup Node # 安装 Node.js
uses: actions/setup-node@v1
with:
node-version: "12.x"

- name: Install Hexo # 安装 Hexo
run: |
npm install hexo-cli -g
- name: Cache Modules # 缓存 Node 插件
uses: actions/cache@v1
id: cache-modules
with:
path: node_modules
key: ${{runner.OS}}-${{hashFiles('**/package-lock.json')}}

- name: 安装主题
run: |
git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly
# npm install hexo-renderer-pug hexo-renderer-stylus --save

- name: Install Dependencies # 如果没有缓存或 插件有更新,则安装插件
if: steps.cache-modules.outputs.cache-hit != 'true'
run: | # **如果仓库里没有 package-lock.json,上传一下,npm ci 必须要有 package-lock.json**
npm ci
- name: Generate # 生成
run: |
hexo clean
hexo generate
- name: Deploy # 部署
run: |
git config --global user.name '${{ secrets.GITHUBUSERNAME }}'
git config --global user.email '${{ secrets.GITHUBEMAIL }}'
git clone https://github.com/GC-ZF/GC-ZF.github.io.git .deploy_git
export TZ='Asia/Shanghai'
hexo deploy

- name: push VPS # 部署到云服务器
uses: cross-the-world/scp-pipeline@master
with:
host: ${{ secrets.USER_HOST }}
user: ${{ secrets.USER_NAME }}
pass: ${{ secrets.USER_PASS }}
connect_timeout: 10s
local: './.deploy_git/*'
remote: ${{ secrets.VPSSITE }}

配置环境变量

之后需要自己到仓库的Settings->Secrets->actions 下添加环境变量,依次添加

hexo自动化部署03

在博客根路径执行

git add .
git commit -m "add actions"
git push

查看actions运行结果,以及xxx.github.io仓库、服务器站点路径中是否更新(可能出现的错误,用户权限不足)

hexo自动化部署04

4.2、方案二(推荐)

使用方案一,github毕竟是外网,服务器在大陆,同步给服务器这一步骤速度感人,第一次同步大概需要半个多小时,当服务器存在文件之后的同步需要5分钟左右,GitHub Actions每个月普通用户只有2000分钟,抛开付费,就这个时间长短不是我的预期,@二花提供给我一个思路,当xxx.github.io仓库有更新自动同步给Gitee,然后服务器执行git clone https://gitee.com/xxx/xxx.git,实测速度不超10s

新建Gitee公有仓库

在Gitee新建一个仓库,并添加默认文件README.md(Github执行工作流,Gitee不能为空,我也不知道为什么,只是见报错提示了),将仓库**公开并确保main**是主分支

利用ssh工具

cd /www/wwwroot/hexo							# 到站点路径下
git clone https://gitee.com/gc-zhang/blog.git # 克隆gitee的仓库

设置网站根目录为blog即我Gitee的仓库名字

hexo自动化部署06

配置密钥

配置密钥是为了让Github和Gitee之间连通,实现同步操作

  1. 在电脑命令行终端或 Git Bash 使用命令 ssh-keygen -t rsa -C "任意命名" -f "id_rsa_github to gitee" 生成 SSH Key。(⚠️注意直接连续三次回车,此处不要设置密码,生成的公私钥用于下面 GitHub / Gitee 的配置,以保证公私钥成对,否则从 GitHub -> Gitee 的同步将会失败。)生成的 id_rsa_github to gitee 是私钥,id_rsa_github to gitee.pub 是公钥。

  2. 在 私有仓库 的「Settings -> Secrets」路径下配置好命名为 Github sncy to GiteeGITEE_PASSWORD 的两个变量。其中:GITEE_RSA_PRIVATE_KEY 存放 id_rsa 私钥;GITEE_PASSWORD 存放 Gitee 帐号的密码。

  1. 在 GitHub 的个人设置页面「Settings -> SSH and GPG keys」配置 SSH 公钥(即:id_rsa_github to gitee.pub),命名随意。
  2. 在 Gitee 的个人设置页面「安全设置 -> SSH 公钥」配置 SSH 公钥(即:id_rsa_github to gitee.pub),命名随意。

关注 Gitee 公众号

如果不需要使用gitee的静态页面跳过此步,如果使用,先做完实名认证再把仓库的Gitee Page打开,确保可以打开,否则工作流会不通过

关注 Gitee 官方公众号,并绑定个人 Gitee 帐号,用于接收帐号登录通知、以及绕过短信验证码校验,见错误及解决方案 第 3 点。

配置Github Actions

在方案一的基础上修改[Blogroot]\Blog\.github\workflows\autodeploy.yml,看64行之后跟着注释配置

name: Deploy # 部署

on: # 触发条件
push:
branches:
- main # 推送到 main 分支(这里的分支名很重要,不要弄错了)

release:
types:
- published # 推送新版本号

workflow_dispatch: # 手动触发

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout # Checkout 仓库
uses: actions/checkout@v2
with:
ref: main

- name: Setup Node # 安装 Node.js
uses: actions/setup-node@v1
with:
node-version: "12.x"

- name: Install Hexo # 安装 Hexo
run: |
npm install hexo-cli -g
- name: Cache Modules # 缓存 Node 插件
uses: actions/cache@v1
id: cache-modules
with:
path: node_modules
key: ${{runner.OS}}-${{hashFiles('**/package-lock.json')}}

- name: Install Dependencies # 如果没有缓存或 插件有更新,则安装插件
if: steps.cache-modules.outputs.cache-hit != 'true'
run: | # **如果仓库里没有 package-lock.json,上传一下,npm ci 必须要有 package-lock.json**
npm ci
- name: Generate # 生成
run: |
hexo clean
hexo generate
- name: Deploy # 部署
run: |
git config --global user.name '${{ secrets.GITHUBUSERNAME }}'
git config --global user.email '${{ secrets.GITHUBEMAIL }}'
git clone https://github.com/GC-ZF/GC-ZF.github.io.git .deploy_git
export TZ='Asia/Shanghai'
hexo deploy

- - name: push VPS # 部署到云服务器
- uses: cross-the-world/scp-pipeline@master
- with:
- host: ${{ secrets.USER_HOST }}
- user: ${{ secrets.USER_NAME }}
- pass: ${{ secrets.USER_PASS }}
- connect_timeout: 10s
- local: './.deploy_git/*'
- remote: ${{ secrets.VPSSITE }}

# 删除方案一,“push VPS”接着往下写
- name: Sync to Gitee # 同步Gitee
uses: wearerequired/git-mirror-action@master
env:
# 注意在 Settings->Secrets 配置 GITEE_RSA_PRIVATE_KEY
SSH_PRIVATE_KEY: ${{ secrets.GITEE_RSA_PRIVATE_KEY }}
with:
# 注意替换为你的 GitHub 源仓库地址
source-repo: git@github.com:GC-ZF/GC-ZF.github.io.git
# 注意替换为你的 Gitee 目标仓库地址
destination-repo: git@gitee.com:gc-zhang/blog.git

# 如果需要Gitee Page,取消注释
# - name: Build Gitee Pages
# uses: yanglbme/gitee-pages-action@main
# with:
# # 注意替换为你的 Gitee 用户名
# gitee-username: gc-zhang
# # 注意在 Settings->Secrets 配置 GITEE_PASSWORD
# gitee-password: ${{ secrets.GITEE_PASSWORD }}
# # 注意替换为你的 Gitee 仓库,仓库名严格区分大小写,请准确填写,否则会出错
# gitee-repo: gc-zhang/blog
# # 要部署的分支,默认是 master,若是其他分支,则需要指定(指定的分支必须存在)
# branch: main

- name: VPS clone Gitee # 连接服务器并克隆Gitee
uses: cross-the-world/ssh-pipeline@master
env:
WELCOME: "ssh pipeline"
with:
host: ${{ secrets.USER_HOST }}
user: ${{ secrets.USER_NAME }}
pass: ${{ secrets.USER_PASS }}
connect_timeout: 10s
script: |
cd /www/wwwroot/hexo/blog # cd /站点路径/Gitee的仓库名字
git pull

配置环境变量

hexo自动化部署05

在博客根路径执行

git add .
git commit -m "add actions"
git push
  1. 检查github私有仓库是否触发工作流,工作流结束之后
  2. 查看Gitee仓库是否更新
  3. 查看服务器站点目录是否更新或直接访问站点
  4. 部署完毕!100篇文章用时2min已经很快了

第三步站点目录未更新?有时可能会由于服务器网络问题导致服务器同步Gitee仓库失败,单独拿出服务器更新这一步,再建一个手动触发的Action[Blogroot]\Blog\.github\workflows\handdeploy.yml,修改21~23,当第三步更新失败可以在Github仓库下手动执行此Action

name: Hand Deploy # 部署

on: # 触发条件
workflow_dispatch: # 手动触发

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: VPS clone Gitee # 连接服务器并克隆Gitee
uses: cross-the-world/ssh-pipeline@master
env:
WELCOME: "ssh pipeline"
with:
host: ${{ secrets.USER_HOST }}
user: ${{ secrets.USER_NAME }}
pass: ${{ secrets.USER_PASS }}
connect_timeout: 10s
script: |
cd /www/wwwroot/hexo # cd /站点路径
rm -rf blog # rm -rf Gitee的仓库名字
git clone https://gitee.com/gc-zhang/blog.git # Gitee仓库

彩蛋?这样自动化部署的目的还有一个优点,你可以直接在[SourceRepo]即Github博客源码仓库中直接修改文章提交后自动触发Github Ations执行自动化部署[GithubBlogRepo]GiteeBlogRepo[服务器站点],有点typecho那感觉了吧嘿嘿,之后本地同步通过在博客路径下git pull同步仓库源码,是不是很方便!小张已经尽力去记录全过程了,如果感觉太晦涩难懂,先简单学习一下git版本控制,或者向我提问嘿嘿


最后感谢@二花指点我好多,自己第一次学着写工作流,边学边写,二花不仅给我讲了特别多我不懂的原理,还提供了Gitee充当媒介的方案,真的好棒!