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 :
@@ -66,12 +69,12 @@ def log_repository_commits(repository: Repository, csv_name):
6669 for commit in repository .get_commits ():
6770 if commit .commit is not None :
6871 info = {'repository name' : repository .full_name ,
69- 'commit id' : commit .commit .sha ,
7072 'author name' : commit .commit .author .name ,
7173 'author login' : EMPTY_FIELD ,
7274 'author email' : EMPTY_FIELD ,
7375 'date and time' : commit .commit .author .date ,
74- 'changed files' : '; ' .join ([file .filename for file in commit .files ])}
76+ 'changed files' : '; ' .join ([file .filename for file in commit .files ]),
77+ 'commit id' : commit .commit .sha }
7578
7679 if commit .author is not None :
7780 info ['author login' ] = commit .author .login
@@ -87,7 +90,8 @@ def log_issue_to_csv(info, csv_name):
8790 fieldnames = ['repository name' , 'number' , 'title' , 'state' , 'task' , 'created at' , 'creator name' , 'creator login' ,
8891 'creator email' , 'closer name' , 'closer login' , 'closer email' , 'closed at' , 'comment body' ,
8992 'comment created at' , 'comment author name' , 'comment author login' , 'comment author email' ,
90- 'assignee story' , ]
93+ 'assignee story' , 'connected pull requests' ]
94+
9195 with open (csv_name , 'a' , newline = '' ) as file :
9296 writer = csv .DictWriter (file , fieldnames = fieldnames )
9397 writer .writerow (info )
@@ -97,7 +101,69 @@ def log_issue_to_stdout(info):
97101 print (info )
98102
99103
100- def log_repository_issues (repository : Repository , csv_name ):
104+ def get_connected_pulls (issue_number , repo_owner , repo_name , token ):
105+ access_token = token
106+ repo_owner = repo_owner .login
107+ # Формирование запроса GraphQL
108+ query = """
109+ {
110+ repository(owner: "%s", name: "%s") {
111+ issue(number: %d) {
112+ timelineItems(first: 50, itemTypes:[CONNECTED_EVENT,CROSS_REFERENCED_EVENT]) {
113+ filteredCount
114+ nodes {
115+ ... on ConnectedEvent {
116+ ConnectedEvent: subject {
117+ ... on PullRequest {
118+ number
119+ title
120+ url
121+ }
122+ }
123+ }
124+ ... on CrossReferencedEvent {
125+ CrossReferencedEvent: source {
126+ ... on PullRequest {
127+ number
128+ title
129+ url
130+ }
131+ }
132+ }
133+ }
134+ }
135+ }
136+ }
137+ }""" % (repo_owner , repo_name , issue_number )
138+
139+ # Формирование заголовков запроса
140+ headers = {
141+ "Authorization" : f"Bearer { access_token } " ,
142+ "Content-Type" : "application/json"
143+ }
144+
145+ # Отправка запроса GraphQL
146+ response = requests .post ("https://api.github.com/graphql" , headers = headers , data = json .dumps ({"query" : query }))
147+ response_data = response .json ()
148+ # Обработка полученных данных
149+ pull_request_data = response_data ["data" ]["repository" ]["issue" ]
150+ list_url = []
151+ if (pull_request_data is not None ):
152+ issues_data = pull_request_data ["timelineItems" ]["nodes" ]
153+ for pulls in issues_data :
154+ if (pulls .get ("CrossReferencedEvent" ) != None and pulls .get ("CrossReferencedEvent" ).get ("url" ) not in list_url ) :
155+ list_url .append (pulls .get ("CrossReferencedEvent" ).get ("url" ))
156+ if (pulls .get ("ConnectedEvent" ) != None and pulls .get ("ConnectedEvent" ).get ("url" ) not in list_url ):
157+ list_url .append (pulls .get ("ConnectedEvent" ).get ("url" ))
158+ if (list_url == []):
159+ return 'Empty field'
160+ else :
161+ return list_url
162+ return 'Empty field'
163+
164+
165+
166+ def log_repository_issues (repository : Repository , csv_name , token ):
101167 for issue in repository .get_issues (state = 'all' ):
102168 info_tmp = {
103169 'repository name' : repository .full_name , 'number' : issue .number , 'title' : issue .title ,
@@ -116,7 +182,11 @@ def log_repository_issues(repository: Repository, csv_name):
116182 'comment author login' : EMPTY_FIELD ,
117183 'comment author email' : EMPTY_FIELD ,
118184 'assignee story' : EMPTY_FIELD ,
185+ 'connected pull requests' : EMPTY_FIELD
119186 }
187+ if issue .number is not None :
188+ info_tmp ['connected pull requests' ] = get_connected_pulls (issue .number , repository .owner , repository .name ,
189+ token )
120190
121191 info_tmp ['assignee story' ] = get_assignee_story (issue )
122192
@@ -149,7 +219,7 @@ def log_pr_to_csv(info, csv_name):
149219 'creator login' , 'creator email' ,
150220 'changed files' , 'comment body' , 'comment created at' , 'comment author name' , 'comment author login' ,
151221 'comment author email' , 'merger name' , 'merger login' , 'merger email' , 'source branch' ,
152- 'target branch' , 'assignee story' , ]
222+ 'target branch' , 'assignee story' , 'related issues' ]
153223 with open (csv_name , 'a' , newline = '' ) as file :
154224 writer = csv .DictWriter (file , fieldnames = fieldnames )
155225 writer .writerow (info )
@@ -159,7 +229,53 @@ def log_pr_to_stdout(info):
159229 print (info )
160230
161231
162- def log_repositories_pr (repository : Repository , csv_name ):
232+ def get_related_issues (pull_request_number , repo_owner , repo_name , token ):
233+ access_token = token
234+ repo_owner = repo_owner .login
235+
236+ # Формирование запроса GraphQL
237+ query = """
238+ {
239+ repository(owner: "%s", name: "%s") {
240+ pullRequest(number: %d) {
241+ id
242+ closingIssuesReferences(first: 50) {
243+ edges {
244+ node {
245+ id
246+ body
247+ number
248+ title
249+ url
250+ }
251+ }
252+ }
253+ }
254+ }
255+ }
256+ """ % (repo_owner , repo_name , pull_request_number )
257+
258+ # Формирование заголовков запроса
259+ headers = {
260+ "Authorization" : f"Bearer { access_token } " ,
261+ "Content-Type" : "application/json"
262+ }
263+
264+ # Отправка запроса GraphQL
265+ response = requests .post ("https://api.github.com/graphql" , headers = headers , data = json .dumps ({"query" : query }))
266+ response_data = response .json ()
267+ # Обработка полученных данных
268+ pull_request_data = response_data ["data" ]["repository" ]["pullRequest" ]
269+ issues_data = pull_request_data ["closingIssuesReferences" ]["edges" ]
270+ list_issues_url = []
271+ # сохранение информации об issues
272+ for issue in issues_data :
273+ issue_node = issue ["node" ]
274+ list_issues_url .append (issue_node ["url" ])
275+ return list_issues_url
276+
277+
278+ def log_repositories_pr (repository : Repository , csv_name , token ):
163279 for pull in repository .get_pulls (state = 'all' ):
164280 info_tmp = {
165281 'repository name' : repository .full_name ,
@@ -183,7 +299,10 @@ def log_repositories_pr(repository: Repository, csv_name):
183299 'source branch' : pull .head .ref ,
184300 'target branch' : pull .base .ref ,
185301 'assignee story' : EMPTY_FIELD ,
302+ 'related issues' : EMPTY_FIELD
186303 }
304+ if pull .issue_url is not None :
305+ info_tmp ['related issues' ] = get_related_issues (pull .number , repository .owner , repository .name , token )
187306
188307 if pull .merged_by is not None :
189308 info_tmp ['merger name' ] = pull .merged_by .name
@@ -207,7 +326,7 @@ def log_repositories_pr(repository: Repository, csv_name):
207326 log_pr_to_stdout (info_tmp )
208327
209328
210- def log_pull_requests (client : Github , repositories , csv_name ):
329+ def log_pull_requests (client : Github , repositories , csv_name , token ):
211330 with open (csv_name , 'w' , newline = '' ) as file :
212331 writer = csv .writer (file )
213332 writer .writerow (
@@ -232,15 +351,17 @@ def log_pull_requests(client: Github, repositories, csv_name):
232351 'merger email' ,
233352 'source branch' ,
234353 'target branch' ,
354+ 'related issues'
235355 'assignee story' ,
356+ 'related issues'
236357 )
237358 )
238359
239360 for repo in get_next_repo (client , repositories ):
240- log_repositories_pr (repo , csv_name )
361+ log_repositories_pr (repo , csv_name , token )
241362
242363
243- def log_issues (client : Github , repositories , csv_name ):
364+ def log_issues (client : Github , repositories , csv_name , token ):
244365 with open (csv_name , 'w' , newline = '' ) as file :
245366 writer = csv .writer (file )
246367 writer .writerow (
@@ -263,12 +384,14 @@ def log_issues(client: Github, repositories, csv_name):
263384 'comment author name' ,
264385 'comment author login' ,
265386 'comment author email' ,
387+ 'connected pull requests'
266388 'assignee story' ,
389+ 'connected pull requests'
267390 )
268391 )
269392
270393 for repo in get_next_repo (client , repositories ):
271- log_repository_issues (repo , csv_name )
394+ log_repository_issues (repo , csv_name , token )
272395
273396
274397def log_commits (client : Github , repositories , csv_name ):
@@ -277,12 +400,12 @@ def log_commits(client: Github, repositories, csv_name):
277400 writer .writerow (
278401 (
279402 'repository name' ,
280- 'commit id' ,
281403 'author name' ,
282404 'author login' ,
283405 'author email' ,
284406 'date and time' ,
285407 'changed files' ,
408+ 'commit id'
286409 )
287410 )
288411
0 commit comments