From 8ab6c5b734ed17a75b05670bd8720f6eb018de8a Mon Sep 17 00:00:00 2001 From: Michael Graf Date: Wed, 18 Sep 2024 23:26:14 -0600 Subject: [PATCH 1/4] adds EventType consts representing the X-Github-Event header values --- github/event.go | 2 +- github/messages.go | 226 +++++++++++++++++++++---------- github/messages_test.go | 2 +- github/repos_hooks_deliveries.go | 2 +- 4 files changed, 155 insertions(+), 77 deletions(-) diff --git a/github/event.go b/github/event.go index e98606bce5d..c0611795173 100644 --- a/github/event.go +++ b/github/event.go @@ -30,7 +30,7 @@ func (e Event) String() string { func (e *Event) ParsePayload() (interface{}, error) { // It would be nice if e.Type were the snake_case name of the event, // but the existing interface uses the struct name instead. - payload := EventForType(typeToMessageMapping[e.GetType()]) + payload := EventForType(string(typeToMessageMapping[e.GetType()])) if err := json.Unmarshal(e.GetRawPayload(), &payload); err != nil { return nil, err diff --git a/github/messages.go b/github/messages.go index f365190ae39..10383d3d65d 100644 --- a/github/messages.go +++ b/github/messages.go @@ -43,82 +43,160 @@ const ( DeliveryIDHeader = "X-Github-Delivery" ) +type EventTyper interface { + EventType() EventType +} + +// EventType corresponds to the X-GitHub-Event: header for Webhooks events and payloads +type EventType string + +const ( + EventTypeBranchProtectionRule EventType = "branch_protection_rule" + EventTypeCheckRun EventType = "check_run" + EventTypeCheckSuite EventType = "check_suite" + EventTypeCodeScanningAlert EventType = "code_scanning_alert" + EventTypeCommitComment EventType = "commit_comment" + EventTypeContentReference EventType = "content_reference" + EventTypeCreate EventType = "create" + EventTypeDelete EventType = "delete" + EventTypeDependabotAlert EventType = "dependabot_alert" + EventTypeDeployKey EventType = "deploy_key" + EventTypeDeployment EventType = "deployment" + EventTypeDeploymentProtectionRule EventType = "deployment_protection_rule" + EventTypeDeploymentReview EventType = "deployment_review" + EventTypeDeploymentStatus EventType = "deployment_status" + EventTypeDiscussion EventType = "discussion" + EventTypeDiscussionComment EventType = "discussion_comment" + EventTypeFork EventType = "fork" + EventTypeGitHubAppAuthorization EventType = "github_app_authorization" + EventTypeGollum EventType = "gollum" + EventTypeInstallation EventType = "installation" + EventTypeInstallationRepositories EventType = "installation_repositories" + EventTypeInstallationTarget EventType = "installation_target" + EventTypeIssueComment EventType = "issue_comment" + EventTypeIssues EventType = "issues" + EventTypeLabel EventType = "label" + EventTypeMarketplacePurchase EventType = "marketplace_purchase" + EventTypeMember EventType = "member" + EventTypeMembership EventType = "membership" + EventTypeMergeGroup EventType = "merge_group" + EventTypeMeta EventType = "meta" + EventTypeMilestone EventType = "milestone" + EventTypeOrgBlock EventType = "org_block" + EventTypeOrganization EventType = "organization" + EventTypePackage EventType = "package" + EventTypePageBuild EventType = "page_build" + EventTypePersonalAccessTokenRequest EventType = "personal_access_token_request" + EventTypePing EventType = "ping" + EventTypeProject EventType = "project" + EventTypeProjectCard EventType = "project_card" + EventTypeProjectColumn EventType = "project_column" + EventTypeProjectV2 EventType = "projects_v2" + EventTypeProjectV2Item EventType = "projects_v2_item" + EventTypePublic EventType = "public" + EventTypePullRequest EventType = "pull_request" + EventTypePullRequestReview EventType = "pull_request_review" + EventTypePullRequestReviewComment EventType = "pull_request_review_comment" + EventTypePullRequestReviewThread EventType = "pull_request_review_thread" + EventTypePullRequestTarget EventType = "pull_request_target" + EventTypePush EventType = "push" + EventTypeRelease EventType = "release" + EventTypeRepository EventType = "repository" + EventTypeRepositoryDispatch EventType = "repository_dispatch" + EventTypeRepositoryImport EventType = "repository_import" + EventTypeRepositoryRuleset EventType = "repository_ruleset" + EventTypeRepositoryVulnerabilityAlert EventType = "repository_vulnerability_alert" + EventTypeSecretScanningAlert EventType = "secret_scanning_alert" + EventTypeSecurityAdvisory EventType = "security_advisory" + EventTypeSecurityAndAnalysis EventType = "security_and_analysis" + EventTypeSponsorship EventType = "sponsorship" + EventTypeStar EventType = "star" + EventTypeStatus EventType = "status" + EventTypeTeam EventType = "team" + EventTypeTeamAdd EventType = "team_add" + EventTypeUser EventType = "user" + EventTypeWatch EventType = "watch" + EventTypeWorkflowDispatch EventType = "workflow_dispatch" + EventTypeWorkflowJob EventType = "workflow_job" + EventTypeWorkflowRun EventType = "workflow_run" +) + var ( // eventTypeMapping maps webhooks types to their corresponding go-github struct types. - eventTypeMapping = map[string]interface{}{ - "branch_protection_rule": &BranchProtectionRuleEvent{}, - "check_run": &CheckRunEvent{}, - "check_suite": &CheckSuiteEvent{}, - "code_scanning_alert": &CodeScanningAlertEvent{}, - "commit_comment": &CommitCommentEvent{}, - "content_reference": &ContentReferenceEvent{}, - "create": &CreateEvent{}, - "delete": &DeleteEvent{}, - "dependabot_alert": &DependabotAlertEvent{}, - "deploy_key": &DeployKeyEvent{}, - "deployment": &DeploymentEvent{}, - "deployment_review": &DeploymentReviewEvent{}, - "deployment_status": &DeploymentStatusEvent{}, - "deployment_protection_rule": &DeploymentProtectionRuleEvent{}, - "discussion": &DiscussionEvent{}, - "discussion_comment": &DiscussionCommentEvent{}, - "fork": &ForkEvent{}, - "github_app_authorization": &GitHubAppAuthorizationEvent{}, - "gollum": &GollumEvent{}, - "installation": &InstallationEvent{}, - "installation_repositories": &InstallationRepositoriesEvent{}, - "installation_target": &InstallationTargetEvent{}, - "issue_comment": &IssueCommentEvent{}, - "issues": &IssuesEvent{}, - "label": &LabelEvent{}, - "marketplace_purchase": &MarketplacePurchaseEvent{}, - "member": &MemberEvent{}, - "membership": &MembershipEvent{}, - "merge_group": &MergeGroupEvent{}, - "meta": &MetaEvent{}, - "milestone": &MilestoneEvent{}, - "organization": &OrganizationEvent{}, - "org_block": &OrgBlockEvent{}, - "package": &PackageEvent{}, - "page_build": &PageBuildEvent{}, - "personal_access_token_request": &PersonalAccessTokenRequestEvent{}, - "ping": &PingEvent{}, - "project": &ProjectEvent{}, - "project_card": &ProjectCardEvent{}, - "project_column": &ProjectColumnEvent{}, - "projects_v2": &ProjectV2Event{}, - "projects_v2_item": &ProjectV2ItemEvent{}, - "public": &PublicEvent{}, - "pull_request": &PullRequestEvent{}, - "pull_request_review": &PullRequestReviewEvent{}, - "pull_request_review_comment": &PullRequestReviewCommentEvent{}, - "pull_request_review_thread": &PullRequestReviewThreadEvent{}, - "pull_request_target": &PullRequestTargetEvent{}, - "push": &PushEvent{}, - "repository": &RepositoryEvent{}, - "repository_dispatch": &RepositoryDispatchEvent{}, - "repository_import": &RepositoryImportEvent{}, - "repository_ruleset": &RepositoryRulesetEvent{}, - "repository_vulnerability_alert": &RepositoryVulnerabilityAlertEvent{}, - "release": &ReleaseEvent{}, - "secret_scanning_alert": &SecretScanningAlertEvent{}, - "security_advisory": &SecurityAdvisoryEvent{}, - "security_and_analysis": &SecurityAndAnalysisEvent{}, - "sponsorship": &SponsorshipEvent{}, - "star": &StarEvent{}, - "status": &StatusEvent{}, - "team": &TeamEvent{}, - "team_add": &TeamAddEvent{}, - "user": &UserEvent{}, - "watch": &WatchEvent{}, - "workflow_dispatch": &WorkflowDispatchEvent{}, - "workflow_job": &WorkflowJobEvent{}, - "workflow_run": &WorkflowRunEvent{}, + eventTypeMapping = map[EventType]interface{}{ + EventTypeBranchProtectionRule: &BranchProtectionRuleEvent{}, + EventTypeCheckRun: &CheckRunEvent{}, + EventTypeCheckSuite: &CheckSuiteEvent{}, + EventTypeCodeScanningAlert: &CodeScanningAlertEvent{}, + EventTypeCommitComment: &CommitCommentEvent{}, + EventTypeContentReference: &ContentReferenceEvent{}, + EventTypeCreate: &CreateEvent{}, + EventTypeDelete: &DeleteEvent{}, + EventTypeDependabotAlert: &DependabotAlertEvent{}, + EventTypeDeployKey: &DeployKeyEvent{}, + EventTypeDeployment: &DeploymentEvent{}, + EventTypeDeploymentProtectionRule: &DeploymentProtectionRuleEvent{}, + EventTypeDeploymentReview: &DeploymentReviewEvent{}, + EventTypeDeploymentStatus: &DeploymentStatusEvent{}, + EventTypeDiscussion: &DiscussionEvent{}, + EventTypeDiscussionComment: &DiscussionCommentEvent{}, + EventTypeFork: &ForkEvent{}, + EventTypeGitHubAppAuthorization: &GitHubAppAuthorizationEvent{}, + EventTypeGollum: &GollumEvent{}, + EventTypeInstallation: &InstallationEvent{}, + EventTypeInstallationRepositories: &InstallationRepositoriesEvent{}, + EventTypeInstallationTarget: &InstallationTargetEvent{}, + EventTypeIssueComment: &IssueCommentEvent{}, + EventTypeIssues: &IssuesEvent{}, + EventTypeLabel: &LabelEvent{}, + EventTypeMarketplacePurchase: &MarketplacePurchaseEvent{}, + EventTypeMember: &MemberEvent{}, + EventTypeMembership: &MembershipEvent{}, + EventTypeMergeGroup: &MergeGroupEvent{}, + EventTypeMeta: &MetaEvent{}, + EventTypeMilestone: &MilestoneEvent{}, + EventTypeOrganization: &OrganizationEvent{}, + EventTypeOrgBlock: &OrgBlockEvent{}, + EventTypePackage: &PackageEvent{}, + EventTypePageBuild: &PageBuildEvent{}, + EventTypePersonalAccessTokenRequest: &PersonalAccessTokenRequestEvent{}, + EventTypePing: &PingEvent{}, + EventTypeProject: &ProjectEvent{}, + EventTypeProjectCard: &ProjectCardEvent{}, + EventTypeProjectColumn: &ProjectColumnEvent{}, + EventTypeProjectV2: &ProjectV2Event{}, + EventTypeProjectV2Item: &ProjectV2ItemEvent{}, + EventTypePublic: &PublicEvent{}, + EventTypePullRequest: &PullRequestEvent{}, + EventTypePullRequestReview: &PullRequestReviewEvent{}, + EventTypePullRequestReviewComment: &PullRequestReviewCommentEvent{}, + EventTypePullRequestReviewThread: &PullRequestReviewThreadEvent{}, + EventTypePullRequestTarget: &PullRequestTargetEvent{}, + EventTypePush: &PushEvent{}, + EventTypeRelease: &ReleaseEvent{}, + EventTypeRepository: &RepositoryEvent{}, + EventTypeRepositoryDispatch: &RepositoryDispatchEvent{}, + EventTypeRepositoryImport: &RepositoryImportEvent{}, + EventTypeRepositoryRuleset: &RepositoryRulesetEvent{}, + EventTypeRepositoryVulnerabilityAlert: &RepositoryVulnerabilityAlertEvent{}, + EventTypeSecretScanningAlert: &SecretScanningAlertEvent{}, + EventTypeSecurityAdvisory: &SecurityAdvisoryEvent{}, + EventTypeSecurityAndAnalysis: &SecurityAndAnalysisEvent{}, + EventTypeSponsorship: &SponsorshipEvent{}, + EventTypeStar: &StarEvent{}, + EventTypeStatus: &StatusEvent{}, + EventTypeTeam: &TeamEvent{}, + EventTypeTeamAdd: &TeamAddEvent{}, + EventTypeUser: &UserEvent{}, + EventTypeWatch: &WatchEvent{}, + EventTypeWorkflowDispatch: &WorkflowDispatchEvent{}, + EventTypeWorkflowJob: &WorkflowJobEvent{}, + EventTypeWorkflowRun: &WorkflowRunEvent{}, } // Forward mapping of event types to the string names of the structs. - messageToTypeName = make(map[string]string, len(eventTypeMapping)) + messageToTypeName = make(map[EventType]string, len(eventTypeMapping)) // Inverse map of the above. - typeToMessageMapping = make(map[string]string, len(eventTypeMapping)) + typeToMessageMapping = make(map[string]EventType, len(eventTypeMapping)) ) func init() { @@ -317,7 +395,7 @@ func DeliveryID(r *http.Request) string { // } // } func ParseWebHook(messageType string, payload []byte) (interface{}, error) { - eventType, ok := messageToTypeName[messageType] + eventType, ok := messageToTypeName[EventType(messageType)] if !ok { return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType) } @@ -334,7 +412,7 @@ func ParseWebHook(messageType string, payload []byte) (interface{}, error) { func MessageTypes() []string { types := make([]string, 0, len(eventTypeMapping)) for t := range eventTypeMapping { - types = append(types, t) + types = append(types, string(t)) } sort.Strings(types) return types @@ -343,7 +421,7 @@ func MessageTypes() []string { // EventForType returns an empty struct matching the specified GitHub event type. // If messageType does not match any known event types, it returns nil. func EventForType(messageType string) interface{} { - prototype := eventTypeMapping[messageType] + prototype := eventTypeMapping[EventType(messageType)] if prototype == nil { return nil } diff --git a/github/messages_test.go b/github/messages_test.go index e04c0b18a7b..bdc4573b746 100644 --- a/github/messages_test.go +++ b/github/messages_test.go @@ -556,7 +556,7 @@ func TestParseWebHook(t *testing.T) { func TestAllMessageTypesMapped(t *testing.T) { t.Parallel() for _, mt := range MessageTypes() { - if obj := EventForType(mt); obj == nil { + if obj := EventForType(EventType(mt)); obj == nil { t.Errorf("messageMap missing message type %q", mt) } } diff --git a/github/repos_hooks_deliveries.go b/github/repos_hooks_deliveries.go index c8029f626b9..e25853a7a57 100644 --- a/github/repos_hooks_deliveries.go +++ b/github/repos_hooks_deliveries.go @@ -132,7 +132,7 @@ func (s *RepositoriesService) RedeliverHookDelivery(ctx context.Context, owner, // ParseRequestPayload parses the request payload. For recognized event types, // a value of the corresponding struct type will be returned. func (d *HookDelivery) ParseRequestPayload() (interface{}, error) { - eType, ok := messageToTypeName[d.GetEvent()] + eType, ok := messageToTypeName[EventType(d.GetEvent())] if !ok { return nil, fmt.Errorf("unsupported event type %q", d.GetEvent()) } From abcf17e3c3c5d5d179f6ac0f5b49f141dade1124 Mon Sep 17 00:00:00 2001 From: Michael Graf Date: Fri, 25 Oct 2024 20:31:12 -0600 Subject: [PATCH 2/4] messages.go: removes unused interface --- github/messages.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/github/messages.go b/github/messages.go index 10383d3d65d..ead5ec82bd2 100644 --- a/github/messages.go +++ b/github/messages.go @@ -43,10 +43,6 @@ const ( DeliveryIDHeader = "X-Github-Delivery" ) -type EventTyper interface { - EventType() EventType -} - // EventType corresponds to the X-GitHub-Event: header for Webhooks events and payloads type EventType string From 1fe5355e3bc92e5e71b051f93828c3dab7e53dd6 Mon Sep 17 00:00:00 2001 From: Michael Graf Date: Fri, 25 Oct 2024 20:32:03 -0600 Subject: [PATCH 3/4] messages.go: comments are complete sentences --- github/messages.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/messages.go b/github/messages.go index ead5ec82bd2..daa60608a49 100644 --- a/github/messages.go +++ b/github/messages.go @@ -43,7 +43,7 @@ const ( DeliveryIDHeader = "X-Github-Delivery" ) -// EventType corresponds to the X-GitHub-Event: header for Webhooks events and payloads +// EventType corresponds to the X-GitHub-Event: header for Webhooks events and payloads. type EventType string const ( From 4aa32d2d2755e07e0b165090b4d20f75f0175611 Mon Sep 17 00:00:00 2001 From: Michael Graf Date: Fri, 25 Oct 2024 20:38:01 -0600 Subject: [PATCH 4/4] messages_test.go: fixed broken test, ran relevant script/*.sh --- github/messages_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/messages_test.go b/github/messages_test.go index bdc4573b746..e04c0b18a7b 100644 --- a/github/messages_test.go +++ b/github/messages_test.go @@ -556,7 +556,7 @@ func TestParseWebHook(t *testing.T) { func TestAllMessageTypesMapped(t *testing.T) { t.Parallel() for _, mt := range MessageTypes() { - if obj := EventForType(EventType(mt)); obj == nil { + if obj := EventForType(mt); obj == nil { t.Errorf("messageMap missing message type %q", mt) } }