Hugo + GitHub Action + Github Pages，搭建博客自动发布

我的方案由以下两个核心部分：

博客源仓库，对博客配置及所有文章 .md 源文件进行版本管理，配合 GitHub Action 进行自动化部署，自动生成静态站点推送到 GitHub Pages 博客发布仓库。

GitHub Pages 博客发布仓库，使用 GitHub Pages 实现网站部署，可以通过域名 CNAME 解析使用自定义域名。

使用 Hugo 搭建博客

Hugo 是用 Go 实现的博客工具，采用 Markdown 进行文章编辑，生成静态站点文件，支持丰富的主题配置，也可以通过 js 嵌入像是评论系统等插件，高度定制化。除了 Hugo 外， 还有 Gatsby、Jekyll、Hexo、Ghost 等选择，实现和使用都差不多，可以根据自己的偏好进行选择。

安装 Hugo

我使用的是 macOS，所以使用官方推荐的 homebrew 方式进行 hugo 程序的安装，其他系统可参考官方文档。

Copy
brew install hugo

完成后，使用以下命令进行验证 (查看版本号)：

Copy
hugo version

创建 Hugo 网站

Copy
hugo new site blog-demo

配置主题

创建我们的站点后，需要进行主题配置，Hugo 社区有很丰富的主题，可以通过官网 Themes 菜单选择自己喜欢的风格，查看预览效果，选择后可以进入主题项目仓库，一般都会有很详细的安装及配置说明。下面我就以我目前在使用的 smol 这个主题为例，演示一下配置流程。

Copy
cd blog-demo
git clone git@github.com:colorchestra/smol.git themes/smol
cd themes/smol
rm -rf .git

初始化主题基础配置后，我们可以在 config.toml 文件中进行站点细节配置，具体配置项参考主题说明文档。

参考 config.toml 内容

Copy
theme = "smol"

发布新文章

Copy
hugo new posts/blog-test.md

本地调试站点

进行本地实时调试预览。

Copy
hugo server

运行服务后，我们可以通过浏览器 http://localhost:1313 地址访问我们的本地预览网页。

GITHUB PAGES 仓库

GitHub Pages 仓库建立完成后，可以在设置中配置自己注册的自定义域名来指向 GitHub Pages 生成的网址。此外，需要将博客站点配置文件 config.toml 中的 baseURL 改为自己的自定义域名。

GitHub Pages 发布博客

我们现在已经可以通过自定义域名来访问我们的 GitHub Pages 页面了，目前因为项目仓库是空的，访问后会报 404 页面。

Hugo 生成的静态网站通过 GitHub Pages 服务进行托管，因此我们需要上传 Hugo 生成的静态网页文件至 GitHub Page 项目仓库。

手动发布

Copy
hugo
cd public

Hugo 默认会将生成的静态网页文件存放在 public/ 目录下，我们可以通过将 public/ 目录初始化为 git 仓库并关联我们的 clin003/blog_html 远程仓库来推送我们的网页静态文件。

Copy
git init
git remote add origin git@github.com:baicaime/meBlog
git add .
git commit -m "debug"
git push origin main

推送到 GitHub Pages 仓库，稍等几分钟即可通过我们的自定义域名来访问我们的博客站点了，和

Copy
hugo server

本地调试完全一致。

自动发布

因为我们的博客基于 GitHub 与 GitHub Pages，可以通过官方提供的 GitHub Action 进行 CI 自动发布。
GitHub Action 是一个持续集成和持续交付 (CI/CD) 平台，可用于自动执行构建、测试和部署管道，可以通过简单的配置即可直接使用。

配置在仓库目录
.github/workflows
下，以 .yml 为后缀。我的 GitHub Action 配置为
deploy.yml
自动发布示例配置如下：

Copy
name: Deploy Hugo site to Pages
on:
push:
branches: [ "main" ]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
defaults:
run:
shell: bash
env:
NAME: BLOG_push
# 推送目标仓库 格式 用户名/仓库名
TARGET_REPOSITORY_NAME: baicaime/meBlog
# 同步临时目录(可选)
CLONE_DIR: tmp_public
# 构建临时目录(可选)
BUILD_DIR: tmp_build
# 配置git用户名
GIT_USERNAME: baicaime

