Skip to content

Commit 5c645c2

Browse files
fix: Support custom repository_dispatch actions (#712)
1 parent ba84c54 commit 5c645c2

File tree

3 files changed

+168
-5
lines changed

3 files changed

+168
-5
lines changed

src/Octokit.Webhooks/Converter/WebhookConverter.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
namespace Octokit.Webhooks.Converter;
22

33
using System.Linq;
4+
using System.Reflection;
45

56
[PublicAPI]
67
public class WebhookConverter<T> : JsonConverter<T>
78
where T : WebhookEvent
89
{
9-
private readonly IDictionary<string, Type> types;
10+
private readonly Dictionary<string, Type> types;
1011

1112
public WebhookConverter()
1213
{
1314
var type = typeof(T);
1415
this.types = this.GetType().Assembly.GetTypes()
1516
.Where(x => type.IsAssignableFrom(x) && x is { IsClass: true, IsAbstract: false } &&
16-
Attribute.GetCustomAttribute(x, typeof(WebhookActionTypeAttribute)) is not null)
17+
x.GetCustomAttribute<WebhookActionTypeAttribute>() is not null)
1718
.ToDictionary(
18-
y => ((WebhookActionTypeAttribute)Attribute.GetCustomAttribute(y, typeof(WebhookActionTypeAttribute))!).ActionType,
19+
y => y.GetCustomAttribute<WebhookActionTypeAttribute>()!.ActionType,
1920
y => y);
2021
}
2122

@@ -27,12 +28,30 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial
2728
}
2829

2930
using var jsonDocument = JsonDocument.ParseValue(ref reader);
30-
if (!jsonDocument.RootElement.TryGetProperty(nameof(WebhookEvent.Action).ToLower(CultureInfo.InvariantCulture), out var action))
31+
if (!jsonDocument.RootElement.TryGetProperty("action", out var action))
3132
{
3233
throw new JsonException();
3334
}
3435

35-
var type = this.types.FirstOrDefault(x => x.Key == action.GetString()).Value ?? throw new JsonException();
36+
Type? type = null;
37+
38+
var actionValue = action.GetString();
39+
40+
if (actionValue is not null && this.types.TryGetValue(actionValue, out var payloadType))
41+
{
42+
type = payloadType;
43+
}
44+
45+
// repository_dispatch events can have custom user-defined actions values
46+
if (type == null && typeToConvert == typeof(Events.RepositoryDispatchEvent))
47+
{
48+
type = typeof(Events.RepositoryDispatch.RepositoryDispatchCustomEvent);
49+
}
50+
51+
if (type is null)
52+
{
53+
throw new JsonException();
54+
}
3655

