1. 程式人生 > >使用Travis CI自動部署博客到github pages和coding pages

使用Travis CI自動部署博客到github pages和coding pages

option 依靠 sub post 電腦 安裝環境 在線 獨立 需要

每次換系統或換電腦之後重新部署博客總是很苦惱?想像jekyll那樣,一次性部署完成後,以後本地不用安裝環境直接 git push 就能生成博客?那推薦你應該使用使用 Travis CI了。

這篇文章我們來講講如何利用 Travis CI把你 push 上去的博客源文件直接生成可訪問的站點,並且同步部署到 github pagescoding pages

這篇文章假設你已經對這些采用 git 版本控制系統的靜態博客托管服務有所了解,並且知道怎麽去簡單的使用 git 以及了解 hexo 寫博客發布到這些 pages 服務的流程。因此本文會寫的較為簡略,旨在指出關鍵的地方以及我遇到的問題、問題產生的原因和提供的解決方案

,希望能夠幫助到大家。

如果大家有什麽問題可以直接在下方評論(獨立博客采用Disqus,可能需要FQ),或者直接給我郵件([email protected]),我可能會在以後的時間逐步把詳細的流程寫出來,時間不多,匆忙之際下筆,望大家見諒。

看完上面的話,是不是有一種“復恐匆匆說不盡,行人臨發又開封。”的感覺,可能廢話太多了,那麽直接開始吧!

令牌的獲取

問個為什麽

首先我們說一下為什麽要獲取令牌?他的作用是什麽?

先給大家幾個流程圖,來自於liolok的博客(前兩張)和CodingLife的博客(第三張)

首先是當我們未采用 Travis CI ,直接使用 hexo 的插件 hexo-deployer-git

執行命令 hexo d -g 部署的流程:

技術分享圖片

然後是使用 Travis CI 進行將倉庫中的站點源文件自動生成站點然後部署到特定倉庫(或特定分支)的流程:

技術分享圖片

還有一張圖大家也可以看看:

技術分享圖片

現在假設一種情況:我們把 username/username.github.io 倉庫 clone 了下來,然後在它裏面新建了一個分支 hexo 並放置我們的站點源文件(也就是你 hexo init blog 出來的 blog 目錄下的所有文件),然後把這個 hexo 分支 push 了上去。

那麽你設置這個倉庫到 Travis CI 之後會做什麽呢?它會尋找 .travis.yml 這個文件,如果存在的話,它就會根據 .travis.yml

來自動執行一些命令,這些命令就可以完成我們的需求。

然後我們回到剛才的話題,為什麽要獲取令牌?

令牌相當於一個通行證,比如要實現我們的需求,我們的 .travis.yml 中需要把 hexo 分支下的站點源文件文件使用 hexo g 生成靜態站點後把這個靜態站點 push 到我們的倉庫,那 github 總不可能讓人想 push 到誰的倉庫就可以直接 push 上去吧,所以它就是靠這個通行證來驗證你的身份。

所以我們把令牌的key字段加到 Travis CI 後就可以讓 github 知道:哦,這個人是已授權的。

那麽怎麽做

那應該怎麽去獲取這個令牌並加到 Travis CI 呢?

哦哦,忘了說一個東西,如果你仔細看了我剛才的描述,那麽你可能對這個 Travis CI 還是不了解,只是大致知道了他可以用來做什麽,借用一下維基百科上的解釋:

Travis CI是在軟件開發領域中的一個在線的,分布式的持續集成服務,用來構建及測試在GitHub托管的代碼。

你可以把它簡單的認為是一個用來 讀取你的倉庫 -> 讀取倉庫下的 .travis.yml 文件 -> 根據 .travis.yml 的內容對這個倉庫來執行一系列linux和git命令去達到你的目的 的工具。

那麽談到令牌的獲取,這個並不麻煩。

如果是 github,登陸後打開設置,然後進入 Developer settings ->Personal access tokens 點擊 Generate new token,然後會提示你選擇這個令牌擁有的權限,因為我們只需要對倉庫進行操作,選中 repo即可。

