開箱即用,Hexo部落格的github+server自動部署

Yuying_Wu發表於2018-05-27

用了一段時間HEXO搭建個人的部落格,但每次釋出文章,都需要開啟電腦hexo g編譯之後,再提交到伺服器上,確實挺麻煩的,和小夥伴聊完他的日誌釋出方式之後,痛定思痛,快捷釋出日誌這個問題需要解決一下了!Travis CLI搞起來!

閒聊日誌的快捷釋出

前幾天,跟小夥伴Pipe一起參加個分享會,看到他做了筆記,結束後我說你發給我呀,他說直接看我部落格(《工作思維方式簡記》)呀!我的天,寫完瞬間就發到站點去了!Pipe非常高產,去看看他的部落格,用“高產似母豬”來描述都不足為過,5月份還沒有過完,釋出了7篇日誌。

我問他,怎麼做到那麼高產?Pipe說,第一點是他的日誌是碎片化的偏記錄的,不一定要憋出大文章才發,然後就是部落格系統要方便,隨寫隨發。

反觀我的部落格,更新頻率真的很低,一方面是喜歡憋專題文章,拖著拖著,然後就沒有然後了。另一方面也是釋出確實麻煩,電腦編輯好markdown,還要執行各種命令,最後push到github和自己的伺服器,文章才能被大家看到,一開始覺得還好蠻geek的,但後來確實由於這些門檻,有打擊到那些隨時來的寫作思緒。

By the way,Pipe用的是jekyll,跟github的持續整合是天生的,而HEXO沒有這樣的優勢。從Hexo換到Jekyll吧,也不是很麻煩,但是我在Hexo生態做了一些東西,還是有點不捨哈。

  • github blog:我的部落格分支
  • hexo-generator-index-plus:hexo小外掛,首頁排序生成器,和原生的index-generator比較顯著的區別是加了置頂功能,可以在front-matter新增top屬性即可。
  • hexo-theme-fresh:hexo部落格主題,綠色小清新,Medium風格。

HEXO的開發分支與生產分支

倉庫分成2個分支,主開發開支dev,以及生產環境的gh-pages分支。 檢視部落格可以通過訪問github pages,又或者直接訪問我的域名 wuyuying.com/blog

開發分支 dev

在我的部落格裡,開發分支是dev,目錄結構就是一開始hexo init後的結構。

- scaffolds // 頁面的模板,包括草稿(draft.md)、頁面(page.md)、文章(post.md)以及其他自定義模板
- source // 放頁面和文章markdown文件
- themes // 部落格主題
- _config.yml // 配置檔案
- package.json
- .travis.yml // 持續整合服務travis的檔案
複製程式碼

本地開發流程一般是這樣。

// hexo server, 啟動本地伺服器,預覽我的文章
hexo s 

// hexo generate,編譯文章,把 `source` 裡面的頁面和文章編譯成 `public` 裡面的html檔案
hexo g

// hexo deploy,如果 _config.yml 有配置deploy的內容,執行該命令是會執行相應的部署邏輯
hexo d
複製程式碼

HEXO的詳細科普和指令在這裡就不寫了哈,官方文件裡都有 >> 傳送門

生產分支 gh-pages

dev分支裡,執行了hexo g編譯之後,編譯後的靜態檔案會存在public資料夾裡,而我們就把裡面的內容挪到最終的生產環境分支gh-pages裡,也就是最終我們看到的靜態部落格。

當我們在github裡把github-pages服務開啟,並渲染gh-pages分支,我們就能訪問自己的部落格了(yuyingwu.github.io/blog/)。

Travis CI

在大致瞭解HEXO的開發流程之後,我們可以開始考慮,如果要實現快捷釋出,是要做什麼?
User Story希望可以在github上寫一篇文章,提交之後,可以直接在我的線上部落格看到

在這裡,我們用到了提供持續整合(CI, Continuous Integration)服務的Travis CI,但其實用到的不是它提供的CI服務,而更多的是通過監聽分支提交的動態,在整合成功後去執行我們自定義的部署邏輯。

持續整合是一種軟體開發實踐,即團隊開發成員經常整合他們的工作,通過每個成員每天至少整合一次,也就意味著每天可能會發生多次整合。每次整合都通過自動化的構建(包括編譯,釋出,自動化測試)來驗證,從而儘早地發現整合錯誤。

