diff --git a/pkg/http/github_webhook_trigger.go b/pkg/http/github_webhook_trigger.go new file mode 100644 index 00000000..05ef10b4 --- /dev/null +++ b/pkg/http/github_webhook_trigger.go @@ -0,0 +1,278 @@ +package http + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "github.com/keel-hq/keel/types" + + "github.com/prometheus/client_golang/prometheus" + + log "github.com/sirupsen/logrus" +) + +var newGithubWebhooksCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Name: "Github_webhook_requests_total", + Help: "How many /v1/webhooks/github requests processed, partitioned by image.", + }, + []string{"image"}, +) + +func init() { + prometheus.MustRegister(newGithubWebhooksCounter) +} + +type githubWebhook struct { + Action string `json:"action"` + RegistryPackage struct { + CreatedAt string `json:"created_at"` + HTMLURL string `json:"html_url"` + ID int `json:"id"` + Name string `json:"name"` + Owner struct { + AvatarURL string `json:"avatar_url"` + EventsURL string `json:"events_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + GravatarID string `json:"gravatar_id"` + HTMLURL string `json:"html_url"` + ID int `json:"id"` + Login string `json:"login"` + NodeID string `json:"node_id"` + OrganizationsURL string `json:"organizations_url"` + ReceivedEventsURL string `json:"received_events_url"` + ReposURL string `json:"repos_url"` + SiteAdmin bool `json:"site_admin"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + Type string `json:"type"` + URL string `json:"url"` + } `json:"owner"` + PackageType string `json:"package_type"` + PackageVersion struct { + Author struct { + AvatarURL string `json:"avatar_url"` + EventsURL string `json:"events_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + GravatarID string `json:"gravatar_id"` + HTMLURL string `json:"html_url"` + ID int `json:"id"` + Login string `json:"login"` + NodeID string `json:"node_id"` + OrganizationsURL string `json:"organizations_url"` + ReceivedEventsURL string `json:"received_events_url"` + ReposURL string `json:"repos_url"` + SiteAdmin bool `json:"site_admin"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + Type string `json:"type"` + URL string `json:"url"` + } `json:"author"` + Body string `json:"body"` + BodyHTML string `json:"body_html"` + CreatedAt string `json:"created_at"` + HTMLURL string `json:"html_url"` + ID int `json:"id"` + InstallationCommand string `json:"installation_command"` + Manifest string `json:"manifest"` + Metadata []interface{} `json:"metadata"` + PackageFiles []struct { + ContentType string `json:"content_type"` + CreatedAt string `json:"created_at"` + DownloadURL string `json:"download_url"` + ID int `json:"id"` + Md5 interface{} `json:"md5"` + Name string `json:"name"` + Sha1 interface{} `json:"sha1"` + Sha256 string `json:"sha256"` + Size int `json:"size"` + State string `json:"state"` + UpdatedAt string `json:"updated_at"` + } `json:"package_files"` + Summary string `json:"summary"` + TargetCommitish string `json:"target_commitish"` + TargetOid string `json:"target_oid"` + UpdatedAt string `json:"updated_at"` + Version string `json:"version"` + } `json:"package_version"` + Registry struct { + AboutURL string `json:"about_url"` + Name string `json:"name"` + Type string `json:"type"` + URL string `json:"url"` + Vendor string `json:"vendor"` + } `json:"registry"` + UpdatedAt string `json:"updated_at"` + } `json:"registry_package"` + Repository struct { + ArchiveURL string `json:"archive_url"` + Archived bool `json:"archived"` + AssigneesURL string `json:"assignees_url"` + BlobsURL string `json:"blobs_url"` + BranchesURL string `json:"branches_url"` + CloneURL string `json:"clone_url"` + CollaboratorsURL string `json:"collaborators_url"` + CommentsURL string `json:"comments_url"` + CommitsURL string `json:"commits_url"` + CompareURL string `json:"compare_url"` + ContentsURL string `json:"contents_url"` + ContributorsURL string `json:"contributors_url"` + CreatedAt string `json:"created_at"` + DefaultBranch string `json:"default_branch"` + DeploymentsURL string `json:"deployments_url"` + Description string `json:"description"` + Disabled bool `json:"disabled"` + DownloadsURL string `json:"downloads_url"` + EventsURL string `json:"events_url"` + Fork bool `json:"fork"` + Forks int `json:"forks"` + ForksCount int `json:"forks_count"` + ForksURL string `json:"forks_url"` + FullName string `json:"full_name"` + GitCommitsURL string `json:"git_commits_url"` + GitRefsURL string `json:"git_refs_url"` + GitTagsURL string `json:"git_tags_url"` + GitURL string `json:"git_url"` + HasDownloads bool `json:"has_downloads"` + HasIssues bool `json:"has_issues"` + HasPages bool `json:"has_pages"` + HasProjects bool `json:"has_projects"` + HasWiki bool `json:"has_wiki"` + Homepage string `json:"homepage"` + HooksURL string `json:"hooks_url"` + HTMLURL string `json:"html_url"` + ID int `json:"id"` + IssueCommentURL string `json:"issue_comment_url"` + IssueEventsURL string `json:"issue_events_url"` + IssuesURL string `json:"issues_url"` + KeysURL string `json:"keys_url"` + LabelsURL string `json:"labels_url"` + Language string `json:"language"` + LanguagesURL string `json:"languages_url"` + License interface{} `json:"license"` + MergesURL string `json:"merges_url"` + MilestonesURL string `json:"milestones_url"` + MirrorURL interface{} `json:"mirror_url"` + Name string `json:"name"` + NodeID string `json:"node_id"` + NotificationsURL string `json:"notifications_url"` + OpenIssues int `json:"open_issues"` + OpenIssuesCount int `json:"open_issues_count"` + Owner struct { + AvatarURL string `json:"avatar_url"` + EventsURL string `json:"events_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + GravatarID string `json:"gravatar_id"` + HTMLURL string `json:"html_url"` + ID int `json:"id"` + Login string `json:"login"` + NodeID string `json:"node_id"` + OrganizationsURL string `json:"organizations_url"` + ReceivedEventsURL string `json:"received_events_url"` + ReposURL string `json:"repos_url"` + SiteAdmin bool `json:"site_admin"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + Type string `json:"type"` + URL string `json:"url"` + } `json:"owner"` + Private bool `json:"private"` + PullsURL string `json:"pulls_url"` + PushedAt string `json:"pushed_at"` + ReleasesURL string `json:"releases_url"` + Size int `json:"size"` + SSHURL string `json:"ssh_url"` + StargazersCount int `json:"stargazers_count"` + StargazersURL string `json:"stargazers_url"` + StatusesURL string `json:"statuses_url"` + SubscribersURL string `json:"subscribers_url"` + SubscriptionURL string `json:"subscription_url"` + SvnURL string `json:"svn_url"` + TagsURL string `json:"tags_url"` + TeamsURL string `json:"teams_url"` + TreesURL string `json:"trees_url"` + UpdatedAt string `json:"updated_at"` + URL string `json:"url"` + Watchers int `json:"watchers"` + WatchersCount int `json:"watchers_count"` + } `json:"repository"` + Sender struct { + AvatarURL string `json:"avatar_url"` + EventsURL string `json:"events_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + GravatarID string `json:"gravatar_id"` + HTMLURL string `json:"html_url"` + ID int `json:"id"` + Login string `json:"login"` + NodeID string `json:"node_id"` + OrganizationsURL string `json:"organizations_url"` + ReceivedEventsURL string `json:"received_events_url"` + ReposURL string `json:"repos_url"` + SiteAdmin bool `json:"site_admin"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + Type string `json:"type"` + URL string `json:"url"` + } `json:"sender"` +} + +// githubHandler - used to react to github webhooks +func (s *TriggerServer) githubHandler(resp http.ResponseWriter, req *http.Request) { + gw := githubWebhook{} + if err := json.NewDecoder(req.Body).Decode(&gw); err != nil { + log.WithFields(log.Fields{ + "error": err, + }).Error("trigger.githubHandler: failed to decode request") + resp.WriteHeader(http.StatusBadRequest) + return + } + + if gw.RegistryPackage.PackageType != "docker" { + resp.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(resp, "registry package type was not docker") + } + + if gw.Repository.FullName == "" { // github package name + resp.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(resp, "repository full name cannot be empty") + return + } + + if gw.RegistryPackage.Name == "" { // github package name + resp.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(resp, "repository package name cannot be empty") + return + } + + if gw.RegistryPackage.PackageVersion.Version == "" { // tag + resp.WriteHeader(http.StatusBadRequest) + fmt.Fprintf(resp, "repository tag cannot be empty") + return + } + + event := types.Event{} + event.CreatedAt = time.Now() + event.TriggerName = "github" + event.Repository.Name = strings.Join( + []string{"docker.pkg.github.com", gw.Repository.FullName, gw.RegistryPackage.Name}, + "/", + ) + event.Repository.Tag = gw.RegistryPackage.PackageVersion.Version + + s.trigger(event) + + resp.WriteHeader(http.StatusOK) + + newGithubWebhooksCounter.With(prometheus.Labels{"image": event.Repository.Name}).Inc() +} diff --git a/pkg/http/github_webhook_trigger_test.go b/pkg/http/github_webhook_trigger_test.go new file mode 100644 index 00000000..8494d2dd --- /dev/null +++ b/pkg/http/github_webhook_trigger_test.go @@ -0,0 +1,274 @@ +package http + +import ( + "bytes" + "net/http" + + "net/http/httptest" + "testing" +) + +var fakeGithubWebhook = `{ + "action": "published", + "registry_package": { + "id": 35087, + "name": "server", + "package_type": "docker", + "html_url": "https://github.com/DingGGu/UtaiteBOX/packages/35087", + "created_at": "2019-10-11T18:18:58Z", + "updated_at": "2019-10-11T18:18:58Z", + "owner": { + "login": "DingGGu", + "id": 2981443, + "node_id": "MDQ6VXNlcjI5ODE0NDM=", + "avatar_url": "https://avatars3.githubusercontent.com/u/2981443?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/DingGGu", + "html_url": "https://github.com/DingGGu", + "followers_url": "https://api.github.com/users/DingGGu/followers", + "following_url": "https://api.github.com/users/DingGGu/following{/other_user}", + "gists_url": "https://api.github.com/users/DingGGu/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DingGGu/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DingGGu/subscriptions", + "organizations_url": "https://api.github.com/users/DingGGu/orgs", + "repos_url": "https://api.github.com/users/DingGGu/repos", + "events_url": "https://api.github.com/users/DingGGu/events{/privacy}", + "received_events_url": "https://api.github.com/users/DingGGu/received_events", + "type": "User", + "site_admin": false + }, + "package_version": { + "id": 130771, + "version": "1.2.3", + "summary": "", + "body": "", + "body_html": "", + "manifest": "{\n \"schemaVersion\": 2,\n \"mediaType\": \"application/vnd.docker.distribution.manifest.v2+json\",\n \"config\": {\n \"mediaType\": \"application/vnd.docker.container.image.v1+json\",\n \"size\": 1709,\n \"digest\": \"sha256:2b94d3d75692e4b04dde5046ad3246fe01cc8889cb641c3e116f10e41c51e164\"\n },\n \"layers\": [\n {\n \"mediaType\": \"application/vnd.docker.image.rootfs.diff.tar.gzip\",\n \"size\": 2789669,\n \"digest\": \"sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609\"\n },\n {\n \"mediaType\": \"application/vnd.docker.image.rootfs.diff.tar.gzip\",\n \"size\": 350,\n \"digest\": \"sha256:957045d2b582f07cdc07ebbc7d971239bb7bc19f78216fe547609ff495b007f5\"\n }\n ]\n}", + "html_url": "https://github.com/DingGGu/UtaiteBOX/packages/35087?version=1.2.3", + "target_commitish": "ts", + "target_oid": "68d2fd4969f35b650b5863da9220a2561ced6f7b", + "created_at": "2019-10-11T18:19:06Z", + "updated_at": "2019-11-01T05:30:31Z", + "metadata": [ + + ], + "package_files": [ + { + "download_url": "https://github-production-registry-package-file-4f11e5.s3.amazonaws.com/32367513/0804d380-ec9f-11e9-8306-7f87c59605d3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20191101%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20191101T053031Z&X-Amz-Expires=300&X-Amz-Signature=d724dc6416ae277e3754530ac83bd5d33b44ceb5fcd8c0fee41c0fa84df1d942&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=filename%3D0804d380-ec9f-11e9-8306-7f87c59605d3&response-content-type=application%2Foctet-stream", + "id": 448033, + "name": "0804d380-ec9f-11e9-8306-7f87c59605d3", + "sha256": "957045d2b582f07cdc07ebbc7d971239bb7bc19f78216fe547609ff495b007f5", + "sha1": null, + "md5": null, + "content_type": "application/octet-stream", + "state": "uploaded", + "size": 350, + "created_at": "2019-10-11T18:18:59Z", + "updated_at": "2019-10-11T18:19:06Z" + }, + { + "download_url": "https://github-production-registry-package-file-4f11e5.s3.amazonaws.com/32367513/0804d380-ec9f-11e9-985b-72c935b667c2?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20191101%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20191101T053031Z&X-Amz-Expires=300&X-Amz-Signature=eee79a1840857f2a651a9299aee338b0e8994800d39985a2d72a77980d86c813&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=filename%3D0804d380-ec9f-11e9-985b-72c935b667c2&response-content-type=application%2Foctet-stream", + "id": 448034, + "name": "0804d380-ec9f-11e9-985b-72c935b667c2", + "sha256": "9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609", + "sha1": null, + "md5": null, + "content_type": "application/octet-stream", + "state": "uploaded", + "size": 2789669, + "created_at": "2019-10-11T18:18:59Z", + "updated_at": "2019-10-11T18:19:06Z" + }, + { + "download_url": "https://github-production-registry-package-file-4f11e5.s3.amazonaws.com/32367513/0a672d80-ec9f-11e9-8b8c-6867f9c0ea4e?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20191101%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20191101T053031Z&X-Amz-Expires=300&X-Amz-Signature=9a0a71caf7b65ec2406ba84aa28552df8b07ca9bad6b0f7091e0beadfa9c11f1&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=filename%3D0a672d80-ec9f-11e9-8b8c-6867f9c0ea4e&response-content-type=application%2Foctet-stream", + "id": 448035, + "name": "0a672d80-ec9f-11e9-8b8c-6867f9c0ea4e", + "sha256": "2b94d3d75692e4b04dde5046ad3246fe01cc8889cb641c3e116f10e41c51e164", + "sha1": null, + "md5": null, + "content_type": "application/octet-stream", + "state": "uploaded", + "size": 1709, + "created_at": "2019-10-11T18:19:03Z", + "updated_at": "2019-10-11T18:19:06Z" + } + ], + "author": { + "login": "DingGGu", + "id": 2981443, + "node_id": "MDQ6VXNlcjI5ODE0NDM=", + "avatar_url": "https://avatars3.githubusercontent.com/u/2981443?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/DingGGu", + "html_url": "https://github.com/DingGGu", + "followers_url": "https://api.github.com/users/DingGGu/followers", + "following_url": "https://api.github.com/users/DingGGu/following{/other_user}", + "gists_url": "https://api.github.com/users/DingGGu/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DingGGu/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DingGGu/subscriptions", + "organizations_url": "https://api.github.com/users/DingGGu/orgs", + "repos_url": "https://api.github.com/users/DingGGu/repos", + "events_url": "https://api.github.com/users/DingGGu/events{/privacy}", + "received_events_url": "https://api.github.com/users/DingGGu/received_events", + "type": "User", + "site_admin": false + }, + "installation_command": "" + }, + "registry": { + "about_url": "https://help.github.com/about-github-package-registry", + "name": "GitHub docker registry", + "type": "docker", + "url": "https://docker.pkg.github.com/DingGGu/UtaiteBOX", + "vendor": "GitHub Inc" + } + }, + "repository": { + "id": 32367513, + "node_id": "MDEwOlJlcG9zaXRvcnkzMjM2NzUxMw==", + "name": "UtaiteBOX", + "full_name": "DingGGu/UtaiteBOX", + "private": true, + "owner": { + "login": "DingGGu", + "id": 2981443, + "node_id": "MDQ6VXNlcjI5ODE0NDM=", + "avatar_url": "https://avatars3.githubusercontent.com/u/2981443?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/DingGGu", + "html_url": "https://github.com/DingGGu", + "followers_url": "https://api.github.com/users/DingGGu/followers", + "following_url": "https://api.github.com/users/DingGGu/following{/other_user}", + "gists_url": "https://api.github.com/users/DingGGu/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DingGGu/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DingGGu/subscriptions", + "organizations_url": "https://api.github.com/users/DingGGu/orgs", + "repos_url": "https://api.github.com/users/DingGGu/repos", + "events_url": "https://api.github.com/users/DingGGu/events{/privacy}", + "received_events_url": "https://api.github.com/users/DingGGu/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/DingGGu/UtaiteBOX", + "description": "UtaiteBOX", + "fork": false, + "url": "https://api.github.com/repos/DingGGu/UtaiteBOX", + "forks_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/forks", + "keys_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/teams", + "hooks_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/hooks", + "issue_events_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/issues/events{/number}", + "events_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/events", + "assignees_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/assignees{/user}", + "branches_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/branches{/branch}", + "tags_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/tags", + "blobs_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/statuses/{sha}", + "languages_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/languages", + "stargazers_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/stargazers", + "contributors_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/contributors", + "subscribers_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/subscribers", + "subscription_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/subscription", + "commits_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/contents/{+path}", + "compare_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/merges", + "archive_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/downloads", + "issues_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/issues{/number}", + "pulls_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/pulls{/number}", + "milestones_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/milestones{/number}", + "notifications_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/labels{/name}", + "releases_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/releases{/id}", + "deployments_url": "https://api.github.com/repos/DingGGu/UtaiteBOX/deployments", + "created_at": "2015-03-17T02:49:38Z", + "updated_at": "2019-01-06T12:48:56Z", + "pushed_at": "2019-08-29T03:07:48Z", + "git_url": "git://github.com/DingGGu/UtaiteBOX.git", + "ssh_url": "git@github.com:DingGGu/UtaiteBOX.git", + "clone_url": "https://github.com/DingGGu/UtaiteBOX.git", + "svn_url": "https://github.com/DingGGu/UtaiteBOX", + "homepage": "https://www.utaitebox.com/", + "size": 113576, + "stargazers_count": 4, + "watchers_count": 4, + "language": "TypeScript", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 1, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 14, + "license": null, + "forks": 1, + "open_issues": 14, + "watchers": 4, + "default_branch": "ts" + }, + "sender": { + "login": "DingGGu", + "id": 2981443, + "node_id": "MDQ6VXNlcjI5ODE0NDM=", + "avatar_url": "https://avatars3.githubusercontent.com/u/2981443?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/DingGGu", + "html_url": "https://github.com/DingGGu", + "followers_url": "https://api.github.com/users/DingGGu/followers", + "following_url": "https://api.github.com/users/DingGGu/following{/other_user}", + "gists_url": "https://api.github.com/users/DingGGu/gists{/gist_id}", + "starred_url": "https://api.github.com/users/DingGGu/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/DingGGu/subscriptions", + "organizations_url": "https://api.github.com/users/DingGGu/orgs", + "repos_url": "https://api.github.com/users/DingGGu/repos", + "events_url": "https://api.github.com/users/DingGGu/events{/privacy}", + "received_events_url": "https://api.github.com/users/DingGGu/received_events", + "type": "User", + "site_admin": false + } +}` + +func TestGithubWebhookHandler(t *testing.T) { + + fp := &fakeProvider{} + srv, teardown := NewTestingServer(fp) + defer teardown() + + req, err := http.NewRequest("POST", "/v1/webhooks/github", bytes.NewBuffer([]byte(fakeGithubWebhook))) + if err != nil { + t.Fatalf("failed to create req: %s", err) + } + + //The response recorder used to record HTTP responses + rec := httptest.NewRecorder() + + srv.router.ServeHTTP(rec, req) + if rec.Code != 200 { + t.Errorf("unexpected status code: %d", rec.Code) + + t.Log(rec.Body.String()) + } + + if len(fp.submitted) != 1 { + t.Fatalf("unexpected number of events submitted: %d", len(fp.submitted)) + } + + if fp.submitted[0].Repository.Name != "docker.pkg.github.com/DingGGu/UtaiteBOX/server" { + t.Errorf("expected docker.pkg.github.com/DingGGu/UtaiteBOX/server but got %s", fp.submitted[0].Repository.Name) + } + + if fp.submitted[0].Repository.Tag != "1.2.3" { + t.Errorf("expected 1.2.3 but got %s", fp.submitted[0].Repository.Tag) + } +} diff --git a/pkg/http/http.go b/pkg/http/http.go index 6e620bc9..9e061ade 100644 --- a/pkg/http/http.go +++ b/pkg/http/http.go @@ -182,6 +182,7 @@ func (s *TriggerServer) registerWebhookRoutes(mux *mux.Router) { mux.HandleFunc("/v1/webhooks/dockerhub", s.requireAdminAuthorization(s.dockerHubHandler)).Methods("POST", "OPTIONS") mux.HandleFunc("/v1/webhooks/quay", s.requireAdminAuthorization(s.quayHandler)).Methods("POST", "OPTIONS") mux.HandleFunc("/v1/webhooks/azure", s.requireAdminAuthorization(s.azureHandler)).Methods("POST", "OPTIONS") + mux.HandleFunc("/v1/webhooks/github", s.requireAdminAuthorization(s.githubHandler)).Methods("POST", "OPTIONS") // Docker registry notifications, used by Docker, Gitlab, Harbor // https://docs.docker.com/registry/notifications/ @@ -192,6 +193,7 @@ func (s *TriggerServer) registerWebhookRoutes(mux *mux.Router) { mux.HandleFunc("/v1/webhooks/dockerhub", s.dockerHubHandler).Methods("POST", "OPTIONS") mux.HandleFunc("/v1/webhooks/quay", s.quayHandler).Methods("POST", "OPTIONS") mux.HandleFunc("/v1/webhooks/azure", s.azureHandler).Methods("POST", "OPTIONS") + mux.HandleFunc("/v1/webhooks/github", s.githubHandler).Methods("POST", "OPTIONS") // Docker registry notifications, used by Docker, Gitlab, Harbor // https://docs.docker.com/registry/notifications/