使用 GitHub Actions 自動部署 Hexo

這兩天把過去 wiki 的資料全部搬過來了。

Wiki 比較像是筆記,所以做個獨立的分頁;另外此網站以技術分享為主,所以有保留程式語言框架專屬的分頁。未來可能 Docker 也會獨立出來,到時再看看了。

做好這些事後,想說用 Travis CI 做自動化建置雖然很方便,但 Travis CI 啟動 VM 的速度感覺比較慢一點,因此想說換 GitHub Actions 來試看看,沒想到踩了一堆雷。

需求

看別人的範例才想到,其實可以把原始文章的 repo 和部署 HTML 的 repo 分開來。這樣就不需要再去 clone 部署 HTML 的專案。然後在分開的時候,順便把 Travis CI 換成 GitHub Actions。

原本 .travis.yml 是使用 GitHub Pages 的外掛部署的,內容如下:

os: linux
dist: xenial
language: node_js
node_js: 14

install:
- npm install --quiet

script:
- npm run clean
- npm run build

cache:
directories:
- $HOME/.nvm
- node_modules

deploy:
- provider: pages
skip_cleanup: true
github_token: ${GITHUB_ACCESS_TOKEN}
local_dir: public
target_branch: master
on:
branch: hexo

換成 Action 比較麻煩的是如何在原始文章 Actions 存取到部署 HTML 的 repo。上面 Travis CI 設定可以看到是用 personal token 存取的。查過 Google 與 GitHub Marketplace 上相關的程式,發現還有另一種方法是直接用 Git + SSH push。

SSH 成功的要件在公私鑰要放對地方,並且要能正確地匯入。

公鑰比較沒問題,要設定在部署目標的專案上,直接 Web GUI 點一點貼一貼就好;私鑰則是要放在 GitHub Actions 的 secret 裡,試了很多次還是失敗。下面是參考 Hexo Action 寫出來的範例:

mkdir -p ~/.ssh/
echo "${DEPLOY_KEY}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts
git config --global user.name "${GITHUB_ACTOR}"
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"

git remote add origin "your-repo-uri"
git checkout --orphan gh-pages
git add --all
git commit --allow-empty -m "Deploying to gh-pages"

git push origin gh-pages --force

GitHub Actions 會回 id_rsa 檔案的內容格式錯誤,但實在是無法知道哪裡有問題,所以最後就是走 Personal access tokens 了。

最終的解法

參考 renzhaosyHexo Deploy Action,因為原始碼是小寫的 dockerfile,而GitHub Actions 在 build Dockerfile 的時候會指定大寫的 Dockerfile,所以會一直失敗。因此只好自己參考重寫了一下。

Dockerfile 主要是把環境安裝移到 image 裡:

FROM node:14

RUN set -xe && \
apt-get update -y && \
apt-get install -y git-core

RUN npm install -g hexo hexo-deployer-git

COPY entrypoint.sh /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

entrypoint.sh 則把一些我覺得不需要的檢查拿掉,其他大同小異。之後應該可以再把 Hexo 指令的功能整合進去,但現在能部署就好了,有空再說XD。

Workflow 的寫法如下:

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
with:
submodules: true
- name: Build and Deploy
uses: MilesChou/hexo-deploy-action@master
env:
PERSONAL_TOKEN: ${{ secrets.GH_PAT }}
PUBLISH_REPOSITORY: MilesChou/mileschou.github.io
BRANCH: master

secrets.GH_PAT 要放 Personal access tokens,因為需要 push,所以需要開 repo 的所有權限。

對 GitHub 來說,下面這個 remote 即有存取 MilesChou/mileschou.github.io 的權限了:

https://x-access-token:${PERSONAL_TOKEN}@github.com/MilesChou/mileschou.github.io.git

只要使用 git remote add 指令新增後,再 git push --force 即可。

參考資料