1. 程式人生 > 實用技巧 >Hexo 實現 Github/Coding 持續整合

Hexo 實現 Github/Coding 持續整合

文章最初載於 szhshp 的第三邊境研究所

轉載請註明

開發背景

  1. 為知筆記的搜尋太慢了。
  2. 我想要遷移筆記。
  3. 我想要遷移筆記。
  4. 我想要遷移筆記。
  5. 我想要遷移筆記。
  6. 我想要遷移筆記。
  7. 我想要遷移筆記。
  8. 我想要遷移筆記。
  9. 我想要遷移筆記。
  10. 我很需要遷移筆記。
  11. 為知筆記的搜尋太慢了。
  12. 希望能有一個免費的筆記託管平臺。

Github & Coding 的服務差異

主要配置:

  1. 一個 Source Repo, 用於存放原始碼
  2. 一個 Release Repo, 用於存放 build 之後的 pages 檔案

Pages 服務的限制:

  • Github 的 pages 服務 repo 必須設定為開源
    , 因此 Source Repo 可以設定為閉源
  • Coding 的 pages 服務 repo 沒有任何限制, 所以 兩個都可以設定為閉源.

其他 CI/CD 服務的限制:

  • Travis 可以用於 Github, 但是不能用於國內的 Coding
  • https://travis-ci.org 不支援私有倉庫, https://travis-ci.com 才支援選擇私有倉庫 (但是對於私有倉庫只有 100 次次數限制)

最終決定:

  1. Github 端使用 Github Actions
  2. Coding 端使用新開放的 持續整合 功能, 類似 Github Actions

Hexo 站點搭建

(略)

Github 操作方法

主要目的:

  1. 建立一個 Github Action
  2. 當我 push 程式碼的時候自動 build
  3. 由於 hexo 自身就有用 deploy 的功能, 所以只需要在 push 的時候執行以下 hexo deploy 將生成的檔案全部部署到 Release Repo
  4. 需要實現從 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)

我說嘗試過的方法:

  1. 修改許可權為 7, Github 上方腳本里面設定的許可權為 6
  2. 生成一對完全不同的新的公鑰
  3. 使用 ssh-add 將新增公鑰到裝置
  4. 公鑰對於 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

  1. 首先建立一個 token

  2. 是在 repo - 開發者選項 - 專案令牌裡面生成

    • 這個東西生成一次就無法再看到了, 一定要複製儲存
  3. 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 RepoRelease Repo

處理方法很簡單:

  1. 因為是同一個 Repo, 在 Repo 裡面建立一個專案 Token
  2. 將 _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
  1. CI 指令碼如上文設定 Coding 操作方法
  2. 這樣子以後就不需要了來回跑兩個不同的 repo 了

參考文獻