Skip to content

Commit c3fc154

Browse files
authored
Merge pull request #6 from getmarkus/cm-branch-5
feat: enhance IssueEvent with additional attributes and types
2 parents a9c4640 + b37dedd commit c3fc154

File tree

4 files changed

+436
-10
lines changed

4 files changed

+436
-10
lines changed

src/domain/aggregate_root.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class BaseEvent(Protocol):
1818
event_id: str
1919
timestamp: datetime
2020

21+
2122
class AggregateRoot(BaseModel, abc.ABC):
2223
version: int = 0
2324

src/domain/issue.json

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
{
2+
"id": 1,
3+
"node_id": "MDU6SXNzdWUx",
4+
"url": "https://api.github.com/repos/octocat/Hello-World/issues/1347",
5+
"repository_url": "https://api.github.com/repos/octocat/Hello-World",
6+
"labels_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347/labels{/name}",
7+
"comments_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347/comments",
8+
"events_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347/events",
9+
"html_url": "https://github.com/octocat/Hello-World/issues/1347",
10+
"number": 1347,
11+
"state": "open",
12+
"title": "Found a bug",
13+
"body": "I'm having a problem with this.",
14+
"user": {
15+
"login": "octocat",
16+
"id": 1,
17+
"node_id": "MDQ6VXNlcjE=",
18+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
19+
"gravatar_id": "",
20+
"url": "https://api.github.com/users/octocat",
21+
"html_url": "https://github.com/octocat",
22+
"followers_url": "https://api.github.com/users/octocat/followers",
23+
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
24+
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
25+
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
26+
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
27+
"organizations_url": "https://api.github.com/users/octocat/orgs",
28+
"repos_url": "https://api.github.com/users/octocat/repos",
29+
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
30+
"received_events_url": "https://api.github.com/users/octocat/received_events",
31+
"type": "User",
32+
"site_admin": false
33+
},
34+
"labels": [
35+
{
36+
"id": 208045946,
37+
"node_id": "MDU6TGFiZWwyMDgwNDU5NDY=",
38+
"url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
39+
"name": "bug",
40+
"description": "Something isn't working",
41+
"color": "f29513",
42+
"default": true
43+
}
44+
],
45+
"assignee": {
46+
"login": "octocat",
47+
"id": 1,
48+
"node_id": "MDQ6VXNlcjE=",
49+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
50+
"gravatar_id": "",
51+
"url": "https://api.github.com/users/octocat",
52+
"html_url": "https://github.com/octocat",
53+
"followers_url": "https://api.github.com/users/octocat/followers",
54+
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
55+
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
56+
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
57+
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
58+
"organizations_url": "https://api.github.com/users/octocat/orgs",
59+
"repos_url": "https://api.github.com/users/octocat/repos",
60+
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
61+
"received_events_url": "https://api.github.com/users/octocat/received_events",
62+
"type": "User",
63+
"site_admin": false
64+
},
65+
"assignees": [
66+
{
67+
"login": "octocat",
68+
"id": 1,
69+
"node_id": "MDQ6VXNlcjE=",
70+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
71+
"gravatar_id": "",
72+
"url": "https://api.github.com/users/octocat",
73+
"html_url": "https://github.com/octocat",
74+
"followers_url": "https://api.github.com/users/octocat/followers",
75+
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
76+
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
77+
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
78+
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
79+
"organizations_url": "https://api.github.com/users/octocat/orgs",
80+
"repos_url": "https://api.github.com/users/octocat/repos",
81+
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
82+
"received_events_url": "https://api.github.com/users/octocat/received_events",
83+
"type": "User",
84+
"site_admin": false
85+
}
86+
],
87+
"milestone": {
88+
"url": "https://api.github.com/repos/octocat/Hello-World/milestones/1",
89+
"html_url": "https://github.com/octocat/Hello-World/milestones/v1.0",
90+
"labels_url": "https://api.github.com/repos/octocat/Hello-World/milestones/1/labels",
91+
"id": 1002604,
92+
"node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==",
93+
"number": 1,
94+
"state": "open",
95+
"title": "v1.0",
96+
"description": "Tracking milestone for version 1.0",
97+
"creator": {
98+
"login": "octocat",
99+
"id": 1,
100+
"node_id": "MDQ6VXNlcjE=",
101+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
102+
"gravatar_id": "",
103+
"url": "https://api.github.com/users/octocat",
104+
"html_url": "https://github.com/octocat",
105+
"followers_url": "https://api.github.com/users/octocat/followers",
106+
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
107+
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
108+
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
109+
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
110+
"organizations_url": "https://api.github.com/users/octocat/orgs",
111+
"repos_url": "https://api.github.com/users/octocat/repos",
112+
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
113+
"received_events_url": "https://api.github.com/users/octocat/received_events",
114+
"type": "User",
115+
"site_admin": false
116+
},
117+
"open_issues": 4,
118+
"closed_issues": 8,
119+
"created_at": "2011-04-10T20:09:31Z",
120+
"updated_at": "2014-03-03T18:58:10Z",
121+
"closed_at": "2013-02-12T13:22:01Z",
122+
"due_on": "2012-10-09T23:39:01Z"
123+
},
124+
"locked": true,
125+
"active_lock_reason": "too heated",
126+
"comments": 0,
127+
"pull_request": {
128+
"url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347",
129+
"html_url": "https://github.com/octocat/Hello-World/pull/1347",
130+
"diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff",
131+
"patch_url": "https://github.com/octocat/Hello-World/pull/1347.patch"
132+
},
133+
"closed_at": null,
134+
"created_at": "2011-04-22T13:33:48Z",
135+
"updated_at": "2011-04-22T13:33:48Z",
136+
"closed_by": {
137+
"login": "octocat",
138+
"id": 1,
139+
"node_id": "MDQ6VXNlcjE=",
140+
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
141+
"gravatar_id": "",
142+
"url": "https://api.github.com/users/octocat",
143+
"html_url": "https://github.com/octocat",
144+
"followers_url": "https://api.github.com/users/octocat/followers",
145+
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
146+
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
147+
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
148+
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
149+
"organizations_url": "https://api.github.com/users/octocat/orgs",
150+
"repos_url": "https://api.github.com/users/octocat/repos",
151+
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
152+
"received_events_url": "https://api.github.com/users/octocat/received_events",
153+
"type": "User",
154+
"site_admin": false
155+
},
156+
"author_association": "COLLABORATOR",
157+
"state_reason": "completed"
158+
}