技術分享圖片

然後復制那一串 token 先保存下來。

如果是 coding,打開 個人設置 -> 訪問令牌,然後點擊 新建令牌,同樣的給予倉庫的控制權限,然後復制保存生成的 token

技術分享圖片

然後打開Travis CI 網站,然後點擊右上角的用github登錄,然後同步你的倉庫,再打開你需要自動部署的倉庫開關,點擊設置進去添加 token 即可。直接給兩張圖。

技術分享圖片

技術分享圖片

需要註意的是

  • 每個Token 自定義的 Name 你需要記住,待會在寫 .travis.yml 的時候會用到
  • Display value in build log 這個選項千萬不要打開,因為log是公網可見的

倉庫的結構

上面完成了,我們來說說倉庫的結構。

  1. 你可以把站點源文件部署到一個新倉庫(假如是 new_repo),那麽你需要更改一下上面的設置,不是打開博客倉庫的開關了,而是換成打開你需要操作的倉庫 new_repo的開關,然後 Travis CI 再通過我們設置好的 .travis.yml 自動部署到博客倉庫

  2. 你也可以把站點源文件部署到博客倉庫(下文我以 akkuman.github.io 代替)的新分支,然後 Travis CI 再通過這個新分支下我們設置好的 .travis.yml 自動部署到博客倉庫 akkuman.github.io

這裏我們采用第二種方案,只是個人愛好,不想再多開一個倉庫。

倉庫的改造

新分支的建立

直接看下面的命令和註釋吧。

# 首先把自己的博客倉庫clone到本地
git clone [email protected]:akkuman/akkuman.github.io.git
cd akkuman.github.io.git
# 我們假設倉庫下的部署分支是master
# 我們先新建並切換到一個新分支,分支名我這裏取為hexo
git checkout -b hexo

現在我們已經切換到了新分支 hexo,緊接著我們刪除 akkuman.github.io 文件夾下除了 .git 文件夾的其他所有文件。

我們把其他地方 hexo init blog 出來的 blog 站點文件夾下所有文件復制到剛才的 akkuman.github.io 文件夾下。

站點主題的處理

這裏我們需要註意:
不知道你的主題是怎麽下載來的,我就分為 1.主題是一個 git 倉庫 2.主題不是一個 git 倉庫,所以主題可能也是一個 git 倉庫,如果你對 git 不熟悉,建議不要 git clone 主題倉庫,而是下載別人的 release 版。

判斷一個文件夾是不是 git 倉庫,就是看該文件夾目錄下有沒有一個 .git文件夾,註意它是一個隱藏文件夾,所以你發現你的主題是一個 git 倉庫的時候,你可以刪除這個隱藏的 .git文件夾。

那麽我們這麽做的目的是什麽呢?

如果我們的主題文件夾也是一個 git 倉庫,那麽我們的這個博客倉庫的 hexo 分支下就嵌套了一個倉庫,當然,git 也給出了解決方案,那就是子模塊。所以目的就是告訴你:圖省事可以直接使用非 git 倉庫的主題,不用折騰子模塊。

多說一點吧:

說到子模塊,子模塊是SSH協議還是HTTPS協議對後面有影響,不過我後面會給一個通用的模板,看後面的註釋即可。

這個子模塊你是使用SSH協議還是HTTPS協議就看個人愛好了,我是自己 fork 了別人的倉庫然後修改了一下,所以我為了方便期間還是使用了SSH協議的倉庫。

然後子模塊怎麽使用呢?

比如我使用的主題倉庫是[email protected]:akkuman/hexo-theme-next.git,現在假設我們在博客倉庫 akkuman.github.io 下,然後執行下面命令把這個主題倉庫下的所有文件復制到站點目錄下的 themes/next 文件夾下。

git submodule add [email protected]:akkuman/hexo-theme-next.git themes/next

