From edf3f876741f0a9641fbf445b49e3f23aa4ed5fb Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Mon, 1 Aug 2016 16:18:40 +0100 Subject: [PATCH 1/4] Move database/types.go to types/types.go in its own 'types' package There is nothing specific to the types to warrant them being under the database package. --- src/github.com/matrix-org/go-neb/api.go | 13 +++++++------ .../matrix-org/go-neb/clients/clients.go | 9 +++++---- src/github.com/matrix-org/go-neb/database/db.go | 11 ++++++----- .../matrix-org/go-neb/database/schema.go | 15 ++++++++------- .../matrix-org/go-neb/services/echo/echo.go | 4 ++-- .../matrix-org/go-neb/services/github/github.go | 4 ++-- .../go-neb/{database => types}/types.go | 4 +++- 7 files changed, 33 insertions(+), 27 deletions(-) rename src/github.com/matrix-org/go-neb/{database => types}/types.go (95%) diff --git a/src/github.com/matrix-org/go-neb/api.go b/src/github.com/matrix-org/go-neb/api.go index a97ec7b..cfec0dc 100644 --- a/src/github.com/matrix-org/go-neb/api.go +++ b/src/github.com/matrix-org/go-neb/api.go @@ -5,6 +5,7 @@ import ( "github.com/matrix-org/go-neb/clients" "github.com/matrix-org/go-neb/database" "github.com/matrix-org/go-neb/errors" + "github.com/matrix-org/go-neb/types" "net/http" ) @@ -24,7 +25,7 @@ func (s *configureClientHandler) OnIncomingRequest(req *http.Request) (interface return nil, &errors.HTTPError{nil, "Unsupported Method", 405} } - var body database.ClientConfig + var body types.ClientConfig if err := json.NewDecoder(req.Body).Decode(&body); err != nil { return nil, &errors.HTTPError{err, "Error parsing request JSON", 400} } @@ -39,8 +40,8 @@ func (s *configureClientHandler) OnIncomingRequest(req *http.Request) (interface } return &struct { - OldClient database.ClientConfig - NewClient database.ClientConfig + OldClient types.ClientConfig + NewClient types.ClientConfig }{oldClient, body}, nil } @@ -67,7 +68,7 @@ func (s *configureServiceHandler) OnIncomingRequest(req *http.Request) (interfac return nil, &errors.HTTPError{nil, `Must supply a "ID", a "Type" and a "Config"`, 400} } - service := database.CreateService(body.ID, body.Type) + service := types.CreateService(body.ID, body.Type) if service == nil { return nil, &errors.HTTPError{nil, "Unknown service type", 400} } @@ -89,7 +90,7 @@ func (s *configureServiceHandler) OnIncomingRequest(req *http.Request) (interfac return &struct { ID string Type string - OldConfig database.Service - NewConfig database.Service + OldConfig types.Service + NewConfig types.Service }{body.ID, body.Type, oldService, service}, nil } diff --git a/src/github.com/matrix-org/go-neb/clients/clients.go b/src/github.com/matrix-org/go-neb/clients/clients.go index 29345d3..8aab734 100644 --- a/src/github.com/matrix-org/go-neb/clients/clients.go +++ b/src/github.com/matrix-org/go-neb/clients/clients.go @@ -5,6 +5,7 @@ import ( "github.com/matrix-org/go-neb/database" "github.com/matrix-org/go-neb/matrix" "github.com/matrix-org/go-neb/plugin" + "github.com/matrix-org/go-neb/types" "net/url" "sync" ) @@ -37,7 +38,7 @@ func (c *Clients) Client(userID string) (*matrix.Client, error) { } // Update updates the config for a matrix client -func (c *Clients) Update(config database.ClientConfig) (database.ClientConfig, error) { +func (c *Clients) Update(config types.ClientConfig) (types.ClientConfig, error) { _, old, err := c.updateClientInDB(config) return old.config, err } @@ -68,7 +69,7 @@ func (c *Clients) Start() error { } type clientEntry struct { - config database.ClientConfig + config types.ClientConfig client *matrix.Client } @@ -105,7 +106,7 @@ func (c *Clients) loadClientFromDB(userID string) (entry clientEntry, err error) return } -func (c *Clients) updateClientInDB(newConfig database.ClientConfig) (new clientEntry, old clientEntry, err error) { +func (c *Clients) updateClientInDB(newConfig types.ClientConfig) (new clientEntry, old clientEntry, err error) { c.dbMutex.Lock() defer c.dbMutex.Unlock() @@ -136,7 +137,7 @@ func (c *Clients) updateClientInDB(newConfig database.ClientConfig) (new clientE return } -func (c *Clients) newClient(config database.ClientConfig) (*matrix.Client, error) { +func (c *Clients) newClient(config types.ClientConfig) (*matrix.Client, error) { homeserverURL, err := url.Parse(config.HomeserverURL) if err != nil { diff --git a/src/github.com/matrix-org/go-neb/database/db.go b/src/github.com/matrix-org/go-neb/database/db.go index b850820..ece6d23 100644 --- a/src/github.com/matrix-org/go-neb/database/db.go +++ b/src/github.com/matrix-org/go-neb/database/db.go @@ -3,6 +3,7 @@ package database import ( "database/sql" "github.com/matrix-org/go-neb/matrix" + "github.com/matrix-org/go-neb/types" "sort" "time" ) @@ -29,7 +30,7 @@ func Open(databaseType, databaseURL string) (serviceDB *ServiceDB, err error) { // StoreMatrixClientConfig stores the Matrix client config for a bot service. // If a config already exists then it will be updated, otherwise a new config // will be inserted. The previous config is returned. -func (d *ServiceDB) StoreMatrixClientConfig(config ClientConfig) (oldConfig ClientConfig, err error) { +func (d *ServiceDB) StoreMatrixClientConfig(config types.ClientConfig) (oldConfig types.ClientConfig, err error) { err = runTransaction(d.db, func(txn *sql.Tx) error { oldConfig, err = selectMatrixClientConfigTxn(txn, config.UserID) now := time.Now() @@ -56,7 +57,7 @@ func (d *ServiceDB) LoadServiceUserIds() (userIDsToRooms map[string][]string, er // LoadMatrixClientConfig loads a Matrix client config from the database. // Returns sql.ErrNoRows if the client isn't in the database. -func (d *ServiceDB) LoadMatrixClientConfig(userID string) (config ClientConfig, err error) { +func (d *ServiceDB) LoadMatrixClientConfig(userID string) (config types.ClientConfig, err error) { err = runTransaction(d.db, func(txn *sql.Tx) error { config, err = selectMatrixClientConfigTxn(txn, userID) return err @@ -66,7 +67,7 @@ func (d *ServiceDB) LoadMatrixClientConfig(userID string) (config ClientConfig, // LoadService loads a service from the database. // Returns sql.ErrNoRows if the service isn't in the database. -func (d *ServiceDB) LoadService(serviceID string) (service Service, err error) { +func (d *ServiceDB) LoadService(serviceID string) (service types.Service, err error) { err = runTransaction(d.db, func(txn *sql.Tx) error { service, err = selectServiceTxn(txn, serviceID) return err @@ -76,7 +77,7 @@ func (d *ServiceDB) LoadService(serviceID string) (service Service, err error) { // LoadServicesInRoom loads all the bot services configured for a room. // Returns the empty list if there aren't any services configured. -func (d *ServiceDB) LoadServicesInRoom(serviceUserID, roomID string) (services []Service, err error) { +func (d *ServiceDB) LoadServicesInRoom(serviceUserID, roomID string) (services []types.Service, err error) { err = runTransaction(d.db, func(txn *sql.Tx) error { serviceIDs, err := selectRoomServicesTxn(txn, serviceUserID, roomID) if err != nil { @@ -97,7 +98,7 @@ func (d *ServiceDB) LoadServicesInRoom(serviceUserID, roomID string) (services [ // StoreService stores a service into the database either by inserting a new // service or updating an existing service. Returns the old service if there // was one. -func (d *ServiceDB) StoreService(service Service, client *matrix.Client) (oldService Service, err error) { +func (d *ServiceDB) StoreService(service types.Service, client *matrix.Client) (oldService types.Service, err error) { err = runTransaction(d.db, func(txn *sql.Tx) error { oldService, err = selectServiceTxn(txn, service.ServiceID()) if err != nil && err != sql.ErrNoRows { diff --git a/src/github.com/matrix-org/go-neb/database/schema.go b/src/github.com/matrix-org/go-neb/database/schema.go index 03817fa..420766f 100644 --- a/src/github.com/matrix-org/go-neb/database/schema.go +++ b/src/github.com/matrix-org/go-neb/database/schema.go @@ -4,6 +4,7 @@ import ( "database/sql" "encoding/json" "fmt" + "github.com/matrix-org/go-neb/types" "time" ) @@ -61,7 +62,7 @@ const selectMatrixClientConfigSQL = ` SELECT client_json FROM matrix_clients WHERE user_id = $1 ` -func selectMatrixClientConfigTxn(txn *sql.Tx, userID string) (config ClientConfig, err error) { +func selectMatrixClientConfigTxn(txn *sql.Tx, userID string) (config types.ClientConfig, err error) { var configJSON []byte err = txn.QueryRow(selectMatrixClientConfigSQL, userID).Scan(&configJSON) if err != nil { @@ -77,7 +78,7 @@ INSERT INTO matrix_clients( ) VALUES ($1, $2, '', $3, $4) ` -func insertMatrixClientConfigTxn(txn *sql.Tx, now time.Time, config ClientConfig) error { +func insertMatrixClientConfigTxn(txn *sql.Tx, now time.Time, config types.ClientConfig) error { t := now.UnixNano() / 1000000 configJSON, err := json.Marshal(&config) if err != nil { @@ -92,7 +93,7 @@ UPDATE matrix_clients SET client_json = $1, time_updated_ms = $2 WHERE user_id = $3 ` -func updateMatrixClientConfigTxn(txn *sql.Tx, now time.Time, config ClientConfig) error { +func updateMatrixClientConfigTxn(txn *sql.Tx, now time.Time, config types.ClientConfig) error { t := now.UnixNano() / 1000000 configJSON, err := json.Marshal(&config) if err != nil { @@ -107,14 +108,14 @@ SELECT service_type, service_json FROM services WHERE service_id = $1 ` -func selectServiceTxn(txn *sql.Tx, serviceID string) (Service, error) { +func selectServiceTxn(txn *sql.Tx, serviceID string) (types.Service, error) { var serviceType string var serviceJSON []byte row := txn.QueryRow(selectServiceSQL, serviceID) if err := row.Scan(&serviceType, &serviceJSON); err != nil { return nil, err } - service := CreateService(serviceID, serviceType) + service := types.CreateService(serviceID, serviceType) if service == nil { return nil, fmt.Errorf("Cannot create services of type %s", serviceType) } @@ -129,7 +130,7 @@ UPDATE services SET service_type=$1, service_json=$2, time_updated_ms=$3 WHERE service_id=$4 ` -func updateServiceTxn(txn *sql.Tx, now time.Time, service Service) error { +func updateServiceTxn(txn *sql.Tx, now time.Time, service types.Service) error { serviceJSON, err := json.Marshal(service) if err != nil { return err @@ -148,7 +149,7 @@ INSERT INTO services( ) VALUES ($1, $2, $3, $4, $5) ` -func insertServiceTxn(txn *sql.Tx, now time.Time, service Service) error { +func insertServiceTxn(txn *sql.Tx, now time.Time, service types.Service) error { serviceJSON, err := json.Marshal(service) if err != nil { return err diff --git a/src/github.com/matrix-org/go-neb/services/echo/echo.go b/src/github.com/matrix-org/go-neb/services/echo/echo.go index 6377a45..d102b20 100644 --- a/src/github.com/matrix-org/go-neb/services/echo/echo.go +++ b/src/github.com/matrix-org/go-neb/services/echo/echo.go @@ -1,9 +1,9 @@ package services import ( - "github.com/matrix-org/go-neb/database" "github.com/matrix-org/go-neb/matrix" "github.com/matrix-org/go-neb/plugin" + "github.com/matrix-org/go-neb/types" "strings" ) @@ -31,7 +31,7 @@ func (e *echoService) Plugin(roomID string) plugin.Plugin { } func init() { - database.RegisterService(func(serviceID string) database.Service { + types.RegisterService(func(serviceID string) types.Service { return &echoService{id: serviceID} }) } diff --git a/src/github.com/matrix-org/go-neb/services/github/github.go b/src/github.com/matrix-org/go-neb/services/github/github.go index df58df0..c81d1a0 100644 --- a/src/github.com/matrix-org/go-neb/services/github/github.go +++ b/src/github.com/matrix-org/go-neb/services/github/github.go @@ -4,9 +4,9 @@ import ( "fmt" log "github.com/Sirupsen/logrus" "github.com/google/go-github/github" - "github.com/matrix-org/go-neb/database" "github.com/matrix-org/go-neb/matrix" "github.com/matrix-org/go-neb/plugin" + "github.com/matrix-org/go-neb/types" "golang.org/x/oauth2" "regexp" "strconv" @@ -91,7 +91,7 @@ func ownerRepoNumberFromText(ownerRepoNumberText string) (string, string, int, e } func init() { - database.RegisterService(func(serviceID string) database.Service { + types.RegisterService(func(serviceID string) types.Service { return &githubService{id: serviceID} }) } diff --git a/src/github.com/matrix-org/go-neb/database/types.go b/src/github.com/matrix-org/go-neb/types/types.go similarity index 95% rename from src/github.com/matrix-org/go-neb/database/types.go rename to src/github.com/matrix-org/go-neb/types/types.go index 2028a9d..7bdc6a8 100644 --- a/src/github.com/matrix-org/go-neb/database/types.go +++ b/src/github.com/matrix-org/go-neb/types/types.go @@ -1,8 +1,9 @@ -package database +package types import ( "errors" "github.com/matrix-org/go-neb/plugin" + // "net/http" "net/url" ) @@ -31,6 +32,7 @@ type Service interface { ServiceType() string RoomIDs() []string Plugin(roomID string) plugin.Plugin + // OnReceiveWebhook(req http.Request) } var servicesByType = map[string]func(string) Service{} From 665d43f726eda3a14073b9517db5bf89fc333574 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Mon, 1 Aug 2016 16:57:27 +0100 Subject: [PATCH 2/4] Parse github webhook requests into suitable HTML messages Verifies requests using an optional secret token. This commit doesn't implement sending of these messages. --- .../matrix-org/go-neb/services/echo/echo.go | 4 + .../go-neb/services/github/github.go | 6 + .../go-neb/services/github/webhook/webhook.go | 259 ++++++++++++++++++ .../matrix-org/go-neb/types/types.go | 4 +- 4 files changed, 271 insertions(+), 2 deletions(-) create mode 100644 src/github.com/matrix-org/go-neb/services/github/webhook/webhook.go diff --git a/src/github.com/matrix-org/go-neb/services/echo/echo.go b/src/github.com/matrix-org/go-neb/services/echo/echo.go index d102b20..ccdc5e4 100644 --- a/src/github.com/matrix-org/go-neb/services/echo/echo.go +++ b/src/github.com/matrix-org/go-neb/services/echo/echo.go @@ -4,6 +4,7 @@ import ( "github.com/matrix-org/go-neb/matrix" "github.com/matrix-org/go-neb/plugin" "github.com/matrix-org/go-neb/types" + "net/http" "strings" ) @@ -29,6 +30,9 @@ func (e *echoService) Plugin(roomID string) plugin.Plugin { }, } } +func (e *echoService) OnReceiveWebhook(w http.ResponseWriter, req http.Request) { + w.WriteHeader(200) // Do nothing +} func init() { types.RegisterService(func(serviceID string) types.Service { diff --git a/src/github.com/matrix-org/go-neb/services/github/github.go b/src/github.com/matrix-org/go-neb/services/github/github.go index c81d1a0..9d86414 100644 --- a/src/github.com/matrix-org/go-neb/services/github/github.go +++ b/src/github.com/matrix-org/go-neb/services/github/github.go @@ -6,8 +6,10 @@ import ( "github.com/google/go-github/github" "github.com/matrix-org/go-neb/matrix" "github.com/matrix-org/go-neb/plugin" + "github.com/matrix-org/go-neb/services/github/webhook" "github.com/matrix-org/go-neb/types" "golang.org/x/oauth2" + "net/http" "regexp" "strconv" ) @@ -60,6 +62,10 @@ func (s *githubService) Plugin(roomID string) plugin.Plugin { }, } } +func (s *githubService) OnReceiveWebhook(w http.ResponseWriter, req http.Request) { + // defer entirely to the webhook package + webhook.OnReceiveRequest(w, req, "") +} // githubClient returns a github Client which can perform Github API operations. // If `token` is empty, a non-authenticated client will be created. This should be diff --git a/src/github.com/matrix-org/go-neb/services/github/webhook/webhook.go b/src/github.com/matrix-org/go-neb/services/github/webhook/webhook.go new file mode 100644 index 0000000..c11cc11 --- /dev/null +++ b/src/github.com/matrix-org/go-neb/services/github/webhook/webhook.go @@ -0,0 +1,259 @@ +package webhook + +import ( + "crypto/hmac" + "crypto/sha1" + "encoding/hex" + "encoding/json" + "fmt" + log "github.com/Sirupsen/logrus" + "github.com/google/go-github/github" + "html" + "io/ioutil" + "net/http" + "strings" +) + +// OnReceiveRequest processes incoming github webhook requests. The secretToken +// parameter is optional. +func OnReceiveRequest(w http.ResponseWriter, r http.Request, secretToken string) { + // Verify the HMAC signature if NEB was configured with a secret token + eventType := r.Header.Get("X-GitHub-Event") + signatureSHA1 := r.Header.Get("X-Hub-Signature") + content, err := ioutil.ReadAll(r.Body) + if err != nil { + log.WithError(err).Print("Failed to read Github webhook body") + w.WriteHeader(400) + return + } + // Verify request if a secret token has been supplied. + if secretToken != "" { + sigHex := strings.Split(signatureSHA1, "=")[1] + var sigBytes []byte + sigBytes, err = hex.DecodeString(sigHex) + if err != nil { + log.WithError(err).WithField("X-Hub-Signature", sigHex).Print( + "Failed to decode signature as hex.") + w.WriteHeader(400) + return + } + + if !checkMAC([]byte(content), sigBytes, []byte(secretToken)) { + log.WithFields(log.Fields{ + "X-Hub-Signature": signatureSHA1, + }).Print("Received Github event which failed MAC check.") + w.WriteHeader(403) + return + } + } + + log.WithFields(log.Fields{ + "event_type": eventType, + "signature": signatureSHA1, + }).Print("Received Github event") + + htmlStr, repo, err := parseGithubEvent(eventType, content) + if err != nil { + log.WithError(err).Print("Failed to parse github event") + w.WriteHeader(500) + return + } + + if err := handleWebhookEvent(eventType, htmlStr, repo); err != nil { + log.WithError(err).Print("Failed to handle Github webhook event") + w.WriteHeader(500) + return + } + w.WriteHeader(200) +} + +// checkMAC reports whether messageMAC is a valid HMAC tag for message. +func checkMAC(message, messageMAC, key []byte) bool { + mac := hmac.New(sha1.New, key) + mac.Write(message) + expectedMAC := mac.Sum(nil) + return hmac.Equal(messageMAC, expectedMAC) +} + +// parseGithubEvent parses a github event type and JSON data and returns an explanatory +// HTML string and the github repository this event affects, or an error. +func parseGithubEvent(eventType string, data []byte) (string, *github.Repository, error) { + if eventType == "pull_request" { + var ev github.PullRequestEvent + if err := json.Unmarshal(data, &ev); err != nil { + return "", nil, err + } + return pullRequestHTMLMessage(ev), ev.Repo, nil + } else if eventType == "issues" { + var ev github.IssuesEvent + if err := json.Unmarshal(data, &ev); err != nil { + return "", nil, err + } + return issueHTMLMessage(ev), ev.Repo, nil + } else if eventType == "push" { + var ev github.PushEvent + if err := json.Unmarshal(data, &ev); err != nil { + return "", nil, err + } + + // The 'push' event repository format is subtly different from normal, so munge the bits we need. + fullName := *ev.Repo.Owner.Name + "/" + *ev.Repo.Name + repo := github.Repository{ + Owner: &github.User{ + Login: ev.Repo.Owner.Name, + }, + Name: ev.Repo.Name, + FullName: &fullName, + } + return pushHTMLMessage(ev), &repo, nil + } else if eventType == "issue_comment" { + var ev github.IssueCommentEvent + if err := json.Unmarshal(data, &ev); err != nil { + return "", nil, err + } + return issueCommentHTMLMessage(ev), ev.Repo, nil + } else if eventType == "pull_request_review_comment" { + var ev github.PullRequestReviewCommentEvent + if err := json.Unmarshal(data, &ev); err != nil { + return "", nil, err + } + return prReviewCommentHTMLMessage(ev), ev.Repo, nil + } + return "", nil, fmt.Errorf("Unrecognized event type") +} + +func handleWebhookEvent(eventType string, htmlStr string, repo *github.Repository) error { + return nil +} + +func pullRequestHTMLMessage(p github.PullRequestEvent) string { + var actionTarget string + if p.PullRequest.Assignee != nil && p.PullRequest.Assignee.Login != nil { + actionTarget = fmt.Sprintf(" to %s", *p.PullRequest.Assignee.Login) + } + return fmt.Sprintf( + "[%s] %s %s pull request #%d: %s [%s]%s - %s", + html.EscapeString(*p.Repo.FullName), + html.EscapeString(*p.Sender.Login), + html.EscapeString(*p.Action), + *p.Number, + html.EscapeString(*p.PullRequest.Title), + html.EscapeString(*p.PullRequest.State), + html.EscapeString(actionTarget), + html.EscapeString(*p.PullRequest.HTMLURL), + ) +} + +func issueHTMLMessage(p github.IssuesEvent) string { + var actionTarget string + if p.Issue.Assignee != nil && p.Issue.Assignee.Login != nil { + actionTarget = fmt.Sprintf(" to %s", *p.Issue.Assignee.Login) + } + return fmt.Sprintf( + "[%s] %s %s issue #%d: %s [%s]%s - %s", + html.EscapeString(*p.Repo.FullName), + html.EscapeString(*p.Sender.Login), + html.EscapeString(*p.Action), + *p.Issue.Number, + html.EscapeString(*p.Issue.Title), + html.EscapeString(*p.Issue.State), + html.EscapeString(actionTarget), + html.EscapeString(*p.Issue.HTMLURL), + ) +} + +func issueCommentHTMLMessage(p github.IssueCommentEvent) string { + var kind string + if p.Issue.PullRequestLinks == nil { + kind = "issue" + } else { + kind = "pull request" + } + + return fmt.Sprintf( + "[%s] %s commented on %s's %s #%d: %s - %s", + html.EscapeString(*p.Repo.FullName), + html.EscapeString(*p.Comment.User.Login), + html.EscapeString(*p.Issue.User.Login), + kind, + *p.Issue.Number, + html.EscapeString(*p.Issue.Title), + html.EscapeString(*p.Issue.HTMLURL), + ) +} + +func prReviewCommentHTMLMessage(p github.PullRequestReviewCommentEvent) string { + assignee := "None" + if p.PullRequest.Assignee != nil { + assignee = html.EscapeString(*p.PullRequest.Assignee.Login) + } + return fmt.Sprintf( + "[%s] %s made a line comment on %s's pull request #%d (assignee: %s): %s - %s", + html.EscapeString(*p.Repo.FullName), + html.EscapeString(*p.Sender.Login), + html.EscapeString(*p.PullRequest.User.Login), + *p.PullRequest.Number, + assignee, + html.EscapeString(*p.PullRequest.Title), + html.EscapeString(*p.Comment.HTMLURL), + ) +} + +func pushHTMLMessage(p github.PushEvent) string { + // /refs/heads/alice/branch-name => alice/branch-name + branch := strings.Replace(*p.Ref, "refs/heads/", "", -1) + + // this branch was deleted, no HeadCommit object and deleted=true + if p.HeadCommit == nil && p.Deleted != nil && *p.Deleted { + return fmt.Sprintf( + `[%s] %s deleted %s`, + html.EscapeString(*p.Repo.FullName), + html.EscapeString(*p.Pusher.Name), + html.EscapeString(branch), + ) + } + + if p.Commits != nil && len(p.Commits) > 1 { + // multi-commit message + // [] pushed commits to : + // + var cList []string + for _, c := range p.Commits { + cList = append(cList, fmt.Sprintf( + `%s: %s`, + html.EscapeString(nameForAuthor(c.Author)), + html.EscapeString(*c.Message), + )) + } + return fmt.Sprintf( + `[%s] %s pushed %d commits to %s: %s
%s`, + html.EscapeString(*p.Repo.FullName), + html.EscapeString(nameForAuthor(p.HeadCommit.Committer)), + len(p.Commits), + html.EscapeString(branch), + html.EscapeString(*p.HeadCommit.URL), + strings.Join(cList, "
"), + ) + } + + // single commit message + // [] pushed to : - + return fmt.Sprintf( + `[%s] %s pushed to %s: %s - %s`, + html.EscapeString(*p.Repo.FullName), + html.EscapeString(nameForAuthor(p.HeadCommit.Committer)), + html.EscapeString(branch), + html.EscapeString(*p.HeadCommit.Message), + html.EscapeString(*p.HeadCommit.URL), + ) +} + +func nameForAuthor(a *github.CommitAuthor) string { + if a == nil { + return "" + } + if a.Login != nil { // prefer to use their GH username than the name they commited as + return *a.Login + } + return *a.Name +} diff --git a/src/github.com/matrix-org/go-neb/types/types.go b/src/github.com/matrix-org/go-neb/types/types.go index 7bdc6a8..c5dc8ce 100644 --- a/src/github.com/matrix-org/go-neb/types/types.go +++ b/src/github.com/matrix-org/go-neb/types/types.go @@ -3,7 +3,7 @@ package types import ( "errors" "github.com/matrix-org/go-neb/plugin" - // "net/http" + "net/http" "net/url" ) @@ -32,7 +32,7 @@ type Service interface { ServiceType() string RoomIDs() []string Plugin(roomID string) plugin.Plugin - // OnReceiveWebhook(req http.Request) + OnReceiveWebhook(w http.ResponseWriter, req http.Request) } var servicesByType = map[string]func(string) Service{} From 0168f920238b6755fad58f0048c104b5693e08bb Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Mon, 1 Aug 2016 17:20:42 +0100 Subject: [PATCH 3/4] Add tests for webhook event parsing to HTML --- .../services/github/webhook/webhook_test.go | 1524 +++++++++++++++++ 1 file changed, 1524 insertions(+) create mode 100644 src/github.com/matrix-org/go-neb/services/github/webhook/webhook_test.go diff --git a/src/github.com/matrix-org/go-neb/services/github/webhook/webhook_test.go b/src/github.com/matrix-org/go-neb/services/github/webhook/webhook_test.go new file mode 100644 index 0000000..3a4b810 --- /dev/null +++ b/src/github.com/matrix-org/go-neb/services/github/webhook/webhook_test.go @@ -0,0 +1,1524 @@ +package webhook + +import ( + "strings" + "testing" +) + +var ghtests = []struct { + eventType string + jsonBody string + outHTML string + outFullRepo string +}{ + {"issues", + `{ + "action": "closed", + "issue": { + "url": "https://api.github.com/repos/DummyAccount/reponame/issues/15", + "repository_url": "https://api.github.com/repos/DummyAccount/reponame", + "labels_url": "https://api.github.com/repos/DummyAccount/reponame/issues/15/labels{/name}", + "comments_url": "https://api.github.com/repos/DummyAccount/reponame/issues/15/comments", + "events_url": "https://api.github.com/repos/DummyAccount/reponame/issues/15/events", + "html_url": "https://github.com/DummyAccount/reponame/issues/15", + "id": 159196956, + "number": 15, + "title": "aaaaaa", + "user": { + "login": "DummyAccount", + "id": 7190048, + "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/DummyAccount", + "html_url": "https://github.com/DummyAccount", + "followers_url": "https://api.github.com/users/DummyAccount/followers", + "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}", + "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions", + "organizations_url": "https://api.github.com/users/DummyAccount/orgs", + "repos_url": "https://api.github.com/users/DummyAccount/repos", + "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}", + "received_events_url": "https://api.github.com/users/DummyAccount/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + + ], + "state": "closed", + "locked": false, + "assignee": null, + "milestone": null, + "comments": 1, + "created_at": "2016-06-08T15:40:44Z", + "updated_at": "2016-06-08T15:41:36Z", + "closed_at": "2016-06-08T15:41:36Z", + "body": "" + }, + "repository": { + "id": 21138172, + "name": "reponame", + "full_name": "DummyAccount/reponame", + "owner": { + "login": "DummyAccount", + "id": 7190048, + "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/DummyAccount", + "html_url": "https://github.com/DummyAccount", + "followers_url": "https://api.github.com/users/DummyAccount/followers", + "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}", + "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions", + "organizations_url": "https://api.github.com/users/DummyAccount/orgs", + "repos_url": "https://api.github.com/users/DummyAccount/repos", + "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}", + "received_events_url": "https://api.github.com/users/DummyAccount/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/DummyAccount/reponame", + "description": "Android Development Device Monitor", + "fork": false, + "url": "https://api.github.com/repos/DummyAccount/reponame", + "forks_url": "https://api.github.com/repos/DummyAccount/reponame/forks", + "keys_url": "https://api.github.com/repos/DummyAccount/reponame/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/DummyAccount/reponame/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/DummyAccount/reponame/teams", + "hooks_url": "https://api.github.com/repos/DummyAccount/reponame/hooks", + "issue_events_url": "https://api.github.com/repos/DummyAccount/reponame/issues/events{/number}", + "events_url": "https://api.github.com/repos/DummyAccount/reponame/events", + "assignees_url": "https://api.github.com/repos/DummyAccount/reponame/assignees{/user}", + "branches_url": "https://api.github.com/repos/DummyAccount/reponame/branches{/branch}", + "tags_url": "https://api.github.com/repos/DummyAccount/reponame/tags", + "blobs_url": "https://api.github.com/repos/DummyAccount/reponame/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/DummyAccount/reponame/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/DummyAccount/reponame/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/DummyAccount/reponame/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/DummyAccount/reponame/statuses/{sha}", + "languages_url": "https://api.github.com/repos/DummyAccount/reponame/languages", + "stargazers_url": "https://api.github.com/repos/DummyAccount/reponame/stargazers", + "contributors_url": "https://api.github.com/repos/DummyAccount/reponame/contributors", + "subscribers_url": "https://api.github.com/repos/DummyAccount/reponame/subscribers", + "subscription_url": "https://api.github.com/repos/DummyAccount/reponame/subscription", + "commits_url": "https://api.github.com/repos/DummyAccount/reponame/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/DummyAccount/reponame/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/DummyAccount/reponame/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/DummyAccount/reponame/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/DummyAccount/reponame/contents/{+path}", + "compare_url": "https://api.github.com/repos/DummyAccount/reponame/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/DummyAccount/reponame/merges", + "archive_url": "https://api.github.com/repos/DummyAccount/reponame/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/DummyAccount/reponame/downloads", + "issues_url": "https://api.github.com/repos/DummyAccount/reponame/issues{/number}", + "pulls_url": "https://api.github.com/repos/DummyAccount/reponame/pulls{/number}", + "milestones_url": "https://api.github.com/repos/DummyAccount/reponame/milestones{/number}", + "notifications_url": "https://api.github.com/repos/DummyAccount/reponame/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/DummyAccount/reponame/labels{/name}", + "releases_url": "https://api.github.com/repos/DummyAccount/reponame/releases{/id}", + "deployments_url": "https://api.github.com/repos/DummyAccount/reponame/deployments", + "created_at": "2014-06-23T18:51:33Z", + "updated_at": "2015-07-22T07:42:19Z", + "pushed_at": "2015-07-22T07:42:19Z", + "git_url": "git://github.com/DummyAccount/reponame.git", + "ssh_url": "git@github.com:DummyAccount/reponame.git", + "clone_url": "https://github.com/DummyAccount/reponame.git", + "svn_url": "https://github.com/DummyAccount/reponame", + "homepage": null, + "size": 725, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Java", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 1, + "mirror_url": null, + "open_issues_count": 0, + "forks": 1, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "DummyAccount", + "id": 7190048, + "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/DummyAccount", + "html_url": "https://github.com/DummyAccount", + "followers_url": "https://api.github.com/users/DummyAccount/followers", + "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}", + "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions", + "organizations_url": "https://api.github.com/users/DummyAccount/orgs", + "repos_url": "https://api.github.com/users/DummyAccount/repos", + "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}", + "received_events_url": "https://api.github.com/users/DummyAccount/received_events", + "type": "User", + "site_admin": false + } + }`, + `[DummyAccount/reponame] DummyAccount closed issue #15: aaaaaa [closed] - https://github.com/DummyAccount/reponame/issues/15`, + "DummyAccount/reponame"}, + // ================================================================== + { + "issue_comment", + `{ + "action": "created", + "issue": { + "url": "https://api.github.com/repos/DummyAccount/arepo/issues/15", + "repository_url": "https://api.github.com/repos/DummyAccount/arepo", + "labels_url": "https://api.github.com/repos/DummyAccount/arepo/issues/15/labels{/name}", + "comments_url": "https://api.github.com/repos/DummyAccount/arepo/issues/15/comments", + "events_url": "https://api.github.com/repos/DummyAccount/arepo/issues/15/events", + "html_url": "https://github.com/DummyAccount/arepo/issues/15", + "id": 159196956, + "number": 15, + "title": "aaaaaa", + "user": { + "login": "DummyAccount", + "id": 7190048, + "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/DummyAccount", + "html_url": "https://github.com/DummyAccount", + "followers_url": "https://api.github.com/users/DummyAccount/followers", + "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}", + "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions", + "organizations_url": "https://api.github.com/users/DummyAccount/orgs", + "repos_url": "https://api.github.com/users/DummyAccount/repos", + "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}", + "received_events_url": "https://api.github.com/users/DummyAccount/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + + ], + "state": "closed", + "locked": false, + "assignee": null, + "milestone": null, + "comments": 2, + "created_at": "2016-06-08T15:40:44Z", + "updated_at": "2016-06-08T15:55:25Z", + "closed_at": "2016-06-08T15:41:36Z", + "body": "" + }, + "comment": { + "url": "https://api.github.com/repos/DummyAccount/arepo/issues/comments/224636064", + "html_url": "https://github.com/DummyAccount/arepo/issues/15#issuecomment-224636064", + "issue_url": "https://api.github.com/repos/DummyAccount/arepo/issues/15", + "id": 224636064, + "user": { + "login": "DummyAccount", + "id": 7190048, + "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/DummyAccount", + "html_url": "https://github.com/DummyAccount", + "followers_url": "https://api.github.com/users/DummyAccount/followers", + "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}", + "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions", + "organizations_url": "https://api.github.com/users/DummyAccount/orgs", + "repos_url": "https://api.github.com/users/DummyAccount/repos", + "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}", + "received_events_url": "https://api.github.com/users/DummyAccount/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2016-06-08T15:55:25Z", + "updated_at": "2016-06-08T15:55:25Z", + "body": "cccccc" + }, + "repository": { + "id": 21138172, + "name": "arepo", + "full_name": "DummyAccount/arepo", + "owner": { + "login": "DummyAccount", + "id": 7190048, + "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/DummyAccount", + "html_url": "https://github.com/DummyAccount", + "followers_url": "https://api.github.com/users/DummyAccount/followers", + "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}", + "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions", + "organizations_url": "https://api.github.com/users/DummyAccount/orgs", + "repos_url": "https://api.github.com/users/DummyAccount/repos", + "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}", + "received_events_url": "https://api.github.com/users/DummyAccount/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/DummyAccount/arepo", + "description": "Android Development Device Monitor", + "fork": false, + "url": "https://api.github.com/repos/DummyAccount/arepo", + "forks_url": "https://api.github.com/repos/DummyAccount/arepo/forks", + "keys_url": "https://api.github.com/repos/DummyAccount/arepo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/DummyAccount/arepo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/DummyAccount/arepo/teams", + "hooks_url": "https://api.github.com/repos/DummyAccount/arepo/hooks", + "issue_events_url": "https://api.github.com/repos/DummyAccount/arepo/issues/events{/number}", + "events_url": "https://api.github.com/repos/DummyAccount/arepo/events", + "assignees_url": "https://api.github.com/repos/DummyAccount/arepo/assignees{/user}", + "branches_url": "https://api.github.com/repos/DummyAccount/arepo/branches{/branch}", + "tags_url": "https://api.github.com/repos/DummyAccount/arepo/tags", + "blobs_url": "https://api.github.com/repos/DummyAccount/arepo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/DummyAccount/arepo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/DummyAccount/arepo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/DummyAccount/arepo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/DummyAccount/arepo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/DummyAccount/arepo/languages", + "stargazers_url": "https://api.github.com/repos/DummyAccount/arepo/stargazers", + "contributors_url": "https://api.github.com/repos/DummyAccount/arepo/contributors", + "subscribers_url": "https://api.github.com/repos/DummyAccount/arepo/subscribers", + "subscription_url": "https://api.github.com/repos/DummyAccount/arepo/subscription", + "commits_url": "https://api.github.com/repos/DummyAccount/arepo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/DummyAccount/arepo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/DummyAccount/arepo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/DummyAccount/arepo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/DummyAccount/arepo/contents/{+path}", + "compare_url": "https://api.github.com/repos/DummyAccount/arepo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/DummyAccount/arepo/merges", + "archive_url": "https://api.github.com/repos/DummyAccount/arepo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/DummyAccount/arepo/downloads", + "issues_url": "https://api.github.com/repos/DummyAccount/arepo/issues{/number}", + "pulls_url": "https://api.github.com/repos/DummyAccount/arepo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/DummyAccount/arepo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/DummyAccount/arepo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/DummyAccount/arepo/labels{/name}", + "releases_url": "https://api.github.com/repos/DummyAccount/arepo/releases{/id}", + "deployments_url": "https://api.github.com/repos/DummyAccount/arepo/deployments", + "created_at": "2014-06-23T18:51:33Z", + "updated_at": "2015-07-22T07:42:19Z", + "pushed_at": "2015-07-22T07:42:19Z", + "git_url": "git://github.com/DummyAccount/arepo.git", + "ssh_url": "git@github.com:DummyAccount/arepo.git", + "clone_url": "https://github.com/DummyAccount/arepo.git", + "svn_url": "https://github.com/DummyAccount/arepo", + "homepage": null, + "size": 725, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Java", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 1, + "mirror_url": null, + "open_issues_count": 0, + "forks": 1, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "DummyAccount", + "id": 7190048, + "avatar_url": "https://avatars.githubusercontent.com/u/7190048?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/DummyAccount", + "html_url": "https://github.com/DummyAccount", + "followers_url": "https://api.github.com/users/DummyAccount/followers", + "following_url": "https://api.github.com/users/DummyAccount/following{/other_user}", + "gists_url": "https://api.github.com/users/DummyAccount/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DummyAccount/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DummyAccount/subscriptions", + "organizations_url": "https://api.github.com/users/DummyAccount/orgs", + "repos_url": "https://api.github.com/users/DummyAccount/repos", + "events_url": "https://api.github.com/users/DummyAccount/events{/privacy}", + "received_events_url": "https://api.github.com/users/DummyAccount/received_events", + "type": "User", + "site_admin": false + } + }`, + "[DummyAccount/arepo] DummyAccount commented on DummyAccount's issue #15: aaaaaa - https://github.com/DummyAccount/arepo/issues/15", + "DummyAccount/arepo", + }, + // ================================================================== + { + "push", + `{ + "ref": "refs/heads/develop", + "before": "352fe606a8ca6f732ad832d8443009599bcb33a8", + "after": "4a05c601f6b806110e63160cf7cf41b37787461f", + "created": false, + "deleted": false, + "forced": false, + "base_ref": "refs/heads/markjh/disable_jenkins_synchrotron", + "compare": "https://github.com/matrix-org/sytest/compare/352fe606a8ca...4a05c601f6b8", + "commits": [ + { + "id": "38367e20fe0f479d6eaaf0407c1e10ec0dadf52b", + "tree_id": "618cf94bc0babe49377ab4a2c790a4749cc46c99", + "distinct": false, + "message": "Fix arguments to postgres connector to work with go", + "timestamp": "2016-06-08T14:02:42+01:00", + "url": "https://github.com/matrix-org/sytest/commit/38367e20fe0f479d6eaaf0407c1e10ec0dadf52b", + "author": { + "name": "Mark Haines", + "email": "mark.haines@matrix.org", + "username": "NegativeMjark" + }, + "committer": { + "name": "Mark Haines", + "email": "mark.haines@matrix.org", + "username": "NegativeMjark" + }, + "added": [ + + ], + "removed": [ + + ], + "modified": [ + "jenkins/prep_sytest_for_postgres.sh" + ] + }, + { + "id": "4a05c601f6b806110e63160cf7cf41b37787461f", + "tree_id": "c97850f05b804882cbb746be123f110ce05311f7", + "distinct": false, + "message": "Add necessary info to the second postgres db", + "timestamp": "2016-06-08T14:22:52+01:00", + "url": "https://github.com/matrix-org/sytest/commit/4a05c601f6b806110e63160cf7cf41b37787461f", + "author": { + "name": "Mark Haines", + "email": "mark.haines@matrix.org", + "username": "NegativeMjark" + }, + "committer": { + "name": "Mark Haines", + "email": "mark.haines@matrix.org", + "username": "NegativeMjark" + }, + "added": [ + + ], + "removed": [ + + ], + "modified": [ + "jenkins/prep_sytest_for_postgres.sh" + ] + } + ], + "head_commit": { + "id": "4a05c601f6b806110e63160cf7cf41b37787461f", + "tree_id": "c97850f05b804882cbb746be123f110ce05311f7", + "distinct": false, + "message": "Add necessary info to the second postgres db", + "timestamp": "2016-06-08T14:22:52+01:00", + "url": "https://github.com/matrix-org/sytest/commit/4a05c601f6b806110e63160cf7cf41b37787461f", + "author": { + "name": "Mark Haines", + "email": "mark.haines@matrix.org", + "username": "NegativeMjark" + }, + "committer": { + "name": "Mark Haines", + "email": "mark.haines@matrix.org", + "username": "NegativeMjark" + }, + "added": [ + + ], + "removed": [ + + ], + "modified": [ + "jenkins/prep_sytest_for_postgres.sh" + ] + }, + "repository": { + "id": 23436169, + "name": "sytest", + "full_name": "matrix-org/sytest", + "owner": { + "name": "matrix-org", + "email": "matrix@matrix.org" + }, + "private": false, + "html_url": "https://github.com/matrix-org/sytest", + "description": "Black-box integration testing for Matrix homeservers", + "fork": false, + "url": "https://github.com/matrix-org/sytest", + "forks_url": "https://api.github.com/repos/matrix-org/sytest/forks", + "keys_url": "https://api.github.com/repos/matrix-org/sytest/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/matrix-org/sytest/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/matrix-org/sytest/teams", + "hooks_url": "https://api.github.com/repos/matrix-org/sytest/hooks", + "issue_events_url": "https://api.github.com/repos/matrix-org/sytest/issues/events{/number}", + "events_url": "https://api.github.com/repos/matrix-org/sytest/events", + "assignees_url": "https://api.github.com/repos/matrix-org/sytest/assignees{/user}", + "branches_url": "https://api.github.com/repos/matrix-org/sytest/branches{/branch}", + "tags_url": "https://api.github.com/repos/matrix-org/sytest/tags", + "blobs_url": "https://api.github.com/repos/matrix-org/sytest/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/matrix-org/sytest/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/matrix-org/sytest/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/matrix-org/sytest/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/matrix-org/sytest/statuses/{sha}", + "languages_url": "https://api.github.com/repos/matrix-org/sytest/languages", + "stargazers_url": "https://api.github.com/repos/matrix-org/sytest/stargazers", + "contributors_url": "https://api.github.com/repos/matrix-org/sytest/contributors", + "subscribers_url": "https://api.github.com/repos/matrix-org/sytest/subscribers", + "subscription_url": "https://api.github.com/repos/matrix-org/sytest/subscription", + "commits_url": "https://api.github.com/repos/matrix-org/sytest/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/matrix-org/sytest/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/matrix-org/sytest/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/matrix-org/sytest/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/matrix-org/sytest/contents/{+path}", + "compare_url": "https://api.github.com/repos/matrix-org/sytest/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/matrix-org/sytest/merges", + "archive_url": "https://api.github.com/repos/matrix-org/sytest/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/matrix-org/sytest/downloads", + "issues_url": "https://api.github.com/repos/matrix-org/sytest/issues{/number}", + "pulls_url": "https://api.github.com/repos/matrix-org/sytest/pulls{/number}", + "milestones_url": "https://api.github.com/repos/matrix-org/sytest/milestones{/number}", + "notifications_url": "https://api.github.com/repos/matrix-org/sytest/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/matrix-org/sytest/labels{/name}", + "releases_url": "https://api.github.com/repos/matrix-org/sytest/releases{/id}", + "deployments_url": "https://api.github.com/repos/matrix-org/sytest/deployments", + "created_at": 1409245543, + "updated_at": "2016-01-11T16:43:34Z", + "pushed_at": 1465400172, + "git_url": "git://github.com/matrix-org/sytest.git", + "ssh_url": "git@github.com:matrix-org/sytest.git", + "clone_url": "https://github.com/matrix-org/sytest.git", + "svn_url": "https://github.com/matrix-org/sytest", + "homepage": "", + "size": 1831, + "stargazers_count": 2, + "watchers_count": 2, + "language": "Perl", + "has_issues": true, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 6, + "forks": 0, + "open_issues": 6, + "watchers": 2, + "default_branch": "develop", + "stargazers": 2, + "master_branch": "develop", + "organization": "matrix-org" + }, + "pusher": { + "name": "NegativeMjark", + "email": "mjark@negativecurvature.net" + }, + "organization": { + "login": "matrix-org", + "id": 8418310, + "url": "https://api.github.com/orgs/matrix-org", + "repos_url": "https://api.github.com/orgs/matrix-org/repos", + "events_url": "https://api.github.com/orgs/matrix-org/events", + "hooks_url": "https://api.github.com/orgs/matrix-org/hooks", + "issues_url": "https://api.github.com/orgs/matrix-org/issues", + "members_url": "https://api.github.com/orgs/matrix-org/members{/member}", + "public_members_url": "https://api.github.com/orgs/matrix-org/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "description": "A new basis for open, interoperable, decentralised real-time communication" + }, + "sender": { + "login": "NegativeMjark", + "id": 904009, + "avatar_url": "https://avatars.githubusercontent.com/u/904009?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/NegativeMjark", + "html_url": "https://github.com/NegativeMjark", + "followers_url": "https://api.github.com/users/NegativeMjark/followers", + "following_url": "https://api.github.com/users/NegativeMjark/following{/other_user}", + "gists_url": "https://api.github.com/users/NegativeMjark/gists{/gist_id}", + "starred_url": "https://api.github.com/users/NegativeMjark/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/NegativeMjark/subscriptions", + "organizations_url": "https://api.github.com/users/NegativeMjark/orgs", + "repos_url": "https://api.github.com/users/NegativeMjark/repos", + "events_url": "https://api.github.com/users/NegativeMjark/events{/privacy}", + "received_events_url": "https://api.github.com/users/NegativeMjark/received_events", + "type": "User", + "site_admin": false + } + }`, + "[matrix-org/sytest] NegativeMjark pushed 2 commits to develop: https://github.com/matrix-org/sytest/commit/4a05c601f6b806110e63160cf7cf41b37787461f
NegativeMjark: Fix arguments to postgres connector to work with go
NegativeMjark: Add necessary info to the second postgres db", + "matrix-org/sytest", + }, + // ================================================================== + { + "pull_request", + `{ + "action": "assigned", + "number": 303, + "pull_request": { + "url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/303", + "id": 73186698, + "html_url": "https://github.com/matrix-org/matrix-react-sdk/pull/303", + "diff_url": "https://github.com/matrix-org/matrix-react-sdk/pull/303.diff", + "patch_url": "https://github.com/matrix-org/matrix-react-sdk/pull/303.patch", + "issue_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/303", + "number": 303, + "state": "open", + "locked": false, + "title": "Factor out common parts of room creation", + "user": { + "login": "richvdh", + "id": 1389908, + "avatar_url": "https://avatars.githubusercontent.com/u/1389908?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/richvdh", + "html_url": "https://github.com/richvdh", + "followers_url": "https://api.github.com/users/richvdh/followers", + "following_url": "https://api.github.com/users/richvdh/following{/other_user}", + "gists_url": "https://api.github.com/users/richvdh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/richvdh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/richvdh/subscriptions", + "organizations_url": "https://api.github.com/users/richvdh/orgs", + "repos_url": "https://api.github.com/users/richvdh/repos", + "events_url": "https://api.github.com/users/richvdh/events{/privacy}", + "received_events_url": "https://api.github.com/users/richvdh/received_events", + "type": "User", + "site_admin": false + }, + "body": "Take the duplicated code out of MatrixChat and MemberInfo, and put it in a\nseparate 'createRoom' module", + "created_at": "2016-06-09T10:00:02Z", + "updated_at": "2016-06-09T10:00:11Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": "162bd3e4c940bcce1de3b98da14827e138121f5d", + "assignee": { + "login": "dbkr", + "id": 986903, + "avatar_url": "https://avatars.githubusercontent.com/u/986903?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/dbkr", + "html_url": "https://github.com/dbkr", + "followers_url": "https://api.github.com/users/dbkr/followers", + "following_url": "https://api.github.com/users/dbkr/following{/other_user}", + "gists_url": "https://api.github.com/users/dbkr/gists{/gist_id}", + "starred_url": "https://api.github.com/users/dbkr/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/dbkr/subscriptions", + "organizations_url": "https://api.github.com/users/dbkr/orgs", + "repos_url": "https://api.github.com/users/dbkr/repos", + "events_url": "https://api.github.com/users/dbkr/events{/privacy}", + "received_events_url": "https://api.github.com/users/dbkr/received_events", + "type": "User", + "site_admin": false + }, + "milestone": null, + "commits_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/303/commits", + "review_comments_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/303/comments", + "review_comment_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/303/comments", + "statuses_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/statuses/de36aa63fb61c9aee011221e2db6159fe1653ae9", + "head": { + "label": "matrix-org:rav/factor_out_createroom", + "ref": "rav/factor_out_createroom", + "sha": "de36aa63fb61c9aee011221e2db6159fe1653ae9", + "user": { + "login": "matrix-org", + "id": 8418310, + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/matrix-org", + "html_url": "https://github.com/matrix-org", + "followers_url": "https://api.github.com/users/matrix-org/followers", + "following_url": "https://api.github.com/users/matrix-org/following{/other_user}", + "gists_url": "https://api.github.com/users/matrix-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matrix-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matrix-org/subscriptions", + "organizations_url": "https://api.github.com/users/matrix-org/orgs", + "repos_url": "https://api.github.com/users/matrix-org/repos", + "events_url": "https://api.github.com/users/matrix-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/matrix-org/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 37144575, + "name": "matrix-react-sdk", + "full_name": "matrix-org/matrix-react-sdk", + "owner": { + "login": "matrix-org", + "id": 8418310, + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/matrix-org", + "html_url": "https://github.com/matrix-org", + "followers_url": "https://api.github.com/users/matrix-org/followers", + "following_url": "https://api.github.com/users/matrix-org/following{/other_user}", + "gists_url": "https://api.github.com/users/matrix-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matrix-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matrix-org/subscriptions", + "organizations_url": "https://api.github.com/users/matrix-org/orgs", + "repos_url": "https://api.github.com/users/matrix-org/repos", + "events_url": "https://api.github.com/users/matrix-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/matrix-org/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/matrix-org/matrix-react-sdk", + "description": "Matrix SDK for React Javascript", + "fork": false, + "url": "https://api.github.com/repos/matrix-org/matrix-react-sdk", + "forks_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/forks", + "keys_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/teams", + "hooks_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/hooks", + "issue_events_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/events{/number}", + "events_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/events", + "assignees_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/assignees{/user}", + "branches_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/branches{/branch}", + "tags_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/tags", + "blobs_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/statuses/{sha}", + "languages_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/languages", + "stargazers_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/stargazers", + "contributors_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/contributors", + "subscribers_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/subscribers", + "subscription_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/subscription", + "commits_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/contents/{+path}", + "compare_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/merges", + "archive_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/downloads", + "issues_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues{/number}", + "pulls_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls{/number}", + "milestones_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/milestones{/number}", + "notifications_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/labels{/name}", + "releases_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/releases{/id}", + "deployments_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/deployments", + "created_at": "2015-06-09T16:37:07Z", + "updated_at": "2016-06-07T11:20:20Z", + "pushed_at": "2016-06-09T10:00:02Z", + "git_url": "git://github.com/matrix-org/matrix-react-sdk.git", + "ssh_url": "git@github.com:matrix-org/matrix-react-sdk.git", + "clone_url": "https://github.com/matrix-org/matrix-react-sdk.git", + "svn_url": "https://github.com/matrix-org/matrix-react-sdk", + "homepage": null, + "size": 2721, + "stargazers_count": 35, + "watchers_count": 35, + "language": "JavaScript", + "has_issues": true, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 17, + "mirror_url": null, + "open_issues_count": 7, + "forks": 17, + "open_issues": 7, + "watchers": 35, + "default_branch": "master" + } + }, + "base": { + "label": "matrix-org:develop", + "ref": "develop", + "sha": "98ef793809a662f4864df75ade0856d0ce52ecd6", + "user": { + "login": "matrix-org", + "id": 8418310, + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/matrix-org", + "html_url": "https://github.com/matrix-org", + "followers_url": "https://api.github.com/users/matrix-org/followers", + "following_url": "https://api.github.com/users/matrix-org/following{/other_user}", + "gists_url": "https://api.github.com/users/matrix-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matrix-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matrix-org/subscriptions", + "organizations_url": "https://api.github.com/users/matrix-org/orgs", + "repos_url": "https://api.github.com/users/matrix-org/repos", + "events_url": "https://api.github.com/users/matrix-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/matrix-org/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 37144575, + "name": "matrix-react-sdk", + "full_name": "matrix-org/matrix-react-sdk", + "owner": { + "login": "matrix-org", + "id": 8418310, + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/matrix-org", + "html_url": "https://github.com/matrix-org", + "followers_url": "https://api.github.com/users/matrix-org/followers", + "following_url": "https://api.github.com/users/matrix-org/following{/other_user}", + "gists_url": "https://api.github.com/users/matrix-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matrix-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matrix-org/subscriptions", + "organizations_url": "https://api.github.com/users/matrix-org/orgs", + "repos_url": "https://api.github.com/users/matrix-org/repos", + "events_url": "https://api.github.com/users/matrix-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/matrix-org/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/matrix-org/matrix-react-sdk", + "description": "Matrix SDK for React Javascript", + "fork": false, + "url": "https://api.github.com/repos/matrix-org/matrix-react-sdk", + "forks_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/forks", + "keys_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/teams", + "hooks_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/hooks", + "issue_events_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/events{/number}", + "events_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/events", + "assignees_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/assignees{/user}", + "branches_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/branches{/branch}", + "tags_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/tags", + "blobs_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/statuses/{sha}", + "languages_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/languages", + "stargazers_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/stargazers", + "contributors_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/contributors", + "subscribers_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/subscribers", + "subscription_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/subscription", + "commits_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/contents/{+path}", + "compare_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/merges", + "archive_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/downloads", + "issues_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues{/number}", + "pulls_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls{/number}", + "milestones_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/milestones{/number}", + "notifications_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/labels{/name}", + "releases_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/releases{/id}", + "deployments_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/deployments", + "created_at": "2015-06-09T16:37:07Z", + "updated_at": "2016-06-07T11:20:20Z", + "pushed_at": "2016-06-09T10:00:02Z", + "git_url": "git://github.com/matrix-org/matrix-react-sdk.git", + "ssh_url": "git@github.com:matrix-org/matrix-react-sdk.git", + "clone_url": "https://github.com/matrix-org/matrix-react-sdk.git", + "svn_url": "https://github.com/matrix-org/matrix-react-sdk", + "homepage": null, + "size": 2721, + "stargazers_count": 35, + "watchers_count": 35, + "language": "JavaScript", + "has_issues": true, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 17, + "mirror_url": null, + "open_issues_count": 7, + "forks": 17, + "open_issues": 7, + "watchers": 35, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/303" + }, + "html": { + "href": "https://github.com/matrix-org/matrix-react-sdk/pull/303" + }, + "issue": { + "href": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/303" + }, + "comments": { + "href": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/303/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/303/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls/303/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/matrix-org/matrix-react-sdk/statuses/de36aa63fb61c9aee011221e2db6159fe1653ae9" + } + }, + "merged": false, + "mergeable": true, + "mergeable_state": "clean", + "merged_by": null, + "comments": 0, + "review_comments": 0, + "commits": 1, + "additions": 97, + "deletions": 86, + "changed_files": 3 + }, + "assignee": { + "login": "dbkr", + "id": 986903, + "avatar_url": "https://avatars.githubusercontent.com/u/986903?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/dbkr", + "html_url": "https://github.com/dbkr", + "followers_url": "https://api.github.com/users/dbkr/followers", + "following_url": "https://api.github.com/users/dbkr/following{/other_user}", + "gists_url": "https://api.github.com/users/dbkr/gists{/gist_id}", + "starred_url": "https://api.github.com/users/dbkr/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/dbkr/subscriptions", + "organizations_url": "https://api.github.com/users/dbkr/orgs", + "repos_url": "https://api.github.com/users/dbkr/repos", + "events_url": "https://api.github.com/users/dbkr/events{/privacy}", + "received_events_url": "https://api.github.com/users/dbkr/received_events", + "type": "User", + "site_admin": false + }, + "repository": { + "id": 37144575, + "name": "matrix-react-sdk", + "full_name": "matrix-org/matrix-react-sdk", + "owner": { + "login": "matrix-org", + "id": 8418310, + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/matrix-org", + "html_url": "https://github.com/matrix-org", + "followers_url": "https://api.github.com/users/matrix-org/followers", + "following_url": "https://api.github.com/users/matrix-org/following{/other_user}", + "gists_url": "https://api.github.com/users/matrix-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matrix-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matrix-org/subscriptions", + "organizations_url": "https://api.github.com/users/matrix-org/orgs", + "repos_url": "https://api.github.com/users/matrix-org/repos", + "events_url": "https://api.github.com/users/matrix-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/matrix-org/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/matrix-org/matrix-react-sdk", + "description": "Matrix SDK for React Javascript", + "fork": false, + "url": "https://api.github.com/repos/matrix-org/matrix-react-sdk", + "forks_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/forks", + "keys_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/teams", + "hooks_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/hooks", + "issue_events_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/events{/number}", + "events_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/events", + "assignees_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/assignees{/user}", + "branches_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/branches{/branch}", + "tags_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/tags", + "blobs_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/statuses/{sha}", + "languages_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/languages", + "stargazers_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/stargazers", + "contributors_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/contributors", + "subscribers_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/subscribers", + "subscription_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/subscription", + "commits_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/contents/{+path}", + "compare_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/merges", + "archive_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/downloads", + "issues_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/issues{/number}", + "pulls_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/pulls{/number}", + "milestones_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/milestones{/number}", + "notifications_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/labels{/name}", + "releases_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/releases{/id}", + "deployments_url": "https://api.github.com/repos/matrix-org/matrix-react-sdk/deployments", + "created_at": "2015-06-09T16:37:07Z", + "updated_at": "2016-06-07T11:20:20Z", + "pushed_at": "2016-06-09T10:00:02Z", + "git_url": "git://github.com/matrix-org/matrix-react-sdk.git", + "ssh_url": "git@github.com:matrix-org/matrix-react-sdk.git", + "clone_url": "https://github.com/matrix-org/matrix-react-sdk.git", + "svn_url": "https://github.com/matrix-org/matrix-react-sdk", + "homepage": null, + "size": 2721, + "stargazers_count": 35, + "watchers_count": 35, + "language": "JavaScript", + "has_issues": true, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 17, + "mirror_url": null, + "open_issues_count": 7, + "forks": 17, + "open_issues": 7, + "watchers": 35, + "default_branch": "master" + }, + "organization": { + "login": "matrix-org", + "id": 8418310, + "url": "https://api.github.com/orgs/matrix-org", + "repos_url": "https://api.github.com/orgs/matrix-org/repos", + "events_url": "https://api.github.com/orgs/matrix-org/events", + "hooks_url": "https://api.github.com/orgs/matrix-org/hooks", + "issues_url": "https://api.github.com/orgs/matrix-org/issues", + "members_url": "https://api.github.com/orgs/matrix-org/members{/member}", + "public_members_url": "https://api.github.com/orgs/matrix-org/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "description": "A new basis for open, interoperable, decentralised real-time communication" + }, + "sender": { + "login": "richvdh", + "id": 1389908, + "avatar_url": "https://avatars.githubusercontent.com/u/1389908?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/richvdh", + "html_url": "https://github.com/richvdh", + "followers_url": "https://api.github.com/users/richvdh/followers", + "following_url": "https://api.github.com/users/richvdh/following{/other_user}", + "gists_url": "https://api.github.com/users/richvdh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/richvdh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/richvdh/subscriptions", + "organizations_url": "https://api.github.com/users/richvdh/orgs", + "repos_url": "https://api.github.com/users/richvdh/repos", + "events_url": "https://api.github.com/users/richvdh/events{/privacy}", + "received_events_url": "https://api.github.com/users/richvdh/received_events", + "type": "User", + "site_admin": false + } + }`, + "[matrix-org/matrix-react-sdk] richvdh assigned pull request #303: Factor out common parts of room creation [open] to dbkr - https://github.com/matrix-org/matrix-react-sdk/pull/303", + "matrix-org/matrix-react-sdk", + }, + // ================================================================== + { + "pull_request_review_comment", + `{ + "action": "created", + "comment": { + "url": "https://api.github.com/repos/matrix-org/synapse/pulls/comments/66413356", + "id": 66413356, + "diff_hunk": "@@ -388,8 +388,8 @@ def get_or_create_user(self, localpart, displayname, duration_seconds):\n \n user = UserID(localpart, self.hs.hostname)\n user_id = user.to_string()\n- auth_handler = self.hs.get_handlers().auth_handler\n- token = auth_handler.generate_short_term_login_token(user_id, duration_seconds)\n+ token = self.auth_handler().generate_short_term_login_token(\n+ user_id, duration_seconds)", + "path": "synapse/handlers/register.py", + "position": 7, + "original_position": 7, + "commit_id": "6e7dc7c7dde377794c23d5db6f25ffacfb08e82a", + "original_commit_id": "6e7dc7c7dde377794c23d5db6f25ffacfb08e82a", + "user": { + "login": "erikjohnston", + "id": 8428120, + "avatar_url": "https://avatars.githubusercontent.com/u/8428120?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/erikjohnston", + "html_url": "https://github.com/erikjohnston", + "followers_url": "https://api.github.com/users/erikjohnston/followers", + "following_url": "https://api.github.com/users/erikjohnston/following{/other_user}", + "gists_url": "https://api.github.com/users/erikjohnston/gists{/gist_id}", + "starred_url": "https://api.github.com/users/erikjohnston/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/erikjohnston/subscriptions", + "organizations_url": "https://api.github.com/users/erikjohnston/orgs", + "repos_url": "https://api.github.com/users/erikjohnston/repos", + "events_url": "https://api.github.com/users/erikjohnston/events{/privacy}", + "received_events_url": "https://api.github.com/users/erikjohnston/received_events", + "type": "User", + "site_admin": false + }, + "body": "Code style wise we prefer the closing parenthesis to be on a new line", + "created_at": "2016-06-09T10:00:43Z", + "updated_at": "2016-06-09T10:00:43Z", + "html_url": "https://github.com/matrix-org/synapse/pull/860#discussion_r66413356", + "pull_request_url": "https://api.github.com/repos/matrix-org/synapse/pulls/860", + "_links": { + "self": { + "href": "https://api.github.com/repos/matrix-org/synapse/pulls/comments/66413356" + }, + "html": { + "href": "https://github.com/matrix-org/synapse/pull/860#discussion_r66413356" + }, + "pull_request": { + "href": "https://api.github.com/repos/matrix-org/synapse/pulls/860" + } + } + }, + "pull_request": { + "url": "https://api.github.com/repos/matrix-org/synapse/pulls/860", + "id": 73166014, + "html_url": "https://github.com/matrix-org/synapse/pull/860", + "diff_url": "https://github.com/matrix-org/synapse/pull/860.diff", + "patch_url": "https://github.com/matrix-org/synapse/pull/860.patch", + "issue_url": "https://api.github.com/repos/matrix-org/synapse/issues/860", + "number": 860, + "state": "open", + "locked": false, + "title": "Fix a bug caused by a change in auth_handler function", + "user": { + "login": "negzi", + "id": 6698393, + "avatar_url": "https://avatars.githubusercontent.com/u/6698393?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/negzi", + "html_url": "https://github.com/negzi", + "followers_url": "https://api.github.com/users/negzi/followers", + "following_url": "https://api.github.com/users/negzi/following{/other_user}", + "gists_url": "https://api.github.com/users/negzi/gists{/gist_id}", + "starred_url": "https://api.github.com/users/negzi/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/negzi/subscriptions", + "organizations_url": "https://api.github.com/users/negzi/orgs", + "repos_url": "https://api.github.com/users/negzi/repos", + "events_url": "https://api.github.com/users/negzi/events{/privacy}", + "received_events_url": "https://api.github.com/users/negzi/received_events", + "type": "User", + "site_admin": false + }, + "body": "Fix a bug caused by a change in auth_handler function\r\nalso fix the relevant unit test cases", + "created_at": "2016-06-09T07:03:30Z", + "updated_at": "2016-06-09T10:00:43Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": "1ceebdb4f9cf46d32e04bc411276bb17e1150fce", + "assignee": null, + "milestone": null, + "commits_url": "https://api.github.com/repos/matrix-org/synapse/pulls/860/commits", + "review_comments_url": "https://api.github.com/repos/matrix-org/synapse/pulls/860/comments", + "review_comment_url": "https://api.github.com/repos/matrix-org/synapse/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/matrix-org/synapse/issues/860/comments", + "statuses_url": "https://api.github.com/repos/matrix-org/synapse/statuses/6e7dc7c7dde377794c23d5db6f25ffacfb08e82a", + "head": { + "label": "negzi:bug_fix_get_or_create_user", + "ref": "bug_fix_get_or_create_user", + "sha": "6e7dc7c7dde377794c23d5db6f25ffacfb08e82a", + "user": { + "login": "negzi", + "id": 6698393, + "avatar_url": "https://avatars.githubusercontent.com/u/6698393?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/negzi", + "html_url": "https://github.com/negzi", + "followers_url": "https://api.github.com/users/negzi/followers", + "following_url": "https://api.github.com/users/negzi/following{/other_user}", + "gists_url": "https://api.github.com/users/negzi/gists{/gist_id}", + "starred_url": "https://api.github.com/users/negzi/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/negzi/subscriptions", + "organizations_url": "https://api.github.com/users/negzi/orgs", + "repos_url": "https://api.github.com/users/negzi/repos", + "events_url": "https://api.github.com/users/negzi/events{/privacy}", + "received_events_url": "https://api.github.com/users/negzi/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 60715519, + "name": "synapse", + "full_name": "negzi/synapse", + "owner": { + "login": "negzi", + "id": 6698393, + "avatar_url": "https://avatars.githubusercontent.com/u/6698393?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/negzi", + "html_url": "https://github.com/negzi", + "followers_url": "https://api.github.com/users/negzi/followers", + "following_url": "https://api.github.com/users/negzi/following{/other_user}", + "gists_url": "https://api.github.com/users/negzi/gists{/gist_id}", + "starred_url": "https://api.github.com/users/negzi/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/negzi/subscriptions", + "organizations_url": "https://api.github.com/users/negzi/orgs", + "repos_url": "https://api.github.com/users/negzi/repos", + "events_url": "https://api.github.com/users/negzi/events{/privacy}", + "received_events_url": "https://api.github.com/users/negzi/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/negzi/synapse", + "description": "Synapse: Matrix reference homeserver", + "fork": true, + "url": "https://api.github.com/repos/negzi/synapse", + "forks_url": "https://api.github.com/repos/negzi/synapse/forks", + "keys_url": "https://api.github.com/repos/negzi/synapse/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/negzi/synapse/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/negzi/synapse/teams", + "hooks_url": "https://api.github.com/repos/negzi/synapse/hooks", + "issue_events_url": "https://api.github.com/repos/negzi/synapse/issues/events{/number}", + "events_url": "https://api.github.com/repos/negzi/synapse/events", + "assignees_url": "https://api.github.com/repos/negzi/synapse/assignees{/user}", + "branches_url": "https://api.github.com/repos/negzi/synapse/branches{/branch}", + "tags_url": "https://api.github.com/repos/negzi/synapse/tags", + "blobs_url": "https://api.github.com/repos/negzi/synapse/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/negzi/synapse/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/negzi/synapse/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/negzi/synapse/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/negzi/synapse/statuses/{sha}", + "languages_url": "https://api.github.com/repos/negzi/synapse/languages", + "stargazers_url": "https://api.github.com/repos/negzi/synapse/stargazers", + "contributors_url": "https://api.github.com/repos/negzi/synapse/contributors", + "subscribers_url": "https://api.github.com/repos/negzi/synapse/subscribers", + "subscription_url": "https://api.github.com/repos/negzi/synapse/subscription", + "commits_url": "https://api.github.com/repos/negzi/synapse/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/negzi/synapse/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/negzi/synapse/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/negzi/synapse/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/negzi/synapse/contents/{+path}", + "compare_url": "https://api.github.com/repos/negzi/synapse/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/negzi/synapse/merges", + "archive_url": "https://api.github.com/repos/negzi/synapse/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/negzi/synapse/downloads", + "issues_url": "https://api.github.com/repos/negzi/synapse/issues{/number}", + "pulls_url": "https://api.github.com/repos/negzi/synapse/pulls{/number}", + "milestones_url": "https://api.github.com/repos/negzi/synapse/milestones{/number}", + "notifications_url": "https://api.github.com/repos/negzi/synapse/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/negzi/synapse/labels{/name}", + "releases_url": "https://api.github.com/repos/negzi/synapse/releases{/id}", + "deployments_url": "https://api.github.com/repos/negzi/synapse/deployments", + "created_at": "2016-06-08T17:09:39Z", + "updated_at": "2016-06-08T17:09:41Z", + "pushed_at": "2016-06-08T21:26:01Z", + "git_url": "git://github.com/negzi/synapse.git", + "ssh_url": "git@github.com:negzi/synapse.git", + "clone_url": "https://github.com/negzi/synapse.git", + "svn_url": "https://github.com/negzi/synapse", + "homepage": "http://matrix.org", + "size": 11243, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Python", + "has_issues": false, + "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" + } + }, + "base": { + "label": "matrix-org:develop", + "ref": "develop", + "sha": "b7fbc9bd9534c88e3c8ffdfab8447d9e9bb6eb75", + "user": { + "login": "matrix-org", + "id": 8418310, + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/matrix-org", + "html_url": "https://github.com/matrix-org", + "followers_url": "https://api.github.com/users/matrix-org/followers", + "following_url": "https://api.github.com/users/matrix-org/following{/other_user}", + "gists_url": "https://api.github.com/users/matrix-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matrix-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matrix-org/subscriptions", + "organizations_url": "https://api.github.com/users/matrix-org/orgs", + "repos_url": "https://api.github.com/users/matrix-org/repos", + "events_url": "https://api.github.com/users/matrix-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/matrix-org/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 22844864, + "name": "synapse", + "full_name": "matrix-org/synapse", + "owner": { + "login": "matrix-org", + "id": 8418310, + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/matrix-org", + "html_url": "https://github.com/matrix-org", + "followers_url": "https://api.github.com/users/matrix-org/followers", + "following_url": "https://api.github.com/users/matrix-org/following{/other_user}", + "gists_url": "https://api.github.com/users/matrix-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matrix-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matrix-org/subscriptions", + "organizations_url": "https://api.github.com/users/matrix-org/orgs", + "repos_url": "https://api.github.com/users/matrix-org/repos", + "events_url": "https://api.github.com/users/matrix-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/matrix-org/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/matrix-org/synapse", + "description": "Synapse: Matrix reference homeserver", + "fork": false, + "url": "https://api.github.com/repos/matrix-org/synapse", + "forks_url": "https://api.github.com/repos/matrix-org/synapse/forks", + "keys_url": "https://api.github.com/repos/matrix-org/synapse/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/matrix-org/synapse/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/matrix-org/synapse/teams", + "hooks_url": "https://api.github.com/repos/matrix-org/synapse/hooks", + "issue_events_url": "https://api.github.com/repos/matrix-org/synapse/issues/events{/number}", + "events_url": "https://api.github.com/repos/matrix-org/synapse/events", + "assignees_url": "https://api.github.com/repos/matrix-org/synapse/assignees{/user}", + "branches_url": "https://api.github.com/repos/matrix-org/synapse/branches{/branch}", + "tags_url": "https://api.github.com/repos/matrix-org/synapse/tags", + "blobs_url": "https://api.github.com/repos/matrix-org/synapse/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/matrix-org/synapse/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/matrix-org/synapse/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/matrix-org/synapse/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/matrix-org/synapse/statuses/{sha}", + "languages_url": "https://api.github.com/repos/matrix-org/synapse/languages", + "stargazers_url": "https://api.github.com/repos/matrix-org/synapse/stargazers", + "contributors_url": "https://api.github.com/repos/matrix-org/synapse/contributors", + "subscribers_url": "https://api.github.com/repos/matrix-org/synapse/subscribers", + "subscription_url": "https://api.github.com/repos/matrix-org/synapse/subscription", + "commits_url": "https://api.github.com/repos/matrix-org/synapse/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/matrix-org/synapse/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/matrix-org/synapse/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/matrix-org/synapse/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/matrix-org/synapse/contents/{+path}", + "compare_url": "https://api.github.com/repos/matrix-org/synapse/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/matrix-org/synapse/merges", + "archive_url": "https://api.github.com/repos/matrix-org/synapse/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/matrix-org/synapse/downloads", + "issues_url": "https://api.github.com/repos/matrix-org/synapse/issues{/number}", + "pulls_url": "https://api.github.com/repos/matrix-org/synapse/pulls{/number}", + "milestones_url": "https://api.github.com/repos/matrix-org/synapse/milestones{/number}", + "notifications_url": "https://api.github.com/repos/matrix-org/synapse/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/matrix-org/synapse/labels{/name}", + "releases_url": "https://api.github.com/repos/matrix-org/synapse/releases{/id}", + "deployments_url": "https://api.github.com/repos/matrix-org/synapse/deployments", + "created_at": "2014-08-11T15:51:42Z", + "updated_at": "2016-06-09T00:24:47Z", + "pushed_at": "2016-06-09T09:58:32Z", + "git_url": "git://github.com/matrix-org/synapse.git", + "ssh_url": "git@github.com:matrix-org/synapse.git", + "clone_url": "https://github.com/matrix-org/synapse.git", + "svn_url": "https://github.com/matrix-org/synapse", + "homepage": "http://matrix.org", + "size": 17364, + "stargazers_count": 899, + "watchers_count": 899, + "language": "Python", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 92, + "mirror_url": null, + "open_issues_count": 16, + "forks": 92, + "open_issues": 16, + "watchers": 899, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/matrix-org/synapse/pulls/860" + }, + "html": { + "href": "https://github.com/matrix-org/synapse/pull/860" + }, + "issue": { + "href": "https://api.github.com/repos/matrix-org/synapse/issues/860" + }, + "comments": { + "href": "https://api.github.com/repos/matrix-org/synapse/issues/860/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/matrix-org/synapse/pulls/860/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/matrix-org/synapse/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/matrix-org/synapse/pulls/860/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/matrix-org/synapse/statuses/6e7dc7c7dde377794c23d5db6f25ffacfb08e82a" + } + } + }, + "repository": { + "id": 22844864, + "name": "synapse", + "full_name": "matrix-org/synapse", + "owner": { + "login": "matrix-org", + "id": 8418310, + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/matrix-org", + "html_url": "https://github.com/matrix-org", + "followers_url": "https://api.github.com/users/matrix-org/followers", + "following_url": "https://api.github.com/users/matrix-org/following{/other_user}", + "gists_url": "https://api.github.com/users/matrix-org/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matrix-org/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matrix-org/subscriptions", + "organizations_url": "https://api.github.com/users/matrix-org/orgs", + "repos_url": "https://api.github.com/users/matrix-org/repos", + "events_url": "https://api.github.com/users/matrix-org/events{/privacy}", + "received_events_url": "https://api.github.com/users/matrix-org/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/matrix-org/synapse", + "description": "Synapse: Matrix reference homeserver", + "fork": false, + "url": "https://api.github.com/repos/matrix-org/synapse", + "forks_url": "https://api.github.com/repos/matrix-org/synapse/forks", + "keys_url": "https://api.github.com/repos/matrix-org/synapse/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/matrix-org/synapse/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/matrix-org/synapse/teams", + "hooks_url": "https://api.github.com/repos/matrix-org/synapse/hooks", + "issue_events_url": "https://api.github.com/repos/matrix-org/synapse/issues/events{/number}", + "events_url": "https://api.github.com/repos/matrix-org/synapse/events", + "assignees_url": "https://api.github.com/repos/matrix-org/synapse/assignees{/user}", + "branches_url": "https://api.github.com/repos/matrix-org/synapse/branches{/branch}", + "tags_url": "https://api.github.com/repos/matrix-org/synapse/tags", + "blobs_url": "https://api.github.com/repos/matrix-org/synapse/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/matrix-org/synapse/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/matrix-org/synapse/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/matrix-org/synapse/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/matrix-org/synapse/statuses/{sha}", + "languages_url": "https://api.github.com/repos/matrix-org/synapse/languages", + "stargazers_url": "https://api.github.com/repos/matrix-org/synapse/stargazers", + "contributors_url": "https://api.github.com/repos/matrix-org/synapse/contributors", + "subscribers_url": "https://api.github.com/repos/matrix-org/synapse/subscribers", + "subscription_url": "https://api.github.com/repos/matrix-org/synapse/subscription", + "commits_url": "https://api.github.com/repos/matrix-org/synapse/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/matrix-org/synapse/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/matrix-org/synapse/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/matrix-org/synapse/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/matrix-org/synapse/contents/{+path}", + "compare_url": "https://api.github.com/repos/matrix-org/synapse/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/matrix-org/synapse/merges", + "archive_url": "https://api.github.com/repos/matrix-org/synapse/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/matrix-org/synapse/downloads", + "issues_url": "https://api.github.com/repos/matrix-org/synapse/issues{/number}", + "pulls_url": "https://api.github.com/repos/matrix-org/synapse/pulls{/number}", + "milestones_url": "https://api.github.com/repos/matrix-org/synapse/milestones{/number}", + "notifications_url": "https://api.github.com/repos/matrix-org/synapse/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/matrix-org/synapse/labels{/name}", + "releases_url": "https://api.github.com/repos/matrix-org/synapse/releases{/id}", + "deployments_url": "https://api.github.com/repos/matrix-org/synapse/deployments", + "created_at": "2014-08-11T15:51:42Z", + "updated_at": "2016-06-09T00:24:47Z", + "pushed_at": "2016-06-09T09:58:32Z", + "git_url": "git://github.com/matrix-org/synapse.git", + "ssh_url": "git@github.com:matrix-org/synapse.git", + "clone_url": "https://github.com/matrix-org/synapse.git", + "svn_url": "https://github.com/matrix-org/synapse", + "homepage": "http://matrix.org", + "size": 17364, + "stargazers_count": 899, + "watchers_count": 899, + "language": "Python", + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 92, + "mirror_url": null, + "open_issues_count": 16, + "forks": 92, + "open_issues": 16, + "watchers": 899, + "default_branch": "master" + }, + "organization": { + "login": "matrix-org", + "id": 8418310, + "url": "https://api.github.com/orgs/matrix-org", + "repos_url": "https://api.github.com/orgs/matrix-org/repos", + "events_url": "https://api.github.com/orgs/matrix-org/events", + "hooks_url": "https://api.github.com/orgs/matrix-org/hooks", + "issues_url": "https://api.github.com/orgs/matrix-org/issues", + "members_url": "https://api.github.com/orgs/matrix-org/members{/member}", + "public_members_url": "https://api.github.com/orgs/matrix-org/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/8418310?v=3", + "description": "A new basis for open, interoperable, decentralised real-time communication" + }, + "sender": { + "login": "erikjohnston", + "id": 8428120, + "avatar_url": "https://avatars.githubusercontent.com/u/8428120?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/erikjohnston", + "html_url": "https://github.com/erikjohnston", + "followers_url": "https://api.github.com/users/erikjohnston/followers", + "following_url": "https://api.github.com/users/erikjohnston/following{/other_user}", + "gists_url": "https://api.github.com/users/erikjohnston/gists{/gist_id}", + "starred_url": "https://api.github.com/users/erikjohnston/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/erikjohnston/subscriptions", + "organizations_url": "https://api.github.com/users/erikjohnston/orgs", + "repos_url": "https://api.github.com/users/erikjohnston/repos", + "events_url": "https://api.github.com/users/erikjohnston/events{/privacy}", + "received_events_url": "https://api.github.com/users/erikjohnston/received_events", + "type": "User", + "site_admin": false + } + }`, + "[matrix-org/synapse] erikjohnston made a line comment on negzi's pull request #860 (assignee: None): Fix a bug caused by a change in auth_handler function - https://github.com/matrix-org/synapse/pull/860#discussion_r66413356", + "matrix-org/synapse", + }, +} + +func TestParseGithubEvent(t *testing.T) { + for _, gh := range ghtests { + outHTML, outRepo, outErr := parseGithubEvent(gh.eventType, []byte(gh.jsonBody)) + if outErr != nil { + t.Fatal(outErr) + } + if strings.TrimSpace(outHTML) != strings.TrimSpace(gh.outHTML) { + t.Fatalf("ParseGithubEvent(%s) => HTML output does not match. Got:\n%s\n\nExpected:\n%s", gh.eventType, + strings.TrimSpace(outHTML), strings.TrimSpace(gh.outHTML)) + } + if outRepo == nil { + t.Fatalf("ParseGithubEvent(%s) => Repo is nil", gh.eventType) + } + if *outRepo.FullName != gh.outFullRepo { + t.Fatalf("ParseGithubEvent(%s) => Repo: Want %s got %s", gh.eventType, gh.outFullRepo, *outRepo.FullName) + } + } +} From 41ba67235adb00ac3693b75b664ad298aa985e84 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Mon, 1 Aug 2016 17:48:12 +0100 Subject: [PATCH 4/4] Add handler for /services/hooks/{serviceType} Defers through to the given service's OnReceiveWebhook method. --- src/github.com/matrix-org/go-neb/api.go | 13 +++++++++++++ src/github.com/matrix-org/go-neb/goneb.go | 1 + .../matrix-org/go-neb/services/echo/echo.go | 2 +- .../matrix-org/go-neb/services/github/github.go | 2 +- .../go-neb/services/github/webhook/webhook.go | 2 +- src/github.com/matrix-org/go-neb/types/types.go | 2 +- 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/github.com/matrix-org/go-neb/api.go b/src/github.com/matrix-org/go-neb/api.go index cfec0dc..8a07874 100644 --- a/src/github.com/matrix-org/go-neb/api.go +++ b/src/github.com/matrix-org/go-neb/api.go @@ -7,6 +7,7 @@ import ( "github.com/matrix-org/go-neb/errors" "github.com/matrix-org/go-neb/types" "net/http" + "strings" ) type heartbeatHandler struct{} @@ -15,6 +16,18 @@ func (*heartbeatHandler) OnIncomingRequest(req *http.Request) (interface{}, *err return &struct{}{}, nil } +func handleWebhook(w http.ResponseWriter, req *http.Request) { + segments := strings.Split(req.URL.Path, "/") + // last path segment is the service type which we will pass the incoming request to + srvType := segments[len(segments)-1] + service := types.CreateService("", srvType) + if service == nil { + w.WriteHeader(404) + return + } + service.OnReceiveWebhook(w, req) +} + type configureClientHandler struct { db *database.ServiceDB clients *clients.Clients diff --git a/src/github.com/matrix-org/go-neb/goneb.go b/src/github.com/matrix-org/go-neb/goneb.go index 062970b..7ba75c2 100644 --- a/src/github.com/matrix-org/go-neb/goneb.go +++ b/src/github.com/matrix-org/go-neb/goneb.go @@ -31,6 +31,7 @@ func main() { http.Handle("/test", server.MakeJSONAPI(&heartbeatHandler{})) http.Handle("/admin/configureClient", server.MakeJSONAPI(&configureClientHandler{db: db, clients: clients})) http.Handle("/admin/configureService", server.MakeJSONAPI(&configureServiceHandler{db: db, clients: clients})) + http.HandleFunc("/services/hooks/", handleWebhook) http.ListenAndServe(bindAddress, nil) } diff --git a/src/github.com/matrix-org/go-neb/services/echo/echo.go b/src/github.com/matrix-org/go-neb/services/echo/echo.go index ccdc5e4..11655d8 100644 --- a/src/github.com/matrix-org/go-neb/services/echo/echo.go +++ b/src/github.com/matrix-org/go-neb/services/echo/echo.go @@ -30,7 +30,7 @@ func (e *echoService) Plugin(roomID string) plugin.Plugin { }, } } -func (e *echoService) OnReceiveWebhook(w http.ResponseWriter, req http.Request) { +func (e *echoService) OnReceiveWebhook(w http.ResponseWriter, req *http.Request) { w.WriteHeader(200) // Do nothing } diff --git a/src/github.com/matrix-org/go-neb/services/github/github.go b/src/github.com/matrix-org/go-neb/services/github/github.go index 9d86414..0796a79 100644 --- a/src/github.com/matrix-org/go-neb/services/github/github.go +++ b/src/github.com/matrix-org/go-neb/services/github/github.go @@ -62,7 +62,7 @@ func (s *githubService) Plugin(roomID string) plugin.Plugin { }, } } -func (s *githubService) OnReceiveWebhook(w http.ResponseWriter, req http.Request) { +func (s *githubService) OnReceiveWebhook(w http.ResponseWriter, req *http.Request) { // defer entirely to the webhook package webhook.OnReceiveRequest(w, req, "") } diff --git a/src/github.com/matrix-org/go-neb/services/github/webhook/webhook.go b/src/github.com/matrix-org/go-neb/services/github/webhook/webhook.go index c11cc11..3def2ca 100644 --- a/src/github.com/matrix-org/go-neb/services/github/webhook/webhook.go +++ b/src/github.com/matrix-org/go-neb/services/github/webhook/webhook.go @@ -16,7 +16,7 @@ import ( // OnReceiveRequest processes incoming github webhook requests. The secretToken // parameter is optional. -func OnReceiveRequest(w http.ResponseWriter, r http.Request, secretToken string) { +func OnReceiveRequest(w http.ResponseWriter, r *http.Request, secretToken string) { // Verify the HMAC signature if NEB was configured with a secret token eventType := r.Header.Get("X-GitHub-Event") signatureSHA1 := r.Header.Get("X-Hub-Signature") diff --git a/src/github.com/matrix-org/go-neb/types/types.go b/src/github.com/matrix-org/go-neb/types/types.go index c5dc8ce..dcf42e6 100644 --- a/src/github.com/matrix-org/go-neb/types/types.go +++ b/src/github.com/matrix-org/go-neb/types/types.go @@ -32,7 +32,7 @@ type Service interface { ServiceType() string RoomIDs() []string Plugin(roomID string) plugin.Plugin - OnReceiveWebhook(w http.ResponseWriter, req http.Request) + OnReceiveWebhook(w http.ResponseWriter, req *http.Request) } var servicesByType = map[string]func(string) Service{}