55import sys
66
77import openai
8- import requests
98from csvtomd import csv_to_table , md_table
109from loguru import logger
1110
11+ from ai import process_with_ai
1212from comment import send_comment
13+ from config import support_langs , csv_result_file , json_result_file , dot_result_file
14+ from diff import gen_diff
15+ from index import gen_index
1316from object import FileList
1417
15- user_dir = "/github/workspace"
16- support_langs = {"golang" , "python" }
17- csv_result_file = "./output.csv"
18- json_result_file = "./output.json"
19- dot_result_file = "./output.dot"
2018
19+ def main ():
20+ args = sys .argv [1 :]
21+ lang = args [0 ]
22+ before_sha = args [1 ]
23+ after_sha = args [2 ]
24+ repo_token = args [3 ]
25+ issue_number = args [4 ]
26+ openai_api_key = args [5 ]
2127
22- def gen_index (lang : str ):
23- set_safe_git_dir ()
24- files = os .listdir (user_dir )
25- logger .info (f"files: { files } " )
26-
27- if lang == "golang" :
28- gen_golang_index ()
29- elif lang == "python" :
30- gen_py_index ()
31- else :
32- logger .error ("no index mapping" )
28+ # check
29+ if lang not in support_langs :
30+ logger .error (f"lang not supported: { lang } , supported: { support_langs } " )
31+ return
32+ if not before_sha or not after_sha :
33+ logger .warning ("sha empty. Use default." )
34+ before_sha = "HEAD~1"
35+ after_sha = "HEAD"
36+ if not repo_token :
37+ logger .error ("no repo token provided" )
3338 return
3439
40+ # data prepare
41+ gen_index (lang )
42+ gen_diff (before_sha , after_sha )
3543
36- def gen_golang_index ():
37- _check_call (["lsif-go" , "-v" ])
38-
39-
40- def gen_py_index ():
41- _check_call (["lsif-py" , "." , "--file" , "./dump.lsif" ])
42-
43-
44- def _check_call (commands : list ):
45- subprocess .check_call (commands , cwd = user_dir )
46-
47-
48- def set_safe_git_dir ():
49- _check_call (["git" , "config" , "--global" , "--add" , "safe.directory" , user_dir ])
44+ with open (csv_result_file , encoding = "utf-8" ) as f :
45+ content = f .read ()
5046
47+ ai_content = "-"
48+ if not openai_api_key :
49+ logger .warning ("no openai api key found. Use raw data." )
50+ else :
51+ logger .info ("process with openai" )
52+ openai .api_key = openai_api_key
53+ ai_content = process_with_ai (content )
5154
52- def gen_diff (before_sha : str , after_sha : str ):
53- # gen diff
54- set_safe_git_dir ()
55- _check_call (
56- [
57- "srctx" ,
58- "diff" ,
59- "--src" ,
60- user_dir ,
61- "--before" ,
62- before_sha ,
63- "--after" ,
64- after_sha ,
65- "--outputCsv" ,
66- csv_result_file ,
67- "--outputJson" ,
68- json_result_file ,
69- "--outputDot" ,
70- dot_result_file ,
71- ]
72- )
55+ # todo: add to feedback?
56+ logger .info (f"ai resp: { ai_content } " )
7357
58+ repo_name = os .getenv ("GITHUB_REPOSITORY" )
59+ process_json (json_result_file , csv_result_file )
60+ diff_desc = f"Start from { before_sha } to { after_sha } ."
61+ summary = get_summary (json_result_file )
62+ md_table_raw = convert_csv_to_md (csv_result_file )
7463
75- def process_with_ai (raw : str ) -> str :
76- req = f"""
77- You are a bot for helping code review.
78- Standard csv report was generated from diff analysis tool.
64+ # graph
65+ svg_bytes = dot_to_svg (dot_result_file )
66+ # todo: have no idea about how to display this graph in comment without any extra servers
7967
80- Here is a csv report below for a specific commit.
81- Evaluate it and indicate the most important parts which reviewers should care.
82- Empty report means that there are no dangerous changes.
68+ final_content = f"""
69+ ## [DiffCtx](https://github.com/williamfzc/diffctx) Report
8370
84- --- report start ---
71+ { diff_desc }
8572
86- { raw }
73+ { summary }
8774
88- --- report end ---
75+ { md_table_raw }
8976"""
77+ logger .info (f"final comment: { final_content } " )
9078
91- completion = openai .ChatCompletion .create (
92- model = "gpt-3.5-turbo" , messages = [{"role" : "user" , "content" : req }]
93- )
94- return completion .choices [0 ].message .content
79+ # feedback
80+ if not issue_number :
81+ logger .warning (
82+ "This action is not triggered by a PR. Will not leave any comments."
83+ )
84+ return
85+ send_comment (repo_token , repo_name , int (issue_number ), final_content )
86+
87+ # # code comments
88+ # lines = parse_file_as(typing.List[LineStat], pathlib.Path(json_result_file))
89+ # send_code_comments(repo_token, after_sha, repo_name, int(issue_number), lines)
9590
9691
9792def convert_csv_to_md (csv_file ) -> str :
@@ -112,9 +107,15 @@ def format_percentage(numerator, denominator):
112107 return f"{ percent :.2f} % ({ numerator } /{ denominator } )"
113108
114109 for file in file_list .files :
115- file .affectedLinePercentRepr = format_percentage (file .affectedLines , file .totalLines )
116- file .affectedFunctionPercentRepr = format_percentage (file .affectedFunctions , file .totalFunctions )
117- file .affectedReferencePercentRepr = format_percentage (file .affectedReferences , file .totalReferences )
110+ file .affectedLinePercentRepr = format_percentage (
111+ file .affectedLines , file .totalLines
112+ )
113+ file .affectedFunctionPercentRepr = format_percentage (
114+ file .affectedFunctions , file .totalFunctions
115+ )
116+ file .affectedReferencePercentRepr = format_percentage (
117+ file .affectedReferences , file .totalReferences
118+ )
118119
119120 file_list .files = sort_files_by_impact (file_list .files )
120121
@@ -124,7 +125,7 @@ def format_percentage(numerator, denominator):
124125 "AffectedFunctions" ,
125126 "AffectedReferences" ,
126127 ]
127- with open (output_csv , "w" , newline = '' ) as f :
128+ with open (output_csv , "w" , newline = "" ) as f :
128129 writer = csv .DictWriter (f , fieldnames = cols )
129130 writer .writeheader ()
130131
@@ -149,10 +150,12 @@ def get_summary(input_json) -> str:
149150 affected_functions = sum ([each .affectedFunctions for each in file_list .files ])
150151 affected_refs = sum ([each .affectedReferences for each in file_list .files ])
151152
152- return f"This commit directly influences { affected_files } files, " \
153- f"{ affected_lines } lines, " \
154- f"{ affected_functions } functions. " \
155- f"Indirectly influences { affected_refs } functions. "
153+ return (
154+ f"This commit directly influences { affected_files } files, "
155+ f"{ affected_lines } lines, "
156+ f"{ affected_functions } functions. "
157+ f"Indirectly influences { affected_refs } functions. "
158+ )
156159
157160
158161def dot_to_svg (dot_file ):
@@ -167,78 +170,5 @@ def sort_key(f):
167170 return sorted (files , key = sort_key , reverse = True )
168171
169172
170- def main ():
171- args = sys .argv [1 :]
172- lang = args [0 ]
173- before_sha = args [1 ]
174- after_sha = args [2 ]
175- repo_token = args [3 ]
176- issue_number = args [4 ]
177- openai_api_key = args [5 ]
178-
179- # check
180- if lang not in support_langs :
181- logger .error (f"lang not supported: { lang } , supported: { support_langs } " )
182- return
183- if not before_sha or not after_sha :
184- logger .warning ("sha empty. Use default." )
185- before_sha = "HEAD~1"
186- after_sha = "HEAD"
187- if not repo_token :
188- logger .error ("no repo token provided" )
189- return
190-
191- # data prepare
192- gen_index (lang )
193- gen_diff (before_sha , after_sha )
194-
195- with open (csv_result_file , encoding = "utf-8" ) as f :
196- content = f .read ()
197-
198- ai_content = "-"
199- if not openai_api_key :
200- logger .warning ("no openai api key found. Use raw data." )
201- else :
202- logger .info ("process with openai" )
203- openai .api_key = openai_api_key
204- ai_content = process_with_ai (content )
205-
206- # todo: add to feedback?
207- logger .info (f"ai resp: { ai_content } " )
208-
209- repo_name = os .getenv ("GITHUB_REPOSITORY" )
210- process_json (json_result_file , csv_result_file )
211- diff_desc = f"Start from { before_sha } to { after_sha } ."
212- summary = get_summary (json_result_file )
213- md_table_raw = convert_csv_to_md (csv_result_file )
214-
215- # graph
216- svg_bytes = dot_to_svg (dot_result_file )
217- # todo: have no idea about how to display this graph in comment without any extra servers
218-
219- final_content = f"""
220- ## [DiffCtx](https://github.com/williamfzc/diffctx) Report
221-
222- { diff_desc }
223-
224- { summary }
225-
226- { md_table_raw }
227- """
228- logger .info (f"final comment: { final_content } " )
229-
230- # feedback
231- if not issue_number :
232- logger .warning (
233- "This action is not triggered by a PR. Will not leave any comments."
234- )
235- return
236- send_comment (repo_token , repo_name , int (issue_number ), final_content )
237-
238- # # code comments
239- # lines = parse_file_as(typing.List[LineStat], pathlib.Path(json_result_file))
240- # send_code_comments(repo_token, after_sha, repo_name, int(issue_number), lines)
241-
242-
243173if __name__ == "__main__" :
244174 main ()
0 commit comments