1. 程式人生 > >利用 Webhooks 實現程式碼的自動拉取

利用 Webhooks 實現程式碼的自動拉取

很長時間沒有更新部落格了,前段時間一直都在忙著找工作,最近才穩定下來,後面有機會的話再說說找工作的經歷。

以前做完一個專案,要放到伺服器上執行,最開始使用 Xftp 將程式碼傳上去,中間如果需要修改程式碼,都是在本地除錯完再傳到伺服器,覆蓋原來的檔案生效,非常麻煩。

後來使用 Git 做版本管理,配合程式碼託管平臺,就不用一個個的傳檔案了,每次修改完程式碼 push 到遠端版本庫以後,只需要登陸到伺服器上,pull 一下,最新的程式碼就被拉下來了,比之前方便了許多。

進了公司在發現,之前的方法還是太笨了,Github 提供了一個功能 Webhooks,利用它可以實現程式碼的自動拉取,每次 push 完程式碼,再也不用登陸伺服器手動拉程式碼了,非常方便。

簡介

Webhooks 是程式碼託管平臺提供的一個功能,對於任意一個專案,可以設定一個 URL,同時選擇一些事件,當觸發了這些事件時,程式碼託管平臺會自動請求該 URL,並帶上一些必要的引數。簡單點說,Webhooks 就是一個專案的鉤子函式,當你執行一些事件時,會自動呼叫這個鉤子函式,事件就是 push、pull request、fork 等等這些操作。

程式碼託管平臺有很多,常見的第三方的 GitHub、碼雲、Coding,或者自己搭建的 GitLab 都提供了 Webhooks 功能,設定方法基本都差不多,本文以 GitHub 為例講解。

過程

設定回撥 URL,選擇事件

登陸 GitHub,新建一個版本庫,命名為 Webhooks,依次點選 Settings

-> Webhooks -> Add webhook,之後如下圖

在這裡插入圖片描述

三個引數:

  • Payload URL:必填,回撥的 URL,每次檢測到事件時,都會向該 URL 傳送一個 POST 請求;
  • Content type:POST 攜帶資料的方式,GitHub 上提供 application/json 和 application/x-www-form-urlencoded 兩種,如果只是實現簡單的拉程式碼,選哪一種無所謂,其它的程式碼託管平臺可能只提供 json 方式;
  • Secret:金鑰,用於驗證,現在先不填。

下面就是事件選擇,預設 push 的時候觸發,一般這樣就可以了,如果想選擇其它事件,點第三個按鈕就可以看到所有的事件,選擇合適的事件後,點 Add webhook

按鈕即可。

新增 Deploy keys

兩個公鑰

  • 使用者公鑰:SSH keys,認證使用者身份,新增使用者公鑰後,對該使用者的所有專案擁有讀寫許可權,用於開發機;
  • 部署公鑰:Deploy keys,對專案進行授權,擁有隻讀許可權,一般用於生產或測試伺服器。

知道兩個公鑰的區別後,通過 SSH 登陸伺服器,執行以下命令

sudo mkdir /var/www/.ssh
sudo chown -R www-data:www-data /var/www/.ssh
sudo -Hu www-data ssh-keygen -t rsa -C "[email protected]"

第二條命令表示將目錄 .ssh 的擁有者、所屬組修改為 www-data,第三條命令表示在 /var/www/.ssh 目錄下生成金鑰,同時將該金鑰的擁有者、所屬組修改為 www-data,為什麼這麼做呢?因為在 Ubuntu 中,PHP 執行時的使用者為 www-data,如果不修改,PHP 執行時的使用者是讀不到這個部署公鑰的,也就拉不了程式碼了。

如果不確定系統的 PHP 執行時使用的哪個使用者,可以隨便新建一個 PHP 檔案,寫下面的程式碼,訪問一下就知道了。

<?php
    system("whoami");
?>

部署公鑰生成後,執行下面的程式碼檢視公鑰,複製

sudo cat /var/www/.ssh/id_rsa.pub

依次點選專案的 Setting -> Deploy keys -> Add deploy key,將公鑰粘進去,點選 Add key 新增完成。

準備鉤子檔案

在 GitHub 上操作完成後,下面的操作都在伺服器上。

在剛才設定的 URL 指向的目錄下,新建一個 index.php 檔案,程式碼如下

<?php
    shell_exec("cd /var/www/html/Webhooks && git pull 2>&1");  // 切換到專案目錄,執行 git pull,加上 2>&1 會輸出一些錯誤資訊,便於除錯
?>

需要說明的是,我上面設定的回撥地址 webhooks.mrzhouxiaofei.com 指向了伺服器上 /var/www/html/webhooks 這個地址,所以新建的 index.php 檔案也在這個目錄下,GitHub 回撥地址時,自然就訪問到了這個檔案。

如果你設定的回撥地址不一樣,可以根據地址訪問的目錄新建檔案。

同樣的,也需要為目錄和檔案設定擁有者、所屬組,命令如下

sudo chown -R www-data:www-data /var/www/html/webhooks

克隆專案檔案

