From 17d1ca33e7c1c91f1dbb99b3ff47ef93242fe127 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Thu, 30 Apr 2015 23:48:11 -0600 Subject: [PATCH 01/32] Initial commit. --- main/main.go | 38 ++++++++++++ packet.go | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++ server.go | 100 ++++++++++++++++++++++++++++++ 3 files changed, 309 insertions(+) create mode 100644 main/main.go create mode 100644 packet.go create mode 100644 server.go diff --git a/main/main.go b/main/main.go new file mode 100644 index 0000000..4dc2255 --- /dev/null +++ b/main/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + + "github.com/cpalone/gohook" +) + +func main() { + // rawJSON, err := ioutil.ReadFile("../sample_push.json") + // if err != nil { + // panic(err) + // } + // var packet gohook.PushEvent + // if err := json.Unmarshal(rawJSON, &packet); err != nil { + // panic(err) + // } + // fmt.Println(packet.Repository.Organization) + server := gohook.NewServer(8000, "secret", "/postreceive") + server.GoListenAndServe() + for { + eAndT := <-server.EventAndTypes + switch eAndT.Type { + case gohook.PingEventType: + packet, ok := eAndT.Event.(gohook.PingEvent) + if !ok { + panic("Could not assert PingEvent as such.") + } + fmt.Println(packet.Organization.Login) + case gohook.PushEventType: + packet, ok := eAndT.Event.(gohook.PushEvent) + if !ok { + panic("Could not assert PushEvent as such.") + } + fmt.Println(packet.Organization.Login) + } + } +} diff --git a/packet.go b/packet.go new file mode 100644 index 0000000..11ec0fa --- /dev/null +++ b/packet.go @@ -0,0 +1,171 @@ +package gohook + +import ( + "encoding/json" +) + +type SenderType struct { + Login string `json:"login"` + ID int `json:"id"` + AvatarURL string `json:"avatar_url"` + GravatarID string `json:"gravatar_id"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + OrganizationsURL string `json:"organizations_url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + ReceivedEventsURL string `json:"received_events_url"` + Type string `json:"type"` + SiteAdmin bool `json:"site_admin"` +} + +type UserType struct { + Name string `json:"name"` + Email string `json:"email"` + Username string `json:"username"` +} + +type PusherType struct { + Name string `json:"name"` + Email string `json:"email"` +} + +type OrgType struct { + Login string `json:"login"` + ID int `json:"id"` + URL string `json:"url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + MembersURL string `json:"members_url"` + PublicMembersURL string `json:"public_members_url"` + AvatarURL string `json:"avatar_url"` + Description string `json:"description"` +} + +type CommitType struct { + ID string `json:"id"` + Distinct bool `json:"distinct"` + Message string `json:"message"` + Timestamp string `json:"timestamp"` + URL string `json:"url"` + Author UserType `json:"author"` + Committer UserType `json:"committer"` + Added []string `json:"added"` + Removed []string `json:"removed"` + Modified []string `json:"modified"` +} + +type RepoType struct { + ID int `json:"id"` + Name string `json:"name"` + FullName string `json:"full_name"` + Owner PusherType `json:"owner"` + Private bool `json:"private"` + HtmlURL string `json:"html_url"` + Description string `json:"description"` + Fork bool `json:"fork"` + URL string `json:"url"` + ForksURL string `json:"forks_url"` + KeysURL string `json:"keys_url"` + CollaboratorsURL string `json:"collaborators_url"` + TeamsURL string `json:"teams_url"` + HooksURL string `json:"hooks_url"` + IssueEventsURL string `json:"issue_events_url"` + EventsURL string `json:"events_url"` + AssigneesURL string `json:"assignees_url"` + BranchesURL string `json:"branches_url"` + TagsURL string `json:"tags_url"` + BlobsURL string `json:"blobs_url"` + GitTagsURL string `json:"git_tags_url"` + GitRefsURL string `json:"git_refs_url"` + TreesURL string `json:"trees_url"` + StatusesURL string `json:"statuses_url"` + LanguagesURL string `json:"languages_url"` + StargazersURL string `json:"stargazers_url"` + ContributorsURL string `json:"contributors_url"` + SubscribersURL string `json:"subscribers_url"` + SubscriptionURL string `json:"subscription_url"` + CommitsURL string `json:"commits_url"` + GitCommitsURL string `json:"git_commits_url"` + CommentsURL string `json:"comments_url"` + IssueCommentURL string `json:"issue_comment_url"` + ContentsURL string `json:"contents_url"` + CompareURL string `json:"compare_url"` + MergesURL string `json:"mergers_url"` + ArchiveURL string `json:"archive_url"` + DownloadsURL string `json:"downloads_url"` + IssuesURL string `json:"issues_url"` + PullsURL string `json:"pulls_url"` + MilestonesURL string `json:"milestones_url"` + NotificationsURL string `json:"notifications_url"` + LabelsURL string `json:"labels_url"` + ReleasesURL string `json:"releases_url"` + CreatedAt int `json:"created_at"` + UpdatedAt string `json:"updated_at"` + PushedAt int `json:"pushed_at"` + GitURL string `json:"git_url"` + SshURL string `json:"ssh_url"` + CloneURL string `json:"clone_url"` + SvnURL string `json:"svn_url"` + Homepage string `json:"homepage"` + Size int `json:"size"` + StargazersCount int `json:"stargazers_count"` + WatchersCount int `json:"watchers_count"` + Language string `json:"language"` + HasIssues bool `json:"has_issues"` + HasDownloads bool `json:"has_downloads"` + HasWiki bool `json:"has_wiki"` + HasPages bool `json:"has_pages"` + ForksCount int `json:"forks_count"` + MirrorURL string `json:"mirror_url"` + OpenIssuesCount int `json:"open_issues_count"` + Forks int `json:"forks"` + OpenIssues int `json:"open_issues"` + Watchers int `json:"watchers"` + DefaultBranch string `json:"default_branch"` + Stargazers int `json:"stargazers"` + MasterBranch string `json:"master_branch"` + Organization string `json:"organization"` +} + +type PushEvent struct { + Ref string `json:"ref"` + Before string `json:"before"` + After string `json:"after"` + Created bool `json:"created"` + Deleted bool `json:"deleted"` + Forced bool `json:"forced"` + BaseRef string `json:"base_ref"` + Compare string `json:"compare"` + Commits []CommitType `json:"commits"` + HeadCommit CommitType `json:"head_commit"` + Repository RepoType `json:"repository"` + Pusher PusherType `json:"pusher"` + Organization OrgType `json:"organization"` + Sender SenderType `json:"sender"` +} + +type PingEvent struct { + Zen string `json:"zen"` + HookID int `json:"hook_id"` + Hook json.RawMessage `json:"hook"` + Organization OrgType `json:"organization"` + Sender SenderType `json:"sender"` +} + +type EventType string + +const ( + PingEventType = EventType("ping") + PushEventType = EventType("push") +) + +type EventAndType struct { + Event interface{} + Type EventType +} diff --git a/server.go b/server.go new file mode 100644 index 0000000..dc1b580 --- /dev/null +++ b/server.go @@ -0,0 +1,100 @@ +package gohook + +import ( + "crypto/hmac" + "crypto/sha1" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" +) + +type Server struct { + Port int + Secret string + Path string + EventAndTypes chan *EventAndType +} + +func NewServer(port int, secret string, path string) *Server { + return &Server{ + Port: port, + Secret: secret, + Path: path, + EventAndTypes: make(chan *EventAndType, 5), + } +} + +func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { + defer req.Body.Close() + + if req.Method != "POST" { + http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed) + } + + if req.URL.Path != s.Path { + http.Error(w, "404 Not found- expected "+s.Path, http.StatusNotFound) + } + + eventType := req.Header.Get("X-Github-Event") + if eventType == "" { + http.Error(w, "400 Bad Request - Missing X-Github-Event Header", http.StatusBadRequest) + return + } + if eventType != "ping" && eventType != "push" { + http.Error(w, "500 Internal Server Error - Event type not yet implemented.", http.StatusInternalServerError) + } + + body, err := ioutil.ReadAll(req.Body) + if err != nil { + http.Error(w, "500 Internal Error - Could not read from request: "+err.Error(), http.StatusInternalServerError) + return + } + + if s.Secret != "" { + signature := req.Header.Get("X-Hub-Signature") + if signature == "" { + http.Error(w, "403 Forbidden- missing secret.", http.StatusForbidden) + return + } + mac := hmac.New(sha1.New, []byte(s.Secret)) + mac.Write(body) + expectedMAC := mac.Sum(nil) + expectedSig := "sha1=" + hex.EncodeToString(expectedMAC) + if !hmac.Equal([]byte(expectedSig), []byte(signature)) { + http.Error(w, "403 Forbidden - Verification of secret failed.", http.StatusForbidden) + return + } + } + var payload interface{} + switch EventType(eventType) { + case PushEventType: + payload = &PushEvent{} + case PingEventType: + payload = &PingEvent{} + } + if err := json.Unmarshal(body, &payload); err != nil { + http.Error(w, "500 Internal Error - Could not unmarshal request: "+err.Error(), http.StatusInternalServerError) + } + go func() { + et := &EventAndType{ + Event: payload, + Type: EventType(eventType), + } + s.EventAndTypes <- et + }() +} + +func (s *Server) ListenAndServe() error { + return http.ListenAndServe(fmt.Sprintf(":%v", s.Port), s) +} + +func (s *Server) GoListenAndServe() { + go func() { + err := s.ListenAndServe() + if err != nil { + panic(err) + } + }() +} From 2039c81eab49be571de394286c268d558b0c799f Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Thu, 30 Apr 2015 23:57:24 -0600 Subject: [PATCH 02/32] Fixed an assertion being off by a pointer. --- main/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/main.go b/main/main.go index 4dc2255..05a9264 100644 --- a/main/main.go +++ b/main/main.go @@ -22,13 +22,13 @@ func main() { eAndT := <-server.EventAndTypes switch eAndT.Type { case gohook.PingEventType: - packet, ok := eAndT.Event.(gohook.PingEvent) + packet, ok := eAndT.Event.(*gohook.PingEvent) if !ok { panic("Could not assert PingEvent as such.") } fmt.Println(packet.Organization.Login) case gohook.PushEventType: - packet, ok := eAndT.Event.(gohook.PushEvent) + packet, ok := eAndT.Event.(*gohook.PushEvent) if !ok { panic("Could not assert PushEvent as such.") } From dfb59cc40e6e45ecb27052dd4fb64b8526037f57 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 00:02:55 -0600 Subject: [PATCH 03/32] Create README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..2ac7c0e --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# gohook +Introduction +--- +gohook is a small library for working with Github webhooks in Go. Currently, ping events and push events are processed, but all others result in a 500 status code and an explanation that the type is not yet implemented. + +gohook is loosely based on phayes' [hookserve.](https://github.com/phayes/hookserve) + From 777afc22ea9e33fd4ec6d1aacc1e6ce5283c2d9b Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 00:04:12 -0600 Subject: [PATCH 04/32] Cleanup. --- main/main.go | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 main/main.go diff --git a/main/main.go b/main/main.go deleted file mode 100644 index 05a9264..0000000 --- a/main/main.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/cpalone/gohook" -) - -func main() { - // rawJSON, err := ioutil.ReadFile("../sample_push.json") - // if err != nil { - // panic(err) - // } - // var packet gohook.PushEvent - // if err := json.Unmarshal(rawJSON, &packet); err != nil { - // panic(err) - // } - // fmt.Println(packet.Repository.Organization) - server := gohook.NewServer(8000, "secret", "/postreceive") - server.GoListenAndServe() - for { - eAndT := <-server.EventAndTypes - switch eAndT.Type { - case gohook.PingEventType: - packet, ok := eAndT.Event.(*gohook.PingEvent) - if !ok { - panic("Could not assert PingEvent as such.") - } - fmt.Println(packet.Organization.Login) - case gohook.PushEventType: - packet, ok := eAndT.Event.(*gohook.PushEvent) - if !ok { - panic("Could not assert PushEvent as such.") - } - fmt.Println(packet.Organization.Login) - } - } -} From 55cdcbd3beacd832236d349beeb3dc21fd871275 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 00:18:29 -0600 Subject: [PATCH 05/32] Documentation. --- example/main.go | 35 +++++++++++++++++++++++++++++++++++ packet.go | 11 +++++++++++ server.go | 14 ++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 example/main.go diff --git a/example/main.go b/example/main.go new file mode 100644 index 0000000..4c85565 --- /dev/null +++ b/example/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" + + "github.com/cpalone/gohook" +) + +func main() { + // Create and start the server. + server := gohook.NewServer(8000, "secret", "/postreceive") + server.GoListenAndServe() + + // Loop continuously, blocking on a receive from server.EventAndTypes + for { + eAndT := <-server.EventAndTypes + + // switch on the packet type and use the appropriate type assertion + // to access the data in the event. + switch eAndT.Type { + case gohook.PingEventType: + packet, ok := eAndT.Event.(*gohook.PingEvent) + if !ok { + panic("Could not assert PingEvent as such.") + } + fmt.Println(packet.Organization.Login) + case gohook.PushEventType: + packet, ok := eAndT.Event.(*gohook.PushEvent) + if !ok { + panic("Could not assert PushEvent as such.") + } + fmt.Println(packet.Organization.Login) + } + } +} diff --git a/packet.go b/packet.go index 11ec0fa..9a1248d 100644 --- a/packet.go +++ b/packet.go @@ -4,6 +4,7 @@ import ( "encoding/json" ) +// SenderType represents the structure of the sender field in push/ping events. type SenderType struct { Login string `json:"login"` ID int `json:"id"` @@ -24,17 +25,20 @@ type SenderType struct { SiteAdmin bool `json:"site_admin"` } +// UserType represents the structure of a user as used in commits. type UserType struct { Name string `json:"name"` Email string `json:"email"` Username string `json:"username"` } +// PusherType represents the structure of a user as used in PushEvents. type PusherType struct { Name string `json:"name"` Email string `json:"email"` } +// OrgType represents the structure of an organization as used in ping/push events. type OrgType struct { Login string `json:"login"` ID int `json:"id"` @@ -47,6 +51,7 @@ type OrgType struct { Description string `json:"description"` } +// CommitType represents the structure of a commit as used in push events. type CommitType struct { ID string `json:"id"` Distinct bool `json:"distinct"` @@ -60,6 +65,7 @@ type CommitType struct { Modified []string `json:"modified"` } +// RepoType represents the structure of a repository as used in push events. type RepoType struct { ID int `json:"id"` Name string `json:"name"` @@ -133,6 +139,7 @@ type RepoType struct { Organization string `json:"organization"` } +// PushEvent represents the basic, top-level structure of a push event. type PushEvent struct { Ref string `json:"ref"` Before string `json:"before"` @@ -150,6 +157,7 @@ type PushEvent struct { Sender SenderType `json:"sender"` } +// PingEvent represents the basic, top-level structure of a ping event. type PingEvent struct { Zen string `json:"zen"` HookID int `json:"hook_id"` @@ -158,13 +166,16 @@ type PingEvent struct { Sender SenderType `json:"sender"` } +// EventType is an alias for string that provides type safety for the event types. type EventType string +// These constants define types for the implemented types of packets. const ( PingEventType = EventType("ping") PushEventType = EventType("push") ) +// EventAndType holds an event and its type, to be used later in a type assertion on the event. type EventAndType struct { Event interface{} Type EventType diff --git a/server.go b/server.go index dc1b580..326d9bd 100644 --- a/server.go +++ b/server.go @@ -10,6 +10,9 @@ import ( "net/http" ) +// Server is the basic type that listens for webhook events and pushes them onto +// the EventAndTypes channel. You should create a Server through the NewServer +// function. type Server struct { Port int Secret string @@ -17,6 +20,9 @@ type Server struct { EventAndTypes chan *EventAndType } +// NewServer creates a new server with the given settings. If secret is the +// zero-length string, no security verification will be done. Path should be +// specified with a leading slash. func NewServer(port int, secret string, path string) *Server { return &Server{ Port: port, @@ -26,6 +32,8 @@ func NewServer(port int, secret string, path string) *Server { } } +// ServeHTTP implements http.Handler interface on Server. You should never need +// to call this yourself. func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() @@ -86,10 +94,16 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { }() } +// ListenAndServe simply returns the error received from a call of +// http.ListenAndServe() with the correct parameters. Use this function if you +// want the call to block. func (s *Server) ListenAndServe() error { return http.ListenAndServe(fmt.Sprintf(":%v", s.Port), s) } +// GoListenAndServe is a convenience function that runs Server.ListenAndServe() +// in a goroutine and panics upon receipt of an error. Use this function if +// you do not want the call to block. func (s *Server) GoListenAndServe() { go func() { err := s.ListenAndServe() From 0d929f0a1b535f27f5cdd5bfe26879f6218cfb0a Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 00:24:09 -0600 Subject: [PATCH 06/32] package level comment. --- doc.go | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 doc.go diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..f31fb4c --- /dev/null +++ b/doc.go @@ -0,0 +1,8 @@ +// gohook provides a simple http server and types to work with github webhooks. +// +// Simply start a Server and receive from its EventAndTypes channel, where +// correctly unmarshalled packets will be available along with its type. The +// type is provided because of the limitations of Go's type system- +// unfortunately, it is necessary to do a type assertion based on the type +// received. You can see a commented example of this in the examples/ directory. +package gohook From 08d9eda0cbd043012b2fd9fcbee4c266762ec6d7 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 00:42:18 -0600 Subject: [PATCH 07/32] Linting and refactoring. --- doc.go | 2 +- packet.go | 6 ++--- server.go | 70 ++++++++++++++++++++++++++++++------------------------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/doc.go b/doc.go index f31fb4c..82ad051 100644 --- a/doc.go +++ b/doc.go @@ -1,4 +1,4 @@ -// gohook provides a simple http server and types to work with github webhooks. +// Package gohook provides a simple http server receive github webhooks. // // Simply start a Server and receive from its EventAndTypes channel, where // correctly unmarshalled packets will be available along with its type. The diff --git a/packet.go b/packet.go index 9a1248d..8066909 100644 --- a/packet.go +++ b/packet.go @@ -11,7 +11,7 @@ type SenderType struct { AvatarURL string `json:"avatar_url"` GravatarID string `json:"gravatar_id"` URL string `json:"url"` - HtmlURL string `json:"html_url"` + HTMLURL string `json:"html_url"` FollowersURL string `json:"followers_url"` FollowingURL string `json:"following_url"` GistsURL string `json:"gists_url"` @@ -72,7 +72,7 @@ type RepoType struct { FullName string `json:"full_name"` Owner PusherType `json:"owner"` Private bool `json:"private"` - HtmlURL string `json:"html_url"` + HTMLURL string `json:"html_url"` Description string `json:"description"` Fork bool `json:"fork"` URL string `json:"url"` @@ -115,7 +115,7 @@ type RepoType struct { UpdatedAt string `json:"updated_at"` PushedAt int `json:"pushed_at"` GitURL string `json:"git_url"` - SshURL string `json:"ssh_url"` + SSHURL string `json:"ssh_url"` CloneURL string `json:"clone_url"` SvnURL string `json:"svn_url"` Homepage string `json:"homepage"` diff --git a/server.go b/server.go index 326d9bd..5673fe8 100644 --- a/server.go +++ b/server.go @@ -32,6 +32,39 @@ func NewServer(port int, secret string, path string) *Server { } } +func (s *Server) verifyAuth(body []byte, req *http.Request) bool { + signature := req.Header.Get("X-Hub-Signature") + if signature == "" { + return false + } + mac := hmac.New(sha1.New, []byte(s.Secret)) + mac.Write(body) + expectedMAC := mac.Sum(nil) + expectedSig := "sha1=" + hex.EncodeToString(expectedMAC) + if !hmac.Equal([]byte(expectedSig), []byte(signature)) { + return false + } + return true +} + +func (s *Server) processPacket(eventType EventType, respBody []byte) { + var payload interface{} + switch eventType { + case PushEventType: + payload = &PushEvent{} + case PingEventType: + payload = &PingEvent{} + } + if err := json.Unmarshal(respBody, &payload); err != nil { + panic(err) + } + et := &EventAndType{ + Event: payload, + Type: eventType, + } + s.EventAndTypes <- et +} + // ServeHTTP implements http.Handler interface on Server. You should never need // to call this yourself. func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { @@ -54,44 +87,17 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { http.Error(w, "500 Internal Server Error - Event type not yet implemented.", http.StatusInternalServerError) } - body, err := ioutil.ReadAll(req.Body) + respBody, err := ioutil.ReadAll(req.Body) if err != nil { http.Error(w, "500 Internal Error - Could not read from request: "+err.Error(), http.StatusInternalServerError) return } - if s.Secret != "" { - signature := req.Header.Get("X-Hub-Signature") - if signature == "" { - http.Error(w, "403 Forbidden- missing secret.", http.StatusForbidden) - return - } - mac := hmac.New(sha1.New, []byte(s.Secret)) - mac.Write(body) - expectedMAC := mac.Sum(nil) - expectedSig := "sha1=" + hex.EncodeToString(expectedMAC) - if !hmac.Equal([]byte(expectedSig), []byte(signature)) { - http.Error(w, "403 Forbidden - Verification of secret failed.", http.StatusForbidden) - return - } - } - var payload interface{} - switch EventType(eventType) { - case PushEventType: - payload = &PushEvent{} - case PingEventType: - payload = &PingEvent{} - } - if err := json.Unmarshal(body, &payload); err != nil { - http.Error(w, "500 Internal Error - Could not unmarshal request: "+err.Error(), http.StatusInternalServerError) + if s.Secret != "" && !s.verifyAuth(respBody, req) { + http.Error(w, "403 Forbidden - Verification of secret failed.", http.StatusForbidden) + return } - go func() { - et := &EventAndType{ - Event: payload, - Type: EventType(eventType), - } - s.EventAndTypes <- et - }() + go s.processPacket(EventType(eventType), respBody) } // ListenAndServe simply returns the error received from a call of From 370a45f79b88d9038126edc8afb05769cc11ebc4 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 02:29:32 -0600 Subject: [PATCH 08/32] Added commit_comment events. --- example/main.go | 8 ++++++- packet.go | 57 +++++++++++++++++++++++++++++++++++++++---------- server.go | 9 +++++--- 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/example/main.go b/example/main.go index 4c85565..1565cd1 100644 --- a/example/main.go +++ b/example/main.go @@ -8,7 +8,7 @@ import ( func main() { // Create and start the server. - server := gohook.NewServer(8000, "secret", "/postreceive") + server := gohook.NewServer(8888, "secret", "/postreceive") server.GoListenAndServe() // Loop continuously, blocking on a receive from server.EventAndTypes @@ -30,6 +30,12 @@ func main() { panic("Could not assert PushEvent as such.") } fmt.Println(packet.Organization.Login) + case gohook.CommitCommentType: + packet, ok := eAndT.Event.(*gohook.CommitCommentEvent) + if !ok { + panic("Could not assert CommitCommentEvent as such.") + } + fmt.Println(packet.Comment.Body) } } } diff --git a/packet.go b/packet.go index 8066909..964eeab 100644 --- a/packet.go +++ b/packet.go @@ -1,9 +1,5 @@ package gohook -import ( - "encoding/json" -) - // SenderType represents the structure of the sender field in push/ping events. type SenderType struct { Login string `json:"login"` @@ -157,13 +153,51 @@ type PushEvent struct { Sender SenderType `json:"sender"` } +type ConfigType struct { + URL string `json:"url"` + ContentType string `json:"content_type"` +} + +type HookType struct { + ID int `json:"id"` + URL string `json:"url"` + TestURL string `json:"test_url"` + PingURL string `json:"ping_url"` + Name string `json:"name"` + Events []string `json:"events"` + Active bool `json:"active"` + Config ConfigType `json:"config"` + UpdatedAt string `json:"updated_at"` + CreatedAt string `json:"created_at"` +} + // PingEvent represents the basic, top-level structure of a ping event. type PingEvent struct { - Zen string `json:"zen"` - HookID int `json:"hook_id"` - Hook json.RawMessage `json:"hook"` - Organization OrgType `json:"organization"` - Sender SenderType `json:"sender"` + Zen string `json:"zen"` + HookID int `json:"hook_id"` + Hook HookType `json:"hook"` + Organization OrgType `json:"organization"` + Sender SenderType `json:"sender"` +} + +type CommentType struct { + URL string `json:"url"` + HTMLURL string `json:"html_url"` + ID int `json:"id"` + User SenderType `json:"user"` + Position string `json:"position"` + Line string `json:"line"` + Path string `json:"path"` + CommitID string `json:"commit_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"created_at"` + Body string `json:"body"` +} + +type CommitCommentEvent struct { + Comment CommentType `json:"comment"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } // EventType is an alias for string that provides type safety for the event types. @@ -171,8 +205,9 @@ type EventType string // These constants define types for the implemented types of packets. const ( - PingEventType = EventType("ping") - PushEventType = EventType("push") + PingEventType = EventType("ping") + PushEventType = EventType("push") + CommitCommentType = EventType("commit_comment") ) // EventAndType holds an event and its type, to be used later in a type assertion on the event. diff --git a/server.go b/server.go index 5673fe8..21efab4 100644 --- a/server.go +++ b/server.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "log" "net/http" ) @@ -54,6 +55,11 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &PushEvent{} case PingEventType: payload = &PingEvent{} + case CommitCommentType: + payload = &CommitCommentEvent{} + default: + log.Printf("Attempt to process unknown packet type: %s", eventType) + return } if err := json.Unmarshal(respBody, &payload); err != nil { panic(err) @@ -83,9 +89,6 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { http.Error(w, "400 Bad Request - Missing X-Github-Event Header", http.StatusBadRequest) return } - if eventType != "ping" && eventType != "push" { - http.Error(w, "500 Internal Server Error - Event type not yet implemented.", http.StatusInternalServerError) - } respBody, err := ioutil.ReadAll(req.Body) if err != nil { From e898f199e660c66b0b471b2d812f82f5b06454a7 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 03:11:37 -0600 Subject: [PATCH 09/32] Added issue comment handling. --- packet.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- server.go | 4 ++- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/packet.go b/packet.go index 964eeab..5db49ba 100644 --- a/packet.go +++ b/packet.go @@ -1,5 +1,7 @@ package gohook +// import "encoding/json" + // SenderType represents the structure of the sender field in push/ping events. type SenderType struct { Login string `json:"login"` @@ -190,7 +192,7 @@ type CommentType struct { Path string `json:"path"` CommitID string `json:"commit_id"` CreatedAt string `json:"created_at"` - UpdatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` Body string `json:"body"` } @@ -200,14 +202,83 @@ type CommitCommentEvent struct { Sender SenderType `json:"sender"` } +type IssueCommentType struct { + ID int `json:"id"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + Body string `json:"body"` + User SenderType `json:"user"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"created_at"` +} + +type LabelType struct { + URL string `json:"url"` + Name string `json:"name"` + Color string `json:"color"` +} + +type MilestoneType struct { + URL string `json:"url"` + HTMLURL string `json:"html_url"` + LabelsURL string `json:"labels_url"` + ID int `json:"id"` + Number int `json:"number"` + State string `json:"state"` + Title string `json:"title"` + Description string `json:"description"` + Creator SenderType `json:"creator"` + OpenIssues int `json:"open_issues"` + ClosedIssues int `json:"closed_issues"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ClosedAt string `json:"closed_at"` + DueOn string `json:"due_on"` +} + +type PullRequestType struct { + URL string `json:"url"` + HTMLURL string `json:"html_url"` + DiffURL string `json:"diff_url"` + PatchURL string `json:"patch_url"` +} + +type IssueType struct { + ID string `json:"id"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + Number int `json:"number"` + State string `json:"state"` + Title string `json:"title"` + Body string `json:"body"` + User SenderType `json:"user"` + Labels []LabelType `json:"labels"` + Assignee SenderType `json:"assignee"` + Milestone MilestoneType `json:"milestone"` + Comments int `json:"comments"` + PullRequest PullRequestType `json:"pull_request"` + ClosedAt string `json:"closed_at"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` +} + +type IssueCommentEvent struct { + Action string `json:"action"` + Issue IssueType `json:"issue"` + Comment IssueCommentType `json:"comment"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + // EventType is an alias for string that provides type safety for the event types. type EventType string // These constants define types for the implemented types of packets. const ( - PingEventType = EventType("ping") - PushEventType = EventType("push") - CommitCommentType = EventType("commit_comment") + PingEventType = EventType("ping") + PushEventType = EventType("push") + CommitCommentEventType = EventType("commit_comment") + IssueCommentEventType = EventType("issue_comment") ) // EventAndType holds an event and its type, to be used later in a type assertion on the event. diff --git a/server.go b/server.go index 21efab4..8f3d20f 100644 --- a/server.go +++ b/server.go @@ -55,8 +55,10 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &PushEvent{} case PingEventType: payload = &PingEvent{} - case CommitCommentType: + case CommitCommentEventType: payload = &CommitCommentEvent{} + case IssueCommentEventType: + payload = &IssueCommentEvent{} default: log.Printf("Attempt to process unknown packet type: %s", eventType) return From 8a78e4cc745fe0e25e0cefa8bc0b25e27a1f453a Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 03:26:49 -0600 Subject: [PATCH 10/32] Added support for issues events. --- packet.go | 10 ++++++++++ server.go | 2 ++ 2 files changed, 12 insertions(+) diff --git a/packet.go b/packet.go index 5db49ba..0c372bc 100644 --- a/packet.go +++ b/packet.go @@ -270,6 +270,15 @@ type IssueCommentEvent struct { Sender SenderType `json:"sender"` } +type IssuesEvent struct { + Action string `json:"action"` + Issue IssueType `json:"issue"` + Assignee SenderType `json:"assignee"` + Label LabelType `json:"label"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + // EventType is an alias for string that provides type safety for the event types. type EventType string @@ -279,6 +288,7 @@ const ( PushEventType = EventType("push") CommitCommentEventType = EventType("commit_comment") IssueCommentEventType = EventType("issue_comment") + IssuesEventType = EventType("issues") ) // EventAndType holds an event and its type, to be used later in a type assertion on the event. diff --git a/server.go b/server.go index 8f3d20f..d713ad2 100644 --- a/server.go +++ b/server.go @@ -59,6 +59,8 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &CommitCommentEvent{} case IssueCommentEventType: payload = &IssueCommentEvent{} + case IssuesEventType: + payload = &IssuesEvent{} default: log.Printf("Attempt to process unknown packet type: %s", eventType) return From 353eb1c82867060aedc9699d0d7e46dd9e614332 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 03:38:05 -0600 Subject: [PATCH 11/32] Added support for create events. --- example/main.go | 6 ++++++ packet.go | 11 +++++++++++ server.go | 2 ++ 3 files changed, 19 insertions(+) diff --git a/example/main.go b/example/main.go index 1565cd1..7bc4b94 100644 --- a/example/main.go +++ b/example/main.go @@ -36,6 +36,12 @@ func main() { panic("Could not assert CommitCommentEvent as such.") } fmt.Println(packet.Comment.Body) + case gohook.IssueCommentType: + packet, ok := eAndT.Event.(*gohook.IssueCommentEvent) + if !ok { + panic("Could not assert IssueCommentEvent as such.") + } + fmt.Println(packet.Comment.Body) } } } diff --git a/packet.go b/packet.go index 0c372bc..b006a74 100644 --- a/packet.go +++ b/packet.go @@ -279,6 +279,16 @@ type IssuesEvent struct { Sender SenderType `json:"sender"` } +type CreateEvent struct { + RefType string `json:"ref_type"` + Ref string `json:"ref"` + MasterBranch string `json:"master_branch"` + Description string `json:"description"` + PusherType string `json:"pusher_type"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + // EventType is an alias for string that provides type safety for the event types. type EventType string @@ -289,6 +299,7 @@ const ( CommitCommentEventType = EventType("commit_comment") IssueCommentEventType = EventType("issue_comment") IssuesEventType = EventType("issues") + CreateEventType = EventType("create") ) // EventAndType holds an event and its type, to be used later in a type assertion on the event. diff --git a/server.go b/server.go index d713ad2..69dda2b 100644 --- a/server.go +++ b/server.go @@ -61,6 +61,8 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &IssueCommentEvent{} case IssuesEventType: payload = &IssuesEvent{} + case CreateEventType: + payload = &CreateEvent{} default: log.Printf("Attempt to process unknown packet type: %s", eventType) return From ac9560a6ab9aaf7b5aea3eaa22ec4ff41e3d87af Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 03:51:15 -0600 Subject: [PATCH 12/32] Added support for repository events. --- packet.go | 17 +++++++++++++++++ server.go | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/packet.go b/packet.go index b006a74..117c1ab 100644 --- a/packet.go +++ b/packet.go @@ -289,6 +289,21 @@ type CreateEvent struct { Sender SenderType `json:"sender"` } +type DeleteEvent struct { + RefType string `json:"ref_type"` + Ref string `json:"ref"` + PusherType string `json:"pusher_type"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type RepositoryEvent struct { + Action string `json:"action"` + Repository RepoType `json:"repository"` + Organization OrgType `json:"organization"` + Sender SenderType `json:"sender"` +} + // EventType is an alias for string that provides type safety for the event types. type EventType string @@ -300,6 +315,8 @@ const ( IssueCommentEventType = EventType("issue_comment") IssuesEventType = EventType("issues") CreateEventType = EventType("create") + DeleteEventType = EventType("delete") + RepositoryEventType = EventType("repository") ) // EventAndType holds an event and its type, to be used later in a type assertion on the event. diff --git a/server.go b/server.go index 69dda2b..3524945 100644 --- a/server.go +++ b/server.go @@ -63,6 +63,10 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &IssuesEvent{} case CreateEventType: payload = &CreateEvent{} + case DeleteEventType: + payload = &DeleteEvent{} + case RepositoryEventType: + payload = &RepositoryEvent{} default: log.Printf("Attempt to process unknown packet type: %s", eventType) return From 92ecc8910801d5e173f0ddc83fe4b5a8b5da95ee Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 04:08:34 -0600 Subject: [PATCH 13/32] Added support for deployment events. --- packet.go | 31 +++++++++++++++++++++++++++++++ server.go | 2 ++ 2 files changed, 33 insertions(+) diff --git a/packet.go b/packet.go index 117c1ab..3cc310d 100644 --- a/packet.go +++ b/packet.go @@ -304,6 +304,36 @@ type RepositoryEvent struct { Sender SenderType `json:"sender"` } +type DeploymentType struct { + URL string `json:"url"` + ID string `json:"id"` + SHA string `json:"sha"` + Ref string `json:"ref"` + Task string `json:"task"` + Payload map[string]string `json:"payload"` + Environment string `json:"environment"` + Description string `json:"description"` + Creator SenderType `json:"creator"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + StatusesURL string `json:"statuses_url"` + RepositoryURL string `json:"repository_url"` +} + +type DeploymentEvent struct { + Deployment DeploymentType `json:"deployment"` + ID string `json:"id"` + SHA string `json:"sha"` + Ref string `json:"ref"` + Task string `json:"task"` + Name string `json:"name"` + Environment string `json:"environment"` + Payload map[string]string `json:"payload"` + Description string `json:"description"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + // EventType is an alias for string that provides type safety for the event types. type EventType string @@ -317,6 +347,7 @@ const ( CreateEventType = EventType("create") DeleteEventType = EventType("delete") RepositoryEventType = EventType("repository") + DeploymentEventType = EventType("deployment") ) // EventAndType holds an event and its type, to be used later in a type assertion on the event. diff --git a/server.go b/server.go index 3524945..2976f2c 100644 --- a/server.go +++ b/server.go @@ -67,6 +67,8 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &DeleteEvent{} case RepositoryEventType: payload = &RepositoryEvent{} + case DeploymentEventType: + payload = &DeploymentEvent{} default: log.Printf("Attempt to process unknown packet type: %s", eventType) return From 8f83c96d63542c0073037694c616369e7d9546c0 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 10:17:27 -0600 Subject: [PATCH 14/32] Added several more event types. --- packet.go | 219 +++++++++++++++++++++++++++++++++++++++++++++++------- server.go | 18 +++++ 2 files changed, 211 insertions(+), 26 deletions(-) diff --git a/packet.go b/packet.go index 3cc310d..d70dfd0 100644 --- a/packet.go +++ b/packet.go @@ -236,7 +236,7 @@ type MilestoneType struct { DueOn string `json:"due_on"` } -type PullRequestType struct { +type ShortPullRequestType struct { URL string `json:"url"` HTMLURL string `json:"html_url"` DiffURL string `json:"diff_url"` @@ -244,22 +244,22 @@ type PullRequestType struct { } type IssueType struct { - ID string `json:"id"` - URL string `json:"url"` - HTMLURL string `json:"html_url"` - Number int `json:"number"` - State string `json:"state"` - Title string `json:"title"` - Body string `json:"body"` - User SenderType `json:"user"` - Labels []LabelType `json:"labels"` - Assignee SenderType `json:"assignee"` - Milestone MilestoneType `json:"milestone"` - Comments int `json:"comments"` - PullRequest PullRequestType `json:"pull_request"` - ClosedAt string `json:"closed_at"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + ID string `json:"id"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + Number int `json:"number"` + State string `json:"state"` + Title string `json:"title"` + Body string `json:"body"` + User SenderType `json:"user"` + Labels []LabelType `json:"labels"` + Assignee SenderType `json:"assignee"` + Milestone MilestoneType `json:"milestone"` + Comments int `json:"comments"` + PullRequest ShortPullRequestType `json:"pull_request"` + ClosedAt string `json:"closed_at"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` } type IssueCommentEvent struct { @@ -334,20 +334,187 @@ type DeploymentEvent struct { Sender SenderType `json:"sender"` } +type DeploymentStatusType struct { + URL string `json:"url"` + ID string `json:"id"` + State string `json:"state"` + Creator SenderType `json:"creator"` + Description string `json:"description"` + TargetURL string `json:"target_url"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + DeploymentURL string `json:"deployment_url"` + RepositoryURL string `json:"repository_url"` +} + +type DeploymentStatusEvent struct { + Deployment DeploymentType `json:"deployment"` + DeploymentStatus DeploymentStatusType `json:"deployment_status"` + ID string `json:"id"` + State string `json:"state"` + TargetURL string `json:"target_url"` + Description string `json:"description"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type ForkEvent struct { + Forkee RepoType `json:"forkee"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type PageType struct { + PageName string `json:"page_name"` + Title string `json:"title"` + Summary string `json:"summary"` + Action string `json:"action"` + SHA string `json:"sha"` + HTMLURL string `json:"html_url"` +} + +type GollumEvent struct { + Pages []PageType `json:"pages"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type MemberEvent struct { + Action string `json:"action"` + Member SenderType `json:"member"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type TeamType struct { + Name string `json:"name"` + ID string `json:"id"` + Slug string `json:"slug"` + Permission string `json:"permission"` + URL string `json:"url"` + MembersURL string `json:"members_url"` + RepositoriesURL string `json:"repositories_url"` +} + +type MembershipEvent struct { + Action string `json:"action"` + Scope string `json:"scope"` + Member SenderType `json:"member"` + Team TeamType `json:"team"` + Sender SenderType `json:"sender"` + Organization OrgType `json:"organization"` +} + +type BuildType struct { + URL string `json:"url"` + Status string `json:"status"` + Error ErrorType `json:"error"` + Pusher SenderType `json:"pusher"` + Commit string `json:"commit"` + Duration int `json:"duration"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` +} + +type PageBuildEvent struct { + ID string `json:"id"` + Build PageBuildType `json:"build"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type PublicEvent struct { + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type BaseHeadType struct { + Label string `json:"label"` + Ref string `json:"ref"` + SHA string `json:"sha"` + User SenderType `json:"user"` + Repo RepoType `json:"repo"` +} + +type Link struct { + HREF string `json:"href"` +} + +type PullRequestType struct { + ID string `json:"id"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + DiffURL string `json:"diff_url"` + PatchURL string `json:"patch_url"` + IssueURL string `json:"issue_url"` + CommitsURL string `json:"commits_url"` + ReviewCommentsURL string `json:"review_comments_url"` + ReviewCommentURL string `json:"review_comment_url"` + CommentsURL string `json:"comments_url"` + StatusesURL string `json:"statuses_url"` + Number int `json:"number"` + State string `json:"state"` + Title string `json:"title"` + Body string `json:"body"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ClosedAt string `json:"closed_at"` + MergedAt string `json:"merged_at"` + Head BaseHeadType `json:"head"` + Repo RepoType `json:"repo"` + Base BaseHeadType `json:"Base"` + Links map[string]Link `json:"_links"` + User SenderType `json:"User"` + MergeCommitSHA string `json:"merge_commit_sha"` + Merged bool `json:"merged"` + Mergeable bool `json:"mergeable"` + MergedBy SenderType `json:"merged_by"` + Comments int `json:"comments"` + Commits int `json:"commits"` + Additions int `json:"additions"` + Deletions int `json:"deletions"` + ChangedFiles int `json:"changed_files"` +} + +type PullRequestEvent struct { + Action string `json:"action"` + Number int `json:"number"` + PullRequest PullRequestType `json:"pull_request"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type PullRequestReviewCommentEvent struct { + Action string `json:"action"` + Comment PullRequestReviewComment `json:"comment"` + PullRequest string `json:"pull_request"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + // EventType is an alias for string that provides type safety for the event types. type EventType string // These constants define types for the implemented types of packets. const ( - PingEventType = EventType("ping") - PushEventType = EventType("push") - CommitCommentEventType = EventType("commit_comment") - IssueCommentEventType = EventType("issue_comment") - IssuesEventType = EventType("issues") - CreateEventType = EventType("create") - DeleteEventType = EventType("delete") - RepositoryEventType = EventType("repository") - DeploymentEventType = EventType("deployment") + PingEventType = EventType("ping") + PushEventType = EventType("push") + CommitCommentEventType = EventType("commit_comment") + IssueCommentEventType = EventType("issue_comment") + IssuesEventType = EventType("issues") + CreateEventType = EventType("create") + DeleteEventType = EventType("delete") + RepositoryEventType = EventType("repository") + DeploymentEventType = EventType("deployment") + DeploymentStatusEventType = EventType("deployment_status") + ForkEventType = EventType("fork") + GollumEventType = EventType("gollum") + MemberEventType = EventType("member") + MembershipEventType = EventType("membership") + PageBuildEventType = EventType("page_build") + PublicEventType = EventType("public") + PullRequestEventType = EventType("pull_request") + PullRequestReviewCommentEventType = EventType("pull_request_review_comment") ) // EventAndType holds an event and its type, to be used later in a type assertion on the event. diff --git a/server.go b/server.go index 2976f2c..ccaee50 100644 --- a/server.go +++ b/server.go @@ -69,6 +69,24 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &RepositoryEvent{} case DeploymentEventType: payload = &DeploymentEvent{} + case DeploymentStatusEventType: + payload = &DeploymentStatusEvent{} + case ForkEventType: + payload = &ForkEvent{} + case GollumEventType: + payload = &GollumEvent{} + case MemberEventType: + payload = &MemberEvent{} + case MembershipEventType: + payload = &MemebershipEvent{} + case PageBuildEventType: + payload = &PageBuildEvent{} + case PublicEventType: + payload = &PublicEvent{} + case PullRequestEventType: + payload = &PullRequestEvent{} + case PullRequestReviewCommentEventType: + payload = &PullRequestReviewCommentEvent{} default: log.Printf("Attempt to process unknown packet type: %s", eventType) return From 3f00a14308f55261cb4919997f5ce1698882d1da Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 12:31:28 -0600 Subject: [PATCH 15/32] Bugfixing and testing. --- gohook_test.go | 82 +++++++++++ packet.go | 282 +++++++++++++++++++++++++------------ server.go | 10 +- testdata/sample_ping.json | 52 +++++++ testdata/sample_push.json | 203 ++++++++++++++++++++++++++ testdata/sample_watch.json | 120 ++++++++++++++++ 6 files changed, 661 insertions(+), 88 deletions(-) create mode 100644 gohook_test.go create mode 100644 testdata/sample_ping.json create mode 100644 testdata/sample_push.json create mode 100644 testdata/sample_watch.json diff --git a/gohook_test.go b/gohook_test.go new file mode 100644 index 0000000..54a925b --- /dev/null +++ b/gohook_test.go @@ -0,0 +1,82 @@ +package gohook + +import ( + "encoding/json" + "io/ioutil" + "testing" +) + +func TestPingEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_ping.json") + if err != nil { + t.Errorf("Error reading sample ping file: %s", err) + } + server := NewServer(8888, "secret", "path") + server.processPacket(PingEventType, raw) + packet := <-server.EventAndTypes + payload, ok := packet.Event.(*PingEvent) + if !ok { + t.Error("Error asserting payload as *PingEvent") + } + if payload.Zen != "Approachable is better than simple." { + t.Error("Incorrect PingEvent.Zen value.") + } + if payload.Hook.Config.ContentType != "json" { + t.Error("Incorrect PingEvent.Hook.Config.ContentType value.") + } + _, err = json.Marshal(payload) + if err != nil { + t.Errorf("Error marshalling PingEvent: %s", err) + } +} + +func TestPushEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_push.json") + if err != nil { + t.Errorf("Error reading sample push file: %s", err) + } + server := NewServer(8888, "secret", "path") + server.processPacket(PushEventType, raw) + packet := <-server.EventAndTypes + payload, ok := packet.Event.(*PushEvent) + if !ok { + t.Error("Error asserting payload as *PushEvent.") + } + if payload.Ref != "refs/heads/master" { + t.Error("Incorrect PushEvent.Ref value.") + } + if payload.Commits[0].Author.Name != "M. Cameron Palone" { + t.Error("Incorrect payload.Commits[0].Author.Name value.") + } + _, err = json.Marshal(payload) + if err != nil { + t.Errorf("Error marshalling PushEvent: %s", err) + } +} + +func TestWatchEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_watch.json") + if err != nil { + t.Errorf("Error reading sample watch file: %s", err) + } + server := NewServer(8888, "secret", "path") + server.processPacket(WatchEventType, raw) + packet := <-server.EventAndTypes + payload, ok := packet.Event.(*WatchEvent) + if !ok { + t.Error("Error asserting payload as *WatchEvent.") + } + if payload.Action != "started" { + t.Error("Incorrect payload.Action value.") + } + if payload.Sender.ID != 16893 { + t.Error("Incorrect payload.Sender.ID value.") + } + if payload.Organization.ID != 12191882 { + t.Error("Incorrect payload.Organization.ID value.") + } + _, err = json.Marshal(payload) + if err != nil { + t.Errorf("Error marshalling PushEvent: %s", err) + } +} diff --git a/packet.go b/packet.go index d70dfd0..2ad5a0a 100644 --- a/packet.go +++ b/packet.go @@ -1,6 +1,6 @@ package gohook -// import "encoding/json" +import "encoding/json" // SenderType represents the structure of the sender field in push/ping events. type SenderType struct { @@ -65,76 +65,76 @@ type CommitType struct { // RepoType represents the structure of a repository as used in push events. type RepoType struct { - ID int `json:"id"` - Name string `json:"name"` - FullName string `json:"full_name"` - Owner PusherType `json:"owner"` - Private bool `json:"private"` - HTMLURL string `json:"html_url"` - Description string `json:"description"` - Fork bool `json:"fork"` - URL string `json:"url"` - ForksURL string `json:"forks_url"` - KeysURL string `json:"keys_url"` - CollaboratorsURL string `json:"collaborators_url"` - TeamsURL string `json:"teams_url"` - HooksURL string `json:"hooks_url"` - IssueEventsURL string `json:"issue_events_url"` - EventsURL string `json:"events_url"` - AssigneesURL string `json:"assignees_url"` - BranchesURL string `json:"branches_url"` - TagsURL string `json:"tags_url"` - BlobsURL string `json:"blobs_url"` - GitTagsURL string `json:"git_tags_url"` - GitRefsURL string `json:"git_refs_url"` - TreesURL string `json:"trees_url"` - StatusesURL string `json:"statuses_url"` - LanguagesURL string `json:"languages_url"` - StargazersURL string `json:"stargazers_url"` - ContributorsURL string `json:"contributors_url"` - SubscribersURL string `json:"subscribers_url"` - SubscriptionURL string `json:"subscription_url"` - CommitsURL string `json:"commits_url"` - GitCommitsURL string `json:"git_commits_url"` - CommentsURL string `json:"comments_url"` - IssueCommentURL string `json:"issue_comment_url"` - ContentsURL string `json:"contents_url"` - CompareURL string `json:"compare_url"` - MergesURL string `json:"mergers_url"` - ArchiveURL string `json:"archive_url"` - DownloadsURL string `json:"downloads_url"` - IssuesURL string `json:"issues_url"` - PullsURL string `json:"pulls_url"` - MilestonesURL string `json:"milestones_url"` - NotificationsURL string `json:"notifications_url"` - LabelsURL string `json:"labels_url"` - ReleasesURL string `json:"releases_url"` - CreatedAt int `json:"created_at"` - UpdatedAt string `json:"updated_at"` - PushedAt int `json:"pushed_at"` - GitURL string `json:"git_url"` - SSHURL string `json:"ssh_url"` - CloneURL string `json:"clone_url"` - SvnURL string `json:"svn_url"` - Homepage string `json:"homepage"` - Size int `json:"size"` - StargazersCount int `json:"stargazers_count"` - WatchersCount int `json:"watchers_count"` - Language string `json:"language"` - HasIssues bool `json:"has_issues"` - HasDownloads bool `json:"has_downloads"` - HasWiki bool `json:"has_wiki"` - HasPages bool `json:"has_pages"` - ForksCount int `json:"forks_count"` - MirrorURL string `json:"mirror_url"` - OpenIssuesCount int `json:"open_issues_count"` - Forks int `json:"forks"` - OpenIssues int `json:"open_issues"` - Watchers int `json:"watchers"` - DefaultBranch string `json:"default_branch"` - Stargazers int `json:"stargazers"` - MasterBranch string `json:"master_branch"` - Organization string `json:"organization"` + ID int `json:"id"` + Name string `json:"name"` + FullName string `json:"full_name"` + Owner SenderType `json:"owner"` + Private bool `json:"private"` + HTMLURL string `json:"html_url"` + Description string `json:"description"` + Fork bool `json:"fork"` + URL string `json:"url"` + ForksURL string `json:"forks_url"` + KeysURL string `json:"keys_url"` + CollaboratorsURL string `json:"collaborators_url"` + TeamsURL string `json:"teams_url"` + HooksURL string `json:"hooks_url"` + IssueEventsURL string `json:"issue_events_url"` + EventsURL string `json:"events_url"` + AssigneesURL string `json:"assignees_url"` + BranchesURL string `json:"branches_url"` + TagsURL string `json:"tags_url"` + BlobsURL string `json:"blobs_url"` + GitTagsURL string `json:"git_tags_url"` + GitRefsURL string `json:"git_refs_url"` + TreesURL string `json:"trees_url"` + StatusesURL string `json:"statuses_url"` + LanguagesURL string `json:"languages_url"` + StargazersURL string `json:"stargazers_url"` + ContributorsURL string `json:"contributors_url"` + SubscribersURL string `json:"subscribers_url"` + SubscriptionURL string `json:"subscription_url"` + CommitsURL string `json:"commits_url"` + GitCommitsURL string `json:"git_commits_url"` + CommentsURL string `json:"comments_url"` + IssueCommentURL string `json:"issue_comment_url"` + ContentsURL string `json:"contents_url"` + CompareURL string `json:"compare_url"` + MergesURL string `json:"mergers_url"` + ArchiveURL string `json:"archive_url"` + DownloadsURL string `json:"downloads_url"` + IssuesURL string `json:"issues_url"` + PullsURL string `json:"pulls_url"` + MilestonesURL string `json:"milestones_url"` + NotificationsURL string `json:"notifications_url"` + LabelsURL string `json:"labels_url"` + ReleasesURL string `json:"releases_url"` + CreatedAt json.RawMessage `json:"created_at"` + UpdatedAt json.RawMessage `json:"updated_at"` + PushedAt json.RawMessage `json:"pushed_at"` + GitURL string `json:"git_url"` + SSHURL string `json:"ssh_url"` + CloneURL string `json:"clone_url"` + SvnURL string `json:"svn_url"` + Homepage string `json:"homepage"` + Size int `json:"size"` + StargazersCount int `json:"stargazers_count"` + WatchersCount int `json:"watchers_count"` + Language string `json:"language"` + HasIssues bool `json:"has_issues"` + HasDownloads bool `json:"has_downloads"` + HasWiki bool `json:"has_wiki"` + HasPages bool `json:"has_pages"` + ForksCount int `json:"forks_count"` + MirrorURL string `json:"mirror_url"` + OpenIssuesCount int `json:"open_issues_count"` + Forks int `json:"forks"` + OpenIssues int `json:"open_issues"` + Watchers int `json:"watchers"` + DefaultBranch string `json:"default_branch"` + Stargazers int `json:"stargazers"` + MasterBranch string `json:"master_branch"` + Organization string `json:"organization"` } // PushEvent represents the basic, top-level structure of a push event. @@ -244,7 +244,7 @@ type ShortPullRequestType struct { } type IssueType struct { - ID string `json:"id"` + ID int `json:"id"` URL string `json:"url"` HTMLURL string `json:"html_url"` Number int `json:"number"` @@ -306,7 +306,7 @@ type RepositoryEvent struct { type DeploymentType struct { URL string `json:"url"` - ID string `json:"id"` + ID int `json:"id"` SHA string `json:"sha"` Ref string `json:"ref"` Task string `json:"task"` @@ -322,7 +322,7 @@ type DeploymentType struct { type DeploymentEvent struct { Deployment DeploymentType `json:"deployment"` - ID string `json:"id"` + ID int `json:"id"` SHA string `json:"sha"` Ref string `json:"ref"` Task string `json:"task"` @@ -336,7 +336,7 @@ type DeploymentEvent struct { type DeploymentStatusType struct { URL string `json:"url"` - ID string `json:"id"` + ID int `json:"id"` State string `json:"state"` Creator SenderType `json:"creator"` Description string `json:"description"` @@ -350,7 +350,7 @@ type DeploymentStatusType struct { type DeploymentStatusEvent struct { Deployment DeploymentType `json:"deployment"` DeploymentStatus DeploymentStatusType `json:"deployment_status"` - ID string `json:"id"` + ID int `json:"id"` State string `json:"state"` TargetURL string `json:"target_url"` Description string `json:"description"` @@ -388,7 +388,7 @@ type MemberEvent struct { type TeamType struct { Name string `json:"name"` - ID string `json:"id"` + ID int `json:"id"` Slug string `json:"slug"` Permission string `json:"permission"` URL string `json:"url"` @@ -405,6 +405,10 @@ type MembershipEvent struct { Organization OrgType `json:"organization"` } +type ErrorType struct { + Message string `json:"message"` +} + type BuildType struct { URL string `json:"url"` Status string `json:"status"` @@ -417,10 +421,10 @@ type BuildType struct { } type PageBuildEvent struct { - ID string `json:"id"` - Build PageBuildType `json:"build"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + ID int `json:"id"` + Build BuildType `json:"build"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type PublicEvent struct { @@ -441,7 +445,7 @@ type Link struct { } type PullRequestType struct { - ID string `json:"id"` + ID int `json:"id"` URL string `json:"url"` HTMLURL string `json:"html_url"` DiffURL string `json:"diff_url"` @@ -484,12 +488,112 @@ type PullRequestEvent struct { Sender SenderType `json:"sender"` } +type PullRequestReviewCommentType struct { + URL string `json:"url"` + ID int `json:"id"` + DiffHunk string `json:"diff_hunk"` + Path string `json:"path"` + Position int `json:"position"` + OriginalPosition int `json:"original_position"` + CommitID string `json:"commit_id"` + OriginalCommitID string `json:"original_commit_id"` + User SenderType `json:"user"` + Body string `json:"body"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + HTMLURL string `json:"html_url"` + PullRequestURL string `json:"pull_request_url"` + Links map[string]Link `json:"_links"` +} + type PullRequestReviewCommentEvent struct { - Action string `json:"action"` - Comment PullRequestReviewComment `json:"comment"` - PullRequest string `json:"pull_request"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + Action string `json:"action"` + Comment PullRequestReviewCommentType `json:"comment"` + PullRequest PullRequestType `json:"pull_request"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type AssetType struct { + URL string `json:"url"` + BrowserDownloadURL string `json:"browser_download_url"` + ID int `json:"id"` + Name string `json:"name"` + Label string `json:"label"` + State string `json:"state"` + ContentType string `json:"content_type"` + Size int `json:"size"` + DownloadCount int `json:"download_count"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + Uploader SenderType `json:"uploader"` +} + +type ReleaseType struct { + URL string `json:"url"` + HTMLURL string `json:"html_url"` + AssetsURL string `json:"assets_url"` + UploadURL string `json:"upload_url"` + TarballURL string `json:"tarball_url"` + ZipballURL string `json:"zipball_url"` + ID int `json:"id"` + TagName string `json:"tag_name"` + TargetCommitish string `json:"target_commitish"` + Name string `json:"name"` + Body string `json:"body"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` + CreatedAt string `json:"created_at"` + PublishedAt string `json:"published_at"` + Author SenderType `json:"author"` + Assets []AssetType `json:"assets"` +} + +type ReleaseEvent struct { + Action string `json:"action"` + Release ReleaseType `json:"release"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type ShortCommitType struct { + SHA string `json:"sha"` + URL string `json:"url"` +} + +type BranchType struct { + Name string `json:"master"` + Commit ShortCommitType `json:"commit"` +} + +type StatusEvent struct { + ID int `json:"id"` + SHA string `json:"sha"` + Name string `json:"name"` + TargetURL string `json:"target_url"` + Context string `json:"context"` + Description string `json:"description"` + State string `json:"state"` + Commit CommitType `json:"commit"` + Branches []BranchType `json:"branches"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` +} + +type TeamAddEvent struct { + Team TeamType `json:"team"` + Repository RepoType `json:"repository"` + Organization OrgType `json:"organization"` + Sender SenderType `json:"sender"` +} + +type WatchEvent struct { + Action string `json:"action"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` + Organization OrgType `json:"organization"` } // EventType is an alias for string that provides type safety for the event types. @@ -515,6 +619,10 @@ const ( PublicEventType = EventType("public") PullRequestEventType = EventType("pull_request") PullRequestReviewCommentEventType = EventType("pull_request_review_comment") + ReleaseEventType = EventType("release") + StatusEventType = EventType("status") + TeamAddEventType = EventType("team_add") + WatchEventType = EventType("watch") ) // EventAndType holds an event and its type, to be used later in a type assertion on the event. diff --git a/server.go b/server.go index ccaee50..a5d4cab 100644 --- a/server.go +++ b/server.go @@ -78,7 +78,7 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { case MemberEventType: payload = &MemberEvent{} case MembershipEventType: - payload = &MemebershipEvent{} + payload = &MembershipEvent{} case PageBuildEventType: payload = &PageBuildEvent{} case PublicEventType: @@ -87,6 +87,14 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &PullRequestEvent{} case PullRequestReviewCommentEventType: payload = &PullRequestReviewCommentEvent{} + case ReleaseEventType: + payload = &ReleaseEvent{} + case StatusEventType: + payload = &StatusEvent{} + case TeamAddEventType: + payload = &TeamAddEvent{} + case WatchEventType: + payload = &WatchEvent{} default: log.Printf("Attempt to process unknown packet type: %s", eventType) return diff --git a/testdata/sample_ping.json b/testdata/sample_ping.json new file mode 100644 index 0000000..1a663a7 --- /dev/null +++ b/testdata/sample_ping.json @@ -0,0 +1,52 @@ +{ + "zen": "Approachable is better than simple.", + "hook_id": 4719659, + "hook": { + "url": "https://api.github.com/orgs/fireside-chat/hooks/4719659", + "ping_url": "https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", + "id": 4719659, + "name": "web", + "active": true, + "events": [ + "push" + ], + "config": { + "url": "http://50.134.233.34:8888", + "content_type": "json", + "insecure_ssl": "0", + "secret": "********" + }, + "updated_at": "2015-05-01T03:15:51Z", + "created_at": "2015-05-01T03:15:51Z" + }, + "organization": { + "login": "fireside-chat", + "id": 12191882, + "url": "https://api.github.com/orgs/fireside-chat", + "repos_url": "https://api.github.com/orgs/fireside-chat/repos", + "events_url": "https://api.github.com/orgs/fireside-chat/events", + "members_url": "https://api.github.com/orgs/fireside-chat/members{/member}", + "public_members_url": "https://api.github.com/orgs/fireside-chat/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "description": null + }, + "sender": { + "login": "cpalone", + "id": 9749483, + "avatar_url": "https://avatars.githubusercontent.com/u/9749483?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/cpalone", + "html_url": "https://github.com/cpalone", + "followers_url": "https://api.github.com/users/cpalone/followers", + "following_url": "https://api.github.com/users/cpalone/following{/other_user}", + "gists_url": "https://api.github.com/users/cpalone/gists{/gist_id}", + "starred_url": "https://api.github.com/users/cpalone/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/cpalone/subscriptions", + "organizations_url": "https://api.github.com/users/cpalone/orgs", + "repos_url": "https://api.github.com/users/cpalone/repos", + "events_url": "https://api.github.com/users/cpalone/events{/privacy}", + "received_events_url": "https://api.github.com/users/cpalone/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/testdata/sample_push.json b/testdata/sample_push.json new file mode 100644 index 0000000..43c3f5a --- /dev/null +++ b/testdata/sample_push.json @@ -0,0 +1,203 @@ +{ + "ref": "refs/heads/master", + "before": "0809cc5f1e1e1eacc5aceb5858a0c6c0797cf3bd", + "after": "dfba7c3d079f9544b28138ca7d9731abe628e344", + "created": false, + "deleted": false, + "forced": false, + "base_ref": null, + "compare": "https://github.com/fireside-chat/githubbot/compare/0809cc5f1e1e...dfba7c3d079f", + "commits": [ + { + "id": "8e6e1b51260c25f14dfdef768b153c4820317964", + "distinct": true, + "message": "Initial code commit.", + "timestamp": "2015-04-30T21:17:21-06:00", + "url": "https://github.com/fireside-chat/githubbot/commit/8e6e1b51260c25f14dfdef768b153c4820317964", + "author": { + "name": "M. Cameron Palone", + "email": "mcameronpalone@gmail.com", + "username": "cpalone" + }, + "committer": { + "name": "M. Cameron Palone", + "email": "mcameronpalone@gmail.com", + "username": "cpalone" + }, + "added": [ + "github.go", + "main/main.go", + "packet.go", + "session.go" + ], + "removed": [ + + ], + "modified": [ + + ] + }, + { + "id": "dfba7c3d079f9544b28138ca7d9731abe628e344", + "distinct": true, + "message": "Merge branch 'master' of https://github.com/fireside-chat/fireside-gitbot", + "timestamp": "2015-04-30T21:17:37-06:00", + "url": "https://github.com/fireside-chat/githubbot/commit/dfba7c3d079f9544b28138ca7d9731abe628e344", + "author": { + "name": "M. Cameron Palone", + "email": "mcameronpalone@gmail.com", + "username": "cpalone" + }, + "committer": { + "name": "M. Cameron Palone", + "email": "mcameronpalone@gmail.com", + "username": "cpalone" + }, + "added": [ + + ], + "removed": [ + + ], + "modified": [ + ".gitignore" + ] + } + ], + "head_commit": { + "id": "dfba7c3d079f9544b28138ca7d9731abe628e344", + "distinct": true, + "message": "Merge branch 'master' of https://github.com/fireside-chat/fireside-gitbot", + "timestamp": "2015-04-30T21:17:37-06:00", + "url": "https://github.com/fireside-chat/githubbot/commit/dfba7c3d079f9544b28138ca7d9731abe628e344", + "author": { + "name": "M. Cameron Palone", + "email": "mcameronpalone@gmail.com", + "username": "cpalone" + }, + "committer": { + "name": "M. Cameron Palone", + "email": "mcameronpalone@gmail.com", + "username": "cpalone" + }, + "added": [ + + ], + "removed": [ + + ], + "modified": [ + ".gitignore" + ] + }, + "repository": { + "id": 34878093, + "name": "githubbot", + "full_name": "fireside-chat/githubbot", + "owner": { + "name": "fireside-chat", + "email": null + }, + "private": false, + "html_url": "https://github.com/fireside-chat/githubbot", + "description": "Listens for github webhook events and posts them as messages to a Euphoria room. ", + "fork": false, + "url": "https://github.com/fireside-chat/githubbot", + "forks_url": "https://api.github.com/repos/fireside-chat/githubbot/forks", + "keys_url": "https://api.github.com/repos/fireside-chat/githubbot/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/fireside-chat/githubbot/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/fireside-chat/githubbot/teams", + "hooks_url": "https://api.github.com/repos/fireside-chat/githubbot/hooks", + "issue_events_url": "https://api.github.com/repos/fireside-chat/githubbot/issues/events{/number}", + "events_url": "https://api.github.com/repos/fireside-chat/githubbot/events", + "assignees_url": "https://api.github.com/repos/fireside-chat/githubbot/assignees{/user}", + "branches_url": "https://api.github.com/repos/fireside-chat/githubbot/branches{/branch}", + "tags_url": "https://api.github.com/repos/fireside-chat/githubbot/tags", + "blobs_url": "https://api.github.com/repos/fireside-chat/githubbot/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/fireside-chat/githubbot/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/fireside-chat/githubbot/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/fireside-chat/githubbot/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/fireside-chat/githubbot/statuses/{sha}", + "languages_url": "https://api.github.com/repos/fireside-chat/githubbot/languages", + "stargazers_url": "https://api.github.com/repos/fireside-chat/githubbot/stargazers", + "contributors_url": "https://api.github.com/repos/fireside-chat/githubbot/contributors", + "subscribers_url": "https://api.github.com/repos/fireside-chat/githubbot/subscribers", + "subscription_url": "https://api.github.com/repos/fireside-chat/githubbot/subscription", + "commits_url": "https://api.github.com/repos/fireside-chat/githubbot/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/fireside-chat/githubbot/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/fireside-chat/githubbot/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/fireside-chat/githubbot/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/fireside-chat/githubbot/contents/{+path}", + "compare_url": "https://api.github.com/repos/fireside-chat/githubbot/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/fireside-chat/githubbot/merges", + "archive_url": "https://api.github.com/repos/fireside-chat/githubbot/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/fireside-chat/githubbot/downloads", + "issues_url": "https://api.github.com/repos/fireside-chat/githubbot/issues{/number}", + "pulls_url": "https://api.github.com/repos/fireside-chat/githubbot/pulls{/number}", + "milestones_url": "https://api.github.com/repos/fireside-chat/githubbot/milestones{/number}", + "notifications_url": "https://api.github.com/repos/fireside-chat/githubbot/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/fireside-chat/githubbot/labels{/name}", + "releases_url": "https://api.github.com/repos/fireside-chat/githubbot/releases{/id}", + "created_at": 1430429909, + "updated_at": "2015-05-01T03:17:42Z", + "pushed_at": 1430450262, + "git_url": "git://github.com/fireside-chat/githubbot.git", + "ssh_url": "git@github.com:fireside-chat/githubbot.git", + "clone_url": "https://github.com/fireside-chat/githubbot.git", + "svn_url": "https://github.com/fireside-chat/githubbot", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Go", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master", + "stargazers": 0, + "master_branch": "master", + "organization": "fireside-chat" + }, + "pusher": { + "name": "cpalone", + "email": "mcameronpalone@gmail.com" + }, + "organization": { + "login": "fireside-chat", + "id": 12191882, + "url": "https://api.github.com/orgs/fireside-chat", + "repos_url": "https://api.github.com/orgs/fireside-chat/repos", + "events_url": "https://api.github.com/orgs/fireside-chat/events", + "members_url": "https://api.github.com/orgs/fireside-chat/members{/member}", + "public_members_url": "https://api.github.com/orgs/fireside-chat/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "description": null + }, + "sender": { + "login": "cpalone", + "id": 9749483, + "avatar_url": "https://avatars.githubusercontent.com/u/9749483?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/cpalone", + "html_url": "https://github.com/cpalone", + "followers_url": "https://api.github.com/users/cpalone/followers", + "following_url": "https://api.github.com/users/cpalone/following{/other_user}", + "gists_url": "https://api.github.com/users/cpalone/gists{/gist_id}", + "starred_url": "https://api.github.com/users/cpalone/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/cpalone/subscriptions", + "organizations_url": "https://api.github.com/users/cpalone/orgs", + "repos_url": "https://api.github.com/users/cpalone/repos", + "events_url": "https://api.github.com/users/cpalone/events{/privacy}", + "received_events_url": "https://api.github.com/users/cpalone/received_events", + "type": "User", + "site_admin": false + } +} + diff --git a/testdata/sample_watch.json b/testdata/sample_watch.json new file mode 100644 index 0000000..b837cd4 --- /dev/null +++ b/testdata/sample_watch.json @@ -0,0 +1,120 @@ +{ + "action": "started", + "repository": { + "id": 34878093, + "name": "githubbot", + "full_name": "fireside-chat/githubbot", + "owner": { + "login": "fireside-chat", + "id": 12191882, + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/fireside-chat", + "html_url": "https://github.com/fireside-chat", + "followers_url": "https://api.github.com/users/fireside-chat/followers", + "following_url": "https://api.github.com/users/fireside-chat/following{/other_user}", + "gists_url": "https://api.github.com/users/fireside-chat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/fireside-chat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/fireside-chat/subscriptions", + "organizations_url": "https://api.github.com/users/fireside-chat/orgs", + "repos_url": "https://api.github.com/users/fireside-chat/repos", + "events_url": "https://api.github.com/users/fireside-chat/events{/privacy}", + "received_events_url": "https://api.github.com/users/fireside-chat/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/fireside-chat/githubbot", + "description": "Listens for github webhook events and posts them as messages to a Euphoria room. ", + "fork": false, + "url": "https://api.github.com/repos/fireside-chat/githubbot", + "forks_url": "https://api.github.com/repos/fireside-chat/githubbot/forks", + "keys_url": "https://api.github.com/repos/fireside-chat/githubbot/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/fireside-chat/githubbot/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/fireside-chat/githubbot/teams", + "hooks_url": "https://api.github.com/repos/fireside-chat/githubbot/hooks", + "issue_events_url": "https://api.github.com/repos/fireside-chat/githubbot/issues/events{/number}", + "events_url": "https://api.github.com/repos/fireside-chat/githubbot/events", + "assignees_url": "https://api.github.com/repos/fireside-chat/githubbot/assignees{/user}", + "branches_url": "https://api.github.com/repos/fireside-chat/githubbot/branches{/branch}", + "tags_url": "https://api.github.com/repos/fireside-chat/githubbot/tags", + "blobs_url": "https://api.github.com/repos/fireside-chat/githubbot/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/fireside-chat/githubbot/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/fireside-chat/githubbot/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/fireside-chat/githubbot/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/fireside-chat/githubbot/statuses/{sha}", + "languages_url": "https://api.github.com/repos/fireside-chat/githubbot/languages", + "stargazers_url": "https://api.github.com/repos/fireside-chat/githubbot/stargazers", + "contributors_url": "https://api.github.com/repos/fireside-chat/githubbot/contributors", + "subscribers_url": "https://api.github.com/repos/fireside-chat/githubbot/subscribers", + "subscription_url": "https://api.github.com/repos/fireside-chat/githubbot/subscription", + "commits_url": "https://api.github.com/repos/fireside-chat/githubbot/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/fireside-chat/githubbot/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/fireside-chat/githubbot/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/fireside-chat/githubbot/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/fireside-chat/githubbot/contents/{+path}", + "compare_url": "https://api.github.com/repos/fireside-chat/githubbot/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/fireside-chat/githubbot/merges", + "archive_url": "https://api.github.com/repos/fireside-chat/githubbot/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/fireside-chat/githubbot/downloads", + "issues_url": "https://api.github.com/repos/fireside-chat/githubbot/issues{/number}", + "pulls_url": "https://api.github.com/repos/fireside-chat/githubbot/pulls{/number}", + "milestones_url": "https://api.github.com/repos/fireside-chat/githubbot/milestones{/number}", + "notifications_url": "https://api.github.com/repos/fireside-chat/githubbot/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/fireside-chat/githubbot/labels{/name}", + "releases_url": "https://api.github.com/repos/fireside-chat/githubbot/releases{/id}", + "created_at": "2015-04-30T21:38:29Z", + "updated_at": "2015-05-01T17:16:05Z", + "pushed_at": "2015-05-01T09:27:40Z", + "git_url": "git://github.com/fireside-chat/githubbot.git", + "ssh_url": "git@github.com:fireside-chat/githubbot.git", + "clone_url": "https://github.com/fireside-chat/githubbot.git", + "svn_url": "https://github.com/fireside-chat/githubbot", + "homepage": null, + "size": 0, + "stargazers_count": 1, + "watchers_count": 1, + "language": "Go", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 1, + "default_branch": "master" + }, + "organization": { + "login": "fireside-chat", + "id": 12191882, + "url": "https://api.github.com/orgs/fireside-chat", + "repos_url": "https://api.github.com/orgs/fireside-chat/repos", + "events_url": "https://api.github.com/orgs/fireside-chat/events", + "members_url": "https://api.github.com/orgs/fireside-chat/members{/member}", + "public_members_url": "https://api.github.com/orgs/fireside-chat/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "description": "" + }, + "sender": { + "login": "chromakode", + "id": 16893, + "avatar_url": "https://avatars.githubusercontent.com/u/16893?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/chromakode", + "html_url": "https://github.com/chromakode", + "followers_url": "https://api.github.com/users/chromakode/followers", + "following_url": "https://api.github.com/users/chromakode/following{/other_user}", + "gists_url": "https://api.github.com/users/chromakode/gists{/gist_id}", + "starred_url": "https://api.github.com/users/chromakode/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/chromakode/subscriptions", + "organizations_url": "https://api.github.com/users/chromakode/orgs", + "repos_url": "https://api.github.com/users/chromakode/repos", + "events_url": "https://api.github.com/users/chromakode/events{/privacy}", + "received_events_url": "https://api.github.com/users/chromakode/received_events", + "type": "User", + "site_admin": false + } +} From 74a7a76e9fa721e6fb4d2c4e63a70c4277fe93e2 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 12:39:49 -0600 Subject: [PATCH 16/32] Added test for CommitCommentEvent. --- gohook_test.go | 26 +++++- testdata/sample_commit_comment.json | 139 ++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 testdata/sample_commit_comment.json diff --git a/gohook_test.go b/gohook_test.go index 54a925b..61aafdc 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -77,6 +77,30 @@ func TestWatchEvent(t *testing.T) { } _, err = json.Marshal(payload) if err != nil { - t.Errorf("Error marshalling PushEvent: %s", err) + t.Errorf("Error marshalling WatchEvent: %s", err) + } +} + +func TestCommitCommentEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_commit_comment.json") + if err != nil { + t.Errorf("Error reading sample commit_comment file: %s", err) + } + server := NewServer(8888, "secret", "path") + server.processPacket(CommitCommentEventType, raw) + packet := <-server.EventAndTypes + payload, ok := packet.Event.(*CommitCommentEvent) + if !ok { + t.Error("Error asserting payload as *CommitCommentEvent.") + } + if payload.Comment.Body != "This is a really good change! :+1:" { + t.Error("Incorrect payload.Comment.Body value.") + } + if payload.Comment.User.Login != "baxterthehacker" { + t.Error("Incorrect payload.Comment.User.Login value.") + } + _, err = json.Marshal(payload) + if err != nil { + t.Errorf("Error marshalling CommitCommentEvent: %s", err) } } diff --git a/testdata/sample_commit_comment.json b/testdata/sample_commit_comment.json new file mode 100644 index 0000000..26422f9 --- /dev/null +++ b/testdata/sample_commit_comment.json @@ -0,0 +1,139 @@ +{ + "comment": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/comments/8108441", + "html_url": "https://github.com/baxterthehacker/public-repo/commit/7b80eb100206a56523dbda6202d8e5daa05e265b#commitcomment-8108441", + "id": 8108441, + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "position": null, + "line": null, + "path": null, + "commit_id": "7b80eb100206a56523dbda6202d8e5daa05e265b", + "created_at": "2014-10-10T00:09:52Z", + "updated_at": "2014-10-10T00:09:52Z", + "body": "This is a really good change! :+1:" + }, + "repository": { + "id": 20000106, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments/{number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2014-05-20T22:39:43Z", + "updated_at": "2014-07-25T16:37:51Z", + "pushed_at": "2014-10-10T00:09:49Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 665, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 26, + "forks": 0, + "open_issues": 26, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} From d7083231b3bde131e9bc71545c0a5d20f4206344 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 13:14:59 -0600 Subject: [PATCH 17/32] More testing. --- gohook_test.go | 97 +++++++++++++++++++++++- testdata/sample_create.json | 124 ++++++++++++++++++++++++++++++ testdata/sample_repository.json | 120 +++++++++++++++++++++++++++++ testdata/sample_team_add.json | 129 ++++++++++++++++++++++++++++++++ 4 files changed, 469 insertions(+), 1 deletion(-) create mode 100644 testdata/sample_create.json create mode 100644 testdata/sample_repository.json create mode 100644 testdata/sample_team_add.json diff --git a/gohook_test.go b/gohook_test.go index 61aafdc..3ee4610 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -1,11 +1,33 @@ package gohook import ( + "bytes" "encoding/json" "io/ioutil" + "net/http" "testing" ) +func TestPingGithub(t *testing.T) { + server := NewServer(8888, "secret", "/postreceive") + server.GoListenAndServe() + _, err := http.Post("https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", "application/json", nil) + if err != nil { + t.Errorf("Error requesting ping: %s", err) + } + packet := <-server.EventAndTypes + if packet.Type != PingEventType { + t.Errorf("Incorrect packet type, got %s", packet.Type) + } + payload, ok := packet.Event.(*PingEvent) + if !ok { + t.Error("Error asserting payload as *PingEvent.") + } + if !payload.Hook.Active { + t.Error("Incorrect payload.Hook.Active value.") + } +} + func TestPingEvent(t *testing.T) { raw, err := ioutil.ReadFile("testdata/sample_ping.json") if err != nil { @@ -16,7 +38,7 @@ func TestPingEvent(t *testing.T) { packet := <-server.EventAndTypes payload, ok := packet.Event.(*PingEvent) if !ok { - t.Error("Error asserting payload as *PingEvent") + t.Error("Error asserting payload as *PingEvent.") } if payload.Zen != "Approachable is better than simple." { t.Error("Incorrect PingEvent.Zen value.") @@ -104,3 +126,76 @@ func TestCommitCommentEvent(t *testing.T) { t.Errorf("Error marshalling CommitCommentEvent: %s", err) } } + +func TestTeamAddEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_team_add.json") + if err != nil { + t.Errorf("Error reading sample team_add file: %s", err) + } + server := NewServer(8888, "secret", "path") + server.processPacket(TeamAddEventType, raw) + packet := <-server.EventAndTypes + payload, ok := packet.Event.(*TeamAddEvent) + if !ok { + t.Error("Error asserting payload as *TeamAddEvent.") + } + if payload.Team.ID != 1474248 { + t.Error("Incorrect payload.Team.ID value.") + } + if payload.Team.Slug != "owners" { + t.Error("Incorrect payload.Team.Slug value.") + } + _, err = json.Marshal(payload) + if err != nil { + t.Errorf("Error marshalling TeamAddEvent: %s", err) + } +} + +func TestCreateEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_create.json") + if err != nil { + t.Errorf("Error reading sample create file: %s", err) + } + server := NewServer(8888, "secret", "path") + server.processPacket(CreateEventType, raw) + packet := <-server.EventAndTypes + payload, ok := packet.Event.(*CreateEvent) + if !ok { + t.Error("Error asserting payload as *CreateEvent.") + } + if payload.Description != + "Stripped down version of euphoria.io's heim written in Go." { + t.Error("Incorrect payload.Description value.") + } + if !bytes.Equal(payload.Repository.CreatedAt, []byte("\"2015-05-01T18:43:26Z\"")) { + t.Errorf("Incorrect payload.Repository.CreatedAt value. Got %s, expected %s", payload.Repository.CreatedAt, []byte("2015-05-01T18:43:26Z")) + } + _, err = json.Marshal(payload) + if err != nil { + t.Errorf("Error marshalling CreatedEvent: %s", err) + } +} + +func TestRepositoryEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_repository.json") + if err != nil { + t.Errorf("Error reading sample create file: %s", err) + } + server := NewServer(8888, "secret", "path") + server.processPacket(RepositoryEventType, raw) + packet := <-server.EventAndTypes + payload, ok := packet.Event.(*RepositoryEvent) + if !ok { + t.Error("Error asserting payload as *CreateEvent.") + } + if payload.Action != "created" { + t.Error("Incorrect payload.Action value.") + } + if payload.Organization.Login != "fireside-chat" { + t.Error("Incorrect payload.Organization.Login value.") + } + _, err = json.Marshal(payload) + if err != nil { + t.Errorf("Error marshalling TeamAddEvent: %s", err) + } +} diff --git a/testdata/sample_create.json b/testdata/sample_create.json new file mode 100644 index 0000000..f4ddc2c --- /dev/null +++ b/testdata/sample_create.json @@ -0,0 +1,124 @@ +{ + "ref": "master", + "ref_type": "branch", + "master_branch": "master", + "description": "Stripped down version of euphoria.io's heim written in Go.", + "pusher_type": "user", + "repository": { + "id": 34917952, + "name": "firesideGo", + "full_name": "fireside-chat/firesideGo", + "owner": { + "login": "fireside-chat", + "id": 12191882, + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/fireside-chat", + "html_url": "https://github.com/fireside-chat", + "followers_url": "https://api.github.com/users/fireside-chat/followers", + "following_url": "https://api.github.com/users/fireside-chat/following{/other_user}", + "gists_url": "https://api.github.com/users/fireside-chat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/fireside-chat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/fireside-chat/subscriptions", + "organizations_url": "https://api.github.com/users/fireside-chat/orgs", + "repos_url": "https://api.github.com/users/fireside-chat/repos", + "events_url": "https://api.github.com/users/fireside-chat/events{/privacy}", + "received_events_url": "https://api.github.com/users/fireside-chat/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/fireside-chat/firesideGo", + "description": "Stripped down version of euphoria.io's heim written in Go.", + "fork": false, + "url": "https://api.github.com/repos/fireside-chat/firesideGo", + "forks_url": "https://api.github.com/repos/fireside-chat/firesideGo/forks", + "keys_url": "https://api.github.com/repos/fireside-chat/firesideGo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/fireside-chat/firesideGo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/fireside-chat/firesideGo/teams", + "hooks_url": "https://api.github.com/repos/fireside-chat/firesideGo/hooks", + "issue_events_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues/events{/number}", + "events_url": "https://api.github.com/repos/fireside-chat/firesideGo/events", + "assignees_url": "https://api.github.com/repos/fireside-chat/firesideGo/assignees{/user}", + "branches_url": "https://api.github.com/repos/fireside-chat/firesideGo/branches{/branch}", + "tags_url": "https://api.github.com/repos/fireside-chat/firesideGo/tags", + "blobs_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/fireside-chat/firesideGo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/fireside-chat/firesideGo/languages", + "stargazers_url": "https://api.github.com/repos/fireside-chat/firesideGo/stargazers", + "contributors_url": "https://api.github.com/repos/fireside-chat/firesideGo/contributors", + "subscribers_url": "https://api.github.com/repos/fireside-chat/firesideGo/subscribers", + "subscription_url": "https://api.github.com/repos/fireside-chat/firesideGo/subscription", + "commits_url": "https://api.github.com/repos/fireside-chat/firesideGo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/fireside-chat/firesideGo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/fireside-chat/firesideGo/contents/{+path}", + "compare_url": "https://api.github.com/repos/fireside-chat/firesideGo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/fireside-chat/firesideGo/merges", + "archive_url": "https://api.github.com/repos/fireside-chat/firesideGo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/fireside-chat/firesideGo/downloads", + "issues_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues{/number}", + "pulls_url": "https://api.github.com/repos/fireside-chat/firesideGo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/fireside-chat/firesideGo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/fireside-chat/firesideGo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/fireside-chat/firesideGo/labels{/name}", + "releases_url": "https://api.github.com/repos/fireside-chat/firesideGo/releases{/id}", + "created_at": "2015-05-01T18:43:26Z", + "updated_at": "2015-05-01T18:43:26Z", + "pushed_at": "2015-05-01T18:43:26Z", + "git_url": "git://github.com/fireside-chat/firesideGo.git", + "ssh_url": "git@github.com:fireside-chat/firesideGo.git", + "clone_url": "https://github.com/fireside-chat/firesideGo.git", + "svn_url": "https://github.com/fireside-chat/firesideGo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "organization": { + "login": "fireside-chat", + "id": 12191882, + "url": "https://api.github.com/orgs/fireside-chat", + "repos_url": "https://api.github.com/orgs/fireside-chat/repos", + "events_url": "https://api.github.com/orgs/fireside-chat/events", + "members_url": "https://api.github.com/orgs/fireside-chat/members{/member}", + "public_members_url": "https://api.github.com/orgs/fireside-chat/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "description": "" + }, + "sender": { + "login": "cpalone", + "id": 9749483, + "avatar_url": "https://avatars.githubusercontent.com/u/9749483?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/cpalone", + "html_url": "https://github.com/cpalone", + "followers_url": "https://api.github.com/users/cpalone/followers", + "following_url": "https://api.github.com/users/cpalone/following{/other_user}", + "gists_url": "https://api.github.com/users/cpalone/gists{/gist_id}", + "starred_url": "https://api.github.com/users/cpalone/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/cpalone/subscriptions", + "organizations_url": "https://api.github.com/users/cpalone/orgs", + "repos_url": "https://api.github.com/users/cpalone/repos", + "events_url": "https://api.github.com/users/cpalone/events{/privacy}", + "received_events_url": "https://api.github.com/users/cpalone/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/testdata/sample_repository.json b/testdata/sample_repository.json new file mode 100644 index 0000000..42d310b --- /dev/null +++ b/testdata/sample_repository.json @@ -0,0 +1,120 @@ +{ + "action": "created", + "repository": { + "id": 34917952, + "name": "firesideGo", + "full_name": "fireside-chat/firesideGo", + "owner": { + "login": "fireside-chat", + "id": 12191882, + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/fireside-chat", + "html_url": "https://github.com/fireside-chat", + "followers_url": "https://api.github.com/users/fireside-chat/followers", + "following_url": "https://api.github.com/users/fireside-chat/following{/other_user}", + "gists_url": "https://api.github.com/users/fireside-chat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/fireside-chat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/fireside-chat/subscriptions", + "organizations_url": "https://api.github.com/users/fireside-chat/orgs", + "repos_url": "https://api.github.com/users/fireside-chat/repos", + "events_url": "https://api.github.com/users/fireside-chat/events{/privacy}", + "received_events_url": "https://api.github.com/users/fireside-chat/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/fireside-chat/firesideGo", + "description": "Stripped down version of euphoria.io's heim written in Go.", + "fork": false, + "url": "https://api.github.com/repos/fireside-chat/firesideGo", + "forks_url": "https://api.github.com/repos/fireside-chat/firesideGo/forks", + "keys_url": "https://api.github.com/repos/fireside-chat/firesideGo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/fireside-chat/firesideGo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/fireside-chat/firesideGo/teams", + "hooks_url": "https://api.github.com/repos/fireside-chat/firesideGo/hooks", + "issue_events_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues/events{/number}", + "events_url": "https://api.github.com/repos/fireside-chat/firesideGo/events", + "assignees_url": "https://api.github.com/repos/fireside-chat/firesideGo/assignees{/user}", + "branches_url": "https://api.github.com/repos/fireside-chat/firesideGo/branches{/branch}", + "tags_url": "https://api.github.com/repos/fireside-chat/firesideGo/tags", + "blobs_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/fireside-chat/firesideGo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/fireside-chat/firesideGo/languages", + "stargazers_url": "https://api.github.com/repos/fireside-chat/firesideGo/stargazers", + "contributors_url": "https://api.github.com/repos/fireside-chat/firesideGo/contributors", + "subscribers_url": "https://api.github.com/repos/fireside-chat/firesideGo/subscribers", + "subscription_url": "https://api.github.com/repos/fireside-chat/firesideGo/subscription", + "commits_url": "https://api.github.com/repos/fireside-chat/firesideGo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/fireside-chat/firesideGo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/fireside-chat/firesideGo/contents/{+path}", + "compare_url": "https://api.github.com/repos/fireside-chat/firesideGo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/fireside-chat/firesideGo/merges", + "archive_url": "https://api.github.com/repos/fireside-chat/firesideGo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/fireside-chat/firesideGo/downloads", + "issues_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues{/number}", + "pulls_url": "https://api.github.com/repos/fireside-chat/firesideGo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/fireside-chat/firesideGo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/fireside-chat/firesideGo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/fireside-chat/firesideGo/labels{/name}", + "releases_url": "https://api.github.com/repos/fireside-chat/firesideGo/releases{/id}", + "created_at": "2015-05-01T18:43:26Z", + "updated_at": "2015-05-01T18:43:26Z", + "pushed_at": "2015-05-01T18:43:26Z", + "git_url": "git://github.com/fireside-chat/firesideGo.git", + "ssh_url": "git@github.com:fireside-chat/firesideGo.git", + "clone_url": "https://github.com/fireside-chat/firesideGo.git", + "svn_url": "https://github.com/fireside-chat/firesideGo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "organization": { + "login": "fireside-chat", + "id": 12191882, + "url": "https://api.github.com/orgs/fireside-chat", + "repos_url": "https://api.github.com/orgs/fireside-chat/repos", + "events_url": "https://api.github.com/orgs/fireside-chat/events", + "members_url": "https://api.github.com/orgs/fireside-chat/members{/member}", + "public_members_url": "https://api.github.com/orgs/fireside-chat/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "description": "" + }, + "sender": { + "login": "cpalone", + "id": 9749483, + "avatar_url": "https://avatars.githubusercontent.com/u/9749483?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/cpalone", + "html_url": "https://github.com/cpalone", + "followers_url": "https://api.github.com/users/cpalone/followers", + "following_url": "https://api.github.com/users/cpalone/following{/other_user}", + "gists_url": "https://api.github.com/users/cpalone/gists{/gist_id}", + "starred_url": "https://api.github.com/users/cpalone/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/cpalone/subscriptions", + "organizations_url": "https://api.github.com/users/cpalone/orgs", + "repos_url": "https://api.github.com/users/cpalone/repos", + "events_url": "https://api.github.com/users/cpalone/events{/privacy}", + "received_events_url": "https://api.github.com/users/cpalone/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/testdata/sample_team_add.json b/testdata/sample_team_add.json new file mode 100644 index 0000000..20f0658 --- /dev/null +++ b/testdata/sample_team_add.json @@ -0,0 +1,129 @@ +{ + "team": { + "name": "Owners", + "id": 1474248, + "slug": "owners", + "description": null, + "permission": "admin", + "url": "https://api.github.com/teams/1474248", + "members_url": "https://api.github.com/teams/1474248/members{/member}", + "repositories_url": "https://api.github.com/teams/1474248/repos" + }, + "repository": { + "id": 34917952, + "name": "firesideGo", + "full_name": "fireside-chat/firesideGo", + "owner": { + "login": "fireside-chat", + "id": 12191882, + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/fireside-chat", + "html_url": "https://github.com/fireside-chat", + "followers_url": "https://api.github.com/users/fireside-chat/followers", + "following_url": "https://api.github.com/users/fireside-chat/following{/other_user}", + "gists_url": "https://api.github.com/users/fireside-chat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/fireside-chat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/fireside-chat/subscriptions", + "organizations_url": "https://api.github.com/users/fireside-chat/orgs", + "repos_url": "https://api.github.com/users/fireside-chat/repos", + "events_url": "https://api.github.com/users/fireside-chat/events{/privacy}", + "received_events_url": "https://api.github.com/users/fireside-chat/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/fireside-chat/firesideGo", + "description": "Stripped down version of euphoria.io's heim written in Go.", + "fork": false, + "url": "https://api.github.com/repos/fireside-chat/firesideGo", + "forks_url": "https://api.github.com/repos/fireside-chat/firesideGo/forks", + "keys_url": "https://api.github.com/repos/fireside-chat/firesideGo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/fireside-chat/firesideGo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/fireside-chat/firesideGo/teams", + "hooks_url": "https://api.github.com/repos/fireside-chat/firesideGo/hooks", + "issue_events_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues/events{/number}", + "events_url": "https://api.github.com/repos/fireside-chat/firesideGo/events", + "assignees_url": "https://api.github.com/repos/fireside-chat/firesideGo/assignees{/user}", + "branches_url": "https://api.github.com/repos/fireside-chat/firesideGo/branches{/branch}", + "tags_url": "https://api.github.com/repos/fireside-chat/firesideGo/tags", + "blobs_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/fireside-chat/firesideGo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/fireside-chat/firesideGo/languages", + "stargazers_url": "https://api.github.com/repos/fireside-chat/firesideGo/stargazers", + "contributors_url": "https://api.github.com/repos/fireside-chat/firesideGo/contributors", + "subscribers_url": "https://api.github.com/repos/fireside-chat/firesideGo/subscribers", + "subscription_url": "https://api.github.com/repos/fireside-chat/firesideGo/subscription", + "commits_url": "https://api.github.com/repos/fireside-chat/firesideGo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/fireside-chat/firesideGo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/fireside-chat/firesideGo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/fireside-chat/firesideGo/contents/{+path}", + "compare_url": "https://api.github.com/repos/fireside-chat/firesideGo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/fireside-chat/firesideGo/merges", + "archive_url": "https://api.github.com/repos/fireside-chat/firesideGo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/fireside-chat/firesideGo/downloads", + "issues_url": "https://api.github.com/repos/fireside-chat/firesideGo/issues{/number}", + "pulls_url": "https://api.github.com/repos/fireside-chat/firesideGo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/fireside-chat/firesideGo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/fireside-chat/firesideGo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/fireside-chat/firesideGo/labels{/name}", + "releases_url": "https://api.github.com/repos/fireside-chat/firesideGo/releases{/id}", + "created_at": "2015-05-01T18:43:26Z", + "updated_at": "2015-05-01T18:43:26Z", + "pushed_at": "2015-05-01T18:43:26Z", + "git_url": "git://github.com/fireside-chat/firesideGo.git", + "ssh_url": "git@github.com:fireside-chat/firesideGo.git", + "clone_url": "https://github.com/fireside-chat/firesideGo.git", + "svn_url": "https://github.com/fireside-chat/firesideGo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "organization": { + "login": "fireside-chat", + "id": 12191882, + "url": "https://api.github.com/orgs/fireside-chat", + "repos_url": "https://api.github.com/orgs/fireside-chat/repos", + "events_url": "https://api.github.com/orgs/fireside-chat/events", + "members_url": "https://api.github.com/orgs/fireside-chat/members{/member}", + "public_members_url": "https://api.github.com/orgs/fireside-chat/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "description": "" + }, + "sender": { + "login": "fireside-chat", + "id": 12191882, + "avatar_url": "https://avatars.githubusercontent.com/u/12191882?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/fireside-chat", + "html_url": "https://github.com/fireside-chat", + "followers_url": "https://api.github.com/users/fireside-chat/followers", + "following_url": "https://api.github.com/users/fireside-chat/following{/other_user}", + "gists_url": "https://api.github.com/users/fireside-chat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/fireside-chat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/fireside-chat/subscriptions", + "organizations_url": "https://api.github.com/users/fireside-chat/orgs", + "repos_url": "https://api.github.com/users/fireside-chat/repos", + "events_url": "https://api.github.com/users/fireside-chat/events{/privacy}", + "received_events_url": "https://api.github.com/users/fireside-chat/received_events", + "type": "Organization", + "site_admin": false + } +} From 6c3d7b86be902b20d1d0e2ce4b51ecd6c9d10a3b Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 13:20:56 -0600 Subject: [PATCH 18/32] Added timeout in ping request. --- gohook_test.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/gohook_test.go b/gohook_test.go index 3ee4610..ead31f0 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "net/http" "testing" + "time" ) func TestPingGithub(t *testing.T) { @@ -15,9 +16,14 @@ func TestPingGithub(t *testing.T) { if err != nil { t.Errorf("Error requesting ping: %s", err) } - packet := <-server.EventAndTypes - if packet.Type != PingEventType { - t.Errorf("Incorrect packet type, got %s", packet.Type) + var packet *EventAndType + select { + case packet = <-server.EventAndTypes: + if packet.Type != PingEventType { + t.Errorf("Incorrect packet type, got %s", packet.Type) + } + case <-time.After(time.Duration(3) * time.Second): + t.Error("Timeout when waiting for ping.") } payload, ok := packet.Event.(*PingEvent) if !ok { From 3a83c5a62bd1541bcefaea9668793ef60599b7b3 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 15:54:44 -0600 Subject: [PATCH 19/32] Commented out nonfunctioning test. --- example/main.go | 8 ++++---- gohook_test.go | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/example/main.go b/example/main.go index 7bc4b94..2e778ae 100644 --- a/example/main.go +++ b/example/main.go @@ -21,25 +21,25 @@ func main() { case gohook.PingEventType: packet, ok := eAndT.Event.(*gohook.PingEvent) if !ok { - panic("Could not assert PingEvent as such.") + panic("Could not assert *PingEvent as such.") } fmt.Println(packet.Organization.Login) case gohook.PushEventType: packet, ok := eAndT.Event.(*gohook.PushEvent) if !ok { - panic("Could not assert PushEvent as such.") + panic("Could not assert *PushEvent as such.") } fmt.Println(packet.Organization.Login) case gohook.CommitCommentType: packet, ok := eAndT.Event.(*gohook.CommitCommentEvent) if !ok { - panic("Could not assert CommitCommentEvent as such.") + panic("Could not assert *CommitCommentEvent as such.") } fmt.Println(packet.Comment.Body) case gohook.IssueCommentType: packet, ok := eAndT.Event.(*gohook.IssueCommentEvent) if !ok { - panic("Could not assert IssueCommentEvent as such.") + panic("Could not assert *IssueCommentEvent as such.") } fmt.Println(packet.Comment.Body) } diff --git a/gohook_test.go b/gohook_test.go index ead31f0..bc38a8d 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -9,30 +9,30 @@ import ( "time" ) -func TestPingGithub(t *testing.T) { - server := NewServer(8888, "secret", "/postreceive") - server.GoListenAndServe() - _, err := http.Post("https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", "application/json", nil) - if err != nil { - t.Errorf("Error requesting ping: %s", err) - } - var packet *EventAndType - select { - case packet = <-server.EventAndTypes: - if packet.Type != PingEventType { - t.Errorf("Incorrect packet type, got %s", packet.Type) - } - case <-time.After(time.Duration(3) * time.Second): - t.Error("Timeout when waiting for ping.") - } - payload, ok := packet.Event.(*PingEvent) - if !ok { - t.Error("Error asserting payload as *PingEvent.") - } - if !payload.Hook.Active { - t.Error("Incorrect payload.Hook.Active value.") - } -} +// func TestPingGithub(t *testing.T) { +// server := NewServer(8888, "secret", "/postreceive") +// server.GoListenAndServe() +// _, err := http.Post("https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", "application/json", nil) +// if err != nil { +// t.Errorf("Error requesting ping: %s", err) +// } +// var packet *EventAndType +// select { +// case packet = <-server.EventAndTypes: +// if packet.Type != PingEventType { +// t.Errorf("Incorrect packet type, got %s", packet.Type) +// } +// case <-time.After(time.Duration(3) * time.Second): +// t.Error("Timeout when waiting for ping.") +// } +// payload, ok := packet.Event.(*PingEvent) +// if !ok { +// t.Error("Error asserting payload as *PingEvent.") +// } +// if !payload.Hook.Active { +// t.Error("Incorrect payload.Hook.Active value.") +// } +// } func TestPingEvent(t *testing.T) { raw, err := ioutil.ReadFile("testdata/sample_ping.json") From f69e007dea421ae95c3ae64157a2eae01814d9ad Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 20:02:58 -0600 Subject: [PATCH 20/32] Fixed ping test- be sure not to leave password in source code! --- gohook_test.go | 56 ++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/gohook_test.go b/gohook_test.go index bc38a8d..41f3a75 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -3,36 +3,44 @@ package gohook import ( "bytes" "encoding/json" + "fmt" "io/ioutil" "net/http" "testing" "time" ) -// func TestPingGithub(t *testing.T) { -// server := NewServer(8888, "secret", "/postreceive") -// server.GoListenAndServe() -// _, err := http.Post("https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", "application/json", nil) -// if err != nil { -// t.Errorf("Error requesting ping: %s", err) -// } -// var packet *EventAndType -// select { -// case packet = <-server.EventAndTypes: -// if packet.Type != PingEventType { -// t.Errorf("Incorrect packet type, got %s", packet.Type) -// } -// case <-time.After(time.Duration(3) * time.Second): -// t.Error("Timeout when waiting for ping.") -// } -// payload, ok := packet.Event.(*PingEvent) -// if !ok { -// t.Error("Error asserting payload as *PingEvent.") -// } -// if !payload.Hook.Active { -// t.Error("Incorrect payload.Hook.Active value.") -// } -// } +func TestPingGithub(t *testing.T) { + server := NewServer(8888, "secret", "/postreceive") + server.GoListenAndServe() + req, _ := http.NewRequest("POST", "https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", nil) + req.SetBasicAuth("cpalone", password) + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + t.Errorf("Error requesting ping: %s", err) + } + if resp.StatusCode != 204 { + t.Errorf("Bad status code requesting ping: %s", resp.StatusCode) + } + fmt.Println(resp.StatusCode) + var packet *EventAndType + select { + case packet = <-server.EventAndTypes: + if packet.Type != PingEventType { + t.Errorf("Incorrect packet type, got %s", packet.Type) + } + case <-time.After(time.Duration(3) * time.Second): + t.Fatal("Timeout when waiting for ping.") + } + payload, ok := packet.Event.(*PingEvent) + if !ok { + t.Error("Error asserting payload as *PingEvent.") + } + if !payload.Hook.Active { + t.Error("Incorrect payload.Hook.Active value.") + } +} func TestPingEvent(t *testing.T) { raw, err := ioutil.ReadFile("testdata/sample_ping.json") From 7847a240e6777b0344773d758357e44d882fcf1f Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Sat, 2 May 2015 02:08:12 +0000 Subject: [PATCH 21/32] Added constant in file outside of VCS to supply github password. --- gohook_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gohook_test.go b/gohook_test.go index 41f3a75..8e7ae37 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -14,7 +14,7 @@ func TestPingGithub(t *testing.T) { server := NewServer(8888, "secret", "/postreceive") server.GoListenAndServe() req, _ := http.NewRequest("POST", "https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", nil) - req.SetBasicAuth("cpalone", password) + req.SetBasicAuth("cpalone", PASSWORD) client := &http.Client{} resp, err := client.Do(req) if err != nil { From e206fb8f1425a6e4814f8a57eea364762f61b2c5 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Sat, 2 May 2015 02:15:59 +0000 Subject: [PATCH 22/32] Keep an up-to-date coverage profile hanging around. --- coverage.out | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 coverage.out diff --git a/coverage.out b/coverage.out new file mode 100644 index 0000000..9cd17f4 --- /dev/null +++ b/coverage.out @@ -0,0 +1,49 @@ +mode: set +github.com/cpalone/gohook/server.go:27.62,34.2 1 1 +github.com/cpalone/gohook/server.go:36.66,38.21 2 1 +github.com/cpalone/gohook/server.go:41.2,45.57 5 1 +github.com/cpalone/gohook/server.go:48.2,48.13 1 1 +github.com/cpalone/gohook/server.go:38.21,40.3 1 0 +github.com/cpalone/gohook/server.go:45.57,47.3 1 0 +github.com/cpalone/gohook/server.go:51.70,53.19 2 1 +github.com/cpalone/gohook/server.go:102.2,102.59 1 1 +github.com/cpalone/gohook/server.go:105.2,109.23 2 1 +github.com/cpalone/gohook/server.go:54.2,55.25 1 1 +github.com/cpalone/gohook/server.go:56.2,57.25 1 1 +github.com/cpalone/gohook/server.go:58.2,59.34 1 1 +github.com/cpalone/gohook/server.go:60.2,61.33 1 0 +github.com/cpalone/gohook/server.go:62.2,63.27 1 0 +github.com/cpalone/gohook/server.go:64.2,65.27 1 1 +github.com/cpalone/gohook/server.go:66.2,67.27 1 0 +github.com/cpalone/gohook/server.go:68.2,69.31 1 1 +github.com/cpalone/gohook/server.go:70.2,71.31 1 0 +github.com/cpalone/gohook/server.go:72.2,73.37 1 0 +github.com/cpalone/gohook/server.go:74.2,75.25 1 0 +github.com/cpalone/gohook/server.go:76.2,77.27 1 0 +github.com/cpalone/gohook/server.go:78.2,79.27 1 0 +github.com/cpalone/gohook/server.go:80.2,81.31 1 0 +github.com/cpalone/gohook/server.go:82.2,83.30 1 0 +github.com/cpalone/gohook/server.go:84.2,85.27 1 0 +github.com/cpalone/gohook/server.go:86.2,87.32 1 0 +github.com/cpalone/gohook/server.go:88.2,89.45 1 0 +github.com/cpalone/gohook/server.go:90.2,91.28 1 0 +github.com/cpalone/gohook/server.go:92.2,93.27 1 0 +github.com/cpalone/gohook/server.go:94.2,95.28 1 1 +github.com/cpalone/gohook/server.go:96.2,97.26 1 1 +github.com/cpalone/gohook/server.go:98.2,100.9 2 0 +github.com/cpalone/gohook/server.go:102.59,104.3 1 0 +github.com/cpalone/gohook/server.go:114.70,117.26 2 1 +github.com/cpalone/gohook/server.go:121.2,121.28 1 1 +github.com/cpalone/gohook/server.go:125.2,126.21 2 1 +github.com/cpalone/gohook/server.go:131.2,132.16 2 1 +github.com/cpalone/gohook/server.go:137.2,137.52 1 1 +github.com/cpalone/gohook/server.go:141.2,141.52 1 1 +github.com/cpalone/gohook/server.go:117.26,119.3 1 0 +github.com/cpalone/gohook/server.go:121.28,123.3 1 0 +github.com/cpalone/gohook/server.go:126.21,129.3 2 0 +github.com/cpalone/gohook/server.go:132.16,135.3 2 0 +github.com/cpalone/gohook/server.go:137.52,140.3 2 0 +github.com/cpalone/gohook/server.go:147.41,149.2 1 1 +github.com/cpalone/gohook/server.go:154.37,155.12 1 1 +github.com/cpalone/gohook/server.go:155.12,157.17 2 1 +github.com/cpalone/gohook/server.go:157.17,159.4 1 0 From fd3e9bc32b54ed057aa4e07ba18683f922a7bcc3 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 20:23:38 -0600 Subject: [PATCH 23/32] Trying a new password scheme. --- gohook_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gohook_test.go b/gohook_test.go index 8e7ae37..a1e05ac 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -11,10 +11,17 @@ import ( ) func TestPingGithub(t *testing.T) { + if testing.Short() { + t.Skip("Skipping ping request to Github.") + } + rawPass, err := ioutil.ReadFile("password.txt") + if err != nil { + t.Skip("Skipping test- error reading password.txt or file is missing.") + } server := NewServer(8888, "secret", "/postreceive") server.GoListenAndServe() req, _ := http.NewRequest("POST", "https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", nil) - req.SetBasicAuth("cpalone", PASSWORD) + req.SetBasicAuth("cpalone", string(rawPass)) client := &http.Client{} resp, err := client.Do(req) if err != nil { From 327b7b5e4d24b03741d660750c80786b9d8db827 Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Sat, 2 May 2015 02:28:20 +0000 Subject: [PATCH 24/32] Fixed a string formatting bug. --- gohook_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gohook_test.go b/gohook_test.go index a1e05ac..831b278 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -28,7 +28,7 @@ func TestPingGithub(t *testing.T) { t.Errorf("Error requesting ping: %s", err) } if resp.StatusCode != 204 { - t.Errorf("Bad status code requesting ping: %s", resp.StatusCode) + t.Errorf("Bad status code requesting ping: %v", resp.StatusCode) } fmt.Println(resp.StatusCode) var packet *EventAndType From 4bbe20fff579b44d070455b11b7d1cb96d55284e Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 20:31:23 -0600 Subject: [PATCH 25/32] Fixed error with password.txt file- need to strip whitespace. --- gohook_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gohook_test.go b/gohook_test.go index 831b278..62219cd 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io/ioutil" "net/http" + "strings" "testing" "time" ) @@ -21,7 +22,7 @@ func TestPingGithub(t *testing.T) { server := NewServer(8888, "secret", "/postreceive") server.GoListenAndServe() req, _ := http.NewRequest("POST", "https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", nil) - req.SetBasicAuth("cpalone", string(rawPass)) + req.SetBasicAuth("cpalone", strings.TrimSpace(string(rawPass))) client := &http.Client{} resp, err := client.Do(req) if err != nil { From f3923fef5eae9c7aec4caaf7ec2308e1f94ac7eb Mon Sep 17 00:00:00 2001 From: "M. Cameron Palone" Date: Fri, 1 May 2015 20:53:44 -0600 Subject: [PATCH 26/32] Added test for DeleteEvent. --- gohook_test.go | 27 ++++++++- testdata/sample_delete.json | 111 ++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 testdata/sample_delete.json diff --git a/gohook_test.go b/gohook_test.go index 62219cd..b1bf72a 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -201,14 +201,14 @@ func TestCreateEvent(t *testing.T) { func TestRepositoryEvent(t *testing.T) { raw, err := ioutil.ReadFile("testdata/sample_repository.json") if err != nil { - t.Errorf("Error reading sample create file: %s", err) + t.Errorf("Error reading sample repo file: %s", err) } server := NewServer(8888, "secret", "path") server.processPacket(RepositoryEventType, raw) packet := <-server.EventAndTypes payload, ok := packet.Event.(*RepositoryEvent) if !ok { - t.Error("Error asserting payload as *CreateEvent.") + t.Error("Error asserting payload as *RepositoryEvent.") } if payload.Action != "created" { t.Error("Incorrect payload.Action value.") @@ -218,6 +218,27 @@ func TestRepositoryEvent(t *testing.T) { } _, err = json.Marshal(payload) if err != nil { - t.Errorf("Error marshalling TeamAddEvent: %s", err) + t.Errorf("Error marshalling RepositoryEvent: %s", err) + } +} + +func TestDeleteEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_delete.json") + if err != nil { + t.Errorf("Error reading sample delete file: %s", err) + } + server := NewServer(8888, "secret", "path") + server.processPacket(DeleteEventType, raw) + packet := <-server.EventAndTypes + payload, ok := packet.Event.(*DeleteEvent) + if !ok { + t.Error("Error asserting payload as *DeleteEvent.") + } + if payload.Ref != "simple-tag" { + t.Error("Incorrect payload.Ref value.") + } + _, err = json.Marshal(payload) + if err != nil { + t.Errorf("Error marshalling DeleteEvent: %s", err) } } diff --git a/testdata/sample_delete.json b/testdata/sample_delete.json new file mode 100644 index 0000000..5e31a84 --- /dev/null +++ b/testdata/sample_delete.json @@ -0,0 +1,111 @@ +{ + "ref": "simple-tag", + "ref_type": "tag", + "pusher_type": "user", + "repository": { + "id": 20000106, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments/{number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2014-05-20T22:39:43Z", + "updated_at": "2014-10-10T00:09:53Z", + "pushed_at": "2014-10-10T00:10:05Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 665, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 26, + "forks": 0, + "open_issues": 26, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} From 5ce269444987436f96c49772269807abe3b7867c Mon Sep 17 00:00:00 2001 From: Cameron Palone Date: Sat, 6 Jun 2015 11:49:47 -0600 Subject: [PATCH 27/32] Cleanup and test rewrite. --- gohook_test.go | 481 +++++++++++++++++++++++++++---------------------- server.go | 20 +- 2 files changed, 275 insertions(+), 226 deletions(-) diff --git a/gohook_test.go b/gohook_test.go index b1bf72a..b68b41c 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -2,243 +2,292 @@ package gohook import ( "bytes" - "encoding/json" - "fmt" + "crypto/hmac" + "crypto/sha1" + "encoding/hex" "io/ioutil" "net/http" - "strings" + "net/http/httptest" "testing" "time" ) -func TestPingGithub(t *testing.T) { - if testing.Short() { - t.Skip("Skipping ping request to Github.") - } - rawPass, err := ioutil.ReadFile("password.txt") - if err != nil { - t.Skip("Skipping test- error reading password.txt or file is missing.") - } - server := NewServer(8888, "secret", "/postreceive") - server.GoListenAndServe() - req, _ := http.NewRequest("POST", "https://api.github.com/orgs/fireside-chat/hooks/4719659/pings", nil) - req.SetBasicAuth("cpalone", strings.TrimSpace(string(rawPass))) - client := &http.Client{} - resp, err := client.Do(req) +// func (s *Server) verifyAuth(body []byte, req *http.Request) bool { +// signature := req.Header.Get("X-Hub-Signature") +// if signature == "" { +// return false +// } +// mac := hmac.New(sha1.New, []byte(s.Secret)) +// mac.Write(body) +// expectedMAC := mac.Sum(nil) +// expectedSig := "sha1=" + hex.EncodeToString(expectedMAC) +// if !hmac.Equal([]byte(expectedSig), []byte(signature)) { +// return false +// } +// return true +// } + +func SendRequest(method, url, secret, eventHeader string, body []byte) (*http.Response, error) { + req, err := http.NewRequest(method, url, bytes.NewBuffer(body)) if err != nil { - t.Errorf("Error requesting ping: %s", err) - } - if resp.StatusCode != 204 { - t.Errorf("Bad status code requesting ping: %v", resp.StatusCode) - } - fmt.Println(resp.StatusCode) - var packet *EventAndType - select { - case packet = <-server.EventAndTypes: - if packet.Type != PingEventType { - t.Errorf("Incorrect packet type, got %s", packet.Type) + return nil, err + } + req.Header.Add("X-Github-Event", eventHeader) + if secret != "" { + mac := hmac.New(sha1.New, []byte(secret)) + _, err := mac.Write(body) + if err != nil { + return nil, err } - case <-time.After(time.Duration(3) * time.Second): - t.Fatal("Timeout when waiting for ping.") - } - payload, ok := packet.Event.(*PingEvent) - if !ok { - t.Error("Error asserting payload as *PingEvent.") - } - if !payload.Hook.Active { - t.Error("Incorrect payload.Hook.Active value.") + macVal := mac.Sum(nil) + sig := "sha1=" + hex.EncodeToString(macVal) + req.Header.Add("X-Hub-Signature", sig) } + client := http.Client{} + return client.Do(req) } -func TestPingEvent(t *testing.T) { - raw, err := ioutil.ReadFile("testdata/sample_ping.json") - if err != nil { - t.Errorf("Error reading sample ping file: %s", err) - } - server := NewServer(8888, "secret", "path") - server.processPacket(PingEventType, raw) - packet := <-server.EventAndTypes - payload, ok := packet.Event.(*PingEvent) - if !ok { - t.Error("Error asserting payload as *PingEvent.") - } - if payload.Zen != "Approachable is better than simple." { - t.Error("Incorrect PingEvent.Zen value.") - } - if payload.Hook.Config.ContentType != "json" { - t.Error("Incorrect PingEvent.Hook.Config.ContentType value.") - } - _, err = json.Marshal(payload) +func TestCreateEvent(t *testing.T) { + raw, err := ioutil.ReadFile("testdata/sample_create.json") if err != nil { - t.Errorf("Error marshalling PingEvent: %s", err) + t.Errorf("Error reading sample create file: %s", err) } -} - -func TestPushEvent(t *testing.T) { - raw, err := ioutil.ReadFile("testdata/sample_push.json") + hookServer := NewServer(8888, "secret", "/path") + server := httptest.NewServer(hookServer) + defer server.Close() + resp, err := SendRequest("POST", server.URL+"/path", "secret", "create", raw) if err != nil { - t.Errorf("Error reading sample push file: %s", err) - } - server := NewServer(8888, "secret", "path") - server.processPacket(PushEventType, raw) - packet := <-server.EventAndTypes - payload, ok := packet.Event.(*PushEvent) - if !ok { - t.Error("Error asserting payload as *PushEvent.") + t.Errorf("SendRequest: %s", err) } - if payload.Ref != "refs/heads/master" { - t.Error("Incorrect PushEvent.Ref value.") + if resp.StatusCode != 200 { + t.Errorf("Bad status code: %s", resp.StatusCode) } - if payload.Commits[0].Author.Name != "M. Cameron Palone" { - t.Error("Incorrect payload.Commits[0].Author.Name value.") - } - _, err = json.Marshal(payload) - if err != nil { - t.Errorf("Error marshalling PushEvent: %s", err) + select { + case <-hookServer.EventAndTypes: + return + case <-time.After(time.Second): + t.Error("Timeout waiting for event from server.") } } -func TestWatchEvent(t *testing.T) { - raw, err := ioutil.ReadFile("testdata/sample_watch.json") - if err != nil { - t.Errorf("Error reading sample watch file: %s", err) - } - server := NewServer(8888, "secret", "path") - server.processPacket(WatchEventType, raw) - packet := <-server.EventAndTypes - payload, ok := packet.Event.(*WatchEvent) - if !ok { - t.Error("Error asserting payload as *WatchEvent.") - } - if payload.Action != "started" { - t.Error("Incorrect payload.Action value.") - } - if payload.Sender.ID != 16893 { - t.Error("Incorrect payload.Sender.ID value.") - } - if payload.Organization.ID != 12191882 { - t.Error("Incorrect payload.Organization.ID value.") - } - _, err = json.Marshal(payload) - if err != nil { - t.Errorf("Error marshalling WatchEvent: %s", err) - } -} +// func TestCreateEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_create.json") +// if err != nil { +// t.Errorf("Error reading sample create file: %s", err) +// } +// hookServer := NewServer(8888, "secret", "path") +// server := httptest.NewServer(hookServer) +// defer server.Close() -func TestCommitCommentEvent(t *testing.T) { - raw, err := ioutil.ReadFile("testdata/sample_commit_comment.json") - if err != nil { - t.Errorf("Error reading sample commit_comment file: %s", err) - } - server := NewServer(8888, "secret", "path") - server.processPacket(CommitCommentEventType, raw) - packet := <-server.EventAndTypes - payload, ok := packet.Event.(*CommitCommentEvent) - if !ok { - t.Error("Error asserting payload as *CommitCommentEvent.") - } - if payload.Comment.Body != "This is a really good change! :+1:" { - t.Error("Incorrect payload.Comment.Body value.") - } - if payload.Comment.User.Login != "baxterthehacker" { - t.Error("Incorrect payload.Comment.User.Login value.") - } - _, err = json.Marshal(payload) - if err != nil { - t.Errorf("Error marshalling CommitCommentEvent: %s", err) - } -} +// } -func TestTeamAddEvent(t *testing.T) { - raw, err := ioutil.ReadFile("testdata/sample_team_add.json") - if err != nil { - t.Errorf("Error reading sample team_add file: %s", err) - } - server := NewServer(8888, "secret", "path") - server.processPacket(TeamAddEventType, raw) - packet := <-server.EventAndTypes - payload, ok := packet.Event.(*TeamAddEvent) - if !ok { - t.Error("Error asserting payload as *TeamAddEvent.") - } - if payload.Team.ID != 1474248 { - t.Error("Incorrect payload.Team.ID value.") - } - if payload.Team.Slug != "owners" { - t.Error("Incorrect payload.Team.Slug value.") - } - _, err = json.Marshal(payload) - if err != nil { - t.Errorf("Error marshalling TeamAddEvent: %s", err) - } -} +// func TestPingEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_ping.json") +// if err != nil { +// t.Errorf("Error reading sample ping file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(PingEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*PingEvent) +// if !ok { +// t.Error("Error asserting payload as *PingEvent.") +// } +// if payload.Zen != "Approachable is better than simple." { +// t.Error("Incorrect PingEvent.Zen value.") +// } +// if payload.Hook.Config.ContentType != "json" { +// t.Error("Incorrect PingEvent.Hook.Config.ContentType value.") +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling PingEvent: %s", err) +// } +// } -func TestCreateEvent(t *testing.T) { - raw, err := ioutil.ReadFile("testdata/sample_create.json") - if err != nil { - t.Errorf("Error reading sample create file: %s", err) - } - server := NewServer(8888, "secret", "path") - server.processPacket(CreateEventType, raw) - packet := <-server.EventAndTypes - payload, ok := packet.Event.(*CreateEvent) - if !ok { - t.Error("Error asserting payload as *CreateEvent.") - } - if payload.Description != - "Stripped down version of euphoria.io's heim written in Go." { - t.Error("Incorrect payload.Description value.") - } - if !bytes.Equal(payload.Repository.CreatedAt, []byte("\"2015-05-01T18:43:26Z\"")) { - t.Errorf("Incorrect payload.Repository.CreatedAt value. Got %s, expected %s", payload.Repository.CreatedAt, []byte("2015-05-01T18:43:26Z")) - } - _, err = json.Marshal(payload) - if err != nil { - t.Errorf("Error marshalling CreatedEvent: %s", err) - } -} +// func TestPushEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_push.json") +// if err != nil { +// t.Errorf("Error reading sample push file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(PushEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*PushEvent) +// if !ok { +// t.Error("Error asserting payload as *PushEvent.") +// } +// if payload.Ref != "refs/heads/master" { +// t.Error("Incorrect PushEvent.Ref value.") +// } +// if payload.Commits[0].Author.Name != "M. Cameron Palone" { +// t.Error("Incorrect payload.Commits[0].Author.Name value.") +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling PushEvent: %s", err) +// } +// } -func TestRepositoryEvent(t *testing.T) { - raw, err := ioutil.ReadFile("testdata/sample_repository.json") - if err != nil { - t.Errorf("Error reading sample repo file: %s", err) - } - server := NewServer(8888, "secret", "path") - server.processPacket(RepositoryEventType, raw) - packet := <-server.EventAndTypes - payload, ok := packet.Event.(*RepositoryEvent) - if !ok { - t.Error("Error asserting payload as *RepositoryEvent.") - } - if payload.Action != "created" { - t.Error("Incorrect payload.Action value.") - } - if payload.Organization.Login != "fireside-chat" { - t.Error("Incorrect payload.Organization.Login value.") - } - _, err = json.Marshal(payload) - if err != nil { - t.Errorf("Error marshalling RepositoryEvent: %s", err) - } -} +// func TestWatchEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_watch.json") +// if err != nil { +// t.Errorf("Error reading sample watch file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(WatchEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*WatchEvent) +// if !ok { +// t.Error("Error asserting payload as *WatchEvent.") +// } +// if payload.Action != "started" { +// t.Error("Incorrect payload.Action value.") +// } +// if payload.Sender.ID != 16893 { +// t.Error("Incorrect payload.Sender.ID value.") +// } +// if payload.Organization.ID != 12191882 { +// t.Error("Incorrect payload.Organization.ID value.") +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling WatchEvent: %s", err) +// } +// } -func TestDeleteEvent(t *testing.T) { - raw, err := ioutil.ReadFile("testdata/sample_delete.json") - if err != nil { - t.Errorf("Error reading sample delete file: %s", err) - } - server := NewServer(8888, "secret", "path") - server.processPacket(DeleteEventType, raw) - packet := <-server.EventAndTypes - payload, ok := packet.Event.(*DeleteEvent) - if !ok { - t.Error("Error asserting payload as *DeleteEvent.") - } - if payload.Ref != "simple-tag" { - t.Error("Incorrect payload.Ref value.") - } - _, err = json.Marshal(payload) - if err != nil { - t.Errorf("Error marshalling DeleteEvent: %s", err) - } -} +// func TestCommitCommentEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_commit_comment.json") +// if err != nil { +// t.Errorf("Error reading sample commit_comment file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(CommitCommentEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*CommitCommentEvent) +// if !ok { +// t.Error("Error asserting payload as *CommitCommentEvent.") +// } +// if payload.Comment.Body != "This is a really good change! :+1:" { +// t.Error("Incorrect payload.Comment.Body value.") +// } +// if payload.Comment.User.Login != "baxterthehacker" { +// t.Error("Incorrect payload.Comment.User.Login value.") +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling CommitCommentEvent: %s", err) +// } +// } + +// func TestTeamAddEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_team_add.json") +// if err != nil { +// t.Errorf("Error reading sample team_add file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(TeamAddEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*TeamAddEvent) +// if !ok { +// t.Error("Error asserting payload as *TeamAddEvent.") +// } +// if payload.Team.ID != 1474248 { +// t.Error("Incorrect payload.Team.ID value.") +// } +// if payload.Team.Slug != "owners" { +// t.Error("Incorrect payload.Team.Slug value.") +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling TeamAddEvent: %s", err) +// } +// } + +// func TestCreateEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_create.json") +// if err != nil { +// t.Errorf("Error reading sample create file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(CreateEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*CreateEvent) +// if !ok { +// t.Error("Error asserting payload as *CreateEvent.") +// } +// if payload.Description != +// "Stripped down version of euphoria.io's heim written in Go." { +// t.Error("Incorrect payload.Description value.") +// } +// if !bytes.Equal(payload.Repository.CreatedAt, []byte("\"2015-05-01T18:43:26Z\"")) { +// t.Errorf("Incorrect payload.Repository.CreatedAt value. Got %s, expected %s", payload.Repository.CreatedAt, []byte("2015-05-01T18:43:26Z")) +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling CreatedEvent: %s", err) +// } +// } + +// func TestRepositoryEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_repository.json") +// if err != nil { +// t.Errorf("Error reading sample repo file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(RepositoryEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*RepositoryEvent) +// if !ok { +// t.Error("Error asserting payload as *RepositoryEvent.") +// } +// if payload.Action != "created" { +// t.Error("Incorrect payload.Action value.") +// } +// if payload.Organization.Login != "fireside-chat" { +// t.Error("Incorrect payload.Organization.Login value.") +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling RepositoryEvent: %s", err) +// } +// } + +// func TestDeleteEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_delete.json") +// if err != nil { +// t.Errorf("Error reading sample delete file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(DeleteEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*DeleteEvent) +// if !ok { +// t.Error("Error asserting payload as *DeleteEvent.") +// } +// if payload.Ref != "simple-tag" { +// t.Error("Incorrect payload.Ref value.") +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling DeleteEvent: %s", err) +// } +// } + +// func TestDeploymentEvent(t *testing.T) { +// raw, err := ioutil.ReadFile("testdata/sample_delete.json") +// if err != nil { +// t.Errorf("Error reading sample delete file: %s", err) +// } +// server := NewServer(8888, "secret", "path") +// server.processPacket(DeploymentEventType, raw) +// packet := <-server.EventAndTypes +// payload, ok := packet.Event.(*DeploymentEvent) +// if !ok { +// t.Error("Error asserting payload as *DeploymentEvent.") +// } +// _, err = json.Marshal(payload) +// if err != nil { +// t.Errorf("Error marshalling DeploymentEvent: %s", err) +// } +// } diff --git a/server.go b/server.go index a5d4cab..21721ed 100644 --- a/server.go +++ b/server.go @@ -51,22 +51,12 @@ func (s *Server) verifyAuth(body []byte, req *http.Request) bool { func (s *Server) processPacket(eventType EventType, respBody []byte) { var payload interface{} switch eventType { - case PushEventType: - payload = &PushEvent{} - case PingEventType: - payload = &PingEvent{} case CommitCommentEventType: payload = &CommitCommentEvent{} - case IssueCommentEventType: - payload = &IssueCommentEvent{} - case IssuesEventType: - payload = &IssuesEvent{} case CreateEventType: payload = &CreateEvent{} case DeleteEventType: payload = &DeleteEvent{} - case RepositoryEventType: - payload = &RepositoryEvent{} case DeploymentEventType: payload = &DeploymentEvent{} case DeploymentStatusEventType: @@ -75,20 +65,30 @@ func (s *Server) processPacket(eventType EventType, respBody []byte) { payload = &ForkEvent{} case GollumEventType: payload = &GollumEvent{} + case IssueCommentEventType: + payload = &IssueCommentEvent{} + case IssuesEventType: + payload = &IssuesEvent{} case MemberEventType: payload = &MemberEvent{} case MembershipEventType: payload = &MembershipEvent{} case PageBuildEventType: payload = &PageBuildEvent{} + case PingEventType: + payload = &PingEvent{} case PublicEventType: payload = &PublicEvent{} case PullRequestEventType: payload = &PullRequestEvent{} case PullRequestReviewCommentEventType: payload = &PullRequestReviewCommentEvent{} + case PushEventType: + payload = &PushEvent{} case ReleaseEventType: payload = &ReleaseEvent{} + case RepositoryEventType: + payload = &RepositoryEvent{} case StatusEventType: payload = &StatusEvent{} case TeamAddEventType: From c179b074a21c0a8fcf787c75f59e068933db5141 Mon Sep 17 00:00:00 2001 From: Cameron Palone Date: Sat, 6 Jun 2015 12:03:13 -0600 Subject: [PATCH 28/32] Fix for multiple calls to header write. --- gohook_test.go | 24 ++++++++---------------- server.go | 2 ++ 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/gohook_test.go b/gohook_test.go index b68b41c..a0e057c 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -12,21 +12,6 @@ import ( "time" ) -// func (s *Server) verifyAuth(body []byte, req *http.Request) bool { -// signature := req.Header.Get("X-Hub-Signature") -// if signature == "" { -// return false -// } -// mac := hmac.New(sha1.New, []byte(s.Secret)) -// mac.Write(body) -// expectedMAC := mac.Sum(nil) -// expectedSig := "sha1=" + hex.EncodeToString(expectedMAC) -// if !hmac.Equal([]byte(expectedSig), []byte(signature)) { -// return false -// } -// return true -// } - func SendRequest(method, url, secret, eventHeader string, body []byte) (*http.Response, error) { req, err := http.NewRequest(method, url, bytes.NewBuffer(body)) if err != nil { @@ -63,7 +48,14 @@ func TestCreateEvent(t *testing.T) { t.Errorf("Bad status code: %s", resp.StatusCode) } select { - case <-hookServer.EventAndTypes: + case et := <-hookServer.EventAndTypes: + if et.Type != CreateEventType { + t.Errorf("Incorrect event type from server: %s", et.Type) + } + _, ok := et.Event.(*CreateEvent) + if !ok { + t.Error("Could not assert event as *CreateEvent.") + } return case <-time.After(time.Second): t.Error("Timeout waiting for event from server.") diff --git a/server.go b/server.go index 21721ed..70090af 100644 --- a/server.go +++ b/server.go @@ -116,10 +116,12 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { http.Error(w, "405 Method not allowed", http.StatusMethodNotAllowed) + return } if req.URL.Path != s.Path { http.Error(w, "404 Not found- expected "+s.Path, http.StatusNotFound) + return } eventType := req.Header.Get("X-Github-Event") From 3e14235a6c5c1f69b2aa50d68a82a981571089e7 Mon Sep 17 00:00:00 2001 From: Cameron Palone Date: Sun, 7 Jun 2015 11:01:20 -0600 Subject: [PATCH 29/32] Continuing to rewrite tests. --- gohook_test.go | 270 +++++++------------------------- testdata/sample_deployment.json | 142 +++++++++++++++++ 2 files changed, 197 insertions(+), 215 deletions(-) create mode 100644 testdata/sample_deployment.json diff --git a/gohook_test.go b/gohook_test.go index a0e057c..205d77e 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -62,224 +62,64 @@ func TestCreateEvent(t *testing.T) { } } -// func TestCreateEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_create.json") -// if err != nil { -// t.Errorf("Error reading sample create file: %s", err) -// } -// hookServer := NewServer(8888, "secret", "path") -// server := httptest.NewServer(hookServer) -// defer server.Close() - -// } - -// func TestPingEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_ping.json") -// if err != nil { -// t.Errorf("Error reading sample ping file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(PingEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*PingEvent) -// if !ok { -// t.Error("Error asserting payload as *PingEvent.") -// } -// if payload.Zen != "Approachable is better than simple." { -// t.Error("Incorrect PingEvent.Zen value.") -// } -// if payload.Hook.Config.ContentType != "json" { -// t.Error("Incorrect PingEvent.Hook.Config.ContentType value.") -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling PingEvent: %s", err) -// } -// } - -// func TestPushEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_push.json") -// if err != nil { -// t.Errorf("Error reading sample push file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(PushEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*PushEvent) -// if !ok { -// t.Error("Error asserting payload as *PushEvent.") -// } -// if payload.Ref != "refs/heads/master" { -// t.Error("Incorrect PushEvent.Ref value.") -// } -// if payload.Commits[0].Author.Name != "M. Cameron Palone" { -// t.Error("Incorrect payload.Commits[0].Author.Name value.") -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling PushEvent: %s", err) -// } -// } - -// func TestWatchEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_watch.json") -// if err != nil { -// t.Errorf("Error reading sample watch file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(WatchEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*WatchEvent) -// if !ok { -// t.Error("Error asserting payload as *WatchEvent.") -// } -// if payload.Action != "started" { -// t.Error("Incorrect payload.Action value.") -// } -// if payload.Sender.ID != 16893 { -// t.Error("Incorrect payload.Sender.ID value.") -// } -// if payload.Organization.ID != 12191882 { -// t.Error("Incorrect payload.Organization.ID value.") -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling WatchEvent: %s", err) -// } -// } +func TestInvalidRequests(t *testing.T) { + correctBody, err := ioutil.ReadFile("testdata/sample_create.json") + if err != nil { + t.Errorf("Error reading sample create file: %s", err) + } + hookServer := NewServer(8888, "secret", "/path") + server := httptest.NewServer(hookServer) + defer server.Close() -// func TestCommitCommentEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_commit_comment.json") -// if err != nil { -// t.Errorf("Error reading sample commit_comment file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(CommitCommentEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*CommitCommentEvent) -// if !ok { -// t.Error("Error asserting payload as *CommitCommentEvent.") -// } -// if payload.Comment.Body != "This is a really good change! :+1:" { -// t.Error("Incorrect payload.Comment.Body value.") -// } -// if payload.Comment.User.Login != "baxterthehacker" { -// t.Error("Incorrect payload.Comment.User.Login value.") -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling CommitCommentEvent: %s", err) -// } -// } + // check wrong method + resp, err := SendRequest("GET", server.URL+"/path", "secret", "create", correctBody) + if err != nil { + t.Errorf("SendRequest: %s", err) + } + defer resp.Body.Close() + if resp.StatusCode != 405 { + t.Errorf("Expected 405 Method Not Allowed, got: %s", resp.StatusCode) + } -// func TestTeamAddEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_team_add.json") -// if err != nil { -// t.Errorf("Error reading sample team_add file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(TeamAddEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*TeamAddEvent) -// if !ok { -// t.Error("Error asserting payload as *TeamAddEvent.") -// } -// if payload.Team.ID != 1474248 { -// t.Error("Incorrect payload.Team.ID value.") -// } -// if payload.Team.Slug != "owners" { -// t.Error("Incorrect payload.Team.Slug value.") -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling TeamAddEvent: %s", err) -// } -// } + // check wrong path + resp, err = SendRequest("POST", server.URL+"/wrongpath", "secret", "create", correctBody) + if err != nil { + t.Errorf("SendRequest: %s", err) + } + defer resp.Body.Close() + if resp.StatusCode != 404 { + t.Errorf("Expected 404 Not Found, got: %s", resp.StatusCode) + } -// func TestCreateEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_create.json") -// if err != nil { -// t.Errorf("Error reading sample create file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(CreateEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*CreateEvent) -// if !ok { -// t.Error("Error asserting payload as *CreateEvent.") -// } -// if payload.Description != -// "Stripped down version of euphoria.io's heim written in Go." { -// t.Error("Incorrect payload.Description value.") -// } -// if !bytes.Equal(payload.Repository.CreatedAt, []byte("\"2015-05-01T18:43:26Z\"")) { -// t.Errorf("Incorrect payload.Repository.CreatedAt value. Got %s, expected %s", payload.Repository.CreatedAt, []byte("2015-05-01T18:43:26Z")) -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling CreatedEvent: %s", err) -// } -// } + // check wrong secret + resp, err = SendRequest("POST", server.URL+"/path", "wrongsecret", "create", correctBody) + if err != nil { + t.Errorf("SendRequest: %s", err) + } + defer resp.Body.Close() + if resp.StatusCode != 403 { + t.Errorf("Expected 403 Unauthorized, got: %s", resp.StatusCode) + } -// func TestRepositoryEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_repository.json") -// if err != nil { -// t.Errorf("Error reading sample repo file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(RepositoryEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*RepositoryEvent) -// if !ok { -// t.Error("Error asserting payload as *RepositoryEvent.") -// } -// if payload.Action != "created" { -// t.Error("Incorrect payload.Action value.") -// } -// if payload.Organization.Login != "fireside-chat" { -// t.Error("Incorrect payload.Organization.Login value.") -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling RepositoryEvent: %s", err) -// } -// } + // check missing event type + resp, err = SendRequest("POST", server.URL+"/path", "secret", "", correctBody) + if err != nil { + t.Errorf("SendRequest: %s", err) + } + defer resp.Body.Close() + if resp.StatusCode != 400 { + t.Errorf("Expected 400 Bad Request, got: %s", resp.StatusCode) + } -// func TestDeleteEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_delete.json") -// if err != nil { -// t.Errorf("Error reading sample delete file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(DeleteEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*DeleteEvent) -// if !ok { -// t.Error("Error asserting payload as *DeleteEvent.") -// } -// if payload.Ref != "simple-tag" { -// t.Error("Incorrect payload.Ref value.") -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling DeleteEvent: %s", err) -// } -// } + // check invalid body + invalidBody := []byte("{{}") -// func TestDeploymentEvent(t *testing.T) { -// raw, err := ioutil.ReadFile("testdata/sample_delete.json") -// if err != nil { -// t.Errorf("Error reading sample delete file: %s", err) -// } -// server := NewServer(8888, "secret", "path") -// server.processPacket(DeploymentEventType, raw) -// packet := <-server.EventAndTypes -// payload, ok := packet.Event.(*DeploymentEvent) -// if !ok { -// t.Error("Error asserting payload as *DeploymentEvent.") -// } -// _, err = json.Marshal(payload) -// if err != nil { -// t.Errorf("Error marshalling DeploymentEvent: %s", err) -// } -// } + resp, err = SendRequest("POST", server.URL+"/path", "secret", "create", correctBody) + if err != nil { + t.Errorf("SendRequest: %s", err) + } + defer resp.Body.Close() + if resp.StatusCode != 400 { + t.Errorf("Expected 400 Bad Request, got: %s", resp.StatusCode) + } +} diff --git a/testdata/sample_deployment.json b/testdata/sample_deployment.json new file mode 100644 index 0000000..b095509 --- /dev/null +++ b/testdata/sample_deployment.json @@ -0,0 +1,142 @@ +{ + "deployment": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692", + "id": 710692, + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "ref": "master", + "task": "deploy", + "payload": { + }, + "environment": "production", + "description": null, + "creator": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2015-05-05T23:40:38Z", + "updated_at": "2015-05-05T23:40:38Z", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692/statuses", + "repository_url": "https://api.github.com/repos/baxterthehacker/public-repo" + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:38Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} \ No newline at end of file From 1c7d94312d10552d2044ef3ff087350c3c078077 Mon Sep 17 00:00:00 2001 From: "Roberto G. Hashioka" Date: Wed, 5 Aug 2015 17:34:20 +0000 Subject: [PATCH 30/32] Convert date fields from string to timet.Time --- gohook_test.go | 12 --------- packet.go | 70 ++++++++++++++++++++++++++------------------------ 2 files changed, 36 insertions(+), 46 deletions(-) diff --git a/gohook_test.go b/gohook_test.go index 205d77e..5f2a349 100644 --- a/gohook_test.go +++ b/gohook_test.go @@ -110,16 +110,4 @@ func TestInvalidRequests(t *testing.T) { if resp.StatusCode != 400 { t.Errorf("Expected 400 Bad Request, got: %s", resp.StatusCode) } - - // check invalid body - invalidBody := []byte("{{}") - - resp, err = SendRequest("POST", server.URL+"/path", "secret", "create", correctBody) - if err != nil { - t.Errorf("SendRequest: %s", err) - } - defer resp.Body.Close() - if resp.StatusCode != 400 { - t.Errorf("Expected 400 Bad Request, got: %s", resp.StatusCode) - } } diff --git a/packet.go b/packet.go index 2ad5a0a..055186e 100644 --- a/packet.go +++ b/packet.go @@ -1,6 +1,8 @@ package gohook -import "encoding/json" +import ( + "time" +) // SenderType represents the structure of the sender field in push/ping events. type SenderType struct { @@ -109,9 +111,9 @@ type RepoType struct { NotificationsURL string `json:"notifications_url"` LabelsURL string `json:"labels_url"` ReleasesURL string `json:"releases_url"` - CreatedAt json.RawMessage `json:"created_at"` - UpdatedAt json.RawMessage `json:"updated_at"` - PushedAt json.RawMessage `json:"pushed_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + PushedAt time.Time `json:"pushed_at"` GitURL string `json:"git_url"` SSHURL string `json:"ssh_url"` CloneURL string `json:"clone_url"` @@ -169,8 +171,8 @@ type HookType struct { Events []string `json:"events"` Active bool `json:"active"` Config ConfigType `json:"config"` - UpdatedAt string `json:"updated_at"` - CreatedAt string `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` } // PingEvent represents the basic, top-level structure of a ping event. @@ -191,8 +193,8 @@ type CommentType struct { Line string `json:"line"` Path string `json:"path"` CommitID string `json:"commit_id"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` Body string `json:"body"` } @@ -208,8 +210,8 @@ type IssueCommentType struct { HTMLURL string `json:"html_url"` Body string `json:"body"` User SenderType `json:"user"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"created_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"created_at"` } type LabelType struct { @@ -230,9 +232,9 @@ type MilestoneType struct { Creator SenderType `json:"creator"` OpenIssues int `json:"open_issues"` ClosedIssues int `json:"closed_issues"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - ClosedAt string `json:"closed_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + ClosedAt *time.Time `json:"closed_at"` DueOn string `json:"due_on"` } @@ -257,9 +259,9 @@ type IssueType struct { Milestone MilestoneType `json:"milestone"` Comments int `json:"comments"` PullRequest ShortPullRequestType `json:"pull_request"` - ClosedAt string `json:"closed_at"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + ClosedAt *time.Time `json:"closed_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } type IssueCommentEvent struct { @@ -314,8 +316,8 @@ type DeploymentType struct { Environment string `json:"environment"` Description string `json:"description"` Creator SenderType `json:"creator"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` StatusesURL string `json:"statuses_url"` RepositoryURL string `json:"repository_url"` } @@ -341,8 +343,8 @@ type DeploymentStatusType struct { Creator SenderType `json:"creator"` Description string `json:"description"` TargetURL string `json:"target_url"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` DeploymentURL string `json:"deployment_url"` RepositoryURL string `json:"repository_url"` } @@ -416,8 +418,8 @@ type BuildType struct { Pusher SenderType `json:"pusher"` Commit string `json:"commit"` Duration int `json:"duration"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } type PageBuildEvent struct { @@ -460,10 +462,10 @@ type PullRequestType struct { State string `json:"state"` Title string `json:"title"` Body string `json:"body"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - ClosedAt string `json:"closed_at"` - MergedAt string `json:"merged_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + ClosedAt *time.Time `json:"closed_at"` + MergedAt *time.Time `json:"merged_at"` Head BaseHeadType `json:"head"` Repo RepoType `json:"repo"` Base BaseHeadType `json:"Base"` @@ -499,8 +501,8 @@ type PullRequestReviewCommentType struct { OriginalCommitID string `json:"original_commit_id"` User SenderType `json:"user"` Body string `json:"body"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` HTMLURL string `json:"html_url"` PullRequestURL string `json:"pull_request_url"` Links map[string]Link `json:"_links"` @@ -524,8 +526,8 @@ type AssetType struct { ContentType string `json:"content_type"` Size int `json:"size"` DownloadCount int `json:"download_count"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` Uploader SenderType `json:"uploader"` } @@ -543,8 +545,8 @@ type ReleaseType struct { Body string `json:"body"` Draft bool `json:"draft"` Prerelease bool `json:"prerelease"` - CreatedAt string `json:"created_at"` - PublishedAt string `json:"published_at"` + CreatedAt time.Time `json:"created_at"` + PublishedAt time.Time `json:"published_at"` Author SenderType `json:"author"` Assets []AssetType `json:"assets"` } @@ -576,8 +578,8 @@ type StatusEvent struct { State string `json:"state"` Commit CommitType `json:"commit"` Branches []BranchType `json:"branches"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` Repository RepoType `json:"repository"` Sender SenderType `json:"sender"` } From bb4149a9110724f5524cb74d04096a90bac0d664 Mon Sep 17 00:00:00 2001 From: Roberto Gandolfo Hashioka Date: Wed, 11 Nov 2015 19:56:21 -0800 Subject: [PATCH 31/32] Fix Unmarshalling for Push Events --- packet.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/packet.go b/packet.go index 055186e..b2692cd 100644 --- a/packet.go +++ b/packet.go @@ -139,6 +139,80 @@ type RepoType struct { Organization string `json:"organization"` } +// RepoType represents the structure of a repository as used in push events. +type RepoPushType struct { + ID int `json:"id"` + Name string `json:"name"` + FullName string `json:"full_name"` + Owner SenderType `json:"owner"` + Private bool `json:"private"` + HTMLURL string `json:"html_url"` + Description string `json:"description"` + Fork bool `json:"fork"` + URL string `json:"url"` + ForksURL string `json:"forks_url"` + KeysURL string `json:"keys_url"` + CollaboratorsURL string `json:"collaborators_url"` + TeamsURL string `json:"teams_url"` + HooksURL string `json:"hooks_url"` + IssueEventsURL string `json:"issue_events_url"` + EventsURL string `json:"events_url"` + AssigneesURL string `json:"assignees_url"` + BranchesURL string `json:"branches_url"` + TagsURL string `json:"tags_url"` + BlobsURL string `json:"blobs_url"` + GitTagsURL string `json:"git_tags_url"` + GitRefsURL string `json:"git_refs_url"` + TreesURL string `json:"trees_url"` + StatusesURL string `json:"statuses_url"` + LanguagesURL string `json:"languages_url"` + StargazersURL string `json:"stargazers_url"` + ContributorsURL string `json:"contributors_url"` + SubscribersURL string `json:"subscribers_url"` + SubscriptionURL string `json:"subscription_url"` + CommitsURL string `json:"commits_url"` + GitCommitsURL string `json:"git_commits_url"` + CommentsURL string `json:"comments_url"` + IssueCommentURL string `json:"issue_comment_url"` + ContentsURL string `json:"contents_url"` + CompareURL string `json:"compare_url"` + MergesURL string `json:"mergers_url"` + ArchiveURL string `json:"archive_url"` + DownloadsURL string `json:"downloads_url"` + IssuesURL string `json:"issues_url"` + PullsURL string `json:"pulls_url"` + MilestonesURL string `json:"milestones_url"` + NotificationsURL string `json:"notifications_url"` + LabelsURL string `json:"labels_url"` + ReleasesURL string `json:"releases_url"` + CreatedAt int64 `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + PushedAt int64 `json:"pushed_at"` + GitURL string `json:"git_url"` + SSHURL string `json:"ssh_url"` + CloneURL string `json:"clone_url"` + SvnURL string `json:"svn_url"` + Homepage string `json:"homepage"` + Size int `json:"size"` + StargazersCount int `json:"stargazers_count"` + WatchersCount int `json:"watchers_count"` + Language string `json:"language"` + HasIssues bool `json:"has_issues"` + HasDownloads bool `json:"has_downloads"` + HasWiki bool `json:"has_wiki"` + HasPages bool `json:"has_pages"` + ForksCount int `json:"forks_count"` + MirrorURL string `json:"mirror_url"` + OpenIssuesCount int `json:"open_issues_count"` + Forks int `json:"forks"` + OpenIssues int `json:"open_issues"` + Watchers int `json:"watchers"` + DefaultBranch string `json:"default_branch"` + Stargazers int `json:"stargazers"` + MasterBranch string `json:"master_branch"` + Organization string `json:"organization"` +} + // PushEvent represents the basic, top-level structure of a push event. type PushEvent struct { Ref string `json:"ref"` @@ -151,7 +225,7 @@ type PushEvent struct { Compare string `json:"compare"` Commits []CommitType `json:"commits"` HeadCommit CommitType `json:"head_commit"` - Repository RepoType `json:"repository"` + Repository RepoPushType `json:"repository"` Pusher PusherType `json:"pusher"` Organization OrgType `json:"organization"` Sender SenderType `json:"sender"` From f316f94bc7a27fd2286353e3bf4382ea15d333d5 Mon Sep 17 00:00:00 2001 From: Roberto Gandolfo Hashioka Date: Fri, 13 Nov 2015 19:25:51 -0800 Subject: [PATCH 32/32] Replaced string with json.Number to avoid unmarshal convertion errors --- packet.go | 933 +++++++++++++++++++++++++++--------------------------- 1 file changed, 467 insertions(+), 466 deletions(-) diff --git a/packet.go b/packet.go index b2692cd..7cc5865 100644 --- a/packet.go +++ b/packet.go @@ -2,227 +2,228 @@ package gohook import ( "time" + "json" ) // SenderType represents the structure of the sender field in push/ping events. type SenderType struct { - Login string `json:"login"` - ID int `json:"id"` - AvatarURL string `json:"avatar_url"` - GravatarID string `json:"gravatar_id"` - URL string `json:"url"` - HTMLURL string `json:"html_url"` - FollowersURL string `json:"followers_url"` - FollowingURL string `json:"following_url"` - GistsURL string `json:"gists_url"` - StarredURL string `json:"starred_url"` - SubscriptionsURL string `json:"subscriptions_url"` - OrganizationsURL string `json:"organizations_url"` - ReposURL string `json:"repos_url"` - EventsURL string `json:"events_url"` - ReceivedEventsURL string `json:"received_events_url"` - Type string `json:"type"` - SiteAdmin bool `json:"site_admin"` + Login json.Number `json:"login"` + ID int `json:"id"` + AvatarURL json.Number `json:"avatar_url"` + GravatarID json.Number `json:"gravatar_id"` + URL json.Number `json:"url"` + HTMLURL json.Number `json:"html_url"` + FollowersURL json.Number `json:"followers_url"` + FollowingURL json.Number `json:"following_url"` + GistsURL json.Number `json:"gists_url"` + StarredURL json.Number `json:"starred_url"` + SubscriptionsURL json.Number `json:"subscriptions_url"` + OrganizationsURL json.Number `json:"organizations_url"` + ReposURL json.Number `json:"repos_url"` + EventsURL json.Number `json:"events_url"` + ReceivedEventsURL json.Number `json:"received_events_url"` + Type json.Number `json:"type"` + SiteAdmin bool `json:"site_admin"` } // UserType represents the structure of a user as used in commits. type UserType struct { - Name string `json:"name"` - Email string `json:"email"` - Username string `json:"username"` + Name json.Number `json:"name"` + Email json.Number `json:"email"` + Username json.Number `json:"username"` } // PusherType represents the structure of a user as used in PushEvents. type PusherType struct { - Name string `json:"name"` - Email string `json:"email"` + Name json.Number `json:"name"` + Email json.Number `json:"email"` } // OrgType represents the structure of an organization as used in ping/push events. type OrgType struct { - Login string `json:"login"` - ID int `json:"id"` - URL string `json:"url"` - ReposURL string `json:"repos_url"` - EventsURL string `json:"events_url"` - MembersURL string `json:"members_url"` - PublicMembersURL string `json:"public_members_url"` - AvatarURL string `json:"avatar_url"` - Description string `json:"description"` + Login json.Number `json:"login"` + ID int `json:"id"` + URL json.Number `json:"url"` + ReposURL json.Number `json:"repos_url"` + EventsURL json.Number `json:"events_url"` + MembersURL json.Number `json:"members_url"` + PublicMembersURL json.Number `json:"public_members_url"` + AvatarURL json.Number `json:"avatar_url"` + Description json.Number `json:"description"` } // CommitType represents the structure of a commit as used in push events. type CommitType struct { - ID string `json:"id"` - Distinct bool `json:"distinct"` - Message string `json:"message"` - Timestamp string `json:"timestamp"` - URL string `json:"url"` - Author UserType `json:"author"` - Committer UserType `json:"committer"` - Added []string `json:"added"` - Removed []string `json:"removed"` - Modified []string `json:"modified"` + ID json.Number `json:"id"` + Distinct bool `json:"distinct"` + Message json.Number `json:"message"` + Timestamp json.Number `json:"timestamp"` + URL json.Number `json:"url"` + Author UserType `json:"author"` + Committer UserType `json:"committer"` + Added []string `json:"added"` + Removed []string `json:"removed"` + Modified []string `json:"modified"` } // RepoType represents the structure of a repository as used in push events. type RepoType struct { - ID int `json:"id"` - Name string `json:"name"` - FullName string `json:"full_name"` - Owner SenderType `json:"owner"` - Private bool `json:"private"` - HTMLURL string `json:"html_url"` - Description string `json:"description"` - Fork bool `json:"fork"` - URL string `json:"url"` - ForksURL string `json:"forks_url"` - KeysURL string `json:"keys_url"` - CollaboratorsURL string `json:"collaborators_url"` - TeamsURL string `json:"teams_url"` - HooksURL string `json:"hooks_url"` - IssueEventsURL string `json:"issue_events_url"` - EventsURL string `json:"events_url"` - AssigneesURL string `json:"assignees_url"` - BranchesURL string `json:"branches_url"` - TagsURL string `json:"tags_url"` - BlobsURL string `json:"blobs_url"` - GitTagsURL string `json:"git_tags_url"` - GitRefsURL string `json:"git_refs_url"` - TreesURL string `json:"trees_url"` - StatusesURL string `json:"statuses_url"` - LanguagesURL string `json:"languages_url"` - StargazersURL string `json:"stargazers_url"` - ContributorsURL string `json:"contributors_url"` - SubscribersURL string `json:"subscribers_url"` - SubscriptionURL string `json:"subscription_url"` - CommitsURL string `json:"commits_url"` - GitCommitsURL string `json:"git_commits_url"` - CommentsURL string `json:"comments_url"` - IssueCommentURL string `json:"issue_comment_url"` - ContentsURL string `json:"contents_url"` - CompareURL string `json:"compare_url"` - MergesURL string `json:"mergers_url"` - ArchiveURL string `json:"archive_url"` - DownloadsURL string `json:"downloads_url"` - IssuesURL string `json:"issues_url"` - PullsURL string `json:"pulls_url"` - MilestonesURL string `json:"milestones_url"` - NotificationsURL string `json:"notifications_url"` - LabelsURL string `json:"labels_url"` - ReleasesURL string `json:"releases_url"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - PushedAt time.Time `json:"pushed_at"` - GitURL string `json:"git_url"` - SSHURL string `json:"ssh_url"` - CloneURL string `json:"clone_url"` - SvnURL string `json:"svn_url"` - Homepage string `json:"homepage"` - Size int `json:"size"` - StargazersCount int `json:"stargazers_count"` - WatchersCount int `json:"watchers_count"` - Language string `json:"language"` - HasIssues bool `json:"has_issues"` - HasDownloads bool `json:"has_downloads"` - HasWiki bool `json:"has_wiki"` - HasPages bool `json:"has_pages"` - ForksCount int `json:"forks_count"` - MirrorURL string `json:"mirror_url"` - OpenIssuesCount int `json:"open_issues_count"` - Forks int `json:"forks"` - OpenIssues int `json:"open_issues"` - Watchers int `json:"watchers"` - DefaultBranch string `json:"default_branch"` - Stargazers int `json:"stargazers"` - MasterBranch string `json:"master_branch"` - Organization string `json:"organization"` + ID int `json:"id"` + Name json.Number `json:"name"` + FullName json.Number `json:"full_name"` + Owner SenderType `json:"owner"` + Private bool `json:"private"` + HTMLURL json.Number `json:"html_url"` + Description json.Number `json:"description"` + Fork bool `json:"fork"` + URL json.Number `json:"url"` + ForksURL json.Number `json:"forks_url"` + KeysURL json.Number `json:"keys_url"` + CollaboratorsURL json.Number `json:"collaborators_url"` + TeamsURL json.Number `json:"teams_url"` + HooksURL json.Number `json:"hooks_url"` + IssueEventsURL json.Number `json:"issue_events_url"` + EventsURL json.Number `json:"events_url"` + AssigneesURL json.Number `json:"assignees_url"` + BranchesURL json.Number `json:"branches_url"` + TagsURL json.Number `json:"tags_url"` + BlobsURL json.Number `json:"blobs_url"` + GitTagsURL json.Number `json:"git_tags_url"` + GitRefsURL json.Number `json:"git_refs_url"` + TreesURL json.Number `json:"trees_url"` + StatusesURL json.Number `json:"statuses_url"` + LanguagesURL json.Number `json:"languages_url"` + StargazersURL json.Number `json:"stargazers_url"` + ContributorsURL json.Number `json:"contributors_url"` + SubscribersURL json.Number `json:"subscribers_url"` + SubscriptionURL json.Number `json:"subscription_url"` + CommitsURL json.Number `json:"commits_url"` + GitCommitsURL json.Number `json:"git_commits_url"` + CommentsURL json.Number `json:"comments_url"` + IssueCommentURL json.Number `json:"issue_comment_url"` + ContentsURL json.Number `json:"contents_url"` + CompareURL json.Number `json:"compare_url"` + MergesURL json.Number `json:"mergers_url"` + ArchiveURL json.Number `json:"archive_url"` + DownloadsURL json.Number `json:"downloads_url"` + IssuesURL json.Number `json:"issues_url"` + PullsURL json.Number `json:"pulls_url"` + MilestonesURL json.Number `json:"milestones_url"` + NotificationsURL json.Number `json:"notifications_url"` + LabelsURL json.Number `json:"labels_url"` + ReleasesURL json.Number `json:"releases_url"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + PushedAt time.Time `json:"pushed_at"` + GitURL json.Number `json:"git_url"` + SSHURL json.Number `json:"ssh_url"` + CloneURL json.Number `json:"clone_url"` + SvnURL json.Number `json:"svn_url"` + Homepage json.Number `json:"homepage"` + Size int `json:"size"` + StargazersCount int `json:"stargazers_count"` + WatchersCount int `json:"watchers_count"` + Language json.Number `json:"language"` + HasIssues bool `json:"has_issues"` + HasDownloads bool `json:"has_downloads"` + HasWiki bool `json:"has_wiki"` + HasPages bool `json:"has_pages"` + ForksCount int `json:"forks_count"` + MirrorURL json.Number `json:"mirror_url"` + OpenIssuesCount int `json:"open_issues_count"` + Forks int `json:"forks"` + OpenIssues int `json:"open_issues"` + Watchers int `json:"watchers"` + DefaultBranch json.Number `json:"default_branch"` + Stargazers int `json:"stargazers"` + MasterBranch json.Number `json:"master_branch"` + Organization json.Number `json:"organization"` } // RepoType represents the structure of a repository as used in push events. type RepoPushType struct { - ID int `json:"id"` - Name string `json:"name"` - FullName string `json:"full_name"` - Owner SenderType `json:"owner"` - Private bool `json:"private"` - HTMLURL string `json:"html_url"` - Description string `json:"description"` - Fork bool `json:"fork"` - URL string `json:"url"` - ForksURL string `json:"forks_url"` - KeysURL string `json:"keys_url"` - CollaboratorsURL string `json:"collaborators_url"` - TeamsURL string `json:"teams_url"` - HooksURL string `json:"hooks_url"` - IssueEventsURL string `json:"issue_events_url"` - EventsURL string `json:"events_url"` - AssigneesURL string `json:"assignees_url"` - BranchesURL string `json:"branches_url"` - TagsURL string `json:"tags_url"` - BlobsURL string `json:"blobs_url"` - GitTagsURL string `json:"git_tags_url"` - GitRefsURL string `json:"git_refs_url"` - TreesURL string `json:"trees_url"` - StatusesURL string `json:"statuses_url"` - LanguagesURL string `json:"languages_url"` - StargazersURL string `json:"stargazers_url"` - ContributorsURL string `json:"contributors_url"` - SubscribersURL string `json:"subscribers_url"` - SubscriptionURL string `json:"subscription_url"` - CommitsURL string `json:"commits_url"` - GitCommitsURL string `json:"git_commits_url"` - CommentsURL string `json:"comments_url"` - IssueCommentURL string `json:"issue_comment_url"` - ContentsURL string `json:"contents_url"` - CompareURL string `json:"compare_url"` - MergesURL string `json:"mergers_url"` - ArchiveURL string `json:"archive_url"` - DownloadsURL string `json:"downloads_url"` - IssuesURL string `json:"issues_url"` - PullsURL string `json:"pulls_url"` - MilestonesURL string `json:"milestones_url"` - NotificationsURL string `json:"notifications_url"` - LabelsURL string `json:"labels_url"` - ReleasesURL string `json:"releases_url"` - CreatedAt int64 `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - PushedAt int64 `json:"pushed_at"` - GitURL string `json:"git_url"` - SSHURL string `json:"ssh_url"` - CloneURL string `json:"clone_url"` - SvnURL string `json:"svn_url"` - Homepage string `json:"homepage"` - Size int `json:"size"` - StargazersCount int `json:"stargazers_count"` - WatchersCount int `json:"watchers_count"` - Language string `json:"language"` - HasIssues bool `json:"has_issues"` - HasDownloads bool `json:"has_downloads"` - HasWiki bool `json:"has_wiki"` - HasPages bool `json:"has_pages"` - ForksCount int `json:"forks_count"` - MirrorURL string `json:"mirror_url"` - OpenIssuesCount int `json:"open_issues_count"` - Forks int `json:"forks"` - OpenIssues int `json:"open_issues"` - Watchers int `json:"watchers"` - DefaultBranch string `json:"default_branch"` - Stargazers int `json:"stargazers"` - MasterBranch string `json:"master_branch"` - Organization string `json:"organization"` + ID int `json:"id"` + Name json.Number `json:"name"` + FullName json.Number `json:"full_name"` + Owner SenderType `json:"owner"` + Private bool `json:"private"` + HTMLURL json.Number `json:"html_url"` + Description json.Number `json:"description"` + Fork bool `json:"fork"` + URL json.Number `json:"url"` + ForksURL json.Number `json:"forks_url"` + KeysURL json.Number `json:"keys_url"` + CollaboratorsURL json.Number `json:"collaborators_url"` + TeamsURL json.Number `json:"teams_url"` + HooksURL json.Number `json:"hooks_url"` + IssueEventsURL json.Number `json:"issue_events_url"` + EventsURL json.Number `json:"events_url"` + AssigneesURL json.Number `json:"assignees_url"` + BranchesURL json.Number `json:"branches_url"` + TagsURL json.Number `json:"tags_url"` + BlobsURL json.Number `json:"blobs_url"` + GitTagsURL json.Number `json:"git_tags_url"` + GitRefsURL json.Number `json:"git_refs_url"` + TreesURL json.Number `json:"trees_url"` + StatusesURL json.Number `json:"statuses_url"` + LanguagesURL json.Number `json:"languages_url"` + StargazersURL json.Number `json:"stargazers_url"` + ContributorsURL json.Number `json:"contributors_url"` + SubscribersURL json.Number `json:"subscribers_url"` + SubscriptionURL json.Number `json:"subscription_url"` + CommitsURL json.Number `json:"commits_url"` + GitCommitsURL json.Number `json:"git_commits_url"` + CommentsURL json.Number `json:"comments_url"` + IssueCommentURL json.Number `json:"issue_comment_url"` + ContentsURL json.Number `json:"contents_url"` + CompareURL json.Number `json:"compare_url"` + MergesURL json.Number `json:"mergers_url"` + ArchiveURL json.Number `json:"archive_url"` + DownloadsURL json.Number `json:"downloads_url"` + IssuesURL json.Number `json:"issues_url"` + PullsURL json.Number `json:"pulls_url"` + MilestonesURL json.Number `json:"milestones_url"` + NotificationsURL json.Number `json:"notifications_url"` + LabelsURL json.Number `json:"labels_url"` + ReleasesURL json.Number `json:"releases_url"` + CreatedAt int64 `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + PushedAt int64 `json:"pushed_at"` + GitURL json.Number `json:"git_url"` + SSHURL json.Number `json:"ssh_url"` + CloneURL json.Number `json:"clone_url"` + SvnURL json.Number `json:"svn_url"` + Homepage json.Number `json:"homepage"` + Size int `json:"size"` + StargazersCount int `json:"stargazers_count"` + WatchersCount int `json:"watchers_count"` + Language json.Number `json:"language"` + HasIssues bool `json:"has_issues"` + HasDownloads bool `json:"has_downloads"` + HasWiki bool `json:"has_wiki"` + HasPages bool `json:"has_pages"` + ForksCount int `json:"forks_count"` + MirrorURL json.Number `json:"mirror_url"` + OpenIssuesCount int `json:"open_issues_count"` + Forks int `json:"forks"` + OpenIssues int `json:"open_issues"` + Watchers int `json:"watchers"` + DefaultBranch json.Number `json:"default_branch"` + Stargazers int `json:"stargazers"` + MasterBranch json.Number `json:"master_branch"` + Organization json.Number `json:"organization"` } // PushEvent represents the basic, top-level structure of a push event. type PushEvent struct { - Ref string `json:"ref"` - Before string `json:"before"` - After string `json:"after"` - Created bool `json:"created"` - Deleted bool `json:"deleted"` - Forced bool `json:"forced"` - BaseRef string `json:"base_ref"` - Compare string `json:"compare"` + Ref json.Number `json:"ref"` + Before json.Number `json:"before"` + After json.Number `json:"after"` + Created bool `json:"created"` + Deleted bool `json:"deleted"` + Forced bool `json:"forced"` + BaseRef json.Number `json:"base_ref"` + Compare json.Number `json:"compare"` Commits []CommitType `json:"commits"` HeadCommit CommitType `json:"head_commit"` Repository RepoPushType `json:"repository"` @@ -232,44 +233,44 @@ type PushEvent struct { } type ConfigType struct { - URL string `json:"url"` - ContentType string `json:"content_type"` + URL json.Number `json:"url"` + ContentType json.Number `json:"content_type"` } type HookType struct { - ID int `json:"id"` - URL string `json:"url"` - TestURL string `json:"test_url"` - PingURL string `json:"ping_url"` - Name string `json:"name"` - Events []string `json:"events"` - Active bool `json:"active"` - Config ConfigType `json:"config"` - UpdatedAt time.Time `json:"updated_at"` - CreatedAt time.Time `json:"created_at"` + ID int `json:"id"` + URL json.Number `json:"url"` + TestURL json.Number `json:"test_url"` + PingURL json.Number `json:"ping_url"` + Name json.Number `json:"name"` + Events []string `json:"events"` + Active bool `json:"active"` + Config ConfigType `json:"config"` + UpdatedAt time.Time `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` } // PingEvent represents the basic, top-level structure of a ping event. type PingEvent struct { - Zen string `json:"zen"` - HookID int `json:"hook_id"` - Hook HookType `json:"hook"` - Organization OrgType `json:"organization"` - Sender SenderType `json:"sender"` + Zen json.Number `json:"zen"` + HookID int `json:"hook_id"` + Hook HookType `json:"hook"` + Organization OrgType `json:"organization"` + Sender SenderType `json:"sender"` } type CommentType struct { - URL string `json:"url"` - HTMLURL string `json:"html_url"` - ID int `json:"id"` - User SenderType `json:"user"` - Position string `json:"position"` - Line string `json:"line"` - Path string `json:"path"` - CommitID string `json:"commit_id"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - Body string `json:"body"` + URL json.Number `json:"url"` + HTMLURL json.Number `json:"html_url"` + ID int `json:"id"` + User SenderType `json:"user"` + Position json.Number `json:"position"` + Line json.Number `json:"line"` + Path json.Number `json:"path"` + CommitID json.Number `json:"commit_id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Body json.Number `json:"body"` } type CommitCommentEvent struct { @@ -279,159 +280,159 @@ type CommitCommentEvent struct { } type IssueCommentType struct { - ID int `json:"id"` - URL string `json:"url"` - HTMLURL string `json:"html_url"` - Body string `json:"body"` - User SenderType `json:"user"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"created_at"` + ID int `json:"id"` + URL json.Number `json:"url"` + HTMLURL json.Number `json:"html_url"` + Body json.Number `json:"body"` + User SenderType `json:"user"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"created_at"` } type LabelType struct { - URL string `json:"url"` - Name string `json:"name"` - Color string `json:"color"` + URL json.Number `json:"url"` + Name json.Number `json:"name"` + Color json.Number `json:"color"` } type MilestoneType struct { - URL string `json:"url"` - HTMLURL string `json:"html_url"` - LabelsURL string `json:"labels_url"` - ID int `json:"id"` - Number int `json:"number"` - State string `json:"state"` - Title string `json:"title"` - Description string `json:"description"` - Creator SenderType `json:"creator"` - OpenIssues int `json:"open_issues"` - ClosedIssues int `json:"closed_issues"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - ClosedAt *time.Time `json:"closed_at"` - DueOn string `json:"due_on"` + URL json.Number `json:"url"` + HTMLURL json.Number `json:"html_url"` + LabelsURL json.Number `json:"labels_url"` + ID int `json:"id"` + Number int `json:"number"` + State json.Number `json:"state"` + Title json.Number `json:"title"` + Description json.Number `json:"description"` + Creator SenderType `json:"creator"` + OpenIssues int `json:"open_issues"` + ClosedIssues int `json:"closed_issues"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + ClosedAt *time.Time `json:"closed_at"` + DueOn json.Number `json:"due_on"` } type ShortPullRequestType struct { - URL string `json:"url"` - HTMLURL string `json:"html_url"` - DiffURL string `json:"diff_url"` - PatchURL string `json:"patch_url"` + URL json.Number `json:"url"` + HTMLURL json.Number `json:"html_url"` + DiffURL json.Number `json:"diff_url"` + PatchURL json.Number `json:"patch_url"` } type IssueType struct { - ID int `json:"id"` - URL string `json:"url"` - HTMLURL string `json:"html_url"` - Number int `json:"number"` - State string `json:"state"` - Title string `json:"title"` - Body string `json:"body"` - User SenderType `json:"user"` - Labels []LabelType `json:"labels"` - Assignee SenderType `json:"assignee"` - Milestone MilestoneType `json:"milestone"` - Comments int `json:"comments"` - PullRequest ShortPullRequestType `json:"pull_request"` - ClosedAt *time.Time `json:"closed_at"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + ID int `json:"id"` + URL json.Number `json:"url"` + HTMLURL json.Number `json:"html_url"` + Number int `json:"number"` + State json.Number `json:"state"` + Title json.Number `json:"title"` + Body json.Number `json:"body"` + User SenderType `json:"user"` + Labels []LabelType `json:"labels"` + Assignee SenderType `json:"assignee"` + Milestone MilestoneType `json:"milestone"` + Comments int `json:"comments"` + PullRequest ShortPullRequestType `json:"pull_request"` + ClosedAt *time.Time `json:"closed_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } type IssueCommentEvent struct { - Action string `json:"action"` - Issue IssueType `json:"issue"` - Comment IssueCommentType `json:"comment"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + Action json.Number `json:"action"` + Issue IssueType `json:"issue"` + Comment IssueCommentType `json:"comment"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type IssuesEvent struct { - Action string `json:"action"` - Issue IssueType `json:"issue"` - Assignee SenderType `json:"assignee"` - Label LabelType `json:"label"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + Action json.Number `json:"action"` + Issue IssueType `json:"issue"` + Assignee SenderType `json:"assignee"` + Label LabelType `json:"label"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type CreateEvent struct { - RefType string `json:"ref_type"` - Ref string `json:"ref"` - MasterBranch string `json:"master_branch"` - Description string `json:"description"` - PusherType string `json:"pusher_type"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + RefType json.Number `json:"ref_type"` + Ref json.Number `json:"ref"` + MasterBranch json.Number `json:"master_branch"` + Description json.Number `json:"description"` + PusherType json.Number `json:"pusher_type"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type DeleteEvent struct { - RefType string `json:"ref_type"` - Ref string `json:"ref"` - PusherType string `json:"pusher_type"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + RefType json.Number `json:"ref_type"` + Ref json.Number `json:"ref"` + PusherType json.Number `json:"pusher_type"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type RepositoryEvent struct { - Action string `json:"action"` - Repository RepoType `json:"repository"` - Organization OrgType `json:"organization"` - Sender SenderType `json:"sender"` + Action json.Number `json:"action"` + Repository RepoType `json:"repository"` + Organization OrgType `json:"organization"` + Sender SenderType `json:"sender"` } type DeploymentType struct { - URL string `json:"url"` - ID int `json:"id"` - SHA string `json:"sha"` - Ref string `json:"ref"` - Task string `json:"task"` - Payload map[string]string `json:"payload"` - Environment string `json:"environment"` - Description string `json:"description"` - Creator SenderType `json:"creator"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - StatusesURL string `json:"statuses_url"` - RepositoryURL string `json:"repository_url"` + URL json.Number `json:"url"` + ID int `json:"id"` + SHA json.Number `json:"sha"` + Ref json.Number `json:"ref"` + Task json.Number `json:"task"` + Payload map[string]string `json:"payload"` + Environment json.Number `json:"environment"` + Description json.Number `json:"description"` + Creator SenderType `json:"creator"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + StatusesURL json.Number `json:"statuses_url"` + RepositoryURL json.Number `json:"repository_url"` } type DeploymentEvent struct { - Deployment DeploymentType `json:"deployment"` - ID int `json:"id"` - SHA string `json:"sha"` - Ref string `json:"ref"` - Task string `json:"task"` - Name string `json:"name"` - Environment string `json:"environment"` - Payload map[string]string `json:"payload"` - Description string `json:"description"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + Deployment DeploymentType `json:"deployment"` + ID int `json:"id"` + SHA json.Number `json:"sha"` + Ref json.Number `json:"ref"` + Task json.Number `json:"task"` + Name json.Number `json:"name"` + Environment json.Number `json:"environment"` + Payload map[string]string `json:"payload"` + Description json.Number `json:"description"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type DeploymentStatusType struct { - URL string `json:"url"` - ID int `json:"id"` - State string `json:"state"` - Creator SenderType `json:"creator"` - Description string `json:"description"` - TargetURL string `json:"target_url"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - DeploymentURL string `json:"deployment_url"` - RepositoryURL string `json:"repository_url"` + URL json.Number `json:"url"` + ID int `json:"id"` + State json.Number `json:"state"` + Creator SenderType `json:"creator"` + Description json.Number `json:"description"` + TargetURL json.Number `json:"target_url"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeploymentURL json.Number `json:"deployment_url"` + RepositoryURL json.Number `json:"repository_url"` } type DeploymentStatusEvent struct { - Deployment DeploymentType `json:"deployment"` - DeploymentStatus DeploymentStatusType `json:"deployment_status"` - ID int `json:"id"` - State string `json:"state"` - TargetURL string `json:"target_url"` - Description string `json:"description"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + Deployment DeploymentType `json:"deployment"` + DeploymentStatus DeploymentStatusType `json:"deployment_status"` + ID int `json:"id"` + State json.Number `json:"state"` + TargetURL json.Number `json:"target_url"` + Description json.Number `json:"description"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type ForkEvent struct { @@ -441,12 +442,12 @@ type ForkEvent struct { } type PageType struct { - PageName string `json:"page_name"` - Title string `json:"title"` - Summary string `json:"summary"` - Action string `json:"action"` - SHA string `json:"sha"` - HTMLURL string `json:"html_url"` + PageName json.Number `json:"page_name"` + Title json.Number `json:"title"` + Summary json.Number `json:"summary"` + Action json.Number `json:"action"` + SHA json.Number `json:"sha"` + HTMLURL json.Number `json:"html_url"` } type GollumEvent struct { @@ -456,44 +457,44 @@ type GollumEvent struct { } type MemberEvent struct { - Action string `json:"action"` - Member SenderType `json:"member"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + Action json.Number `json:"action"` + Member SenderType `json:"member"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type TeamType struct { - Name string `json:"name"` - ID int `json:"id"` - Slug string `json:"slug"` - Permission string `json:"permission"` - URL string `json:"url"` - MembersURL string `json:"members_url"` - RepositoriesURL string `json:"repositories_url"` + Name json.Number `json:"name"` + ID int `json:"id"` + Slug json.Number `json:"slug"` + Permission json.Number `json:"permission"` + URL json.Number `json:"url"` + MembersURL json.Number `json:"members_url"` + RepositoriesURL json.Number `json:"repositories_url"` } type MembershipEvent struct { - Action string `json:"action"` - Scope string `json:"scope"` - Member SenderType `json:"member"` - Team TeamType `json:"team"` - Sender SenderType `json:"sender"` - Organization OrgType `json:"organization"` + Action json.Number `json:"action"` + Scope json.Number `json:"scope"` + Member SenderType `json:"member"` + Team TeamType `json:"team"` + Sender SenderType `json:"sender"` + Organization OrgType `json:"organization"` } type ErrorType struct { - Message string `json:"message"` + Message json.Number `json:"message"` } type BuildType struct { - URL string `json:"url"` - Status string `json:"status"` - Error ErrorType `json:"error"` - Pusher SenderType `json:"pusher"` - Commit string `json:"commit"` - Duration int `json:"duration"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + URL json.Number `json:"url"` + Status json.Number `json:"status"` + Error ErrorType `json:"error"` + Pusher SenderType `json:"pusher"` + Commit json.Number `json:"commit"` + Duration int `json:"duration"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } type PageBuildEvent struct { @@ -509,81 +510,81 @@ type PublicEvent struct { } type BaseHeadType struct { - Label string `json:"label"` - Ref string `json:"ref"` - SHA string `json:"sha"` - User SenderType `json:"user"` - Repo RepoType `json:"repo"` + Label json.Number `json:"label"` + Ref json.Number `json:"ref"` + SHA json.Number `json:"sha"` + User SenderType `json:"user"` + Repo RepoType `json:"repo"` } type Link struct { - HREF string `json:"href"` + HREF json.Number `json:"href"` } type PullRequestType struct { - ID int `json:"id"` - URL string `json:"url"` - HTMLURL string `json:"html_url"` - DiffURL string `json:"diff_url"` - PatchURL string `json:"patch_url"` - IssueURL string `json:"issue_url"` - CommitsURL string `json:"commits_url"` - ReviewCommentsURL string `json:"review_comments_url"` - ReviewCommentURL string `json:"review_comment_url"` - CommentsURL string `json:"comments_url"` - StatusesURL string `json:"statuses_url"` - Number int `json:"number"` - State string `json:"state"` - Title string `json:"title"` - Body string `json:"body"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - ClosedAt *time.Time `json:"closed_at"` - MergedAt *time.Time `json:"merged_at"` - Head BaseHeadType `json:"head"` - Repo RepoType `json:"repo"` - Base BaseHeadType `json:"Base"` - Links map[string]Link `json:"_links"` - User SenderType `json:"User"` - MergeCommitSHA string `json:"merge_commit_sha"` - Merged bool `json:"merged"` - Mergeable bool `json:"mergeable"` - MergedBy SenderType `json:"merged_by"` - Comments int `json:"comments"` - Commits int `json:"commits"` - Additions int `json:"additions"` - Deletions int `json:"deletions"` - ChangedFiles int `json:"changed_files"` + ID int `json:"id"` + URL json.Number `json:"url"` + HTMLURL json.Number `json:"html_url"` + DiffURL json.Number `json:"diff_url"` + PatchURL json.Number `json:"patch_url"` + IssueURL json.Number `json:"issue_url"` + CommitsURL json.Number `json:"commits_url"` + ReviewCommentsURL json.Number `json:"review_comments_url"` + ReviewCommentURL json.Number `json:"review_comment_url"` + CommentsURL json.Number `json:"comments_url"` + StatusesURL json.Number `json:"statuses_url"` + Number int `json:"number"` + State json.Number `json:"state"` + Title json.Number `json:"title"` + Body json.Number `json:"body"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + ClosedAt *time.Time `json:"closed_at"` + MergedAt *time.Time `json:"merged_at"` + Head BaseHeadType `json:"head"` + Repo RepoType `json:"repo"` + Base BaseHeadType `json:"Base"` + Links map[string]Link `json:"_links"` + User SenderType `json:"User"` + MergeCommitSHA json.Number `json:"merge_commit_sha"` + Merged bool `json:"merged"` + Mergeable bool `json:"mergeable"` + MergedBy SenderType `json:"merged_by"` + Comments int `json:"comments"` + Commits int `json:"commits"` + Additions int `json:"additions"` + Deletions int `json:"deletions"` + ChangedFiles int `json:"changed_files"` } type PullRequestEvent struct { - Action string `json:"action"` - Number int `json:"number"` - PullRequest PullRequestType `json:"pull_request"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` + Action json.Number `json:"action"` + Number int `json:"number"` + PullRequest PullRequestType `json:"pull_request"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` } type PullRequestReviewCommentType struct { - URL string `json:"url"` - ID int `json:"id"` - DiffHunk string `json:"diff_hunk"` - Path string `json:"path"` - Position int `json:"position"` - OriginalPosition int `json:"original_position"` - CommitID string `json:"commit_id"` - OriginalCommitID string `json:"original_commit_id"` - User SenderType `json:"user"` - Body string `json:"body"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - HTMLURL string `json:"html_url"` - PullRequestURL string `json:"pull_request_url"` - Links map[string]Link `json:"_links"` + URL json.Number `json:"url"` + ID int `json:"id"` + DiffHunk json.Number `json:"diff_hunk"` + Path json.Number `json:"path"` + Position int `json:"position"` + OriginalPosition int `json:"original_position"` + CommitID json.Number `json:"commit_id"` + OriginalCommitID json.Number `json:"original_commit_id"` + User SenderType `json:"user"` + Body json.Number `json:"body"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + HTMLURL json.Number `json:"html_url"` + PullRequestURL json.Number `json:"pull_request_url"` + Links map[string]Link `json:"_links"` } type PullRequestReviewCommentEvent struct { - Action string `json:"action"` + Action json.Number `json:"action"` Comment PullRequestReviewCommentType `json:"comment"` PullRequest PullRequestType `json:"pull_request"` Repository RepoType `json:"repository"` @@ -591,65 +592,65 @@ type PullRequestReviewCommentEvent struct { } type AssetType struct { - URL string `json:"url"` - BrowserDownloadURL string `json:"browser_download_url"` - ID int `json:"id"` - Name string `json:"name"` - Label string `json:"label"` - State string `json:"state"` - ContentType string `json:"content_type"` - Size int `json:"size"` - DownloadCount int `json:"download_count"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - Uploader SenderType `json:"uploader"` + URL json.Number `json:"url"` + BrowserDownloadURL json.Number `json:"browser_download_url"` + ID int `json:"id"` + Name json.Number `json:"name"` + Label json.Number `json:"label"` + State json.Number `json:"state"` + ContentType json.Number `json:"content_type"` + Size int `json:"size"` + DownloadCount int `json:"download_count"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Uploader SenderType `json:"uploader"` } type ReleaseType struct { - URL string `json:"url"` - HTMLURL string `json:"html_url"` - AssetsURL string `json:"assets_url"` - UploadURL string `json:"upload_url"` - TarballURL string `json:"tarball_url"` - ZipballURL string `json:"zipball_url"` - ID int `json:"id"` - TagName string `json:"tag_name"` - TargetCommitish string `json:"target_commitish"` - Name string `json:"name"` - Body string `json:"body"` - Draft bool `json:"draft"` - Prerelease bool `json:"prerelease"` - CreatedAt time.Time `json:"created_at"` - PublishedAt time.Time `json:"published_at"` - Author SenderType `json:"author"` - Assets []AssetType `json:"assets"` + URL json.Number `json:"url"` + HTMLURL json.Number `json:"html_url"` + AssetsURL json.Number `json:"assets_url"` + UploadURL json.Number `json:"upload_url"` + TarballURL json.Number `json:"tarball_url"` + ZipballURL json.Number `json:"zipball_url"` + ID int `json:"id"` + TagName json.Number `json:"tag_name"` + TargetCommitish json.Number `json:"target_commitish"` + Name json.Number `json:"name"` + Body json.Number `json:"body"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` + CreatedAt time.Time `json:"created_at"` + PublishedAt time.Time `json:"published_at"` + Author SenderType `json:"author"` + Assets []AssetType `json:"assets"` } type ReleaseEvent struct { - Action string `json:"action"` + Action json.Number `json:"action"` Release ReleaseType `json:"release"` Repository RepoType `json:"repository"` Sender SenderType `json:"sender"` } type ShortCommitType struct { - SHA string `json:"sha"` - URL string `json:"url"` + SHA json.Number `json:"sha"` + URL json.Number `json:"url"` } type BranchType struct { - Name string `json:"master"` + Name json.Number `json:"master"` Commit ShortCommitType `json:"commit"` } type StatusEvent struct { ID int `json:"id"` - SHA string `json:"sha"` - Name string `json:"name"` - TargetURL string `json:"target_url"` - Context string `json:"context"` - Description string `json:"description"` - State string `json:"state"` + SHA json.Number `json:"sha"` + Name json.Number `json:"name"` + TargetURL json.Number `json:"target_url"` + Context json.Number `json:"context"` + Description json.Number `json:"description"` + State json.Number `json:"state"` Commit CommitType `json:"commit"` Branches []BranchType `json:"branches"` CreatedAt time.Time `json:"created_at"` @@ -666,10 +667,10 @@ type TeamAddEvent struct { } type WatchEvent struct { - Action string `json:"action"` - Repository RepoType `json:"repository"` - Sender SenderType `json:"sender"` - Organization OrgType `json:"organization"` + Action json.Number `json:"action"` + Repository RepoType `json:"repository"` + Sender SenderType `json:"sender"` + Organization OrgType `json:"organization"` } // EventType is an alias for string that provides type safety for the event types.