11import csv
2+ import requests
3+ import json
24
35from github import Github , Repository , GithubException , PullRequest
46
79
810def login (token ):
911 client = Github (login_or_token = token )
12+
1013 try :
1114 client .get_user ().login
1215 except GithubException as err :
@@ -67,12 +70,12 @@ def log_repository_commits(repository: Repository, csv_name):
6770 for commit in repository .get_commits ():
6871 if commit .commit is not None :
6972 info = {'repository name' : repository .full_name ,
70- 'commit id' : commit .commit .sha ,
7173 'author name' : commit .commit .author .name ,
7274 'author login' : EMPTY_FIELD ,
7375 'author email' : EMPTY_FIELD ,
7476 'date and time' : commit .commit .author .date ,
75- 'changed files' : '; ' .join ([file .filename for file in commit .files ])}
77+ 'changed files' : '; ' .join ([file .filename for file in commit .files ]),
78+ 'commit id' : commit .commit .sha }
7679
7780 if commit .author is not None :
7881 info ['author login' ] = commit .author .login
@@ -89,7 +92,8 @@ def log_issue_to_csv(info, csv_name):
8992 fieldnames = ['repository name' , 'number' , 'title' , 'state' , 'task' , 'created at' , 'creator name' , 'creator login' ,
9093 'creator email' , 'closer name' , 'closer login' , 'closer email' , 'closed at' , 'comment body' ,
9194 'comment created at' , 'comment author name' , 'comment author login' , 'comment author email' ,
92- 'assignee story' , ]
95+ 'assignee story' , 'connected pull requests' ]
96+
9397 with open (csv_name , 'a' , newline = '' ) as file :
9498 writer = csv .DictWriter (file , fieldnames = fieldnames )
9599 writer .writerow (info )
@@ -99,7 +103,69 @@ def log_issue_to_stdout(info):
99103 print (info )
100104
101105
102- def log_repository_issues (repository : Repository , csv_name ):
106+ def get_connected_pulls (issue_number , repo_owner , repo_name , token ):
107+ access_token = token
108+ repo_owner = repo_owner .login
109+ # Формирование запроса GraphQL
110+ query = """
111+ {
112+ repository(owner: "%s", name: "%s") {
113+ issue(number: %d) {
114+ timelineItems(first: 50, itemTypes:[CONNECTED_EVENT,CROSS_REFERENCED_EVENT]) {
115+ filteredCount
116+ nodes {
117+ ... on ConnectedEvent {
118+ ConnectedEvent: subject {
119+ ... on PullRequest {
120+ number
121+ title
122+ url
123+ }
124+ }
125+ }
126+ ... on CrossReferencedEvent {
127+ CrossReferencedEvent: source {
128+ ... on PullRequest {
129+ number
130+ title
131+ url
132+ }
133+ }
134+ }
135+ }
136+ }
137+ }
138+ }
139+ }""" % (repo_owner , repo_name , issue_number )
140+
141+ # Формирование заголовков запроса
142+ headers = {
143+ "Authorization" : f"Bearer { access_token } " ,
144+ "Content-Type" : "application/json"
145+ }
146+
147+ # Отправка запроса GraphQL
148+ response = requests .post ("https://api.github.com/graphql" , headers = headers , data = json .dumps ({"query" : query }))
149+ response_data = response .json ()
150+ # Обработка полученных данных
151+ pull_request_data = response_data ["data" ]["repository" ]["issue" ]
152+ list_url = []
153+ if (pull_request_data is not None ):
154+ issues_data = pull_request_data ["timelineItems" ]["nodes" ]
155+ for pulls in issues_data :
156+ if (pulls .get ("CrossReferencedEvent" ) != None and pulls .get ("CrossReferencedEvent" ).get ("url" ) not in list_url ) :
157+ list_url .append (pulls .get ("CrossReferencedEvent" ).get ("url" ))
158+ if (pulls .get ("ConnectedEvent" ) != None and pulls .get ("ConnectedEvent" ).get ("url" ) not in list_url ):
159+ list_url .append (pulls .get ("ConnectedEvent" ).get ("url" ))
160+ if (list_url == []):
161+ return 'Empty field'
162+ else :
163+ return list_url
164+ return 'Empty field'
165+
166+
167+
168+ def log_repository_issues (repository : Repository , csv_name , token ):
103169 for issue in repository .get_issues (state = 'all' ):
104170 info_tmp = {
105171 'repository name' : repository .full_name , 'number' : issue .number , 'title' : issue .title ,
@@ -118,7 +184,11 @@ def log_repository_issues(repository: Repository, csv_name):
118184 'comment author login' : EMPTY_FIELD ,
119185 'comment author email' : EMPTY_FIELD ,
120186 'assignee story' : EMPTY_FIELD ,
187+ 'connected pull requests' : EMPTY_FIELD
121188 }
189+ if issue .number is not None :
190+ info_tmp ['connected pull requests' ] = get_connected_pulls (issue .number , repository .owner , repository .name ,
191+ token )
122192
123193 info_tmp ['assignee story' ] = get_assignee_story (issue )
124194
@@ -152,7 +222,7 @@ def log_pr_to_csv(info, csv_name):
152222 'creator login' , 'creator email' ,
153223 'changed files' , 'comment body' , 'comment created at' , 'comment author name' , 'comment author login' ,
154224 'comment author email' , 'merger name' , 'merger login' , 'merger email' , 'source branch' ,
155- 'target branch' , 'assignee story' , ]
225+ 'target branch' , 'assignee story' , 'related issues' ]
156226 with open (csv_name , 'a' , newline = '' ) as file :
157227 writer = csv .DictWriter (file , fieldnames = fieldnames )
158228 writer .writerow (info )
@@ -162,7 +232,53 @@ def log_pr_to_stdout(info):
162232 print (info )
163233
164234
165- def log_repositories_pr (repository : Repository , csv_name ):
235+ def get_related_issues (pull_request_number , repo_owner , repo_name , token ):
236+ access_token = token
237+ repo_owner = repo_owner .login
238+
239+ # Формирование запроса GraphQL
240+ query = """
241+ {
242+ repository(owner: "%s", name: "%s") {
243+ pullRequest(number: %d) {
244+ id
245+ closingIssuesReferences(first: 50) {
246+ edges {
247+ node {
248+ id
249+ body
250+ number
251+ title
252+ url
253+ }
254+ }
255+ }
256+ }
257+ }
258+ }
259+ """ % (repo_owner , repo_name , pull_request_number )
260+
261+ # Формирование заголовков запроса
262+ headers = {
263+ "Authorization" : f"Bearer { access_token } " ,
264+ "Content-Type" : "application/json"
265+ }
266+
267+ # Отправка запроса GraphQL
268+ response = requests .post ("https://api.github.com/graphql" , headers = headers , data = json .dumps ({"query" : query }))
269+ response_data = response .json ()
270+ # Обработка полученных данных
271+ pull_request_data = response_data ["data" ]["repository" ]["pullRequest" ]
272+ issues_data = pull_request_data ["closingIssuesReferences" ]["edges" ]
273+ list_issues_url = []
274+ # сохранение информации об issues
275+ for issue in issues_data :
276+ issue_node = issue ["node" ]
277+ list_issues_url .append (issue_node ["url" ])
278+ return list_issues_url
279+
280+
281+ def log_repositories_pr (repository : Repository , csv_name , token ):
166282 for pull in repository .get_pulls (state = 'all' ):
167283 info_tmp = {
168284 'repository name' : repository .full_name ,
@@ -186,7 +302,10 @@ def log_repositories_pr(repository: Repository, csv_name):
186302 'source branch' : pull .head .ref ,
187303 'target branch' : pull .base .ref ,
188304 'assignee story' : EMPTY_FIELD ,
305+ 'related issues' : EMPTY_FIELD
189306 }
307+ if pull .issue_url is not None :
308+ info_tmp ['related issues' ] = get_related_issues (pull .number , repository .owner , repository .name , token )
190309
191310 if pull .merged_by is not None :
192311 info_tmp ['merger name' ] = pull .merged_by .name
@@ -211,7 +330,7 @@ def log_repositories_pr(repository: Repository, csv_name):
211330 sleep (0.05 )
212331
213332
214- def log_pull_requests (client : Github , repositories , csv_name ):
333+ def log_pull_requests (client : Github , repositories , csv_name , token ):
215334 with open (csv_name , 'w' , newline = '' ) as file :
216335 writer = csv .writer (file )
217336 writer .writerow (
@@ -236,7 +355,9 @@ def log_pull_requests(client: Github, repositories, csv_name):
236355 'merger email' ,
237356 'source branch' ,
238357 'target branch' ,
358+ 'related issues'
239359 'assignee story' ,
360+ 'related issues'
240361 )
241362 )
242363
@@ -249,7 +370,7 @@ def log_pull_requests(client: Github, repositories, csv_name):
249370
250371
251372
252- def log_issues (client : Github , repositories , csv_name ):
373+ def log_issues (client : Github , repositories , csv_name , token ):
253374 with open (csv_name , 'w' , newline = '' ) as file :
254375 writer = csv .writer (file )
255376 writer .writerow (
@@ -272,7 +393,9 @@ def log_issues(client: Github, repositories, csv_name):
272393 'comment author name' ,
273394 'comment author login' ,
274395 'comment author email' ,
396+ 'connected pull requests'
275397 'assignee story' ,
398+ 'connected pull requests'
276399 )
277400 )
278401
@@ -291,12 +414,12 @@ def log_commits(client: Github, repositories, csv_name):
291414 writer .writerow (
292415 (
293416 'repository name' ,
294- 'commit id' ,
295417 'author name' ,
296418 'author login' ,
297419 'author email' ,
298420 'date and time' ,
299421 'changed files' ,
422+ 'commit id'
300423 )
301424 )
302425
0 commit comments