原文發(fā)布于自己的博客平臺(tái)【http://www.jetchen.cn/github-webhooks/】
背景
博客原是 WordPress 搭建的,由于某些個(gè)人無法接受的原因,準(zhǔn)備轉(zhuǎn)成靜態(tài)博客滋早,之前轉(zhuǎn)過毁渗,使用的是 HEXO哥捕,基本成功了蝶柿,但是是部署在 github pages 上面的鞠评,如今準(zhǔn)備部署在國(guó)內(nèi)的阿里云服務(wù)器上脱茉。
問題
使用 HEXO 搭建的博客平臺(tái)剪芥,進(jìn)行寫博客的流程是:
1、本地使用 Markdown 編寫博客琴许,
2税肪、本地編譯成 html 文件,
3榜田、將 html 文件上傳至服務(wù)器益兄,一般免費(fèi)的有 github page,gitee 等
所以此處需要改造的點(diǎn)其實(shí)很簡(jiǎn)單箭券,就是把 github 倉(cāng)庫(kù)中的 html 文件全部下載至服務(wù)器上净捅,然后利用 web 服務(wù)器做個(gè)反向代理即可,比如 nginx辩块。
后續(xù)的部署流程:
1蛔六、本地寫完博客荆永,編譯完成后上傳至 github 倉(cāng)庫(kù)
2、登陸到服務(wù)器上面進(jìn)行 git update 操作
問題就此暴露出來了国章,每次寫完博客都要登陸下服務(wù)器去更新下 html 文件具钥,我的天,這誰頂?shù)米 ?/p>
解決
于是自然而然想到了 git 倉(cāng)庫(kù)的 web 鉤子捉腥,即當(dāng) git 倉(cāng)庫(kù)收到 push 或者其他命令時(shí)氓拼,會(huì)自動(dòng)調(diào)我們的鉤子程序(其實(shí)就是向我們指定的地址發(fā)送一個(gè) post 請(qǐng)求),而我們只需要讓我們的這個(gè)程序去跟新下服務(wù)器上面的代碼(html 文件)即可抵碟。
流程示例圖見下圖:
從上面可以出桃漾,我們只剩 2 件事需要做,一是配置下 github 的 webhook拟逮,二是在我們的服務(wù)器上寫一個(gè) web 程序來處理 github 發(fā)送過來的請(qǐng)求撬统。
1、webhook 配置
配置比較簡(jiǎn)單敦迄,需要注意的是恋追,秘鑰雖然是非必填的,但是最好還是加上罚屋,為了安全苦囱。
請(qǐng)求的數(shù)據(jù),每個(gè)平臺(tái)都不一樣脾猛,在此以 github 為例撕彤,數(shù)據(jù)內(nèi)容見下圖:
注:請(qǐng)求頭中有一個(gè)很重要的簽名參數(shù),該參數(shù)前部分為加密方式猛拴,后部分為的簽名羹铅,而明文就是我們?cè)?webhook 中配置的秘鑰。這點(diǎn)很重要哦愉昆。
2职员、程序編寫
寫一個(gè)簡(jiǎn)單是 web 程序。
本人主要是編寫 java 代碼的跛溉,如果要用 java 來寫的話焊切,比較麻煩,所以考慮選擇一款解釋性語言來編寫倒谷,其實(shí)用啥語言都無所謂啦蛛蒙,畢竟代碼處理邏輯很簡(jiǎn)單,選用自己熟悉的就行渤愁,例如 Python牵祟、PHP、nodejs 等都行抖格。
此處選擇的是使用 Python 來編寫诺苹,web 框架是比較輕量的 Flask咕晋,操作 git 使用的是 gitPython,所以需要安裝下:
pip install flask
pip install gitpython
代碼比較簡(jiǎn)單收奔,不多贅述掌呜,主要就是兩點(diǎn):
1、簽名校驗(yàn)
2坪哄、git update
詳細(xì)代碼如下:
from flask import Flask, request, Blueprint, jsonify, current_app
from git import Repo
import hmac
app = Flask(__name__)
@app.route("/api/github_hook", methods=['POST'])
def github_web_hook():
header_signature_origin = request.headers.get('X-Hub-Signature')
if header_signature_origin is None:
return '你沒有權(quán)限訪問质蕉!'
hash_type, header_signature = header_signature_origin.split('=')
if hash_type != 'sha1':
return '不支持的加密方式!'
secret = str.encode("http://www.jetchen.cn")
hashhex = hmac.new(secret, request.data, digestmod='sha1').hexdigest()
if hmac.compare_digest(hashhex, header_signature):
repo = Repo('/data/blog-test/blog.github.io/') # 獲取本地git倉(cāng)庫(kù)
# repo = Repo('D:\project\mixed\\blog.github.io\\') # 獲取本地git倉(cāng)庫(kù)
# origin = repo.remotes.origin # 獲取遠(yuǎn)程庫(kù) & 遠(yuǎn)程分支
# origin.pull('--rebase') # 拉代碼
remote = repo.remote()
remote.pull('master')
if 'after' in request.json:
commit = request.json['after'][0:6] # pull 的最新的commit
print('Repository updated with commit {}'.format(commit))
else:
return '簽名校驗(yàn)失旚婕 模暗!'
return jsonify({}), 200
if __name__ == "__main__":
app.run(port=8001)