3756
var jsonObject = jsonDocument.RootElement.GetRawText();
3857
return (T)JsonSerializer.Deserialize(jsonObject, type, options)!;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
namespace Octokit.Webhooks.Events.RepositoryDispatch;
2+
3+
[PublicAPI]
4+
public sealed record RepositoryDispatchCustomEvent : RepositoryDispatchEvent;
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
{
2+
"action": "foo",
3+
"branch": "main",
4+
"client_payload": { "foo": 42, "bar": "baz" },
5+
"repository": {
6+
"id": 17273051,
7+
"node_id": "MDEwOlJlcG9zaXRvcnkxNzI3MzA1MQ==",
8+
"name": "octo-repo",
9+
"full_name": "octo-org/octo-repo",
10+
"private": true,
11+
"owner": {
12+
"login": "octo-org",
13+
"id": 6811672,
14+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjY4MTE2NzI=",
15+
"avatar_url": "https://avatars3.githubusercontent.com/u/6811672?v=4",
16+
"gravatar_id": "",
17+
"url": "https://api.github.com/users/octo-org",
18+
"html_url": "https://github.com/octo-org",
19+
"followers_url": "https://api.github.com/users/octo-org/followers",
20+
"following_url": "https://api.github.com/users/octo-org/following{/other_user}",
21+
"gists_url": "https://api.github.com/users/octo-org/gists{/gist_id}",
22+
"starred_url": "https://api.github.com/users/octo-org/starred{/owner}{/repo}",
23+
"subscriptions_url": "https://api.github.com/users/octo-org/subscriptions",
24+
"organizations_url": "https://api.github.com/users/octo-org/orgs",
25+
"repos_url": "https://api.github.com/users/octo-org/repos",
26+
"events_url": "https://api.github.com/users/octo-org/events{/privacy}",
27+
"received_events_url": "https://api.github.com/users/octo-org/received_events",
28+
"type": "Organization",
29+
"site_admin": false
30+
},
31+
"html_url": "https://github.com/octo-org/octo-repo",
32+
"description": "My first repo on GitHub!",
33+
"fork": false,
34+
"url": "https://api.github.com/repos/octo-org/octo-repo",
35+
"forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks",
36+
"keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}",
37+
"collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}",
38+
"teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams",
39+
"hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks",
40+
"issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}",
41+
"events_url": "https://api.github.com/repos/octo-org/octo-repo/events",
42+
"assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}",
43+
"branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}",
44+
"tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags",
45+
"blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}",
46+
"git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}",
47+
"git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}",
48+
"trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}",
49+
"statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}",
50+
"languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages",
51+
"stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers",
52+
"contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors",
53+
"subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers",
54+
"subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription",
55+
"commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}",
56+
"git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}",
57+
"comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}",
58+
"issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}",
59+
"contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}",
60+
"compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}",
61+
"merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges",
62+
"archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}",
63+
"downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads",
64+
"issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}",
65+
"pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}",
66+
"milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}",
67+
"notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}",
68+
"labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}",
69+
"releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}",
70+
"deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments",
71+
"created_at": "2014-02-28T02:42:51Z",
72+
"updated_at": "2018-10-10T15:58:51Z",
73+
"pushed_at": "2018-10-10T15:58:47Z",
74+
"git_url": "git://github.com/octo-org/octo-repo.git",
75+
"ssh_url": "git@github.com:octo-org/octo-repo.git",
76+
"clone_url": "https://github.com/octo-org/octo-repo.git",
77+
"svn_url": "https://github.com/octo-org/octo-repo",
78+
"homepage": "https://example.com",
79+
"size": 59,
80+
"stargazers_count": 0,
81+
"watchers_count": 0,
82+
"language": "JavaScript",
83+
"has_issues": true,
84+
"has_projects": true,
85+
"has_downloads": true,
86+
"has_wiki": true,
87+
"has_pages": false,
88+
"forks_count": 1,
89+
"mirror_url": null,
90+
"archived": false,
91+
"open_issues_count": 23,
92+
"license": null,
93+
"forks": 1,
94+
"open_issues": 23,
95+
"watchers": 0,
96+
"default_branch": "master",
97+
"is_template": false,
98+
"topics": [],
99+
"visibility": "public",
100+
"web_commit_signoff_required": false
101+
},
102+
"organization": {
103+
"login": "octo-org",
104+
"id": 6811672,
105+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjY4MTE2NzI=",
106+
"url": "https://api.github.com/orgs/octo-org",
107+
"repos_url": "https://api.github.com/orgs/octo-org/repos",
108+
"events_url": "https://api.github.com/orgs/octo-org/events",
109+
"hooks_url": "https://api.github.com/orgs/octo-org/hooks",
110+
"issues_url": "https://api.github.com/orgs/octo-org/issues",
111+
"members_url": "https://api.github.com/orgs/octo-org/members{/member}",
112+
"public_members_url": "https://api.github.com/orgs/octo-org/public_members{/member}",
113+
"avatar_url": "https://avatars3.githubusercontent.com/u/6811672?v=4",
114+
"description": "Working better together!"
115+
},
116+
"sender": {
117+
"login": "Codertocat",
118+
"id": 21031067,
119+
"node_id": "MDQ6VXNlcjIxMDMxMDY3",
120+
"avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
121+
"gravatar_id": "",
122+
"url": "https://api.github.com/users/Codertocat",
123+
"html_url": "https://github.com/Codertocat",
124+
"followers_url": "https://api.github.com/users/Codertocat/followers",
125+
"following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
126+
"gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
127+
"starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
128+
"subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
129+
"organizations_url": "https://api.github.com/users/Codertocat/orgs",
130+
"repos_url": "https://api.github.com/users/Codertocat/repos",
131+
"events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
132+
"received_events_url": "https://api.github.com/users/Codertocat/received_events",
133+
"type": "User",
134+
"site_admin": false
135+
},
136+
"installation": {
137+
"id": 375706,
138+
"node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMzc1NzA2"
139+
}
140+
}

0 commit comments

Comments
 (0)