然後你的目錄下會出現一個 .gitmodules 文件,內容格式大致是

[submodule "themes/next"]
    path = themes/next
    url = [email protected]:akkuman/hexo-theme-next.git

關於子模塊的知識可以自己查閱資料,我這裏不細說了,待會在後面我會給出參考資料。

git需要忽略的文件

git 依靠 .gitignore 文件判斷那些文件不納入倉庫,一般通過 hexo init 命令出來的站點文件夾下都會有這麽個文件。沒有也沒關系,自己新建一個 .gitignore 文件,內容為

.DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/

node_modules目錄是hexo博客實例的npm環境依賴,,據說是質量比黑洞還大的物體, 我們選擇忽略它, 反正最後到了Travis那裏也會重新跑一遍npm install,,這些東西本來也會刪了重來, 沒有同步的意義.
public目錄是hexo生成的靜態文件, db.json是數據庫文件,,同理,,由於Travis構建流程中會執行hexo clean,,都不需要同步。

.travis.yml的設置

上面的操作完成後,我們開始著手寫 .travis.yml了,先提供一個最簡單也是網上博客教程裏面最多的版本

language: node_js # 設置語言
node_js: stable # 設置相應版本
install:
    - npm install # 安裝hexo及插件
script:
    - hexo clean # 清除
    - hexo g # 生成
after_script:
    - cd ./public
    - git init
    - git config user.name "yourname" # 修改name
    - git config user.email "your email" # 修改email
    - git add .
    - git commit -m "Travis CI Auto Builder"
    - git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:master # GH_TOKEN是在Travis中配置token的名稱
branches:
    only:
        - hexo #只監測hexo分支,hexo是我的分支的名稱,可根據自己情況設置
env:
    global:
        - GH_REF: github.com/yourname/yourname.github.io.git #設置GH_REF,註意更改yourname

這個是針對 github 倉庫的最簡版本,不過有個問題,我們從執行的命令中也能看到,就是部署到 master 分支的站點文件每次都會 init 後在提交,所以每次都只有一次 commit 記錄,我建議你把下面的看完。

我先把文件給出來:

.travis.yml 文件:

language: node_js

node_js: stable

cache:
    apt: true
    directories:
        - node_modules

notifications:
    email:
        recipients:
            - [email protected]
        on_success: change
        on_failure: always

# turn off the clone of submodules for change the SSH to HTTPS in .gitmodules to avoid the error
git:
  submodules: false
        
before_install:
    # Use sed to replace the SSH URL with the public URL if .gitmodules exists
    - test -e ".gitmodules" && sed -i 's/[email protected]:/https:\/\/github.com\//' .gitmodules
    # update the submodule in repo by manual
    - git submodule update --init --recursive
    - export TZ='Asia/Shanghai'
    - npm install hexo-cli -g
    - chmod +x ./publish-to-gh-pages.sh

install:
    - npm install

script:
    - hexo clean
    - hexo g

after_script:
    - ./publish-to-gh-pages.sh

branches:
    only:
        - hexo

env:
    global:
        # Github Pages
        - GH_REF: github.com/akkuman/akkuman.github.io.git
        # Coding Pages
        - CD_REF: git.coding.net/Akkuman/Akkuman.git

我把需要執行的腳本放到了 publish-to-gh-pages.sh 文件。

publish-to-gh-pages.sh 文件:

#!/bin/bash
set -ev


# get clone master
git clone https://${GH_REF} .deploy_git
cd .deploy_git
git checkout master

cd ../
mv .deploy_git/.git/ ./public/

cd ./public

git config user.name "Akkuman"
git config user.email "[email protected]"

# add commit timestamp
git add .
git commit -m "Travis CI Auto Builder at `date +"%Y-%m-%d %H:%M"`"

# Github Pages
git push --force --quiet "https://${GITHUB_TOKEN}@${GH_REF}" master:master

# Coding Pages
git push --force --quiet "https://Akkuman:${CODING_TOKEN}@${CD_REF}" master:master

