forked from remind101/conveyor
/
server.go
95 lines (76 loc) · 2.16 KB
/
server.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
package conveyor
import (
"encoding/json"
"io"
"net/http"
"regexp"
"strings"
"golang.org/x/net/context"
"github.com/codegangsta/negroni"
"github.com/ejholmes/hookshot"
"github.com/ejholmes/hookshot/events"
"github.com/remind101/conveyor/builder"
)
// Server implements the http.Handler interface for serving build requests via
// GitHub webhooks.
type Server struct {
Queue BuildQueue
// mux contains the routes.
mux http.Handler
}
// NewServer returns a new Server instance
func NewServer(q BuildQueue) *Server {
s := &Server{Queue: q}
r := hookshot.NewRouter()
r.HandleFunc("ping", s.Ping)
r.HandleFunc("push", s.Push)
n := negroni.Classic()
n.UseHandler(r)
s.mux = n
return s
}
// ServeHTTP implements the http.Handler interface.
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.mux.ServeHTTP(w, r)
}
// Ping is an http.HandlerFunc that will handle the `ping` event from GitHub.
func (s *Server) Ping(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Ok\n")
}
// Push is an http.HandlerFunc that will handle the `push` event from GitHub.
func (s *Server) Push(w http.ResponseWriter, r *http.Request) {
ctx := context.TODO()
var event events.Push
if err := json.NewDecoder(r.Body).Decode(&event); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Don't build forks.
if event.Repository.Fork {
io.WriteString(w, "Not building fork")
return
}
// Don't build deleted branches.
if event.Deleted {
io.WriteString(w, "Not building deleted branch")
return
}
opts := builder.BuildOptions{
Repository: event.Repository.FullName,
Branch: strings.Replace(event.Ref, "refs/heads/", "", -1),
Sha: event.HeadCommit.ID,
NoCache: noCache(event.HeadCommit.Message),
}
// Enqueue the build
if err := s.Queue.Push(ctx, opts); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
// http://rubular.com/r/y8oJAY9eAS
var noCacheRegexp = regexp.MustCompile(`\[docker nocache\]`)
// noCache returns whether the docker layer cache should be used for this build
// or not.
func noCache(message string) bool {
return noCacheRegexp.MatchString(message)
}