From 642df989c0adb6993b7bb8b8d149d43723916426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?U=C4=9Fur=20=C3=96zy=C4=B1lmazel?= Date: Mon, 13 Jan 2025 19:29:41 +0300 Subject: [PATCH] feat: add ping payload for organization --- github/github.go | 22 +++++++++- github/github_test.go | 10 +++++ github/payload.go | 58 +++++++++++++++++++++++++ testdata/github/ping-organization.json | 59 ++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 testdata/github/ping-organization.json diff --git a/github/github.go b/github/github.go index 7411e0c..f185c54 100644 --- a/github/github.go +++ b/github/github.go @@ -90,6 +90,15 @@ const ( IssueSubtype EventSubtype = "issues" ) +// InstallationTargetType defines a GitHub Hook HTTP Header type +type InstallationTargetType string + +// GitHub hook HTTP header installation target types +const ( + InstallationTargetTypeRepository InstallationTargetType = "repository" + InstallationTargetTypeOrganization InstallationTargetType = "organization" +) + // Option is a configuration option for the webhook type Option func(*Webhook) error @@ -178,6 +187,12 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) } } + targetType := InstallationTargetTypeRepository + instTargetType := InstallationTargetType(r.Header.Get("X-GitHub-Hook-Installation-Target-Type")) + if instTargetType == InstallationTargetTypeOrganization { + targetType = InstallationTargetTypeOrganization + } + switch gitHubEvent { case CheckRunEvent: var pl CheckRunPayload @@ -272,7 +287,12 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) err = json.Unmarshal([]byte(payload), &pl) return pl, err case PingEvent: - var pl PingPayload + if targetType == InstallationTargetTypeRepository { + var pl PingPayload + err = json.Unmarshal([]byte(payload), &pl) + return pl, err + } + var pl PingOrganizationPayload err = json.Unmarshal([]byte(payload), &pl) return pl, err case ProjectCardEvent: diff --git a/github/github_test.go b/github/github_test.go index 66e7408..366a943 100644 --- a/github/github_test.go +++ b/github/github_test.go @@ -366,6 +366,16 @@ func TestWebhooks(t *testing.T) { "X-Github-Event": []string{"ping"}, }, }, + { + name: "PingEvent", + event: PingEvent, + typ: PingOrganizationPayload{}, + filename: "../testdata/github/ping-organization.json", + headers: http.Header{ + "X-Github-Event": []string{"ping"}, + "X-GitHub-Hook-Installation-Target-Type": []string{"organization"}, + }, + }, { name: "ProjectCardEvent", event: ProjectCardEvent, diff --git a/github/payload.go b/github/payload.go index 986d8a1..49f0976 100644 --- a/github/payload.go +++ b/github/payload.go @@ -3336,6 +3336,64 @@ type PingPayload struct { } `json:"sender"` } +// PingOrganizationPayload contains the information for GitHub's organization ping hook event +type PingOrganizationPayload struct { + Zen string `json:"zen"` + 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"` + Config struct { + ContentType string `json:"content_type"` + InsecureSSL string `json:"insecure_ssl"` + Secret string `json:"secret"` + URL string `json:"url"` + } `json:"config"` + UpdatedAt time.Time `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + URL string `json:"url"` + PingURL string `json:"ping_url"` + DeliveriesURL string `json:"deliveries_url"` + } `json:"hook"` + Organization struct { + Login string `json:"login"` + ID int64 `json:"id"` + NodeID string `json:"node_id"` + URL string `json:"url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + HooksURL string `json:"hooks_url"` + IssuesURL string `json:"issues_url"` + MembersURL string `json:"members_url"` + PublicMembersURL string `json:"public_members_url"` + AvatarURL string `json:"avatar_url"` + Description string `json:"description"` + } `json:"organization"` + Sender struct { + Login string `json:"login"` + ID int64 `json:"id"` + NodeID string `json:"node_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"` +} + // ProjectCardPayload contains the information for GitHub's project_payload hook event type ProjectCardPayload struct { Action string `json:"action"` diff --git a/testdata/github/ping-organization.json b/testdata/github/ping-organization.json new file mode 100644 index 0000000..96c70e9 --- /dev/null +++ b/testdata/github/ping-organization.json @@ -0,0 +1,59 @@ +{ + "zen": "Avoid administrative distraction.", + "hook_id": 523968606, + "hook": { + "type": "Organization", + "id": 523968606, + "name": "web", + "active": true, + "events": [ + "*" + ], + "config": { + "content_type": "json", + "insecure_ssl": "0", + "secret": "********", + "url": "https://github.devchain.network/v1/webhook/github" + }, + "updated_at": "2025-01-13T07:08:59Z", + "created_at": "2025-01-13T07:08:59Z", + "url": "https://api.github.com/orgs/vbyazilim/hooks/523968606", + "ping_url": "https://api.github.com/orgs/vbyazilim/hooks/523968606/pings", + "deliveries_url": "https://api.github.com/orgs/vbyazilim/hooks/523968606/deliveries" + }, + "organization": { + "login": "vbyazilim", + "id": 34422235, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjM0NDIyMjM1", + "url": "https://api.github.com/orgs/vbyazilim", + "repos_url": "https://api.github.com/orgs/vbyazilim/repos", + "events_url": "https://api.github.com/orgs/vbyazilim/events", + "hooks_url": "https://api.github.com/orgs/vbyazilim/hooks", + "issues_url": "https://api.github.com/orgs/vbyazilim/issues", + "members_url": "https://api.github.com/orgs/vbyazilim/members{/member}", + "public_members_url": "https://api.github.com/orgs/vbyazilim/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/34422235?v=4", + "description": "Software Development, Training and Consultancy" + }, + "sender": { + "login": "vigo", + "id": 82952, + "node_id": "MDQ6VXNlcjgyOTUy", + "avatar_url": "https://avatars.githubusercontent.com/u/82952?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vigo", + "html_url": "https://github.com/vigo", + "followers_url": "https://api.github.com/users/vigo/followers", + "following_url": "https://api.github.com/users/vigo/following{/other_user}", + "gists_url": "https://api.github.com/users/vigo/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vigo/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vigo/subscriptions", + "organizations_url": "https://api.github.com/users/vigo/orgs", + "repos_url": "https://api.github.com/users/vigo/repos", + "events_url": "https://api.github.com/users/vigo/events{/privacy}", + "received_events_url": "https://api.github.com/users/vigo/received_events", + "type": "User", + "user_view_type": "public", + "site_admin": false + } +} \ No newline at end of file