github-events 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- github_events/__init__.py +42 -0
- github_events/_models.py +7033 -0
- github_events/_registry.py +485 -0
- github_events/dispatch.py +138 -0
- github_events/dispatch.pyi +878 -0
- github_events/fastapi.py +56 -0
- github_events/py.typed +0 -0
- github_events/validation.py +70 -0
- github_events-0.1.0.dist-info/METADATA +37 -0
- github_events-0.1.0.dist-info/RECORD +11 -0
- github_events-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
"""Event name/type registry. GENERATED by scripts/generate_models.py (octokit/webhooks-schemas 7.6.1)."""
|
|
2
|
+
|
|
3
|
+
from types import UnionType
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from github_events import _models as m
|
|
7
|
+
|
|
8
|
+
EventName = Literal[
|
|
9
|
+
'branch_protection_configuration',
|
|
10
|
+
'branch_protection_rule',
|
|
11
|
+
'check_run',
|
|
12
|
+
'check_suite',
|
|
13
|
+
'code_scanning_alert',
|
|
14
|
+
'commit_comment',
|
|
15
|
+
'create',
|
|
16
|
+
'custom_property',
|
|
17
|
+
'custom_property_values',
|
|
18
|
+
'delete',
|
|
19
|
+
'dependabot_alert',
|
|
20
|
+
'deploy_key',
|
|
21
|
+
'deployment',
|
|
22
|
+
'deployment_protection_rule',
|
|
23
|
+
'deployment_review',
|
|
24
|
+
'deployment_status',
|
|
25
|
+
'discussion',
|
|
26
|
+
'discussion_comment',
|
|
27
|
+
'fork',
|
|
28
|
+
'github_app_authorization',
|
|
29
|
+
'gollum',
|
|
30
|
+
'installation',
|
|
31
|
+
'installation_repositories',
|
|
32
|
+
'installation_target',
|
|
33
|
+
'issue_comment',
|
|
34
|
+
'issues',
|
|
35
|
+
'label',
|
|
36
|
+
'marketplace_purchase',
|
|
37
|
+
'member',
|
|
38
|
+
'membership',
|
|
39
|
+
'merge_group',
|
|
40
|
+
'meta',
|
|
41
|
+
'milestone',
|
|
42
|
+
'org_block',
|
|
43
|
+
'organization',
|
|
44
|
+
'package',
|
|
45
|
+
'page_build',
|
|
46
|
+
'ping',
|
|
47
|
+
'project',
|
|
48
|
+
'project_card',
|
|
49
|
+
'project_column',
|
|
50
|
+
'projects_v2_item',
|
|
51
|
+
'public',
|
|
52
|
+
'pull_request',
|
|
53
|
+
'pull_request_review',
|
|
54
|
+
'pull_request_review_comment',
|
|
55
|
+
'pull_request_review_thread',
|
|
56
|
+
'push',
|
|
57
|
+
'registry_package',
|
|
58
|
+
'release',
|
|
59
|
+
'repository',
|
|
60
|
+
'repository_dispatch',
|
|
61
|
+
'repository_import',
|
|
62
|
+
'repository_vulnerability_alert',
|
|
63
|
+
'secret_scanning_alert',
|
|
64
|
+
'secret_scanning_alert_location',
|
|
65
|
+
'security_advisory',
|
|
66
|
+
'sponsorship',
|
|
67
|
+
'star',
|
|
68
|
+
'status',
|
|
69
|
+
'team',
|
|
70
|
+
'team_add',
|
|
71
|
+
'watch',
|
|
72
|
+
'workflow_dispatch',
|
|
73
|
+
'workflow_job',
|
|
74
|
+
'workflow_run',
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
EVENT_NAMES: tuple[str, ...] = ('branch_protection_configuration', 'branch_protection_rule', 'check_run', 'check_suite', 'code_scanning_alert', 'commit_comment', 'create', 'custom_property', 'custom_property_values', 'delete', 'dependabot_alert', 'deploy_key', 'deployment', 'deployment_protection_rule', 'deployment_review', 'deployment_status', 'discussion', 'discussion_comment', 'fork', 'github_app_authorization', 'gollum', 'installation', 'installation_repositories', 'installation_target', 'issue_comment', 'issues', 'label', 'marketplace_purchase', 'member', 'membership', 'merge_group', 'meta', 'milestone', 'org_block', 'organization', 'package', 'page_build', 'ping', 'project', 'project_card', 'project_column', 'projects_v2_item', 'public', 'pull_request', 'pull_request_review', 'pull_request_review_comment', 'pull_request_review_thread', 'push', 'registry_package', 'release', 'repository', 'repository_dispatch', 'repository_import', 'repository_vulnerability_alert', 'secret_scanning_alert', 'secret_scanning_alert_location', 'security_advisory', 'sponsorship', 'star', 'status', 'team', 'team_add', 'watch', 'workflow_dispatch', 'workflow_job', 'workflow_run')
|
|
78
|
+
|
|
79
|
+
EVENT_TYPES: dict[str, object] = {
|
|
80
|
+
'branch_protection_configuration': m.BranchProtectionConfigurationEvent,
|
|
81
|
+
'branch_protection_rule': m.BranchProtectionRuleEvent,
|
|
82
|
+
'check_run': m.CheckRunEvent,
|
|
83
|
+
'check_suite': m.CheckSuiteEvent,
|
|
84
|
+
'code_scanning_alert': m.CodeScanningAlertEvent,
|
|
85
|
+
'commit_comment': m.CommitCommentEvent,
|
|
86
|
+
'create': m.CreateEvent,
|
|
87
|
+
'custom_property': m.CustomPropertyEvent,
|
|
88
|
+
'custom_property_values': m.CustomPropertyValuesEvent,
|
|
89
|
+
'delete': m.DeleteEvent,
|
|
90
|
+
'dependabot_alert': m.DependabotAlertEvent,
|
|
91
|
+
'deploy_key': m.DeployKeyEvent,
|
|
92
|
+
'deployment': m.DeploymentEvent,
|
|
93
|
+
'deployment_protection_rule': m.DeploymentProtectionRuleEvent,
|
|
94
|
+
'deployment_review': m.DeploymentReviewEvent,
|
|
95
|
+
'deployment_status': m.DeploymentStatusEvent,
|
|
96
|
+
'discussion': m.DiscussionEvent,
|
|
97
|
+
'discussion_comment': m.DiscussionCommentEvent,
|
|
98
|
+
'fork': m.ForkEvent,
|
|
99
|
+
'github_app_authorization': m.GitHubAppAuthorizationEvent,
|
|
100
|
+
'gollum': m.GollumEvent,
|
|
101
|
+
'installation': m.InstallationEvent,
|
|
102
|
+
'installation_repositories': m.InstallationRepositoriesEvent,
|
|
103
|
+
'installation_target': m.InstallationTargetEvent,
|
|
104
|
+
'issue_comment': m.IssueCommentEvent,
|
|
105
|
+
'issues': m.IssuesEvent,
|
|
106
|
+
'label': m.LabelEvent,
|
|
107
|
+
'marketplace_purchase': m.MarketplacePurchaseEvent,
|
|
108
|
+
'member': m.MemberEvent,
|
|
109
|
+
'membership': m.MembershipEvent,
|
|
110
|
+
'merge_group': m.MergeGroupEvent,
|
|
111
|
+
'meta': m.MetaEvent,
|
|
112
|
+
'milestone': m.MilestoneEvent,
|
|
113
|
+
'org_block': m.OrgBlockEvent,
|
|
114
|
+
'organization': m.OrganizationEvent,
|
|
115
|
+
'package': m.PackageEvent,
|
|
116
|
+
'page_build': m.PageBuildEvent,
|
|
117
|
+
'ping': m.PingEvent,
|
|
118
|
+
'project': m.ProjectEvent,
|
|
119
|
+
'project_card': m.ProjectCardEvent,
|
|
120
|
+
'project_column': m.ProjectColumnEvent,
|
|
121
|
+
'projects_v2_item': m.ProjectsV2ItemEvent,
|
|
122
|
+
'public': m.PublicEvent,
|
|
123
|
+
'pull_request': m.PullRequestEvent,
|
|
124
|
+
'pull_request_review': m.PullRequestReviewEvent,
|
|
125
|
+
'pull_request_review_comment': m.PullRequestReviewCommentEvent,
|
|
126
|
+
'pull_request_review_thread': m.PullRequestReviewThreadEvent,
|
|
127
|
+
'push': m.PushEvent,
|
|
128
|
+
'registry_package': m.RegistryPackageEvent,
|
|
129
|
+
'release': m.ReleaseEvent,
|
|
130
|
+
'repository': m.RepositoryEvent,
|
|
131
|
+
'repository_dispatch': m.RepositoryDispatchEvent,
|
|
132
|
+
'repository_import': m.RepositoryImportEvent,
|
|
133
|
+
'repository_vulnerability_alert': m.RepositoryVulnerabilityAlertEvent,
|
|
134
|
+
'secret_scanning_alert': m.SecretScanningAlertEvent,
|
|
135
|
+
'secret_scanning_alert_location': m.SecretScanningAlertLocationEvent,
|
|
136
|
+
'security_advisory': m.SecurityAdvisoryEvent,
|
|
137
|
+
'sponsorship': m.SponsorshipEvent,
|
|
138
|
+
'star': m.StarEvent,
|
|
139
|
+
'status': m.StatusEvent,
|
|
140
|
+
'team': m.TeamEvent,
|
|
141
|
+
'team_add': m.TeamAddEvent,
|
|
142
|
+
'watch': m.WatchEvent,
|
|
143
|
+
'workflow_dispatch': m.WorkflowDispatchEvent,
|
|
144
|
+
'workflow_job': m.WorkflowJobEvent,
|
|
145
|
+
'workflow_run': m.WorkflowRunEvent,
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
ACTION_EVENTS: frozenset[str] = frozenset({
|
|
149
|
+
'branch_protection_configuration',
|
|
150
|
+
'branch_protection_rule',
|
|
151
|
+
'check_run',
|
|
152
|
+
'check_suite',
|
|
153
|
+
'code_scanning_alert',
|
|
154
|
+
'commit_comment',
|
|
155
|
+
'custom_property',
|
|
156
|
+
'custom_property_values',
|
|
157
|
+
'dependabot_alert',
|
|
158
|
+
'deploy_key',
|
|
159
|
+
'deployment',
|
|
160
|
+
'deployment_protection_rule',
|
|
161
|
+
'deployment_review',
|
|
162
|
+
'deployment_status',
|
|
163
|
+
'discussion',
|
|
164
|
+
'discussion_comment',
|
|
165
|
+
'github_app_authorization',
|
|
166
|
+
'installation',
|
|
167
|
+
'installation_repositories',
|
|
168
|
+
'installation_target',
|
|
169
|
+
'issue_comment',
|
|
170
|
+
'issues',
|
|
171
|
+
'label',
|
|
172
|
+
'marketplace_purchase',
|
|
173
|
+
'member',
|
|
174
|
+
'membership',
|
|
175
|
+
'merge_group',
|
|
176
|
+
'meta',
|
|
177
|
+
'milestone',
|
|
178
|
+
'org_block',
|
|
179
|
+
'organization',
|
|
180
|
+
'package',
|
|
181
|
+
'project',
|
|
182
|
+
'project_card',
|
|
183
|
+
'project_column',
|
|
184
|
+
'projects_v2_item',
|
|
185
|
+
'pull_request',
|
|
186
|
+
'pull_request_review',
|
|
187
|
+
'pull_request_review_comment',
|
|
188
|
+
'pull_request_review_thread',
|
|
189
|
+
'registry_package',
|
|
190
|
+
'release',
|
|
191
|
+
'repository',
|
|
192
|
+
'repository_vulnerability_alert',
|
|
193
|
+
'secret_scanning_alert',
|
|
194
|
+
'secret_scanning_alert_location',
|
|
195
|
+
'security_advisory',
|
|
196
|
+
'sponsorship',
|
|
197
|
+
'star',
|
|
198
|
+
'team',
|
|
199
|
+
'watch',
|
|
200
|
+
'workflow_job',
|
|
201
|
+
'workflow_run',
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
ACTION_TYPES: dict[tuple[str, str], type | UnionType] = {
|
|
205
|
+
('branch_protection_configuration', 'disabled'): m.BranchProtectionConfigurationDisabledEvent,
|
|
206
|
+
('branch_protection_configuration', 'enabled'): m.BranchProtectionConfigurationEnabledEvent,
|
|
207
|
+
('branch_protection_rule', 'created'): m.BranchProtectionRuleCreatedEvent,
|
|
208
|
+
('branch_protection_rule', 'deleted'): m.BranchProtectionRuleDeletedEvent,
|
|
209
|
+
('branch_protection_rule', 'edited'): m.BranchProtectionRuleEditedEvent,
|
|
210
|
+
('check_run', 'completed'): m.CheckRunCompletedEvent,
|
|
211
|
+
('check_run', 'created'): m.CheckRunCreatedEvent,
|
|
212
|
+
('check_run', 'requested_action'): m.CheckRunRequestedActionEvent,
|
|
213
|
+
('check_run', 'rerequested'): m.CheckRunRerequestedEvent,
|
|
214
|
+
('check_suite', 'completed'): m.CheckSuiteCompletedEvent,
|
|
215
|
+
('check_suite', 'requested'): m.CheckSuiteRequestedEvent,
|
|
216
|
+
('check_suite', 'rerequested'): m.CheckSuiteRerequestedEvent,
|
|
217
|
+
('code_scanning_alert', 'appeared_in_branch'): m.CodeScanningAlertAppearedInBranchEvent,
|
|
218
|
+
('code_scanning_alert', 'closed_by_user'): m.CodeScanningAlertClosedByUserEvent,
|
|
219
|
+
('code_scanning_alert', 'created'): m.CodeScanningAlertCreatedEvent,
|
|
220
|
+
('code_scanning_alert', 'fixed'): m.CodeScanningAlertFixedEvent,
|
|
221
|
+
('code_scanning_alert', 'reopened'): m.CodeScanningAlertReopenedEvent,
|
|
222
|
+
('code_scanning_alert', 'reopened_by_user'): m.CodeScanningAlertReopenedByUserEvent,
|
|
223
|
+
('commit_comment', 'created'): m.CommitCommentCreatedEvent,
|
|
224
|
+
('custom_property', 'created'): m.CustomPropertyCreatedEvent,
|
|
225
|
+
('custom_property', 'deleted'): m.CustomPropertyDeletedEvent,
|
|
226
|
+
('custom_property_values', 'updated'): m.CustomPropertyValuesUpdatedEvent,
|
|
227
|
+
('dependabot_alert', 'created'): m.DependabotAlertCreatedEvent,
|
|
228
|
+
('dependabot_alert', 'dismissed'): m.DependabotAlertDismissedEvent,
|
|
229
|
+
('dependabot_alert', 'fixed'): m.DependabotAlertFixedEvent,
|
|
230
|
+
('dependabot_alert', 'reintroduced'): m.DependabotAlertReintroducedEvent,
|
|
231
|
+
('dependabot_alert', 'reopened'): m.DependabotAlertReopenedEvent,
|
|
232
|
+
('deploy_key', 'created'): m.DeployKeyCreatedEvent,
|
|
233
|
+
('deploy_key', 'deleted'): m.DeployKeyDeletedEvent,
|
|
234
|
+
('deployment', 'created'): m.DeploymentCreatedEvent,
|
|
235
|
+
('deployment_protection_rule', 'requested'): m.DeploymentProtectionRuleRequestedEvent,
|
|
236
|
+
('deployment_review', 'approved'): m.DeploymentReviewApprovedEvent,
|
|
237
|
+
('deployment_review', 'rejected'): m.DeploymentReviewRejectedEvent,
|
|
238
|
+
('deployment_review', 'requested'): m.DeploymentReviewRequestedEvent,
|
|
239
|
+
('deployment_status', 'created'): m.DeploymentStatusCreatedEvent,
|
|
240
|
+
('discussion', 'answered'): m.DiscussionAnsweredEvent,
|
|
241
|
+
('discussion', 'category_changed'): m.DiscussionCategoryChangedEvent,
|
|
242
|
+
('discussion', 'created'): m.DiscussionCreatedEvent,
|
|
243
|
+
('discussion', 'deleted'): m.DiscussionDeletedEvent,
|
|
244
|
+
('discussion', 'edited'): m.DiscussionEditedEvent,
|
|
245
|
+
('discussion', 'labeled'): m.DiscussionLabeledEvent,
|
|
246
|
+
('discussion', 'locked'): m.DiscussionLockedEvent,
|
|
247
|
+
('discussion', 'pinned'): m.DiscussionPinnedEvent,
|
|
248
|
+
('discussion', 'transferred'): m.DiscussionTransferredEvent,
|
|
249
|
+
('discussion', 'unanswered'): m.DiscussionUnansweredEvent,
|
|
250
|
+
('discussion', 'unlabeled'): m.DiscussionUnlabeledEvent,
|
|
251
|
+
('discussion', 'unlocked'): m.DiscussionUnlockedEvent,
|
|
252
|
+
('discussion', 'unpinned'): m.DiscussionUnpinnedEvent,
|
|
253
|
+
('discussion_comment', 'created'): m.DiscussionCommentCreatedEvent,
|
|
254
|
+
('discussion_comment', 'deleted'): m.DiscussionCommentDeletedEvent,
|
|
255
|
+
('discussion_comment', 'edited'): m.DiscussionCommentEditedEvent,
|
|
256
|
+
('github_app_authorization', 'revoked'): m.GitHubAppAuthorizationRevokedEvent,
|
|
257
|
+
('installation', 'created'): m.InstallationCreatedEvent,
|
|
258
|
+
('installation', 'deleted'): m.InstallationDeletedEvent,
|
|
259
|
+
('installation', 'new_permissions_accepted'): m.InstallationNewPermissionsAcceptedEvent,
|
|
260
|
+
('installation', 'suspend'): m.InstallationSuspendEvent,
|
|
261
|
+
('installation', 'unsuspend'): m.InstallationUnsuspendEvent,
|
|
262
|
+
('installation_repositories', 'added'): m.InstallationRepositoriesAddedEvent,
|
|
263
|
+
('installation_repositories', 'removed'): m.InstallationRepositoriesRemovedEvent,
|
|
264
|
+
('installation_target', 'renamed'): m.InstallationTargetRenamedEvent,
|
|
265
|
+
('issue_comment', 'created'): m.IssueCommentCreatedEvent,
|
|
266
|
+
('issue_comment', 'deleted'): m.IssueCommentDeletedEvent,
|
|
267
|
+
('issue_comment', 'edited'): m.IssueCommentEditedEvent,
|
|
268
|
+
('issues', 'assigned'): m.IssuesAssignedEvent,
|
|
269
|
+
('issues', 'closed'): m.IssuesClosedEvent,
|
|
270
|
+
('issues', 'deleted'): m.IssuesDeletedEvent,
|
|
271
|
+
('issues', 'demilestoned'): m.IssuesDemilestonedEvent,
|
|
272
|
+
('issues', 'edited'): m.IssuesEditedEvent,
|
|
273
|
+
('issues', 'labeled'): m.IssuesLabeledEvent,
|
|
274
|
+
('issues', 'locked'): m.IssuesLockedEvent,
|
|
275
|
+
('issues', 'milestoned'): m.IssuesMilestonedEvent,
|
|
276
|
+
('issues', 'opened'): m.IssuesOpenedEvent,
|
|
277
|
+
('issues', 'pinned'): m.IssuesPinnedEvent,
|
|
278
|
+
('issues', 'reopened'): m.IssuesReopenedEvent,
|
|
279
|
+
('issues', 'transferred'): m.IssuesTransferredEvent,
|
|
280
|
+
('issues', 'unassigned'): m.IssuesUnassignedEvent,
|
|
281
|
+
('issues', 'unlabeled'): m.IssuesUnlabeledEvent,
|
|
282
|
+
('issues', 'unlocked'): m.IssuesUnlockedEvent,
|
|
283
|
+
('issues', 'unpinned'): m.IssuesUnpinnedEvent,
|
|
284
|
+
('label', 'created'): m.LabelCreatedEvent,
|
|
285
|
+
('label', 'deleted'): m.LabelDeletedEvent,
|
|
286
|
+
('label', 'edited'): m.LabelEditedEvent,
|
|
287
|
+
('marketplace_purchase', 'cancelled'): m.MarketplacePurchaseCancelledEvent,
|
|
288
|
+
('marketplace_purchase', 'changed'): m.MarketplacePurchaseChangedEvent,
|
|
289
|
+
('marketplace_purchase', 'pending_change'): m.MarketplacePurchasePendingChangeEvent,
|
|
290
|
+
('marketplace_purchase', 'pending_change_cancelled'): m.MarketplacePurchasePendingChangeCancelledEvent,
|
|
291
|
+
('marketplace_purchase', 'purchased'): m.MarketplacePurchasePurchasedEvent,
|
|
292
|
+
('member', 'added'): m.MemberAddedEvent,
|
|
293
|
+
('member', 'edited'): m.MemberEditedEvent,
|
|
294
|
+
('member', 'removed'): m.MemberRemovedEvent,
|
|
295
|
+
('membership', 'added'): m.MembershipAddedEvent,
|
|
296
|
+
('membership', 'removed'): m.MembershipRemovedEvent,
|
|
297
|
+
('merge_group', 'checks_requested'): m.MergeGroupChecksRequestedEvent,
|
|
298
|
+
('merge_group', 'destroyed'): m.MergeGroupDestroyedEvent,
|
|
299
|
+
('meta', 'deleted'): m.MetaDeletedEvent,
|
|
300
|
+
('milestone', 'closed'): m.MilestoneClosedEvent,
|
|
301
|
+
('milestone', 'created'): m.MilestoneCreatedEvent,
|
|
302
|
+
('milestone', 'deleted'): m.MilestoneDeletedEvent,
|
|
303
|
+
('milestone', 'edited'): m.MilestoneEditedEvent,
|
|
304
|
+
('milestone', 'opened'): m.MilestoneOpenedEvent,
|
|
305
|
+
('org_block', 'blocked'): m.OrgBlockBlockedEvent,
|
|
306
|
+
('org_block', 'unblocked'): m.OrgBlockUnblockedEvent,
|
|
307
|
+
('organization', 'deleted'): m.OrganizationDeletedEvent,
|
|
308
|
+
('organization', 'member_added'): m.OrganizationMemberAddedEvent,
|
|
309
|
+
('organization', 'member_invited'): m.OrganizationMemberInvitedEvent,
|
|
310
|
+
('organization', 'member_removed'): m.OrganizationMemberRemovedEvent,
|
|
311
|
+
('organization', 'renamed'): m.OrganizationRenamedEvent,
|
|
312
|
+
('package', 'published'): m.PackagePublishedEvent,
|
|
313
|
+
('package', 'updated'): m.PackageUpdatedEvent,
|
|
314
|
+
('project', 'closed'): m.ProjectClosedEvent,
|
|
315
|
+
('project', 'created'): m.ProjectCreatedEvent,
|
|
316
|
+
('project', 'deleted'): m.ProjectDeletedEvent,
|
|
317
|
+
('project', 'edited'): m.ProjectEditedEvent,
|
|
318
|
+
('project', 'reopened'): m.ProjectReopenedEvent,
|
|
319
|
+
('project_card', 'converted'): m.ProjectCardConvertedEvent,
|
|
320
|
+
('project_card', 'created'): m.ProjectCardCreatedEvent,
|
|
321
|
+
('project_card', 'deleted'): m.ProjectCardDeletedEvent,
|
|
322
|
+
('project_card', 'edited'): m.ProjectCardEditedEvent,
|
|
323
|
+
('project_card', 'moved'): m.ProjectCardMovedEvent,
|
|
324
|
+
('project_column', 'created'): m.ProjectColumnCreatedEvent,
|
|
325
|
+
('project_column', 'deleted'): m.ProjectColumnDeletedEvent,
|
|
326
|
+
('project_column', 'edited'): m.ProjectColumnEditedEvent,
|
|
327
|
+
('project_column', 'moved'): m.ProjectColumnMovedEvent,
|
|
328
|
+
('projects_v2_item', 'archived'): m.ProjectsV2ItemArchivedEvent,
|
|
329
|
+
('projects_v2_item', 'converted'): m.ProjectsV2ItemConvertedEvent,
|
|
330
|
+
('projects_v2_item', 'created'): m.ProjectsV2ItemCreatedEvent,
|
|
331
|
+
('projects_v2_item', 'deleted'): m.ProjectsV2ItemDeletedEvent,
|
|
332
|
+
('projects_v2_item', 'edited'): m.ProjectsV2ItemEditedEvent,
|
|
333
|
+
('projects_v2_item', 'reordered'): m.ProjectsV2ItemReorderedEvent,
|
|
334
|
+
('projects_v2_item', 'restored'): m.ProjectsV2ItemRestoredEvent,
|
|
335
|
+
('pull_request', 'assigned'): m.PullRequestAssignedEvent,
|
|
336
|
+
('pull_request', 'auto_merge_disabled'): m.PullRequestAutoMergeDisabledEvent,
|
|
337
|
+
('pull_request', 'auto_merge_enabled'): m.PullRequestAutoMergeEnabledEvent,
|
|
338
|
+
('pull_request', 'closed'): m.PullRequestClosedEvent,
|
|
339
|
+
('pull_request', 'converted_to_draft'): m.PullRequestConvertedToDraftEvent,
|
|
340
|
+
('pull_request', 'demilestoned'): m.PullRequestDemilestonedEvent,
|
|
341
|
+
('pull_request', 'dequeued'): m.PullRequestDequeuedEvent,
|
|
342
|
+
('pull_request', 'edited'): m.PullRequestEditedEvent,
|
|
343
|
+
('pull_request', 'enqueued'): m.PullRequestEnqueuedEvent,
|
|
344
|
+
('pull_request', 'labeled'): m.PullRequestLabeledEvent,
|
|
345
|
+
('pull_request', 'locked'): m.PullRequestLockedEvent,
|
|
346
|
+
('pull_request', 'milestoned'): m.PullRequestMilestonedEvent,
|
|
347
|
+
('pull_request', 'opened'): m.PullRequestOpenedEvent,
|
|
348
|
+
('pull_request', 'ready_for_review'): m.PullRequestReadyForReviewEvent,
|
|
349
|
+
('pull_request', 'reopened'): m.PullRequestReopenedEvent,
|
|
350
|
+
('pull_request', 'review_request_removed'): m.PullRequestReviewRequestRemovedEvent,
|
|
351
|
+
('pull_request', 'review_requested'): m.PullRequestReviewRequestedEvent,
|
|
352
|
+
('pull_request', 'synchronize'): m.PullRequestSynchronizeEvent,
|
|
353
|
+
('pull_request', 'unassigned'): m.PullRequestUnassignedEvent,
|
|
354
|
+
('pull_request', 'unlabeled'): m.PullRequestUnlabeledEvent,
|
|
355
|
+
('pull_request', 'unlocked'): m.PullRequestUnlockedEvent,
|
|
356
|
+
('pull_request_review', 'dismissed'): m.PullRequestReviewDismissedEvent,
|
|
357
|
+
('pull_request_review', 'edited'): m.PullRequestReviewEditedEvent,
|
|
358
|
+
('pull_request_review', 'submitted'): m.PullRequestReviewSubmittedEvent,
|
|
359
|
+
('pull_request_review_comment', 'created'): m.PullRequestReviewCommentCreatedEvent,
|
|
360
|
+
('pull_request_review_comment', 'deleted'): m.PullRequestReviewCommentDeletedEvent,
|
|
361
|
+
('pull_request_review_comment', 'edited'): m.PullRequestReviewCommentEditedEvent,
|
|
362
|
+
('pull_request_review_thread', 'resolved'): m.PullRequestReviewThreadResolvedEvent,
|
|
363
|
+
('pull_request_review_thread', 'unresolved'): m.PullRequestReviewThreadUnresolvedEvent,
|
|
364
|
+
('registry_package', 'published'): m.RegistryPackagePublishedEvent,
|
|
365
|
+
('registry_package', 'updated'): m.RegistryPackageUpdatedEvent,
|
|
366
|
+
('release', 'created'): m.ReleaseCreatedEvent,
|
|
367
|
+
('release', 'deleted'): m.ReleaseDeletedEvent,
|
|
368
|
+
('release', 'edited'): m.ReleaseEditedEvent,
|
|
369
|
+
('release', 'prereleased'): m.ReleasePrereleasedEvent,
|
|
370
|
+
('release', 'published'): m.ReleasePublishedEvent,
|
|
371
|
+
('release', 'released'): m.ReleaseReleasedEvent,
|
|
372
|
+
('release', 'unpublished'): m.ReleaseUnpublishedEvent,
|
|
373
|
+
('repository', 'archived'): m.RepositoryArchivedEvent,
|
|
374
|
+
('repository', 'created'): m.RepositoryCreatedEvent,
|
|
375
|
+
('repository', 'deleted'): m.RepositoryDeletedEvent,
|
|
376
|
+
('repository', 'edited'): m.RepositoryEditedEvent,
|
|
377
|
+
('repository', 'privatized'): m.RepositoryPrivatizedEvent,
|
|
378
|
+
('repository', 'publicized'): m.RepositoryPublicizedEvent,
|
|
379
|
+
('repository', 'renamed'): m.RepositoryRenamedEvent,
|
|
380
|
+
('repository', 'transferred'): m.RepositoryTransferredEvent,
|
|
381
|
+
('repository', 'unarchived'): m.RepositoryUnarchivedEvent,
|
|
382
|
+
('repository_vulnerability_alert', 'create'): m.RepositoryVulnerabilityAlertCreateEvent,
|
|
383
|
+
('repository_vulnerability_alert', 'dismiss'): m.RepositoryVulnerabilityAlertDismissEvent,
|
|
384
|
+
('repository_vulnerability_alert', 'reopen'): m.RepositoryVulnerabilityAlertReopenEvent,
|
|
385
|
+
('repository_vulnerability_alert', 'resolve'): m.RepositoryVulnerabilityAlertResolveEvent,
|
|
386
|
+
('secret_scanning_alert', 'created'): m.SecretScanningAlertCreatedEvent,
|
|
387
|
+
('secret_scanning_alert', 'reopened'): m.SecretScanningAlertReopenedEvent,
|
|
388
|
+
('secret_scanning_alert', 'resolved'): m.SecretScanningAlertResolvedEvent,
|
|
389
|
+
('secret_scanning_alert', 'revoked'): m.SecretScanningAlertRevokedEvent,
|
|
390
|
+
('secret_scanning_alert_location', 'created'): m.SecretScanningAlertLocationCreatedEvent,
|
|
391
|
+
('security_advisory', 'performed'): m.SecurityAdvisoryPerformedEvent,
|
|
392
|
+
('security_advisory', 'published'): m.SecurityAdvisoryPublishedEvent,
|
|
393
|
+
('security_advisory', 'updated'): m.SecurityAdvisoryUpdatedEvent,
|
|
394
|
+
('security_advisory', 'withdrawn'): m.SecurityAdvisoryWithdrawnEvent,
|
|
395
|
+
('sponsorship', 'cancelled'): m.SponsorshipCancelledEvent,
|
|
396
|
+
('sponsorship', 'created'): m.SponsorshipCreatedEvent,
|
|
397
|
+
('sponsorship', 'edited'): m.SponsorshipEditedEvent,
|
|
398
|
+
('sponsorship', 'pending_cancellation'): m.SponsorshipPendingCancellationEvent,
|
|
399
|
+
('sponsorship', 'pending_tier_change'): m.SponsorshipPendingTierChangeEvent,
|
|
400
|
+
('sponsorship', 'tier_changed'): m.SponsorshipTierChangedEvent,
|
|
401
|
+
('star', 'created'): m.StarCreatedEvent,
|
|
402
|
+
('star', 'deleted'): m.StarDeletedEvent,
|
|
403
|
+
('team', 'added_to_repository'): m.TeamAddedToRepositoryEvent,
|
|
404
|
+
('team', 'created'): m.TeamCreatedEvent,
|
|
405
|
+
('team', 'deleted'): m.TeamDeletedEvent,
|
|
406
|
+
('team', 'edited'): m.TeamEditedEvent,
|
|
407
|
+
('team', 'removed_from_repository'): m.TeamRemovedFromRepositoryEvent,
|
|
408
|
+
('watch', 'started'): m.WatchStartedEvent,
|
|
409
|
+
('workflow_job', 'completed'): m.WorkflowJobCompletedEvent,
|
|
410
|
+
('workflow_job', 'in_progress'): m.WorkflowJobInProgressEvent,
|
|
411
|
+
('workflow_job', 'queued'): m.WorkflowJobQueuedEvent,
|
|
412
|
+
('workflow_job', 'waiting'): m.WorkflowJobWaitingEvent,
|
|
413
|
+
('workflow_run', 'completed'): m.WorkflowRunCompletedEvent,
|
|
414
|
+
('workflow_run', 'in_progress'): m.WorkflowRunInProgressEvent,
|
|
415
|
+
('workflow_run', 'requested'): m.WorkflowRunRequestedEvent,
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
WebhookEvent = (
|
|
419
|
+
m.BranchProtectionConfigurationEvent
|
|
420
|
+
| m.BranchProtectionRuleEvent
|
|
421
|
+
| m.CheckRunEvent
|
|
422
|
+
| m.CheckSuiteEvent
|
|
423
|
+
| m.CodeScanningAlertEvent
|
|
424
|
+
| m.CommitCommentEvent
|
|
425
|
+
| m.CreateEvent
|
|
426
|
+
| m.CustomPropertyEvent
|
|
427
|
+
| m.CustomPropertyValuesEvent
|
|
428
|
+
| m.DeleteEvent
|
|
429
|
+
| m.DependabotAlertEvent
|
|
430
|
+
| m.DeployKeyEvent
|
|
431
|
+
| m.DeploymentEvent
|
|
432
|
+
| m.DeploymentProtectionRuleEvent
|
|
433
|
+
| m.DeploymentReviewEvent
|
|
434
|
+
| m.DeploymentStatusEvent
|
|
435
|
+
| m.DiscussionEvent
|
|
436
|
+
| m.DiscussionCommentEvent
|
|
437
|
+
| m.ForkEvent
|
|
438
|
+
| m.GitHubAppAuthorizationEvent
|
|
439
|
+
| m.GollumEvent
|
|
440
|
+
| m.InstallationEvent
|
|
441
|
+
| m.InstallationRepositoriesEvent
|
|
442
|
+
| m.InstallationTargetEvent
|
|
443
|
+
| m.IssueCommentEvent
|
|
444
|
+
| m.IssuesEvent
|
|
445
|
+
| m.LabelEvent
|
|
446
|
+
| m.MarketplacePurchaseEvent
|
|
447
|
+
| m.MemberEvent
|
|
448
|
+
| m.MembershipEvent
|
|
449
|
+
| m.MergeGroupEvent
|
|
450
|
+
| m.MetaEvent
|
|
451
|
+
| m.MilestoneEvent
|
|
452
|
+
| m.OrgBlockEvent
|
|
453
|
+
| m.OrganizationEvent
|
|
454
|
+
| m.PackageEvent
|
|
455
|
+
| m.PageBuildEvent
|
|
456
|
+
| m.PingEvent
|
|
457
|
+
| m.ProjectEvent
|
|
458
|
+
| m.ProjectCardEvent
|
|
459
|
+
| m.ProjectColumnEvent
|
|
460
|
+
| m.ProjectsV2ItemEvent
|
|
461
|
+
| m.PublicEvent
|
|
462
|
+
| m.PullRequestEvent
|
|
463
|
+
| m.PullRequestReviewEvent
|
|
464
|
+
| m.PullRequestReviewCommentEvent
|
|
465
|
+
| m.PullRequestReviewThreadEvent
|
|
466
|
+
| m.PushEvent
|
|
467
|
+
| m.RegistryPackageEvent
|
|
468
|
+
| m.ReleaseEvent
|
|
469
|
+
| m.RepositoryEvent
|
|
470
|
+
| m.RepositoryDispatchEvent
|
|
471
|
+
| m.RepositoryImportEvent
|
|
472
|
+
| m.RepositoryVulnerabilityAlertEvent
|
|
473
|
+
| m.SecretScanningAlertEvent
|
|
474
|
+
| m.SecretScanningAlertLocationEvent
|
|
475
|
+
| m.SecurityAdvisoryEvent
|
|
476
|
+
| m.SponsorshipEvent
|
|
477
|
+
| m.StarEvent
|
|
478
|
+
| m.StatusEvent
|
|
479
|
+
| m.TeamEvent
|
|
480
|
+
| m.TeamAddEvent
|
|
481
|
+
| m.WatchEvent
|
|
482
|
+
| m.WorkflowDispatchEvent
|
|
483
|
+
| m.WorkflowJobEvent
|
|
484
|
+
| m.WorkflowRunEvent
|
|
485
|
+
)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Framework-free GitHub webhook dispatch: verify, parse, validate, route.
|
|
2
|
+
|
|
3
|
+
Works with any HTTP framework (or none) — you bring the raw request body and
|
|
4
|
+
headers, WebhookDispatcher does the rest. github_events.fastapi wraps this for
|
|
5
|
+
FastAPI apps.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import hashlib
|
|
11
|
+
import hmac
|
|
12
|
+
import inspect
|
|
13
|
+
import json
|
|
14
|
+
from collections.abc import Callable
|
|
15
|
+
from typing import Any, TypeVar
|
|
16
|
+
|
|
17
|
+
__all__ = ["SignatureVerificationError", "WebhookDispatcher", "WebhookError"]
|
|
18
|
+
|
|
19
|
+
Handler = TypeVar("Handler", bound=Callable[..., Any])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class WebhookError(Exception):
|
|
23
|
+
"""Base class for dispatch failures."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SignatureVerificationError(WebhookError):
|
|
27
|
+
"""X-Hub-Signature-256 was missing or didn't match the body."""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class WebhookDispatcher:
|
|
31
|
+
"""Handler registry keyed by (event, action), with signature verification.
|
|
32
|
+
|
|
33
|
+
@hook.on("issues", action="opened") -> called with an IssuesOpenedEvent payload
|
|
34
|
+
@hook.on("issues") -> called with every issues action
|
|
35
|
+
@hook.on_any -> called with (event_name, payload) for all deliveries
|
|
36
|
+
|
|
37
|
+
Handlers may be sync or async. With validate=True (the default, requires
|
|
38
|
+
pydantic) payloads are checked against the generated TypedDicts before
|
|
39
|
+
dispatch; events GitHub adds after generation pass through unvalidated.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, secret: str | bytes | None = None, *, validate: bool = True) -> None:
|
|
43
|
+
if isinstance(secret, str):
|
|
44
|
+
secret = secret.encode()
|
|
45
|
+
self._secret = secret
|
|
46
|
+
self._handlers: dict[tuple[str, str | None], list[Callable[..., Any]]] = {}
|
|
47
|
+
self._any_handlers: list[Callable[..., Any]] = []
|
|
48
|
+
self._validate: Callable[[str, str | None, Any], Any]
|
|
49
|
+
if validate:
|
|
50
|
+
from github_events.validation import validate_payload
|
|
51
|
+
|
|
52
|
+
self._validate = validate_payload
|
|
53
|
+
else:
|
|
54
|
+
self._validate = lambda _event, _action, data: data
|
|
55
|
+
|
|
56
|
+
def on(
|
|
57
|
+
self, event: str, action: str | list[str] | None = None
|
|
58
|
+
) -> Callable[[Handler], Handler]:
|
|
59
|
+
"""Register a handler for one event, optionally narrowed to one action
|
|
60
|
+
or a list of actions (the handler fires for any of them)."""
|
|
61
|
+
actions: list[str | None]
|
|
62
|
+
if action is None:
|
|
63
|
+
actions = [None]
|
|
64
|
+
elif isinstance(action, str):
|
|
65
|
+
actions = [action]
|
|
66
|
+
else:
|
|
67
|
+
actions = list(dict.fromkeys(action)) # dedupe, keep order
|
|
68
|
+
if not actions:
|
|
69
|
+
raise ValueError("action list must not be empty")
|
|
70
|
+
|
|
71
|
+
def register(fn: Handler) -> Handler:
|
|
72
|
+
for a in actions:
|
|
73
|
+
self._handlers.setdefault((event, a), []).append(fn)
|
|
74
|
+
return fn
|
|
75
|
+
|
|
76
|
+
return register
|
|
77
|
+
|
|
78
|
+
def on_any(self, fn: Handler) -> Handler:
|
|
79
|
+
"""Register a handler called with (event_name, payload) for every delivery."""
|
|
80
|
+
self._any_handlers.append(fn)
|
|
81
|
+
return fn
|
|
82
|
+
|
|
83
|
+
def verify_signature(self, body: bytes, signature_256: str | None) -> None:
|
|
84
|
+
"""Constant-time HMAC-SHA256 check. No-op unless a secret is configured."""
|
|
85
|
+
if self._secret is None:
|
|
86
|
+
return
|
|
87
|
+
if not signature_256:
|
|
88
|
+
raise SignatureVerificationError("missing X-Hub-Signature-256 header")
|
|
89
|
+
expected = "sha256=" + hmac.new(self._secret, body, hashlib.sha256).hexdigest()
|
|
90
|
+
if not hmac.compare_digest(expected, signature_256):
|
|
91
|
+
raise SignatureVerificationError("X-Hub-Signature-256 mismatch")
|
|
92
|
+
|
|
93
|
+
async def dispatch(
|
|
94
|
+
self,
|
|
95
|
+
event: str,
|
|
96
|
+
body: bytes | str | dict[str, Any],
|
|
97
|
+
*,
|
|
98
|
+
signature_256: str | None = None,
|
|
99
|
+
) -> Any:
|
|
100
|
+
"""Verify, parse, validate and route one delivery; returns the payload.
|
|
101
|
+
|
|
102
|
+
Raises SignatureVerificationError (a secret is configured and the
|
|
103
|
+
signature is missing/wrong), json.JSONDecodeError (malformed body), and
|
|
104
|
+
— with validation enabled — pydantic.ValidationError when a field that
|
|
105
|
+
is present has the wrong type.
|
|
106
|
+
"""
|
|
107
|
+
if isinstance(body, dict):
|
|
108
|
+
if self._secret is not None:
|
|
109
|
+
raise ValueError(
|
|
110
|
+
"cannot verify a signature against a pre-parsed body; pass raw bytes"
|
|
111
|
+
)
|
|
112
|
+
data = body
|
|
113
|
+
else:
|
|
114
|
+
raw = body.encode() if isinstance(body, str) else body
|
|
115
|
+
self.verify_signature(raw, signature_256)
|
|
116
|
+
data = json.loads(raw)
|
|
117
|
+
action = data.get("action") if isinstance(data, dict) else None
|
|
118
|
+
payload = self._validate(event, action if isinstance(action, str) else None, data)
|
|
119
|
+
# dict.fromkeys dedupes (action-less events would otherwise route twice)
|
|
120
|
+
for key in dict.fromkeys(((event, action), (event, None))):
|
|
121
|
+
for fn in self._handlers.get(key, []):
|
|
122
|
+
if inspect.isawaitable(result := fn(payload)):
|
|
123
|
+
await result
|
|
124
|
+
for fn in self._any_handlers:
|
|
125
|
+
if inspect.isawaitable(result := fn(event, payload)):
|
|
126
|
+
await result
|
|
127
|
+
return payload
|
|
128
|
+
|
|
129
|
+
def as_fastapi_router(self, *, path: str = "/") -> Any:
|
|
130
|
+
"""Build a FastAPI APIRouter with a POST endpoint wired to this dispatcher.
|
|
131
|
+
|
|
132
|
+
Requires fastapi (github-events[fastapi]). Returns fastapi.APIRouter.
|
|
133
|
+
"""
|
|
134
|
+
from github_events.fastapi import create_router
|
|
135
|
+
|
|
136
|
+
# Suppression needed because the .pyi stub shadows this module, so
|
|
137
|
+
# `self`'s impl type doesn't unify with the stub's WebhookDispatcher.
|
|
138
|
+
return create_router(self, path=path) # ty: ignore[invalid-argument-type]
|