diff --git a/github/github.go b/github/github.go index 2702d1f..2b5c933 100644 --- a/github/github.go +++ b/github/github.go @@ -36,6 +36,8 @@ const ( DeploymentStatusEvent Event = "deployment_status" ForkEvent Event = "fork" GollumEvent Event = "gollum" + InstallationEvent Event = "installation" + IntegrationInstallationEvent Event = "integration_installation" IssueCommentEvent Event = "issue_comment" IssuesEvent Event = "issues" LabelEvent Event = "label" @@ -45,6 +47,7 @@ const ( OrganizationEvent Event = "organization" OrgBlockEvent Event = "org_block" PageBuildEvent Event = "page_build" + PingEvent Event = "ping" ProjectCardEvent Event = "project_card" ProjectColumnEvent Event = "project_column" ProjectEvent Event = "project" @@ -179,6 +182,10 @@ func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) { var g GollumPayload json.Unmarshal([]byte(payload), &g) hook.runProcessPayloadFunc(fn, g, hd) + case InstallationEvent, IntegrationInstallationEvent: + var i InstallationPayload + json.Unmarshal([]byte(payload), &i) + hook.runProcessPayloadFunc(fn, i, hd) case IssueCommentEvent: var i IssueCommentPayload json.Unmarshal([]byte(payload), &i) @@ -215,6 +222,10 @@ func (hook Webhook) ParsePayload(w http.ResponseWriter, r *http.Request) { var p PageBuildPayload json.Unmarshal([]byte(payload), &p) hook.runProcessPayloadFunc(fn, p, hd) + case PingEvent: + var p PingPayload + json.Unmarshal([]byte(payload), &p) + hook.runProcessPayloadFunc(fn, p, hd) case ProjectCardEvent: var p ProjectCardPayload json.Unmarshal([]byte(payload), &p) diff --git a/github/github_test.go b/github/github_test.go index 58c74ad..af606ca 100644 --- a/github/github_test.go +++ b/github/github_test.go @@ -48,6 +48,8 @@ func TestMain(m *testing.M) { DeploymentStatusEvent, ForkEvent, GollumEvent, + InstallationEvent, + IntegrationInstallationEvent, IssueCommentEvent, IssuesEvent, LabelEvent, @@ -57,6 +59,7 @@ func TestMain(m *testing.M) { OrganizationEvent, OrgBlockEvent, PageBuildEvent, + PingEvent, ProjectCardEvent, ProjectColumnEvent, ProjectEvent, @@ -1309,6 +1312,186 @@ func TestGollumEvent(t *testing.T) { Equal(t, resp.StatusCode, http.StatusOK) } +func TestInstallationEvent(t *testing.T) { + + payload := `{ + "action": "created", + "installation": { + "id": 80429, + "account": { + "login": "PombeirP", + "id": 138074, + "avatar_url": "https://avatars1.githubusercontent.com/u/138074?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/PombeirP", + "html_url": "https://github.com/PombeirP", + "followers_url": "https://api.github.com/users/PombeirP/followers", + "following_url": "https://api.github.com/users/PombeirP/following{/other_user}", + "gists_url": "https://api.github.com/users/PombeirP/gists{/gist_id}", + "starred_url": "https://api.github.com/users/PombeirP/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/PombeirP/subscriptions", + "organizations_url": "https://api.github.com/users/PombeirP/orgs", + "repos_url": "https://api.github.com/users/PombeirP/repos", + "events_url": "https://api.github.com/users/PombeirP/events{/privacy}", + "received_events_url": "https://api.github.com/users/PombeirP/received_events", + "type": "User", + "site_admin": false + }, + "repository_selection": "selected", + "access_tokens_url": "https://api.github.com/installations/80429/access_tokens", + "repositories_url": "https://api.github.com/installation/repositories", + "html_url": "https://github.com/settings/installations/80429", + "app_id": 8157, + "target_id": 138074, + "target_type": "User", + "permissions": { + "repository_projects": "write", + "issues": "read", + "metadata": "read", + "pull_requests": "read" + }, + "events": [ + "pull_request" + ], + "created_at": 1516025475, + "updated_at": 1516025475, + "single_file_name": null + }, + "repositories": [ + { + "id": 117381220, + "name": "status-github-bot", + "full_name": "PombeirP/status-github-bot" + } + ], + "sender": { + "login": "PombeirP", + "id": 138074, + "avatar_url": "https://avatars1.githubusercontent.com/u/138074?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/PombeirP", + "html_url": "https://github.com/PombeirP", + "followers_url": "https://api.github.com/users/PombeirP/followers", + "following_url": "https://api.github.com/users/PombeirP/following{/other_user}", + "gists_url": "https://api.github.com/users/PombeirP/gists{/gist_id}", + "starred_url": "https://api.github.com/users/PombeirP/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/PombeirP/subscriptions", + "organizations_url": "https://api.github.com/users/PombeirP/orgs", + "repos_url": "https://api.github.com/users/PombeirP/repos", + "events_url": "https://api.github.com/users/PombeirP/events{/privacy}", + "received_events_url": "https://api.github.com/users/PombeirP/received_events", + "type": "User", + "site_admin": false + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Github-Event", "installation") + req.Header.Set("X-Hub-Signature", "sha1=987338c6e5c21794ab6c258abe51284f9b1df728") + + Equal(t, err, nil) + + client := &http.Client{} + resp, err := client.Do(req) + Equal(t, err, nil) + + defer resp.Body.Close() + + Equal(t, resp.StatusCode, http.StatusOK) +} + +func TestIntegrationInstallationEvent(t *testing.T) { + + payload := `{ + "action": "created", + "installation": { + "id": 80429, + "account": { + "login": "PombeirP", + "id": 138074, + "avatar_url": "https://avatars1.githubusercontent.com/u/138074?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/PombeirP", + "html_url": "https://github.com/PombeirP", + "followers_url": "https://api.github.com/users/PombeirP/followers", + "following_url": "https://api.github.com/users/PombeirP/following{/other_user}", + "gists_url": "https://api.github.com/users/PombeirP/gists{/gist_id}", + "starred_url": "https://api.github.com/users/PombeirP/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/PombeirP/subscriptions", + "organizations_url": "https://api.github.com/users/PombeirP/orgs", + "repos_url": "https://api.github.com/users/PombeirP/repos", + "events_url": "https://api.github.com/users/PombeirP/events{/privacy}", + "received_events_url": "https://api.github.com/users/PombeirP/received_events", + "type": "User", + "site_admin": false + }, + "repository_selection": "selected", + "access_tokens_url": "https://api.github.com/installations/80429/access_tokens", + "repositories_url": "https://api.github.com/installation/repositories", + "html_url": "https://github.com/settings/installations/80429", + "app_id": 8157, + "target_id": 138074, + "target_type": "User", + "permissions": { + "repository_projects": "write", + "issues": "read", + "metadata": "read", + "pull_requests": "read" + }, + "events": [ + "pull_request" + ], + "created_at": 1516025475, + "updated_at": 1516025475, + "single_file_name": null + }, + "repositories": [ + { + "id": 117381220, + "name": "status-github-bot", + "full_name": "PombeirP/status-github-bot" + } + ], + "sender": { + "login": "PombeirP", + "id": 138074, + "avatar_url": "https://avatars1.githubusercontent.com/u/138074?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/PombeirP", + "html_url": "https://github.com/PombeirP", + "followers_url": "https://api.github.com/users/PombeirP/followers", + "following_url": "https://api.github.com/users/PombeirP/following{/other_user}", + "gists_url": "https://api.github.com/users/PombeirP/gists{/gist_id}", + "starred_url": "https://api.github.com/users/PombeirP/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/PombeirP/subscriptions", + "organizations_url": "https://api.github.com/users/PombeirP/orgs", + "repos_url": "https://api.github.com/users/PombeirP/repos", + "events_url": "https://api.github.com/users/PombeirP/events{/privacy}", + "received_events_url": "https://api.github.com/users/PombeirP/received_events", + "type": "User", + "site_admin": false + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Github-Event", "integration_installation") + req.Header.Set("X-Hub-Signature", "sha1=987338c6e5c21794ab6c258abe51284f9b1df728") + + Equal(t, err, nil) + + client := &http.Client{} + resp, err := client.Do(req) + Equal(t, err, nil) + + defer resp.Body.Close() + + Equal(t, resp.StatusCode, http.StatusOK) +} + func TestIssueCommentEvent(t *testing.T) { payload := `{ @@ -2560,6 +2743,48 @@ func TestPageBuildEvent(t *testing.T) { Equal(t, resp.StatusCode, http.StatusOK) } +func TestPingEvent(t *testing.T) { + + payload := `{ + "zen": "Keep it logically awesome.", + "hook_id": 20081052, + "hook": { + "type": "App", + "id": 20081052, + "name": "web", + "active": true, + "events": [ + "pull_request" + ], + "config": { + "content_type": "json", + "insecure_ssl": "0", + "secret": "********", + "url": "https://ngrok.io/webhook" + }, + "updated_at": "2018-01-15T10:48:54Z", + "created_at": "2018-01-15T10:48:54Z", + "app_id": 8157 + } +} +` + + req, err := http.NewRequest("POST", "http://127.0.0.1:3010/webhooks", bytes.NewBuffer([]byte(payload))) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Github-Event", "ping") + req.Header.Set("X-Hub-Signature", "sha1=f82267eb5c6408d5986209da906747f57c11b33b") + + Equal(t, err, nil) + + client := &http.Client{} + resp, err := client.Do(req) + Equal(t, err, nil) + + defer resp.Body.Close() + + Equal(t, resp.StatusCode, http.StatusOK) +} + func TestProjectCardEvent(t *testing.T) { payload := `{ diff --git a/github/payload.go b/github/payload.go index 053c6ec..dbf8ed1 100644 --- a/github/payload.go +++ b/github/payload.go @@ -1007,6 +1007,74 @@ type GollumPayload struct { } `json:"sender"` } +// InstallationPayload contains the information for GitHub's installation and integration_installation hook events +type InstallationPayload struct { + Action string `json:"action"` + Installation struct { + ID int64 `json:"id"` + Account struct { + Login string `json:"login"` + ID int64 `json:"id"` + AvatarURL string `json:"avatar_url"` + GravatarID string `json:"gravatar_id"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + OrganizationsURL string `json:"organizations_url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + ReceivedEventsURL string `json:"received_events_url"` + Type string `json:"type"` + SiteAdmin bool `json:"site_admin"` + } `json:"account"` + RepositorySelection string `json:"repository_selection"` + AccessTokensURL string `json:"access_tokens_url"` + RepositoriesURL string `json:"repositories_url"` + HTMLURL string `json:"html_url"` + AppID int `json:"app_id"` + TargetID int `json:"target_id"` + TargetType string `json:"target_type"` + Permissions struct { + Issues string `json:"issues"` + Metadata string `json:"metadata"` + PullRequests string `json:"pull_requests"` + RepositoryProjects string `json:"repository_projects"` + } `json:"permissions"` + Events []string `json:"events"` + CreatedAt int64 `json:"created_at"` + UpdatedAt int64 `json:"updated_at"` + SingleFileName *string `json:"single_file_name"` + } `json:"installation"` + Repositories []struct { + ID int64 `json:"id"` + Name string `json:"name"` + FullName string `json:"full_name"` + } `json:"repositories"` + Sender struct { + Login string `json:"login"` + ID int64 `json:"id"` + AvatarURL string `json:"avatar_url"` + GravatarID string `json:"gravatar_id"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + OrganizationsURL string `json:"organizations_url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + ReceivedEventsURL string `json:"received_events_url"` + Type string `json:"type"` + SiteAdmin bool `json:"site_admin"` + } `json:"sender"` +} + // IssueCommentPayload contains the information for GitHub's issue_comment hook event type IssueCommentPayload struct { Action string `json:"action"` @@ -2094,6 +2162,27 @@ type PageBuildPayload struct { } `json:"sender"` } +// PingPayload contains the information for GitHub's ping hook event +type PingPayload struct { + HookID int `json:"hook_id"` + Hook struct { + Type string `json:"type"` + ID int64 `json:"id"` + Name string `json:"name"` + Active bool `json:"active"` + Events []string `json:"events"` + AppID int `json:"app_id"` + Config struct { + ContentType string `json:"content_type"` + InsecureSSL int `json:"insecure_ssl"` + Secret string `json:"secret"` + URL string `json:"url"` + } `json:"config"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + } `json:"hook"` +} + // ProjectCardPayload contains the information for GitHub's project_payload hook event type ProjectCardPayload struct { Action string `json:"action"`