利用 GitHook 構建持續交付和部署

原文地址:https://blog.coding.net/blog/GitHook-for-delivery-and-deploymentphp

一、爲何要打造可持續交付和部署

軟件發佈是一個使人頭痛的過程,很是耗時且風險很高。對於小團隊來講通常分爲兩種:「簽入時交付」和「定時交付」。git

「簽入時交付」策略的優點在於立刻產生的知足感。根據代碼庫的規模,從簽入新功能代碼到可以在交付準備服務器上測試,一兩分鐘就夠了。github

這種方式的主要問題在於:交付準備服務器會被蹂躪得不穩定。不少時候,我見到有人試圖測試某個功能,忽然新的版本推到交付準備服務器上了,破壞了正在運行的測試。更糟糕的是:交付準備服務器經常做爲演示服務器使用,在某些重要的演示時,極可能出現嚴重的後果。web

按期交付策略更易於預測。全部人都知道交付什麼時候啓動,並能夠規劃本身的代碼簽入是在交付以前仍是以後進行。典型作法是一天構建/交付一次或兩次。shell

因爲架構的特殊性,服務器將會愈來愈多。試想一下你要在幾十臺服務器上更新代碼是一件多麼繁瑣的事情。對於咱們公司來講面臨着嚴重的如何更快交付和部署代碼的問題。apache

咱們須要將經歷過測試的代碼可以迅速部署到服務器上,原本考慮過jekins,但jekins對咱們來講又太過繁瑣。json

二、交付與部署過程

目前咱們使用的是阿里雲服務,阿里雲服務有個很方便的地方就是鏡像,一次製做整個集羣均可以使用。ubuntu

工程師將代碼上傳到開發環境的庫中,經過GitHook自動讓測試用的服務器更新代碼,測試完成後只要將相關的代碼稍稍修改成生產環境的配置並上傳到生產環境的Git庫,經過GitHook全部與這個庫有關的服務器都會自動更新代碼。segmentfault

測試的具體過程就不在此論述了。bash

三、GitHook

咱們來看下官方解釋:

鉤子(hooks)是一些在"$GIT-DIR/hooks"目錄的腳本, 在被特定的事件(certain points)觸發後被調用。當"git init"命令被調用後, 一些很是有用的示例鉤子文件(hooks)被拷到新倉庫的hooks目錄中; 可是在默認狀況下這些鉤子(hooks)是不生效的。 把這些鉤子文件(hooks)的".sample"文件名後綴去掉就可使它們生效了。

簡單地來講有點相似回調,就是特定事情完成後回調執行事件。

四、如何搭建

咱們公司使用的是coding、服務器上是已經裝好jetty的ubuntu,不過github、gitlab跟這個的配置方法相似。

Git-SSH

首先如今coding上創建一個代碼庫,而後在生產環境上的代碼部署的地方git clone剛剛新建的代碼庫。

沒有git的要安裝git,ubuntu下是apt-get install git

爲了讓git可以自動更新代碼庫而不須要輸入帳號密碼,這時候就須要用到git-ssh了。

若是是第一次使用要先設置git的名字和郵箱(本身隨便取個名字和郵箱就行):

git config --global user.name "test"
git config --global user.email "test@zomake.com"

而後經過上一個命令輸入的郵箱來生成密鑰

ssh-keygen -t rsa -C "test@zomake.com"

若是不須要設置密鑰的密碼的話,直接三個回車。而後你就在命令行上看到生成了兩個文件:id_rsa和id_rsa.pub。

(若是不是第一次的話執行命令會提示overwrite,輸入y就行。)

而後咱們把密鑰交給ssh-agent來管理,能夠經過eval "$(ssh-agent -s)" 看看是否是正常運行,是的話會輸出它的pid。

ssh-add ~/.ssh/id_rsa

用上面這個命令將剛剛生成的私鑰交給ssh-agent。路徑填你在終端上看到的。

登陸coding,點擊帳戶-SSH公鑰-添加。將以前生成的id_rsa.pub裏的內容複製進去。

最後進到以前clone下來的代碼庫中修改.git文件夾下config中的url,改成遠端倉庫的SSH訪問地址,如git@git.coding.net:t-baby/test.git

這樣一來在服務器上git就無需輸入帳號密碼了。

準備update.sh

cd /vi git_update.sh

而後將下面的東西複製進去並保存:

#!/bin/bash

cd /opt/jetty/webapps

git remote update -p

git checkout -f origin/master

git submodule update --init

service jetty restart

第二行和最後一行根據須要自行更換,由於咱們的代碼是Java的,放在jetty中運行。將第二行的cd改爲你本身的代碼所在目錄。而最後一行代碼是用來重啓jetty服務器的,你能夠去掉或加上本身服務器的重啓代碼。

保存後給這個腳本文件777的權限。

準備githook.php

因爲一些緣由,爲了方便咱們使用了php做爲GitHook回調的地址。

先裝好PHP環境並修改端口爲8080,apache默認文件夾爲/var/www(80已經被jetty佔了,具體安裝方法見我另外一篇文章)

在/var/www/中新建一個叫githook.php,而後放入如下代碼:

shell_exec('cd /var/www && php gitpull.php');

而後再在當前文件夾下建個gitpull.php

$pid = pcntl_fork();
if ($pid == -1){
} else if ($pid > 0){
$fs = fopen('./git_hook.log', 'a');

fwrite($fs, 'Request on ['.date("Y-m-d H:i:s").']'.PHP_EOL);

$json = file_get_contents('php://input');
$data = json_decode($json, true);
fwrite($fs, 'Data: '.print_r($data, true).PHP_EOL);

fwrite($fs, '======================================================================='.PHP_EOL);
$fs and fclose($fs);

pcntl_wait($status); 

} else if ($pid == 0){

exec('sudo sh /git_update.sh &');
}

執行git_update.sh更新git倉庫。

爲何要這樣作呢。由於coding的webhook的等待時間是寫死的,要5秒內有反應,這就會致使包含一些須要時間的命令會讓webhook的地址驗證不成功,從而在push後不回調到地址上。

因此咱們用了多進程來讓其中一個執行日誌的記錄,另外一個負責執行sh文件。

填入回調地址

緊接着咱們在coding中打開部署用的代碼庫,左側點擊設置-WebHook。好比咱們剛剛的是 http://111.111.111.111:8080/githook.php

(ps:直接填寫IP能夠減小域名解析所耗費的時間)

給apache權限

聰明的朋友們測試的時候確定發現了問題,exec裏面的代碼並不執行怎麼辦?其實很簡單是由於apache的權限不夠,只要給予權限就行。

咱們能夠先經過lsof -i:80看看apache的執行用戶是誰。

圖片

好比我這裏是www-data用戶,而後執行visudo。

圖片

而後找到圖片上的位置修改爲圖片上那樣,後面那行www-data是要本身添加的。接着保存。保存的話就是ctrl+x而後回車。

這樣就可讓apache不須要密碼就能夠用管理員權限執行了。

趕忙測試下看看是否是成功了!

如何部署代碼以及結論

如今只要你一更新倉庫的代碼,就會自動回調到githook.php從而讓服務器自動更新代碼。即便多幾臺服務器也是同樣的,最簡單的方法就是利用公有云服務的鏡像功能作成鏡像裝在集羣中的其它機器,而後在coding的WebHook那裏加上這些服務器的IP就行。

這應該是全網最完善的相關教程了吧。本身靠着百度到不少不完整的資料琢磨了一自然後寫下此教程。找教程。。。最後別太相信百度到的,血的教訓~。

相關文章
相關標籤/搜索