GO语言实现Github webhook接收处理服务

本文主要目的是使用go语言实现github webhook的接收处理,对下文提及的go语言、github、webhook、hexo博客框架不做过多介绍,如果想要学习GO语言使用,想要了解什么是github以及gwebhook, 想要使用hexo框架快速搭建博客系统的可自行百度搜索学习。

1、背景

此前使用hexo框架搭建了一套博客系统,博客系统是放在群晖的docker中的,一般写完文章会push到VPS的git仓库中,再由nginx展示静态页。 今天心血来潮,将代码push到github的仓库里,然后使用github pages来展示页面,但vps 就接收不到了,虽然hexo框架支持一键部署到GitHub Pages,但正好最近在学习go语言,并且想了解一下Github webhook,所以使用go语言实现Github webhook接收处理。

2、解决思路

通过GO语言开发一个webhook接收处理的web服务,并部署在VPS上,该web服务用于接收github的webhook请求。当你将本地代码 push到github之后,github通过webhook请求VPS上部署的服务地址,发送一个push状态,VPS上的web服务接收请求并验证通过后自动pull github上的代码至nginx的根目录,从而实现VPS和github代码的同步更新。

3、实现代码

废话不多说,直接看代码实现。

/**
 * @author zander
 * @version 1.0
*/
package main
import (
	"fmt"
    "net/http"
    "log"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"io/ioutil"
	"os/exec"
)
//处理请求
func wsHandler(w http.ResponseWriter, r *http.Request) {
	var Secret string ="xxxx"
	if (r.Header.Get("x-github-event") == "push" || r.Header.Get("x-github-event") == "ping") {
		bodyContent, _ := ioutil.ReadAll(r.Body)
		r.Body.Close()
		signature := r.Header.Get("X-Hub-Signature")
		if VerifySignature(signature, string(bodyContent), Secret) { //检验 github 发过来的 签名
			//("验证通过,启动部署任务")
			//校验通过,执行shell命令
            //pull最新代码至nginx根目录下
			cmd := exec.Command("/bin/sh","-c","cd /www && git reset --hard master && git pull") 
			_, err := cmd.Output()
			if err == nil {
				fmt.Fprintln(w, "{\"code\":200, \"description\":\"false\"}")
			} else {
				fmt.Fprintln(w, "{\"code\":200, \"description\":\"OK\"}")
			}
		} else {
			fmt.Fprintln(w, "{\"code\":200, \"error\":\"Signature error\"}")
		}
	} else {
		fmt.Fprintln(w, "{\"code\":200, \"error\":\"Unmatch x-github-event\"}")
	}
}
//main入口函数
func main()  {
    // 当有请求访问ws时,执行此回调方法
    http.HandleFunc("/",wsHandler)
    // 监听127.0.0.1:7777
    err := http.ListenAndServe("127.0.0.1:7777", nil)
    if err != nil {
        log.Fatal("ListenAndServe", err.Error())
    }
}
//根据 密钥和 body 生成签名
func generateHashSignature(message string, secret string) string {
	h := hmac.New(sha1.New, []byte(secret))
	h.Write([]byte(message))
	return "sha1=" + hex.EncodeToString(h.Sum(nil))
}
// 比较签名结果
func VerifySignature(signature string, data string, secret string) bool {
	return signature == generateHashSignature(string(data), secret)
}
 
  

注1、 上述代码exec.Command("/bin/sh","-c","cd /www && git reset --hard master && git pull")中的/www目录是 nginx 的root目录,我本地的静态页是直接pull到www的,所以该路径下存在.git文件,但是.git文件不应支持对外访问,因此nginx中需要屏蔽对.git的访问。

注2、上述代码的编写参考了:GitHub - moonagic/GoWebhook: github webhook service written by go.。

最后,在github的webhook中的payload url指定VPS上服务对应地址。GO语言实现Github webhook接收处理服务_第1张图片

你可能感兴趣的:(github,git)