11package main
22
33import (
4- "bytes"
54 "context"
6- "encoding/json"
75 "fmt"
8- "io"
9- "net/http"
106 "os"
117 "strings"
128
9+ "github.com/google/go-github/v51/github"
1310 "github.com/jessevdk/go-flags"
1411 "github.com/sashabaranov/go-openai"
1512)
@@ -37,116 +34,87 @@ func main() {
3734 }
3835 os .Exit (0 )
3936 }
40- openaiClient := openai .NewClient (opts .OpenAIToken )
37+ openaiClient := NewOpenAIClient (opts .OpenAIToken )
38+ githubClient := NewGithubClient (context .Background (), opts .GithubToken )
4139
42- diff , err := getDiffContent ( opts . GithubToken , opts .Owner , opts .Repo , opts .PRNumber )
40+ diff , err := githubClient . GetPullRequestDiff ( context . Background () , opts .Owner , opts .Repo , opts .PRNumber )
4341 if err != nil {
44- fmt .Printf ("Error fetching diff content : %v\n " , err )
42+ fmt .Printf ("Error getting pull request diff : %v\n " , err )
4543 return
4644 }
47- filesDiff , err := parseGitDiffAndSplitPerFile (diff )
45+ filesDiff , err := parseGitDiffAndSplitPerFile (diff , strings . Split ( opts . SkipFiles , "," ) )
4846 if err != nil {
4947 return
5048 }
5149
5250 var messages []openai.ChatCompletionMessage
53- prompt := fmt .Sprintf (
54- "Generate a GitHub pull request description based on the following changes " +
55- "without basic prefix in markdown format with ###Description and ###Changes blocks:\n " ,
56- )
51+ prompt := fmt .Sprintf ("Generate a GitHub pull request description based on the following changes without basic prefix in markdown format with ###Description and ###Changes blocks:\n " )
5752 messages = append (messages , openai.ChatCompletionMessage {
5853 Role : openai .ChatMessageRoleUser ,
5954 Content : prompt ,
6055 })
6156 for _ , fileDiff := range filesDiff {
6257 fileName := getFilenameFromDiffHeader (fileDiff .Header )
6358
64- isSkipped := false
65- for _ , skipFile := range strings .Split (opts .SkipFiles , "," ) {
66- if strings .Contains (fileName , skipFile ) {
67- isSkipped = true
68- break
69- }
70- }
71- if isSkipped {
72- continue
73- }
74-
7559 prompt := fmt .Sprintf ("File %s:\n %s\n %s\n " , fileName , fileDiff .Header , fileDiff .Diff )
7660 messages = append (messages , openai.ChatCompletionMessage {
7761 Role : openai .ChatMessageRoleUser ,
7862 Content : prompt ,
7963 })
8064 }
81- chatGPTDescription , err := generatePRDescription ( openaiClient , messages )
65+ chatGPTDescription , err := openaiClient . ChatCompletion ( context . Background () , messages )
8266 if err != nil {
8367 fmt .Printf ("Error generating pull request description: %v\n " , err )
8468 return
8569 }
8670
87- title , err := getPullRequestTitle ( opts . GithubToken , opts .Owner , opts .Repo , opts .PRNumber )
71+ pr , err := githubClient . GetPullRequest ( context . Background () , opts .Owner , opts .Repo , opts .PRNumber )
8872 if err != nil {
73+ fmt .Printf ("Error getting pull request: %v\n " , err )
8974 return
9075 }
9176
92- jiraLink := generateJiraLinkByTitle (title )
77+ jiraLink := generateJiraLinkByTitle (* pr . Title )
9378
9479 description := fmt .Sprintf ("### Jira\n %s\n %s" , jiraLink , chatGPTDescription )
9580 if opts .Test {
9681 fmt .Println (description )
9782 os .Exit (0 )
9883 }
9984 // Update the pull request with the generated description
100- err = updatePullRequestDescription (opts .GithubToken , opts .Owner , opts .Repo , opts .PRNumber , description )
85+ _ , err = githubClient .UpdatePullRequest (
86+ context .Background (), opts .Owner , opts .Repo , opts .PRNumber , & github.PullRequest {Body : & description },
87+ )
10188 if err != nil {
102- fmt .Printf ("Error updating pull request description : %v\n " , err )
89+ fmt .Printf ("Error updating pull request: %v\n " , err )
10390 return
10491 }
105-
106- fmt .Println ("Pull request description updated successfully" )
107- }
108-
109- func getDiffContent (token , owner , repo string , prNumber int ) (string , error ) {
110- url := fmt .Sprintf ("https://api.github.com/repos/%s/%s/pulls/%d" , owner , repo , prNumber )
111- method := "GET"
112-
113- client := & http.Client {}
114- req , err := http .NewRequest (method , url , nil )
115-
116- if err != nil {
117- fmt .Println (err )
118- return "" , err
119- }
120- req .Header .Add ("Accept" , "application/vnd.github.v3.diff" )
121- req .Header .Add ("Authorization" , fmt .Sprintf ("token %s" , token ))
122- //req.Header.Add("Cookie", "logged_in=no")
123-
124- res , err := client .Do (req )
125- if err != nil {
126- return "" , err
127- }
128- defer res .Body .Close ()
129-
130- body , err := io .ReadAll (res .Body )
131- if err != nil {
132- return "" , err
133- }
134-
135- return string (body ), nil
13692}
13793
13894// parseGitDiffAndSplitPerFile parses a git diff and splits it into a slice of FileDiff.
139- func parseGitDiffAndSplitPerFile (diff string ) ([]FileDiff , error ) {
95+ func parseGitDiffAndSplitPerFile (diff string , skipFiles [] string ) ([]FileDiff , error ) {
14096 lines := strings .Split (diff , "\n " )
14197 var fileDiffs []FileDiff
14298
143- inFileDiff := false
99+ inFileDiff , isSkipFile := false , false
144100 var currentFileDiff FileDiff
145101 for _ , line := range lines {
146102 if strings .HasPrefix (line , "diff --git" ) {
147103 if inFileDiff {
148104 fileDiffs = append (fileDiffs , currentFileDiff )
149105 }
106+ if len (skipFiles ) > 0 {
107+ isSkipFile = false
108+ for _ , skipFile := range skipFiles {
109+ if strings .Contains (line , skipFile ) {
110+ isSkipFile = true
111+ break
112+ }
113+ }
114+ }
115+ if isSkipFile {
116+ continue
117+ }
150118 currentFileDiff = FileDiff {Header : line }
151119 inFileDiff = true
152120 } else if inFileDiff {
@@ -178,57 +146,6 @@ func getFilenameFromDiffHeader(diffHeader string) string {
178146 }
179147}
180148
181- func generatePRDescription (client * openai.Client , messages []openai.ChatCompletionMessage ) (string , error ) {
182- resp , err := client .CreateChatCompletion (
183- context .Background (),
184- openai.ChatCompletionRequest {
185- Model : openai .GPT3Dot5Turbo ,
186- Messages : messages ,
187- },
188- )
189-
190- if err != nil {
191- fmt .Printf ("ChatCompletion error: %v\n " , err )
192- return "" , err
193- }
194-
195- return resp .Choices [0 ].Message .Content , nil
196- }
197-
198- func getPullRequestTitle (token , owner , repo string , prNumber int ) (string , error ) {
199- url := fmt .Sprintf ("https://api.github.com/repos/%s/%s/pulls/%d" , owner , repo , prNumber )
200-
201- req , err := http .NewRequest ("GET" , url , nil )
202- if err != nil {
203- return "" , err
204- }
205-
206- req .Header .Set ("Authorization" , fmt .Sprintf ("token %s" , token ))
207- req .Header .Set ("Accept" , "application/vnd.github.v3+json" )
208-
209- client := & http.Client {}
210- resp , err := client .Do (req )
211- if err != nil {
212- return "" , err
213- }
214- defer resp .Body .Close ()
215-
216- if resp .StatusCode != http .StatusOK {
217- return "" , fmt .Errorf ("Failed to fetch pull request details. Status code: %d" , resp .StatusCode )
218- }
219-
220- var pr struct {
221- Title string `json:"title"`
222- }
223-
224- err = json .NewDecoder (resp .Body ).Decode (& pr )
225- if err != nil {
226- return "" , err
227- }
228-
229- return pr .Title , nil
230- }
231-
232149func generateJiraLinkByTitle (title string ) string {
233150 //NCR-1234
234151 issueKey := strings .ToUpper (strings .Split (title , " " )[0 ])
@@ -239,38 +156,3 @@ func generateJiraLinkByTitle(title string) string {
239156
240157 return fmt .Sprintf ("[%s](%s%s)" , issueKey , jiraBaseURL , issueKey )
241158}
242-
243- func updatePullRequestDescription (token string , o string , r string , number int , description string ) error {
244- url := fmt .Sprintf ("https://api.github.com/repos/%s/%s/pulls/%d" , o , r , number )
245-
246- data := map [string ]string {
247- "body" : description ,
248- }
249-
250- payload , err := json .Marshal (data )
251- if err != nil {
252- return err
253- }
254-
255- req , err := http .NewRequest ("PATCH" , url , bytes .NewBuffer (payload ))
256- if err != nil {
257- return err
258- }
259-
260- req .Header .Set ("Authorization" , fmt .Sprintf ("token %s" , token ))
261- req .Header .Set ("Accept" , "application/vnd.github.v3+json" )
262- req .Header .Set ("Content-Type" , "application/json" )
263-
264- client := & http.Client {}
265- resp , err := client .Do (req )
266- if err != nil {
267- return err
268- }
269- defer resp .Body .Close ()
270-
271- if resp .StatusCode != http .StatusOK {
272- return fmt .Errorf ("failed to update pull request description. Status code: %d" , resp .StatusCode )
273- }
274-
275- return nil
276- }
0 commit comments