6
6
OWNER_REPO = "compiler-explorer/compiler-explorer"
7
7
USER_AGENT = "CE Live Now Notification Bot"
8
8
9
+ NOW_LIVE_LABEL = "live"
10
+ NOW_LIVE_MESSAGE = "This is now live"
11
+
9
12
10
13
def post (entity : str , token : str , query : dict = None , dry = False ) -> dict :
11
14
if query is None :
@@ -74,25 +77,33 @@ def list_inbetween_commits(end_commit: str, new_commit: str, token: str) -> List
74
77
75
78
76
79
def get_linked_pr (commit : str , token : str ) -> dict :
80
+ """Returns a list whose items are the PR associated to each commit"""
77
81
pr = get (f"repos/{ OWNER_REPO } /commits/{ commit } /pulls" , token = token )
78
- return pr
82
+ return pr [ 0 ] if len ( pr ) == 1 else {}
79
83
80
84
81
85
def get_linked_issues (pr : str , token : str ):
82
86
query = """
83
- query {
84
- repository(owner: "compiler-explorer", name: "compiler-explorer") {
85
- pullRequest(number: %s) {
86
- closingIssuesReferences(first: 10) {
87
- edges {
88
- node {
89
- number
90
- }
87
+ query {
88
+ repository(owner: "compiler-explorer", name: "compiler-explorer") {
89
+ pullRequest(number: %s) {
90
+ closingIssuesReferences(first: 10) {
91
+ edges {
92
+ node {
93
+ labels(first: 10) {
94
+ edges {
95
+ node {
96
+ name
91
97
}
92
98
}
93
99
}
100
+ number
101
+ }
94
102
}
103
+ }
95
104
}
105
+ }
106
+ }
96
107
""" % pr
97
108
return post ("graphql" , token , {"query" : query })
98
109
@@ -102,33 +113,67 @@ def get_issue_comments(issue: str, token: str) -> List[dict]:
102
113
103
114
104
115
def comment_on_issue (issue : str , msg : str , token : str ):
105
- result = post (f"repos/{ OWNER_REPO } /issues/{ issue } /comments" , token , {"body" : msg }, dry = True )
116
+ result = post (f"repos/{ OWNER_REPO } /issues/{ issue } /comments" , token , {"body" : msg })
106
117
return result
107
118
108
119
120
+ def set_issue_labels (issue : str , labels : List [str ], token : str ):
121
+ post (f"repos/{ OWNER_REPO } /issues/{ issue } /labels" , token , {"labels" : labels })
122
+
123
+
124
+ def should_send_comment_to_issue (issue : str , token : str ):
125
+ """Only send a comment to the issue if nothing like the live message is there already"""
126
+ comments = get_issue_comments (issue , token )
127
+ return all ([NOW_LIVE_MESSAGE not in comment ["body" ] for comment in comments ])
128
+
129
+
109
130
def send_live_message (issue : str , token : str ):
110
- comment_on_issue (issue , "This is now live" , token = token )
131
+ set_issue_labels (issue , [NOW_LIVE_LABEL ], token )
132
+ if should_send_comment_to_issue (issue , token ):
133
+ comment_on_issue (issue , NOW_LIVE_MESSAGE , token )
111
134
112
135
113
136
def get_edges (issue : dict ) -> List [dict ]:
114
137
return issue ["data" ]["repository" ]["pullRequest" ]["closingIssuesReferences" ]["edges" ]
115
138
116
139
140
+ def should_process_pr (pr_labels ):
141
+ """Only process PRs that do not have the live label already set"""
142
+ return all ([label ["name" ] != NOW_LIVE_LABEL for label in labels ])
143
+
144
+
145
+ def should_notify_issue (edge ) -> bool :
146
+ """We want to notify the issue if:
147
+ - there's one linked ("number" in edge) AND
148
+ - either:
149
+ - the linked issue has no labels ("labels" not in edge["node"]) OR
150
+ - the NOW_LIVE_LABEL label is not among its labels"""
151
+ return "number" in edge and (("labels" not in edge ) or all (
152
+ [label ["node" ]["name" ] != NOW_LIVE_LABEL for label in edge ["labels" ]["edges" ]]))
153
+
154
+
117
155
def handle_notify (base , new , token ):
118
- print (f'Notifying from { base } to { new } ' )
156
+ print (f'Checking for live notifications from { base } to { new } ' )
119
157
120
158
commits = list_inbetween_commits (base , new , token )
121
-
122
159
prs = [get_linked_pr (commit ["sha" ], token ) for commit in commits ]
123
- ids = [pr [0 ]["number" ] for pr in prs ]
124
- linked_issues = [get_linked_issues (pr , token ) for pr in ids ]
125
- issues_ids = [get_edges (issue ) for issue in linked_issues if len (get_edges (issue )) > 0 ]
126
-
127
- for edge in issues_ids :
128
- for node in edge :
129
- issue = node ["node" ]["number" ]
130
- comments = get_issue_comments (issue , token )
131
- if not any (["This is now live" in comment ["body" ] for comment in comments ]):
132
- send_live_message (issue , token )
160
+
161
+ for pr_data in prs :
162
+ pr_id = pr_data ["number" ]
163
+ if should_process_pr (pr_data ["labels" ]):
164
+ print (f"Notifying PR { pr_id } " )
165
+ send_live_message (pr_id , token )
166
+
167
+ linked_issues = get_linked_issues (pr_id , token )
168
+ issues_edges = get_edges (linked_issues )
169
+ if len (issues_edges ) == 1 and "node" in issues_edges [0 ]:
170
+ edge = issues_edges [0 ]["node" ]
171
+ if should_notify_issue (edge ):
172
+ print (f"Notifying issue { edge ['number' ]} " )
173
+ send_live_message (edge ['number' ], token )
174
+ else :
175
+ print (f"Skipping notifying issue { edge ['number' ]} " )
133
176
else :
134
- print (f"Skipping notifying { issue } , it's already been done" )
177
+ print (f"No issues in which to notify for PR { pr_id } " )
178
+ else :
179
+ print (f"Skipping notifying PR { pr_id } " )
0 commit comments