請把對應的 Akkumanemail 還有 username 改成你的配置。

這裏我不詳解配置,因為這篇文章已經花了很長時間了,如果大家有需要我再詳細寫。下面我會給出我的倉庫地址,如果有不懂可以去看看我倉庫下的例子。

說著不詳解,但是我還是有點自己踩過的坑需要提點一下,Travis CI 進行 git clone 操作的時候,默認是開啟 --recursive 參數的,也就是克隆庫的時候會默認初始化子模塊。這個操作本來是沒問題的,那麽我為什麽要單獨提出來說?

我上面說到了:

說到子模塊,子模塊是SSH協議還是HTTPS協議對後面有影響

問題就是這裏了,如果你是用的HTTPS協議,根據 .gitmodules 文件默認初始化子模塊的時候是沒問題。但是如果使用SSH協議,不管是 clonepush還是其他等等操作, 是要求本機上有私鑰,並且倉庫那邊要有對應的公鑰才可以。但是Travis CI 自動部署執行 clone 的時候沒有這個公私鑰,所以我們只能使用HTTPS協議,但是我使用的是 .gitmodules 文件裏面定義的子模塊SSH協議呀!我在這裏也查了一下,解決方案就是上面的那樣。節選出來:

# turn off the clone of submodules for change the SSH to HTTPS in .gitmodules to avoid the error
git:
  submodules: false
        
before_install:
    # Use sed to replace the SSH URL with the public URL if .gitmodules exists
    - test -e ".gitmodules" && sed -i 's/[email protected]:/https:\/\/github.com\//' .gitmodules
    # update the submodule in repo by manual
    - git submodule update --init --recursive

先關閉了 Travis CI 的默認初始化子模塊功能,然後後面我們先判斷子模塊配置文件是否存在(所以我剛才說最省事的就是使用 releases 主題,也就是不含 .git 文件夾的,具體見上面),然後判斷子模塊配置文件如果存在存在,就使用 sed 把命令把 .gitmodules 子模塊配置文件中的SSH協議換成HTTPS協議再執行後面的操作。

開啟自動構建之旅

現在你的博客倉庫 akkuman.github.io 文件夾下的 hexo 分支下的東西已經配置好了。

新分支有了,.travis.yml 文件也有了。

你現在可以直接 push 上去:

git add .
git commit -m ":constructin_worker: The introduction of Travis CI"
git push origin hexo:hexo

然後打開 Travis CI 網站即可看到你的網站正在構建,如果構建失敗,上面也有詳細的報錯可以幫你分析原因。構建成功後即可看到你煥然一新的網站了。

以後更新 md 就可以用上面的命令 push 到倉庫,然後 Travis CI 會自動幫你構建到 master 分支

題外話

為了以後不用打

git push origin hexo:hexo

而是直接可以使用

git push

我們可以設置上遊分支,如果是第一次執行 git push origin hexo:hexo,它會提示你使用

git push --set-upstream origin hexo

使用上面的命令即可把本地的 hexo 的上遊分支設置為遠程倉庫的 hexo 分支,以後 push 就可以簡化命令為 git push 了。

當然你也可以手動設置上遊分支,使用下面的命令把本地的 hexo 的上遊分支設置為遠程倉庫的 hexo 分支:

git branch --set-upstream-to=origin/hexo hexo

我的站點倉庫配置示例

見 akkuman/akkuman.github.io

參考資料

  • Hexo + Travis CI 博客管理
  • 使用Travis CI自動構建hexo博客
  • 使用Travis CI自動部署Hexo博客
  • Travis CI官方幫助文檔
  • git中submodule子模塊的添加、使用和刪除
  • Git Submodule 用法筆記
  • CODING幫助文檔-個人訪問令牌

    提一句上面的git push --force --quiet "https://Akkuman:${CODING_TOKEN}@${CD_REF}" 網址格式是查詢的CODING幫助文檔

使用Travis CI自動部署博客到github pages和coding pages