jobs:
# This workflow contains a single job called "build"
build:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.117.0
steps:
- name: Install Hugo CLI
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
- uses: actions/checkout@v3
- name: Build with Hugo
env:
# For maximum backward compatibility with Hugo modules
HUGO_ENVIRONMENT: production
HUGO_ENV: production
run: |
hugo \
--minify \
--baseURL "${{ steps.pages.outputs.base_url }}/" \
-d ${{ env.BUILD_DIR }}

- name: Git Config
run: |
git config --global user.email "actions-push-noreply@baicai.me"
git config --global user.name "${{ env.GIT_USERNAME }}"
echo "配置git完成"

- name: Git clone
run: |
echo "同步目标仓库(开始)"
git clone --depth 1 https://github.com/${{ env.TARGET_REPOSITORY_NAME }}.git ${{ env.CLONE_DIR }} &> /dev/null
echo "同步目标仓库(完成)"

- name: Git push
run: |
cp -rf ${{ env.BUILD_DIR }}/* ${{ env.CLONE_DIR }}/
cd ${{ env.CLONE_DIR }}
echo "${{ github.event.head_commit.message }} `date +%FT%T%z`" > _pub_time.html
git add .
git commit --message "Update ${{ env.NAME }} from ${{ env.TARGET_REPOSITORY_NAME }} ${{ github.event.head_commit.message }}"
git push -f -q https://oauth2:${{ secrets.GIT_TOKEN }}@github.com/${{ env.TARGET_REPOSITORY_NAME }}.git main
echo "git push ${{ env.TARGET_REPOSITORY_NAME }} (完成)"

on 表示 GitHub Action 触发条件，我设置了 push 和 workflow_dispatch 两个条件：

push，当这个项目仓库发生推送动作后，执行 GitHub Action

workflow_dispatch，可以在 GitHub 项目仓库的 Action 工具栏进行手动调用

jobs 表示 GitHub Action 中的任务，我们设置了一个 build 任务，
runs-on 表示 GitHub Action 运行环境，我们选择了 ubuntu-latest。
build 任务包含了 Install Hugo CLI 、Checkout、Build with Hugo、Git Config、Git clone 和 Git push 六个主要步骤，
其中 run 是执行的命令，uses 是 GitHub Action 中的一个插件，我们使用了 actions/checkout 这个插件。
其中 Checkout 步骤中，可以在 with 中配置 submodules 值为 true 同步博客源仓库的子模块（比如主题模块，由于我们没有使用子模块方式安装 hugo 主题，所以不需要这个参数）。

需要将上述 deploy.yml 中：

Copy
TARGET_REPOSITORY_NAME 改为自己的 GitHub Pages 仓库，如我的设置为 baicaime/meBlog
GIT_USERNAME 改为自己 GitHub Pages 仓库的用户名

因为我们需要从博客仓库推送到外部 GitHub Pages 仓库，需要特定权限，要在 GitHub 账户下 Setting - Developer setting - Personal access tokens 下创建一个 Token。

权限需要：

Copy
Contents read/write

配置后复制生成的 Token（注：只会出现一次），然后在博客源仓库的

Copy
Settings - secrets and variables - Actions

中添加

Copy
GIT_TOKEN

环境变量为刚才的 Token，这样 GitHub Action 就可以获取到 Token 了。

推送测试

完成上述配置后，推送代码至仓库，即可触发 GitHub Action，自动生成博客页面并推送至 GitHub Pages 仓库。

GitHub Pages 仓库更新后，又会自动触发官方页面部署 CI，实现网站发布。

现在每当我们本地通过熟悉的 Markdown 语法完成博客内容编辑后，只需要推送代码，等待几分钟，即可通过我们的自定义域名访问更新后的网站。

以上就是我通过 Hugo 与 GitHub Action 实现的博客自动部署系统，我自己的实现仓库在 baicaime/meBlog 仓库中