diff --git a/daemon/inertiad/webhook/doc.go b/daemon/inertiad/webhook/doc.go new file mode 100644 index 00000000..acdcada9 --- /dev/null +++ b/daemon/inertiad/webhook/doc.go @@ -0,0 +1,2 @@ +// Package webhook contains Inertia's webhook parsing code +package webhook diff --git a/daemon/inertiad/webhook/github.go b/daemon/inertiad/webhook/github.go new file mode 100644 index 00000000..26c6ffd0 --- /dev/null +++ b/daemon/inertiad/webhook/github.go @@ -0,0 +1,67 @@ +package webhook + +import ( + "encoding/json" + "errors" + "fmt" + "net/http" +) + +// GithubPushEvent represents a push to a Github repository +// see https://developer.github.com/v3/activity/events/types/#pushevent +type GithubPushEvent struct { + eventType string + Ref string `json:"ref"` + Repo GithubPushEventRepository `json:"repository"` +} + +// GithubPushEventRepository represents the repository object in a Github PushEvent +// see https://developer.github.com/v3/activity/events/types/#pushevent +type GithubPushEventRepository struct { + FullName string `json:"full_name"` + GitURL string `json:"clone_url"` + SSHURL string `json:"ssh_url"` +} + +func parseGithubEvent(r *http.Request, event string) (Payload, error) { + var payload Payload + switch event { + case "push": + fmt.Println("Push event") + payload = GithubPushEvent{eventType: event} + default: + return nil, errors.New("Unsupported Github event") + } + + err := json.NewDecoder(r.Body).Decode(&payload) + if err != nil { + return nil, errors.New("Error decoding body") + } + + return payload, nil +} + +// GetEventType returns the event type of the webhook +func (g GithubPushEvent) GetEventType() string { + return g.eventType +} + +// GetRepoName returns the full repo name +func (g GithubPushEvent) GetRepoName() string { + return g.Repo.FullName +} + +// GetRef returns the full ref +func (g GithubPushEvent) GetRef() string { + return g.Ref +} + +// GetGitURL returns the git clone URL +func (g GithubPushEvent) GetGitURL() string { + return g.Repo.GitURL +} + +// GetSSHURL returns the ssh URL +func (g GithubPushEvent) GetSSHURL() string { + return g.Repo.SSHURL +} diff --git a/daemon/inertiad/webhook/webhook.go b/daemon/inertiad/webhook/webhook.go new file mode 100644 index 00000000..7add10cc --- /dev/null +++ b/daemon/inertiad/webhook/webhook.go @@ -0,0 +1,49 @@ +package webhook + +import ( + "errors" + "fmt" + "net/http" + "strings" +) + +// Payload represents a generic webhook payload +type Payload interface { + GetEventType() string + GetRepoName() string + GetRef() string + GetGitURL() string + GetSSHURL() string +} + +// Parse takes in a webhook request and parses it into one of the supported types +func Parse(r *http.Request) (Payload, error) { + fmt.Println("Parsing webhook...") + + if r.Header.Get("content-type") != "application/json" { + return nil, errors.New("Content-Type must be JSON") + } + + // Try Github + githubEventHeader := r.Header.Get("x-github-event") + if len(githubEventHeader) > 0 { + fmt.Println("Github webhook received") + return parseGithubEvent(r, githubEventHeader) + } + + // Try Gitlab + gitlabEventHeader := r.Header.Get("x-gitlab-event") + if len(gitlabEventHeader) > 0 { + fmt.Println("Gitlab webhook received") + return nil, errors.New("Unsupported webhook received") + } + + // Try Bitbucket + userAgent := r.Header.Get("user-agent") + if strings.Contains(userAgent, "Bitbucket") { + fmt.Println("Bitbucket webhook received") + return nil, errors.New("Unsupported webhook received") + } + + return nil, errors.New("Unsupported webhook received") +}