准备工作

创建两个Github仓库

  • 用来放org文件、markdown文件及Hugo相关配置,可以设置成私有,如blog。
  • Github Pages仓库,用来放生成的静态文件。一般是{username}.github.io。

安装Hugo

  • a static site generator written in Go

安装ox-hugo

  • 将org文件翻译成markdown文件,written in Emacs Lisp。Hugo支持Org Mode,但据说支持得不是很好1。毕竟Emacs Lisp处理org文件相关的包比Go多,就直接用ox-hugo转markdown的方案了。

不是Emacs用户?

  • 可跳过Org Mode相关内容

配置环境

各软件版本

  • Emacs 27.1
  • Org Mode 9.3
  • ox-hugo 20210916.1332
  • Hugo v0.89.4

1、配置Hugo

1
2
3
4
5
# 在blog仓库中新建hugo site
cd /path/to/blog && hugo new site hugo
# 选个主题,并设置成子模块(后续升级/替换都比较方便)
git submodule add https://github.com/olOwOlo/hugo-theme-even.git hugo/themes/even
# 修改默认配置

2、开启本地实时预览

1
2
# 配置修改、markdown文件改动都会被监控到
cd blog && hugo --source hugo server -D

3、配置ox-hugo

1
2
3
4
5
6
;;; 在init.el里或其他文件里加以下代码
(with-eval-after-load 'ox
  (require 'ox-hugo))

;;; 可选。全局配置,如导出目录等字段,也可以在org文件里进行配置
;;; M-x customize-variable org-hugo

写博客

1、新建org目录及文件

1
2
cd blog && mkdir -p org/2021/11
# 可选,可以不按年月日分拆分目录。拆分后方便管理,但如果用户直接访问某年的数据,页面就会404

2、新建org文件,如test.org

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#+OPTIONS: author:nil ^:{}
# 告诉ox-hugo将导出的markdown文件放到哪里。注意:even主题需要发布到post目录。
# see: https://ox-hugo.scripter.co/#before-you-export
#+HUGO_BASE_DIR: ../../../hugo
#+HUGO_SECTION: post/2021/11
#+HUGO_CUSTOM_FRONT_MATTER: :toc true
#+HUGO_AUTO_SET_LASTMOD: t
#+HUGO_DRAFT: false
#+DATE: [2021-11-28 Sun 19:28]
#+TITLE: 标题
#+HUGO_TAGS: tag1 tag2
#+HUGO_CATEGORIES: category1 category2

Hello,World

3、导出org到markdown文件

  • 在Emacs里执行C-c C-e H h(File to Md file)导出整个org文件到markdown文件,也可以导出subtree,具体看个人喜好

4、访问http://127.0.0.1:1313/
5、正常情况就会看到博客界面啦
6、提交org及markdown文件到blog仓库
7、使用Yasnippet(推荐) 下次新建文件就不用copy一些元数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# -*- mode: snippet -*-
# name: hugo
# key: hugo
# --
#+OPTIONS: author:nil ^:{}
#+HUGO_BASE_DIR: ../../../hugo
#+HUGO_SECTION: post/`(format-time-string "%Y/%m")`
#+HUGO_CUSTOM_FRONT_MATTER: :toc true
#+HUGO_AUTO_SET_LASTMOD: t
#+HUGO_DRAFT: false
#+DATE: `(format-time-string "[%Y-%m-%d %a %H:%M]")`
#+TITLE: $1
#+HUGO_TAGS: $2
#+HUGO_CATEGORIES: $3

$0

目录结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
  <!-- blog仓库目录结构如下 -->
  <!-- tree -a -d -L 3 -I .git -->
.
├── .github
│   └── workflows
├── hugo
│   ├── archetypes
│   ├── content
│   │   └── post
│   ├── data
│   ├── layouts
│   │   └── _internal
│   ├── static
│   └── themes
│       └── even
├── org
│   └── 2021
│       └── 11
└── scripts

部署篇

配置Github Action

在blog仓库下新增.github/workflows/main.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
name: GitHub Pages

on:
  push:
    branches:
      - main  # Set a branch to deploy
  pull_request:

jobs:
  deploy:
    runs-on: ubuntu-20.04
    concurrency:
      group: ${{ github.workflow }}-${{ github.ref }}
    steps:
      # 修改时区
      - name: Set Timezone
	run: sudo timedatectl set-timezone 'Asia/Shanghai'

      - uses: actions/checkout@v2
	with:
	  submodules: true  # Fetch Hugo themes (true OR recursive)
	  fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Setup Hugo
	uses: peaceiris/actions-hugo@v2
	with:
	  # 建议和本地用的版本保持一致,从而获得一致的体验
	  hugo-version: '0.89.4'
	  # extended: true

      - name: Build
	run: |
	  hugo --source hugo --minify --buildFuture --buildExpired

      - name: Deploy
	uses: peaceiris/actions-gh-pages@v3
	if: ${{ github.ref == 'refs/heads/main' }}
	with:
	  # github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
	  # publish_branch: gh-pages
	  # publish_dir: hugo/public
	  deploy_key: ${{ secrets.DEPLOY_KEY }}
	  external_repository: superbear/superbear.github.io
	  # 默认是master目录,github上可修改
	  publish_branch: master
	  publish_dir: hugo/public

配置DEPLOY_KEY

生成github deploy-keys
1、将公钥添加至{username}.github.io仓的Deploy keys(Settings -> Deploy keys)中;
2、将私钥添加至blog仓库的secrets(Settings -> Secrets)中;
3、将本地blog目录的改动push到远程blog仓库master分支;
4、正常情况下,一段时间之后,可以在{username}.github.io的master分支下看到hugo生成的静态文件;
5、没有的话,可以根据blog仓库的Github Actions日志排查下。

遇到的问题

1、部署完成却没有生成文件,就只有一个.nojekyll文件

1
2
<!-- actions log -->
cp: no such file or directory: /home/runner/work/blog/hugo/public/*

排查思路:排查Github Actions日志,以及写一些shell命令查看路径相关信息

2、Hugo生成静态文件报错,报错信息如下:

1
- unmarshal failed: Near line 4 (last key parsed 'tags'): Array contains values of type 'Integer' and 'String', but arrays must be homogeneous.

原因:tags的类型不一致,标签混用了数字和字符串
解决方案:去掉数字类型的标签或升级至最新版本的hugo

参考文档

博客写作流程之工具篇: emacs, orgmode, hugo & ox-hugo

Hugo使用Github Action自动部署博客到Github Pages

actions-gh-pages

GitHub Actions