克隆專案,同時修改專案的擁有者、所屬組,如下

sudo -Hu www-data git clone [email protected]:mrzhouxiaofei/Webhooks.git

執行完後,伺服器的 /var/www/ 目錄結構如下

----/var/www
------------/.ssh   部署公鑰,擁有者、所屬組為 www-data
------------/html
----------------/webhooks/index.php 鉤子檔案,擁有者、所屬組為 www-data
----------------/Webhooks 專案目錄,擁有者、所屬組為 www-data

到此為止,伺服器應該就能自動拉取專案檔案了,可以在 GitHub 上的 Webhooks 專案裡新建一個檔案,然後看下伺服器的專案目錄裡有沒有拉取新檔案。

測試

開啟專案,點選 Setting -> Webhooks,可以看到剛剛設定的回撥 URL,點進去拉到最下面 Recent Deliveries,可是看到所有的被觸發事件的請求,任意點選一個檢視,如下圖所示

在這裡插入圖片描述

  • Request
    • Headers:請求頭,包含一些基本資訊;
    • Payload:觸發這次事件的所有資訊都包含在這裡面,包括專案名、commit、使用者名稱等等,如果伺服器上的鉤子檔案要做一些高階操作,就可以解析這個欄位。
  • Response
    • Headers:響應頭
    • Body:伺服器鉤子檔案的返回資訊,除錯輸出資訊可以寫到鉤子檔案裡,請求後在這裡檢視。

每一種事件傳送的 Payload 格式是不一樣的,關於 Payload 更多資訊,請看官方文件: Event Types & Payloads

驗證

對於基本的專案拉取程式碼,以上的內容已經足夠了。

但是很容易就能想到一個問題,如果別人知道了你回撥的 URL,然後他在自己專案的 Webhooks 裡填上你的 URL,然後瘋狂 push 怎麼辦?儘管沒辦法獲取你的程式碼,但是你的伺服器會執行一些不必要的 git pull,顯然這是我們不能容忍的。

這個時候,Secret 就派上用場了。新增 Webhooks 的時候,Secret 列填上一個隨機字串,在伺服器上的鉤子檔案裡再寫個驗證就可以了,這樣就可以擋住惡意的攻擊了。

具體來說,在 Secret 裡填上一個字串,比如說填上 mrzhouxiaofei,登陸伺服器,編輯 /var/www/html/webhooks 目錄下的鉤子檔案 index.php,內容如下

<?php
$secret = "mrzhouxiaofei";  //金鑰,和 GitHub 上對應
$path = "/var/www/html/Webhooks";  //伺服器上的專案檔案目錄
$signature = $_SERVER["HTTP_X_HUB_SIGNATURE"];  //獲取雜湊字串
if($signature) {
    $rawPost = file_get_contents("php://input");  //獲取收到的資料
    list($algo, $hash) = explode("=", $signature, 2);  //獲取雜湊演算法、雜湊值
    if ($hash === hash_hmac($algo, $rawPost, $secret)) {  //驗證
		shell_exec("cd /var/www/html/Webhooks && git pull 2>&1");
		echo "程式碼拉取成功";
	} else {
	    echo "Secret 驗證失敗";
	}
} else {
    echo "請輸入 Secret";
}

這樣,每次觸發事件,GitHub 會使用 SHA-1 將傳送的資料和 Secret 一起雜湊,生成一個雜湊字串,在鉤子檔案中需要對這個雜湊字串進行驗證。

對於其它程式碼託管平臺,有的不提供 Secret 欄位,有的 Secret 在鉤子檔案中直接驗證,至於使用哪一種,看對應的官方文件就行了。

相關推薦

利用 Webhooks 實現程式碼自動

很長時間沒有更新部落格了,前段時間一直都在忙著找工作,最近才穩定下來,後面有機會的話再說說找工作的經歷。 以前做完一個專案,要放到伺服器上執行,最開始使用 Xftp 將程式碼傳上去,中間如果需要修改程式碼,都是在本地除錯完再傳到伺服器,覆蓋原來的檔案生效,非常

linux下實現svn自動程式碼併發布

正常在釋出專案的時候是將專案打包成war包,並將程式碼上傳到伺服器中,執行伺服器,整個過程較為複雜,在測試過程中會涉及到多次程式碼的修改,重新打包釋出,這樣就很不友好,接下來就簡單介紹一種方法,只要執行一個shell指令碼檔案就能把整個過程全部搞定。 第一步:安裝svn

利用Python實現導彈自動追蹤!室友面前的裝逼利器!史上最詳細!

