Handel Webhook Github Menggunakan Golang

Handel Webhook Github Menggunakan Golang

Sebelumnya sudah saya tulis tentang webhook github dan di handle pakai Flask. Ketika saya browsing-browsing, saya menemukan sesuatu yang menarik, yaitu library Golang untuk handel webhook dari github. Setelah melihat example dari reponya, wah layak dicoba, sederhana dan mudah di implementasi.

Saya putuskan untuk mengganti program dari python dan flask, dengan Golang. Flownya sih masih sama:

Ketika terjadi event push di repo github maka VPS akan melakukan pull, rebuild jekyll, dan deploy ke production.

Baiklah langsung saja

Pertama saya membuat direktori kerja

Begini susunannya:

go
└── src
    └── jekhook
        ├── jekhook
        ├── main.go
        └── rebuild.sh
  • jekhook: nanti muncul setelah kita melakukan go build
  • main.go: Source code golang untuk handel webhook github
  • rebuild.sh: bash script untuk pull, rebuild, dan deploy jekyll

Unduh library pendukung

Dalam hal ini saya memakai library webhooks.v5, sangat membantu.

go get -u gopkg.in/go-playground/webhooks.v5

Tulis program main.go

nano go/src/main.go

Isinya adalah:

package main

import (
	"fmt"
	"net/http"
	"gopkg.in/go-playground/webhooks.v5/github"
	"os/exec"
	"log"
)

const (
	path = "/webhooks"
)

func main() {
	hook, _ := github.New(github.Options.Secret("secret webhook kamu"))

	http.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
		payload, err := hook.Parse(r, github.PushEvent) //github.ReleaseEvent, github.PullRequestEvent, github.PushEvent
		if err != nil {
			if err == github.ErrEventNotFound {
				// ok event wasn;t one of the ones asked to be parsed
			}
		}
		switch payload.(type) {
		case github.PushPayload:
			cmd, err := exec.Command("/bin/bash", "rebuild.sh").Output()
			if err != nil {
        			log.Fatal(err)
    			}
			fmt.Printf("%s\n", cmd)
		}
	})
	http.ListenAndServe("127.0.0.1:5000", nil)
}

Untuk bagian secret webhook kamu silakan sesuaikan.

Saya memakai ip 127.0.0.1 dengan port 5000, nantinya saya harus melakukan reverse proxy ke port tersebut. Saya juga memakai path /webhooks sehingga reverse proxy harus ke 127.0.0.1:5000/webhooks

Tulis bash script rebuild.sh

#!/bin/bash
source /home/sumarsono/.rvm/scripts/rvm;

cd ~/blog/unomind.github.io;

echo "pulling new post";
git pull origin master;

echo "rebuild site";
bundle exec jekyll build;

echo "deploying to production"
cp -rf ~/blog/unomind.github.io/_site/* /var/www/html/sumarsono/;

Lakukan build

cd go/src/jekhook/
go build

Akan muncul satu file executable bernama jekhook.

konfigurasi nginx

server {

  listen 80;

  root /var/www/html/api/;
  server_name api.sumarsono.com;

  error_log /var/log/nginx/api/error.log warn;
  access_log /var/log/nginx/api/access.log combined;

  location /webhooks {
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Server $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass http://localhost:5000/webhooks;
  }

Jangan lupa reload nginx

jalankan jekhook

Hasil dari go build adalah file bernama jekhook, kita jalankan file tersebut:

./jekhook

konfigurasi webhook di repo github

Untuk konfigurasinya, seperti gambar dibawah ini: gh-webhook.png

Coba untuk push

Perhatikan repon di server VPS, seharusnya begini:

pulling new post
Updating d579392..2351df6
Fast-forward
 webhook-test     | 2 --
 webhook-test.txt | 0
 2 files changed, 2 deletions(-)
 delete mode 100644 webhook-test
 create mode 100644 webhook-test.txt
rebuild site
Configuration file: /home/sumarsono/blog/unomind.github.io/_config.yml
            Source: /home/sumarsono/blog/unomind.github.io
       Destination: /home/sumarsono/blog/unomind.github.io/_site
 Incremental build: disabled. Enable with --incremental
      Generating...
       Jekyll Feed: Generating feed for posts
                    done in 2.884 seconds.
 Auto-regeneration: disabled. Use --watch to enable.
deploying to production

Selesai, tinggal run jekhook di background dan leyeh-leyeh.