-
Notifications
You must be signed in to change notification settings - Fork 0
/
wumpe.go
102 lines (88 loc) · 2.06 KB
/
wumpe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2017 Julien Schmidt. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be found
// in the LICENSE file.
package main
import (
"bytes"
"log"
"net/http"
"os"
"os/exec"
"strings"
"github.com/naoina/toml"
)
type hook struct {
Ref string
Secret string
Dir string
Cmd string
}
type config struct {
Listen string
Hooks map[string]hook
}
var cfg config
func sendErr(w http.ResponseWriter, code int) {
http.Error(w, http.StatusText(code), code)
}
func Build(w http.ResponseWriter, req *http.Request) {
if req.Method != "POST" || req.URL.Path != "/build" {
log.Println(req.Method, req.URL.Path)
sendErr(w, http.StatusTeapot)
return
}
// try to detect which type of request (GitLab or GitHub) this is
var h hook
var status int
switch {
case strings.HasPrefix(req.UserAgent(), "GitHub-Hookshot/"):
h, status = parseGitHubRequest(req)
case req.Header.Get("X-Gitlab-Token") != "":
h, status = parseGitLabRequest(req)
}
if status != http.StatusOK {
sendErr(w, status)
return
}
// pull the updates
cmd := exec.Command("/usr/bin/git", "pull")
cmd.Dir = h.Dir
out, err := cmd.CombinedOutput()
log.Println(string(out))
if err != nil {
log.Println("git error:", err)
sendErr(w, http.StatusInternalServerError)
return
}
out = bytes.TrimSpace(out)
var gitUnchanged = []byte("Already up-to-date.")
if bytes.HasPrefix(out, gitUnchanged) {
// no new commits
w.WriteHeader(http.StatusConflict)
w.Write(gitUnchanged)
return
}
// if new commits were pulled, call the hook command
args := strings.Fields(h.Cmd)
cmd = exec.Command(args[0], args[1:]...)
cmd.Dir = h.Dir
out, err = cmd.CombinedOutput()
log.Println(string(out))
if err != nil {
log.Println("cmd error:", err)
sendErr(w, http.StatusInternalServerError)
return
}
}
func main() {
f, err := os.Open("/etc/wumpe.toml")
if err != nil {
panic(err)
}
defer f.Close()
if err := toml.NewDecoder(f).Decode(&cfg); err != nil {
panic(err)
}
http.HandleFunc("/", Build)
log.Fatal(http.ListenAndServe(cfg.Listen, nil))
}