Hexo 實現 Github/Coding 持續整合
文章最初載於 szhshp 的第三邊境研究所
轉載請註明
開發背景
- 為知筆記的搜尋太慢了。
- 我想要遷移筆記。
- 我想要遷移筆記。
- 我想要遷移筆記。
- 我想要遷移筆記。
- 我想要遷移筆記。
- 我想要遷移筆記。
- 我想要遷移筆記。
- 我想要遷移筆記。
- 我很需要遷移筆記。
- 為知筆記的搜尋太慢了。
- 希望能有一個免費的筆記託管平臺。
Github & Coding 的服務差異
主要配置:
- 一個 Source Repo, 用於存放原始碼
- 一個 Release Repo, 用於存放 build 之後的 pages 檔案
Pages 服務的限制:
- Github 的 pages 服務 repo 必須設定為開源
- Coding 的 pages 服務 repo 沒有任何限制, 所以 兩個都可以設定為閉源.
其他 CI/CD 服務的限制:
- Travis 可以用於 Github, 但是不能用於國內的 Coding
- https://travis-ci.org 不支援私有倉庫, https://travis-ci.com 才支援選擇私有倉庫 (但是對於私有倉庫只有 100 次次數限制)
最終決定:
- Github 端使用 Github Actions
- Coding 端使用新開放的
持續整合
功能, 類似 Github Actions
Hexo 站點搭建
(略)
Github 操作方法
主要目的:
- 建立一個 Github Action
- 當我 push 程式碼的時候自動 build
- 由於 hexo 自身就有用 deploy 的功能, 所以只需要在 push 的時候執行以下
hexo deploy
將生成的檔案全部部署到 Release Repo - 需要實現從 Source Repo 中提交到 Release Repo 的認證
- 最大的麻煩就是這一步
認證模式: SSH
生成一對公鑰和私鑰
公鑰放置在 請求操作端: 本機或者遠端伺服器 (一般放置在 .ssh/rsa_id)
私鑰放置在 目標端, 可以放在兩個地方:
- 如果放置在使用者級別的私鑰處設定 (Github-Setting-SSH and GPG Keys), 那麼可以不需要賬號密碼操作整個使用者的所有 repo
- 如果放置在單個 repo 的 deploy key 中, 那麼如果擁有這個私鑰, 就可以不需要賬號密碼操作單個 repo
設定 SSH
我們這裡實現單個 repo 的 SSH 訪問
首先本地使用 ssh-keygen 可以生成一個私鑰, 一個公鑰
首先跑到 bash 裡面執行 ssh-genkey
如果是 windows 系統, 就可以直接跑到
${GitDirectory}\usr\bin\ssh-keygen.exe
然後使用 管理員許可權 + CMD 執行
最後生成了一個公鑰 TESTKEY.PUB
, 一個私鑰 TESTKEY
.
將生成的 私鑰全部內容 (不要擔心格式) 放置在 Source Repo 的 Serect 裡面, 然後取一個名字, 比如我給他取名成 DEPLOY_KEY
然後將 公鑰全部內容 放置到 Release Repo 的 Deployed Keys 裡面, 並且要賦予讀寫的許可權, 公鑰的名字不重要
這個公鑰並不是放置在使用者的公鑰設定裡面, 我們僅僅對 Release Repo 進行操作
_config.yml 設定
這一段程式碼放置在 Source Repo 裡面. 下方設定了對應的 Release Repo 的名字以及對應的分支名字.
deploy:
type: git
repo: [email protected]:szhielelp/notebook-release.git # 改成你自己的 repo 地址,需要設定 SSH 地址。
branch: master # 改成你自己的分支名稱。
設定完之後本地測試一下
hexo d
因為對應的私鑰同時也儲存在本地, 所以應該可以部署成功.
建立 Github Action
跑到 Github Action 的頁面建立一個新的 action, 然後這個 action 就會被放置在 Repo 的根目錄的 .github/workflows/nodejs.yml
資料夾下面
name: Notebook Deployment
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x]
steps:
- name: Deployment Start
uses: actions/checkout@v1
- name: Setup Node ${{matrix.node-version}}
uses: actions/setup-node@v1
with:
node-version: ${{matrix.node-version}}
- name: Setup Git Env
env:
DEPLOY_KEY: ${{secrets.DEPLOY_KEY}} # 這裡寫上剛才在 Secret 裡面設定的變數名
run: |
mkdir -p ~/.ssh/
echo "$DEPLOY_KEY" > ~/.ssh/id_rsa # 將私鑰的全部內容輸出到一個檔案裡面。
chmod 600 ~/.ssh/id_rsa # 修改對應私鑰檔案的許可權。
ssh-keyscan github.com >> ~/.ssh/known_hosts # 將 Github.com 新增到已知檔案列表。
git config --global user.name "你的 Github 使用者名稱" # 設定一下提交的姓名和郵箱。
git config --global user.email "你的 Github 郵箱"
- name: Setup Hexo CI
run: |
npm i -g hexo-cli # 全域性安裝需要的庫。
npm i
- name: Setup other package
run: |
npm install
- name: Deploy
run: |
rm -rf .deploy_git
hexo g && hexo deploy # 開始部署
rm ~/.ssh/id_rsa
Coding 操作方法
主要目的基本相同, 但是選用的一個完全不同的認證方法
SSH 認證模式的問題
理論上按照 github 的模式可以實現, 但是 SSH 模式請求的時候一直報 Permission denied (publickey)
我說嘗試過的方法:
- 修改許可權為 7, Github 上方腳本里面設定的許可權為 6
- 生成一對完全不同的新的公鑰
- 使用 ssh-add 將新增公鑰到裝置
- 公鑰對於 git.coding.net 無效,應該改成 e.coding.net
最終發現使用者級別公鑰可以實現本地的部署, 但是無法實現 repo 之間的部署, 一直出現 Permission denied (publickey)
最終決定選用另一種認證方式.
2020-03-23 更新: Alliot 同學實現了 SSH 認證方法, 但是他是最終通過 scp 提交到他自己的伺服器。和我的需求不同, 有需要可以檢視一下: https://www.iots.vip/post/hexo-coding-ci-scp-server.html
認證模式: Token
首先建立一個 token
是在 repo - 開發者選項 - 專案令牌裡面生成
- 這個東西生成一次就無法再看到了, 一定要複製儲存
Token 也可以放在兩個地方: 一個是使用者級的 Token 可以操作所有 Repo, 一個是 Repo 級的 token 只能操作單個 repo
Config.yml 設定
同樣的, 在 Source Repo 那邊設定:
注意, 下方需要設定的是 HTTPS 的連結, 然後需要將你得到的 token 的賬號密碼扔進去.
deploy:
type: git
repo: https://[token name]:[token password]@e.coding.net/szhshp/szhshp-notebook-release.git
branch: master
同樣現在本地測試一下, 這種模式上並沒有使用任何的 SSH 訪問, 直接就可以部署成功
建立持續整合任務
因為這個地方沒有使用 SSH 訪問, 並且 token 已經設定到了上方的連結當中, 直接 push 即可.
pipeline {
agent any
stages {
stage('檢出') {
steps {
checkout([$class: 'GitSCM', branches: [[name: env.GIT_BUILD_REF]],
userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]])
}
}
stage('構建') {
steps {
echo '構建中。..'
sh '''
git config --global user.name szhshp
git config --global user.email [email protected]
npm i -g hexo-cli
npm i
rm -rf .deploy_git
hexo g && hexo deploy
'''
echo '構建完成。'
}
}
}
environment {
HOSTINFO = 'Host coding.net IdentityFile ~/.ssh/id_rsa.coding User szhshp'
}
}
Troubleshoot
版本不同
建議在指令碼的前三行寫上, 這樣除錯的時候可以先確定是否是因為版本不同的問題導致的。
node -v
npm -v
yarn -v
Hint-考慮使用 cnpm 或 yarn
本身在本地除錯的時候使用 cnpm 下載一些庫 (比較典型的就是 sass 的 loader) 就非常慢, 換到 Coding 伺服器用 npm 可能也很慢.
因此在這個時候可以考慮一下在扣釘上使用 cnpm 或者 yarn, 一個 cnpm 的例子:
下面這一段是放到視覺化編輯框裡面的, 如果直接貼上到 Jenkin 指令碼, 記得將裡面的單引號進行轉義。
cd clientV2
npm install cnpm -g
cnpm install
cnpm run build
git clone https://{token name}:{token pswd}@e.coding.net/szhshp/notebook/release.git
mv dist/* release/
cd release
git config user.email "[email protected]"
git config user.name "szhshp"
git add -A
git commit -a -m "Build & Release"
git push
另外也可以考慮換用 yarn
Nice Work !!!
花了我三天, 搞定了累死我了
Coding 單 Repo 多倉庫操作方法
Coding 更新後, 一個專案裡面可以有多個倉庫
實際上就是多個 Repo
在這種情況下完全可以只用一個專案控制 Source Repo 和 Release Repo
處理方法很簡單:
- 因為是同一個 Repo, 在 Repo 裡面建立一個專案 Token
- 將 _config.yml 裡面 deploy 一列的 repo 改為 release 倉庫對應的 HTTPS 連線, 記得帶上 token
deploy:
type: git
repo: https://{token name}:{token pswd}@e.coding.net/szhshp/szhshp-notebook/release.git
branch: master
- CI 指令碼如上文設定 Coding 操作方法
- 這樣子以後就不需要了來回跑兩個不同的 repo 了
參考文獻
- https://www.iots.vip/post/hexo-ci-wiki.html
- https://segmentfault.com/a/1190000002900848
- https://blog.csdn.net/qq_33619378/article/details/81191564
- https://zhuanlan.zhihu.com/p/26625249
- https://hexo.io/zh-cn/docs/commands.html
- https://www.jianshu.com/p/5691815b81b6
- https://www.voidking.com/dev-hexo-travis-ci/
- https://www.cnblogs.com/milovetingting/p/12159100.html
- https://hdj.me/github-actions-hexo-cicd/
- https://yanyinhong.github.io/2017/05/02/How-to-insert-image-in-hexo-post/