技術 取數 跟隨鼠標 構造 制作 思想 室友 相同 精確 不好意思 ,上傳錯了。接著看圖! 由於待會要用pygame演示,他的坐標系是y軸向下,所以這裏我們也用y向下的坐標系。 算法總的思想就是根據上圖,把時間t分割成足夠小的片段(比如1/1000,

android 使用TableLayout 實現佈局自動伸寬度 LinearLayout中元素按比例分配寬度

TableLayout 實現佈局自動拉伸寬度  <TableLayout android:layout_width="match_parent" android:layout_height="match_parent" android:

(telegram自動實現)python對於telegram開發交流分享 python 實現telegram自動人進群

可氣的是上篇文章被舉報了=這次不賣自動拉人軟體啦! 實習在公司開發用python實現telegram(電報群)自動拉人進群--分享心得 當時做了自動註冊 爬取最近兩天登入使用者 telegram自動拉人 機器人管理。。。。一路艱辛----- 給大家推薦非常良心的開源專案 

手摸手,帶你實現程式碼自動部署

為什麼? 為什麼要實現自動部署? 在2個月的時間裡,一直都在忙著整理部落格,每一個程式設計師都有一個部落格夢(當然也不排除有些是沒有的),我先後使用過各種部落格系統: vuepress react-static jekyll hexo ... 這些都因為前前後後的原因,

git hook實現程式碼自動部署

原理與流程 git使用者執行git push操作 遠端倉庫發現有使用者執行了push操作,就會執行一個指令碼post-receive(鉤子) 在post-receive指令碼中,將git倉庫的程式碼拷貝到web站點目錄下 建立git倉庫 我們可以在自己的伺服器上建立g

GIT 合併程式碼遠端分支合併本地的問題

1. git fetch:相當於是從遠端獲取最新版本到本地,不會自動mergegit pull = git fetch + git mergegit pull --rebase = git fetch + git rebase場景: 昨天拉取過最新的,但是今天早上同事有更新P

win環境下SVN利用鉤子實現程式碼同步到WEB目錄

思路:  找 到SVN Server中的倉庫(Repositories)資料夾的位置,在相應的專案資料夾中找到hooks資料夾。在該資料夾中新增一個post- commit檔案;當有commit動作發生時(提交到SVN Server時)就會執行這個post-commit檔案,

利用ScrollView實現佈局自動滾動

首先1,獲得ScrollView sc = (ScrollView) findViewById(R.id.scroll);//scroll物件      LinearLayout mlayout = (LinearLayout) findViewById(R.id.mlayo

linux伺服器程式碼衝突方案

常規:git add 新增已修改檔案必須執行改命令 git commit -m "3" 必須提交評論本地 git push 提交線上伺服器(非特殊情況不要加其他引數)   衝突解決: 1.git status -uno 檢視衝突檔案和衝突狀態 2.vi開啟衝突檔案後會發現,程式碼中會被&

Jenkins+Maven+Svn實現程式碼自動打包與釋出

安裝jdk、tomcat環境 [root@centos6 ~]# tar zxf jdk-8u111-linux-x64.tar.gz -C /usr/local/ [root@centos6 ~]# tar zxf apache-tomcat-8.5.9.t

Android 利用popwindow實現類似下框效果

1.實現思路。 利用popwindow的showAsDropDown方法,結合自定義background樣式。 2.java程式碼 PopupWindow searchConditionPopwind

PHPStorm 配置遠端伺服器資料夾在本地windows映象,實現程式碼自動同步(類似於Samba架構檔案同步功能)

場景介紹:這是一種類似samba架構,也和 filezilla+xshell 模式相類似的程式碼檔案同步的模式,但是卻更加優雅,也更加方便簡潔。環境介紹:本地windows端:編輯器phpstorm遠端Linux端:centos(香港節點伺服器)LNMP一、實現檔案同步1、在

如何實現新聞自動

我想做一個系統能夠從一些別的網站抓新聞,然後動態新增到我的站點上來,請問如何實現?新浪的新聞抓取1。首頁呼叫<style type="text/css"><!--body {  font-size: 12px}--></style><

章魚哥—VB.NET 如何實現程式碼自動生成控制元件 新增繫結事件

這個問題其實非常簡單,我看到網上也有很多的例子,大家只要一搜就會明白。 但是我在這裡試圖比較詳細的介紹自動生成控制元件的步驟'**************************************************************************

Windows下Jenkins自動編譯SVN專案併發布Tomcat和Jboss

本文主要記錄一些重要的配置,忽略Jenkins的安裝。配置主要分為三個重要部分: 1、外掛配置            主要涉及3個外掛的安裝。          Deploy to container Plugin:This plugin takes a war/ear

利用Jquery實現二級下選單

     最近在學習前端的內容:看到別人做的二級選單挺好看的。下載別人的Demo看起來比較麻煩,所以就嘗試了自己做一個簡單二級下拉選單: 效果圖如下: 下拉選單實現後的效果圖: 沒有做什麼美化,只是從功能上實現下拉選單 HTML程式碼: <!DOCTYPE ht

SVN利用鉤子實現程式碼同步到web目錄

系統環境:windows server 2003 web伺服器:IIS 第一步:svn伺服器的安裝 由於使用的是windows伺服器,所以我選擇了最方便配置的VisualSVN伺服器。到VisualSVN官網上下載VisualSVN的msi安裝包,在windows

Shell 自動 git 分支,mvn 打包,部署遠端除錯的指令碼

#!/bin/bash chose_branch=$1 server_list=("axxxx" "axxxxxxxx") srcDir='/usr/xxxxxx/xxxxxx/' functi