噢,還有些事前準備:

  • 先在dev分支裡,建立.travis.yml
  • Travis CLI平臺上開啟這個分支的CI開關

1. 編譯並同步到gh-pages

那直接上我的CI配置程式碼吧。

language: node_js
node_js: stable

addons: # Travis CI建議加的,自動更新api
  apt:
    update: true

cache:
  directories: 
  - node_modules # 快取 node_modules

install:
- npm install # 初次安裝,在CI環境中,執行安裝npm依賴

# before_script: 

script:
- hexo g # 執行 hexo generate,把文章編譯到public中

after_success: # 執行script成功後,進入到public,把裡面的程式碼提交到部落格的gh-pages分支
- cd ./public
- git init
- git config user.name "Yuying Wu"
- git config user.email "wuyuying1128@gmail.com"
- git add .
- git commit -m "Update site"
- git push --force --quiet "https://${GH_TOKEN}@${GH_REF}" master:gh-pages

branches:
  only:
  - dev # CI 只針對分支 dev

env:
  global: # 全域性變數,上面的提交到github的命令有用到
  - GH_REF: github.com/YuyingWu/blog.git
  - secure: 
# secure是自動生成的,執行`travis encrypt 'GH_TOKEN=${your_github_personal_access_token}' --add`
複製程式碼

相信程式碼和註釋寫得很清楚了,有個地方需要進一步解釋的,github提交那part,涉及github access token的生成和加密。

  1. 生成github的Personal Access Tokens(開啟分支提交的許可權)
  2. 安裝Travis CLI gem install travis(如果登入遇到環境問題,可以看看下面參考文章裡面的解決方案)
  3. 進入到本地dev目錄下(帶有.travis.yml),執行travis login登入,再執行travis encrypt 'GH_TOKEN=${your_github_personal_access_token}' --add加密你的personal access token(也就是後來.travis.ymlenv.global.secure的值)

.travis.yml提交之後,看看Travis CLI上,開始持續整合了哈。

大功告成,整合之後,在github pages的頁面上也能看到文章的更新。

2. CI到我的伺服器

我的伺服器是DO家(Digital Ocean)的,那一開始伺服器初始化的過程,大家可以參考各個server商提供的setup文件哈,總的來說,在本地有個伺服器信任的id_rsa的ssh檔案,我們是可以通過ssh user@ip_address登入到伺服器的。

# 這個命令會自動把 id_rsa 加密傳送到 .git 指定的倉庫對應的 travis 中去(在我本地這個檔案叫qq_rsa,不是預設的id_rsa)
travis encrypt-file ~/.ssh/id_rsa --add
複製程式碼

執行這個命令後,.travis.yml多了一行程式碼:(注意把其中的轉義符\幹掉哈),也會在分支目錄下生成一個id_rsa.enc的加密檔案,記得把這個檔案也提交上去喲。

before_install:
- openssl aes-256-cbc -K $encrypted_3cf6c1fd150f_key -iv $encrypted_3cf6c1fd150f_iv
  -in qq_rsa.enc -out ~/.ssh/id_rsa -d
複製程式碼

然後為了保證在Travis裡面能正常執行,我們處理下執行環境的rsa檔案許可權和輸出提示資訊,before_install如下。

before_install:
- openssl aes-256-cbc -K $encrypted_3cf6c1fd150f_key -iv $encrypted_3cf6c1fd150f_iv
  -in qq_rsa.enc -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host 主機IP地址\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
複製程式碼

最後,在after_success裡新增拷貝目標檔案到伺服器目標目錄的操作,就大功告成了!

after_success
# other actions
- scp -o stricthostkeychecking=no -r ./* root@138.68.161.48:/home/wyyNode/public/blog/
複製程式碼

參考文章

關於我

Yuying Wu

前端愛好者 / 鼓勵師 / 紐西蘭打工度假 / 鏟屎官

目前就職於某大型電商的B2B前端團隊。

如果你和我一樣喜歡前端,喜歡搗騰獨立部落格或者前沿技術,或者有什麼職業疑問,可以關注我的知乎ID Yuying Wu / 獨立部落格 wuyuying.com / Github,歡迎各種交流哈。

相關文章