更新日誌
2021/08/22
Token 可以直接使用 GITHUB_TOKEN 比用 ACCESS_TOKEN 方便,但是權限會限制在當前的 repo,所以如果要引用其他 private repo 的話還是要使用 ACCESS_TOKEN
2023/07/25
把網站遷移到自己的 domain 下,並新增處理 Lastmod 問題的指令

Hugo 搭配 Github Actions 實現 Github Pages 的自動部署

最近透過 Hugo 重建了 Github Pages (本站)。順便嘗試了一下 Github Actions,目標是以後發布文章時就只要推 source 上去,部署的工作就交給 CI/CD 自動化處理。在這邊紀錄一下研究的過程。

環境介紹

Repository

本站建立在 https://github.com/kaiiiz/kaiiiz.github.io 這個 repo 下下面,原本想說要 push 到 gh-pages 這個 branch,後來發現 User 或 Organization 的 Page 在設定上沒辦法選擇 page 的 source,只能使用預設的 master branch。

文件是這樣說的:

The default publishing source for user and organization sites is the master branch. If the repository for your user or organization site has a master branch, your site will publish automatically from that branch. You cannot choose a different publishing source for user or organization sites.

路不轉人轉,所以我建了一個 source 的 branch,用來存 source code,這會讓後面 Github Actions 的部份有些地方需要修改。

Hugo

Hugo 主題的開發,因為之前看到 Tailwind CSS 這個 CSS framework,想試試看好不好用,但因為不想自己造輪子,所以我查了一下有沒有現成的可以用,就查到了 dirkolbrich/hugo-theme-tailwindcss-starter 這款,已經幫我把開發環境都設定好了,於是我就直接拿這個當作主題的基底進行開發,他有一些 node.js 的依賴,所以在後面的 Github Actions 建立環境時也要注意有一些修改。

設定 Github

取得 Repository 的 Access Token

到 Settings/Developer Settings 下的 Personal access tokens 生成一組 Access Token。因為我的 theme 是一個 private repo,所以我要了有關 repo 這個 scope 的所有權限。

添加 Secrets

在 Github Pages 的 Repository 下的 Settings > Secrets 新增一組 Secrets,我這邊叫做 ACCESS_TOKEN,之後在腳本上會用到。

建立腳本

.github/workflows 下新增一個檔案,我叫做 gh-pages.yml

我是以 peaceiris/actions-hugo 這套為基礎做了一些修改,紀錄一下改的部份:

  • 觸發的時機需要改成 push 到 source 這個 branch
1
2
3
4
on:
  push:
    branches:
      - source
  • checkout 時先 checkout 到 source branch
  • 並且因為 submodule 是 private repo,所以帶上 token,值是剛剛在 secrets 頁面設定的 ACCESS_TOKEN
1
2
3
4
5
6
- uses: actions/checkout@v2
  with:
    ref: source
    token: ${{ secrets.ACCESS_TOKEN }}
    submodules: true  # Fetch Hugo themes (true OR recursive)
    fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod
  • 因為主題有依賴的關係,所以設定一下 node,安裝需要的 packages
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
- name: Setup Node.js
  uses: actions/setup-node@v1
  with:
    node-version: '12'

- name: Setup PostCSS
  run: npm install -g postcss-cli && npm install -g autoprefixer

- name: Setup Theme Dependency
  run: npm install --prefix themes/hugo-theme-yk
  • 透過 git worktree 將 public 目錄追蹤在 master branch
  • 清除舊的 public,hugo 預設不會自動清除
1
2
3
4
5
- name: Setup public
  run: git worktree add -B master public origin/master

- name: Clean public
  run: rm -rf public/*
  • 部署時,將 public 目錄部署到 master branch
1
2
3
4
5
6
- name: Deploy
  uses: peaceiris/actions-gh-pages@v3
  with:
    github_token: ${{ secrets.ACCESS_TOKEN }}
    publish_dir: ./public
    publish_branch: master

總結

最後整個腳本長這樣:

 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
name: github pages

on:
  push:
    branches:
      - source

jobs:
  deploy:
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@v2
        with:
          ref: source
          token: ${{ secrets.ACCESS_TOKEN }}
          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.71.1'

      - name: Setup Node.js
        uses: actions/setup-node@v1
        with:
          node-version: '12'

      - name: Setup PostCSS
        run: npm install -g postcss-cli && npm install -g autoprefixer

      - name: Setup Theme Dependency
        run: npm install --prefix themes/hugo-theme-yk

      - name: Setup public
        run: git worktree add -B master public origin/master

      - name: Clean public
        run: rm -rf public/*

      - name: Build
        run: hugo

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.ACCESS_TOKEN }}
          publish_dir: ./public
          publish_branch: master

當把 source 推上去時,會自動部署 public 到 master,看到綠綠的一整排就代表部署成功囉


2023/07/25 更新

因為想要把 Github Pages 遷到自己的 domain 下,但是如果把 <username>.github.io 的 repo 設定成 custom domain 的話,其他 repo 的 custom domain 也會強制被指向到那個網域。但是因為我不想要讓其他 repo 的 Github Pages 也被遷到我自己的 domain,所以只好再建一個 repo,並只在那個 repo 上設定 custom domain,然後改成把 public 推到 gh-pages branch 上。

後來還遇到 hugo 在 Github Actions 上 build 完後,所有的文章的 Lastmod 都會是 build 的時候的時間,查了一下發現是 git 遇到中文的問題。這篇提到當路徑包含非 ASCII 字元時,git 預設會把路徑用 quote 包起來,但這樣 hugo 就會因此讀不到 .GitInfo 的資訊而導致前面提到的問題,因此還需要在腳本上把 quotePath 給關掉才可以正常使用 Lastmod

 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
on:
  push:
    branches:
      - source

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: source
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Disable quotePath
        run: git config --global core.quotePath false

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: '0.115.4'
          extended: true

      - name: Setup public
        run: git worktree add -B gh-pages public origin/gh-pages

      - name: Clean public
        run: rm -rf public/*

      - name: Build
        run: hugo --minify --environment production

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
          publish_dir: ./public
          publish_branch: gh-pages
comments powered by Disqus