src/domain/issue.py

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,105 @@
11
from datetime import datetime
22
from enum import Enum
3+
from typing import Optional
34

45
from src.domain.aggregate_root import AggregateRoot, BaseCommand, BaseEvent
56

7+
# https://docs.github.com/en/rest/using-the-rest-api/github-event-types?apiVersion=2022-11-28#issuesevent
8+
# https://docs.github.com/en/rest/using-the-rest-api/issue-event-types?apiVersion=2022-11-28
9+
# https://docs.github.com/en/rest/issues/events?apiVersion=2022-11-28#get-an-issue-event
10+
# https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#update-an-issue
11+
# https://docs.github.com/en/rest/issues/timeline?apiVersion=2022-11-28
12+
# https://github.blog/open-source/maintainers/metrics-for-issues-pull-requests-and-discussions/
613

714
class IssueState(Enum):
815
OPEN = "OPEN"
916
CLOSED = "CLOSED"
10-
IN_PROGRESS = "IN_PROGRESS"
11-
REOPENED = "REOPENED"
12-
RESOLVED = "RESOLVED"
1317

1418
@property
1519
def is_open(self):
1620
return self == IssueState.OPEN
1721

22+
class IssueStateTransition(Enum):
23+
COMPLETED = "COMPLETED"
24+
NOT_PLANNED = "NOT_PLANNED"
25+
REOPENED = "REOPENED"
26+
1827
class IssueEventType(Enum):
1928
OPENED = "OPENED"
29+
EDITED = "EDITED"
2030
CLOSED = "CLOSED"
21-
IN_PROGRESS = "IN_PROGRESS"
2231
REOPENED = "REOPENED"
23-
RESOLVED = "RESOLVED"
24-
25-
@property
26-
def is_open(self):
27-
return self == IssueEventType.OPENED
32+
ASSIGNED = "ASSIGNED"
33+
UNASSIGNED = "UNASSIGNED"
34+
LABLED = "LABLED"
35+
UNLABLED = "UNLABLED"
2836

2937
### Events ###
3038
class IssueEvent(BaseEvent):
3139
event_id: str
3240
timestamp: datetime
3341
issue_number: int
3442
issue_state: IssueState
43+
issue_state_transition: IssueStateTransition
3544
issue_event_type: IssueEventType
45+
changes: dict[str, any]
46+
previous_title: str
47+
previous_body: str
48+
assignee: Optional[str]
49+
label: Optional[str]
50+
51+
def __init__(
52+
self,
53+
event_id: str,
54+
timestamp: datetime,
55+
issue_number: int,
56+
issue_state: IssueState,
57+
issue_state_transition: IssueStateTransition,
58+
issue_event_type: IssueEventType,
59+
changes: dict[str, any],
60+
previous_title: str,
61+
previous_body: str,
62+
assignee: Optional[str] = None,
63+
label: Optional[str] = None
64+
):
65+
super().__init__()
66+
self.event_id = event_id
67+
self.timestamp = timestamp
68+
self.issue_number = issue_number
69+
self.issue_state = issue_state
70+
self.issue_state_transition = issue_state_transition
71+
self.issue_event_type = issue_event_type
72+
self.changes = changes
73+
self.previous_title = previous_title
74+
self.previous_body = previous_body
75+
self.assignee = assignee
76+
self.label = label
77+
78+
## potential sub-events
79+
# - connected
80+
# - disconnected
81+
# - converted_to_discussion
82+
# - milestoned
83+
# - demilestoned
84+
# - locked
85+
# - mentioned
86+
# - marked_as_duplicate
87+
# - unmarked_as_duplicate
88+
# - pinned
89+
# - unpinned
90+
# - referenced
91+
# - renamed
92+
# - subscribed
93+
# - transferred
94+
# - unlocked
95+
# - user_blocked
96+
# - commented OR IssueCommentEvent
3697

3798
### Commands ###
3899
class IssueCommand(BaseCommand):
39100
command_id: str
40101
timestamp: datetime
41102
issue_number: int
42-
issue_state: IssueState
43103

44104
# might need specification pattern here
45105
def validate(self) -> bool:

0 commit comments

Comments
 (0)