在當下使用 GIT 來管理代碼已是一種很是流行的方式了。使用 GIT 能夠很方便的給代碼建立分支,撤銷不須要的提交,與他人合做共同編寫代碼。php
GitLab 是基於 GIT 實現的現代化的開發者協做平臺,它將 issues, code review, CI 和 CD 整合到獨立的網站UI,彌補了 GIT 在可視化操做方面的不足。git
本文的目的是配置實如今 GitLab 平臺上的代碼自動部署。想要達到的效果是這樣子的,當客戶端向 GitLab 服務器的特定分支(如:prod)提交代碼時,GitLab 服務器會發送通知給線上代碼服務器,代碼服務器收到通知以後再拉取 GitLab 服務器上該分支的最新代碼。web
效果圖以下: shell
有了 GitLab ,只須要三步就能夠實現以上描述的效果了。json
在代碼服務器端準備好一份處理 GitLab 服務器通知的腳本和一份拉取代碼的腳本。 bash
GitLab 服務器所發出來的通知,其實就是向代碼服務器發出一個 http 請求,請求中包含了本次提交中的相關信息,如所提交的分支、誰提交的、本次更新的代碼等等信息。服務器
因此在代碼服務器中添加一個腳本,專門處理該請求便可。ssh
能夠參考一下的 PHP 代碼:gitlab
<?php // 處理 GitLab 請求的腳本 $rowData = file_get_contents('php://input', 'r');; $rowData = json_decode($rowData,true); $output = ''; $type = $_GET['type']; // 只拉取 prod 分支的代碼到服務器 if($rowData['ref'] == 'refs/heads/prod'){ if('ims' == $type){ // 觸發拉取代碼的腳本 exec('./post-ims',$output); } logg($type." output:".json_encode($output)); } logg($type.':'.$rowData['user_name']." commit to branch:".$rowData['ref']); function logg($data){ $text = '['.date('Y-m-d H:i:s').'] '.$data."\n"; file_put_contents('./log/gitlab'.date('ym').'.log',$text,FILE_APPEND); }
還有一個就是處理拉取 GitLab 服務器更新到代碼服務器的腳本。該腳本能夠很簡單,只須要將當前工做目錄切換到項目的工做目錄,而後執行拉取代碼的命令便可。post
參考如下 shell 腳本:
#!/bin/bash # 拉取代碼的腳本 cd /www/ims/ git pull origin prod
在項目中配置 webhooks(Web 鉤子) 其實就是在項目中註冊一個觸發器,當項目中的某個事件發生時,該觸發器就會被觸發。在 GitLab 中的觸發器就是一個 http 請求,即一個 http 連接。
在 GitLab 中,要達到咱們上面預設的效果,咱們須要設置項目的推送事件的 webhook。一個能訪問到咱們步驟一添加的 PHP 腳本的連接。
配置所在的路徑是:
項目主頁 > setting > webhooks
在該頁面添加一個推送事件的觸發器便可,相似這樣子的 URL:
http://example.com/gitlab.php?type=ims
保存以後,能夠測試下該連接是否正確。它會模擬發送一個推送請求的數據,格式和正常的推送的同樣。在代碼服務器端就能夠根據這個來調試了。
既然是代碼自動部署,那固然是徹底不須要人爲參與的啦,這將包括不須要人爲輸入密碼。
GitLab 提供了讓每一個帳號使用祕鑰登陸的功能,配置了帳號祕鑰以後就能夠無密碼登陸帳號了。代碼自動部署正是須要這樣子的功能了。
首先要在代碼服務器端生成祕鑰:
使用命令
ssh-keygen
,連續按三次回車便可生成一對無密碼保護的祕鑰,它們的名稱分別是id_rsa
和id_rsa.pub
而後將 id_rsa.pub
的內容添加到 GitLab 帳號:
在 GitLab 帳號的 profile setting > SSH keys 粘貼並保存便可
經過以上三步,如今已經可以實現代碼自動部署了。
若是完成了以上步驟以後,還不能實現代碼自動部署,最可能出現問題的是帳號的權限問題了。有兩個地方可能出現權限的問題。
GitLab 帳號的權限
自動部署所綁定的帳號須要有權限訪問該項目。
代碼服務器端執行腳本的用戶的權限
首先,該用戶須要有權限對項目目錄進行讀寫; 而後是,該用戶的祕鑰信息綁定的是正確的 GitLab 帳號
(完)