Skip to content

Commit

Permalink
Merge 51dee15 into 0c4136e
Browse files Browse the repository at this point in the history
  • Loading branch information
brian-nguyen committed Jul 7, 2018
2 parents 0c4136e + 51dee15 commit fdbfdb0
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 44 deletions.
2 changes: 1 addition & 1 deletion daemon/inertiad/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func run(host, port, version string) {
)

// GitHub webhook endpoint
handler.AttachPublicHandlerFunc("/webhook", gitHubWebHookHandler)
handler.AttachPublicHandlerFunc("/webhook", webhookHandler)

// CLI API endpoints
handler.AttachUserRestrictedHandlerFunc("/status", statusHandler)
Expand Down
62 changes: 19 additions & 43 deletions daemon/inertiad/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,40 @@ import (
"os"

docker "github.com/docker/docker/client"
"github.com/google/go-github/github"
"github.com/ubclaunchpad/inertia/common"
"github.com/ubclaunchpad/inertia/daemon/inertiad/project"
"github.com/ubclaunchpad/inertia/daemon/inertiad/webhook"
)

var webhookSecret = "inertia"

// gitHubWebHookHandler writes a response to a request into the given ResponseWriter.
func gitHubWebHookHandler(w http.ResponseWriter, r *http.Request) {
// webhookHandler writes a response to a request into the given ResponseWriter.
func webhookHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, common.MsgDaemonOK)

payload, err := github.ValidatePayload(r, []byte(webhookSecret))
payload, err := webhook.Parse(r)
if err != nil {
println(err.Error())
println(err)
return
}

event, err := github.ParseWebHook(github.WebHookType(r), payload)
if err != nil {
println(err.Error())
return
}

switch event := event.(type) {
case *github.PushEvent:
processPushEvent(event)
case *github.PullRequestEvent:
processPullRequestEvent(event)
switch event := payload.GetEventType(); event {
case webhook.PushEvent:
processPushEvent(payload)
// case webhook.PullEvent:
// processPullRequestEvent(payload)
default:
println("Unrecognized event type")
}
}

// processPushEvent prints information about the given PushEvent.
func processPushEvent(event *github.PushEvent) {
repo := event.GetRepo()
branch := common.GetBranchFromRef(event.GetRef())
func processPushEvent(payload webhook.Payload) {
branch := common.GetBranchFromRef(payload.GetRef())

println("Received PushEvent")
println(fmt.Sprintf("Repository Name: %s", *repo.Name))
println(fmt.Sprintf("Repository Git URL: %s", *repo.GitURL))
println(fmt.Sprintf("Repository Name: %s", payload.GetRepoName()))
println(fmt.Sprintf("Repository Git URL: %s", payload.GetGitURL()))
println(fmt.Sprintf("Branch: %s", branch))

// Ignore event if repository not set up yet, otherwise
Expand All @@ -56,9 +50,9 @@ func processPushEvent(event *github.PushEvent) {
}

// Check for matching remotes
err := deployment.CompareRemotes(common.GetSSHRemoteURL(repo.GetGitURL()))
err := deployment.CompareRemotes(payload.GetSSHURL())
if err != nil {
println(err.Error())
println(err)
return
}

Expand All @@ -67,7 +61,7 @@ func processPushEvent(event *github.PushEvent) {
println("Event branch matches deployed branch " + branch)
cli, err := docker.NewEnvClient()
if err != nil {
println(err.Error())
println(err)
return
}
defer cli.Close()
Expand All @@ -77,7 +71,7 @@ func processPushEvent(event *github.PushEvent) {
SkipUpdate: false,
})
if err != nil {
println(err.Error())
println(err)
}
} else {
println(
Expand All @@ -86,21 +80,3 @@ func processPushEvent(event *github.PushEvent) {
)
}
}

// processPullRequestEvent prints information about the given PullRequestEvent.
// Handling PRs is unnecessary because merging one will trigger a PushEvent.
// For now, simply logs events - may in the future do something configured
// by the user.
func processPullRequestEvent(event *github.PullRequestEvent) {
repo := event.GetRepo()
pr := event.GetPullRequest()
merged := "false"
if *pr.Merged {
merged = "true"
}
println("Received PullRequestEvent")
println(fmt.Sprintf("Repository Name: %s", *repo.Name))
println(fmt.Sprintf("Repository Git URL: %s", *repo.GitURL))
println(fmt.Sprintf("Ref: %s", pr.GetBase().GetRef()))
println(fmt.Sprintf("Merge status: %v", merged))
}
2 changes: 2 additions & 0 deletions daemon/inertiad/webhook/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package webhook contains Inertia's webhook parsing code
package webhook
71 changes: 71 additions & 0 deletions daemon/inertiad/webhook/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package webhook

import (
"encoding/json"
"errors"
"net/http"
)

// x-github-event header values
var (
GithubPushHeader = "push"
// GithubPullHeader = "pull"
)

// 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) {
dec := json.NewDecoder(r.Body)

switch event {
case GithubPushHeader:
payload := GithubPushEvent{eventType: PushEvent}

if err := dec.Decode(&payload); err != nil {
return nil, errors.New("Error parsing PushEvent")
}

return payload, nil
default:
return nil, errors.New("Unsupported Github event")
}
}

// 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
}
53 changes: 53 additions & 0 deletions daemon/inertiad/webhook/webhook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package webhook

import (
"errors"
"fmt"
"net/http"
"strings"
)

// Constants for the generic webhook interface
var (
PushEvent = "push"
// PullEvent = "pull"
)

// 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) {
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 detected")
return parseGithubEvent(r, githubEventHeader)
}

// Try Gitlab
gitlabEventHeader := r.Header.Get("x-gitlab-event")
if len(gitlabEventHeader) > 0 {
fmt.Println("Gitlab webhook detected")
return nil, errors.New("Unsupported webhook received")
}

// Try Bitbucket
userAgent := r.Header.Get("user-agent")
if strings.Contains(userAgent, "Bitbucket") {
fmt.Println("Bitbucket webhook detected")
return nil, errors.New("Unsupported webhook received")
}

return nil, errors.New("Unsupported webhook received")
}

0 comments on commit fdbfdb0

Please sign in to comment.