@@ -231,7 +231,8 @@ func runGitHubPR(stdout io.Writer, cfg *federation.Config, doltPath, branch stri
231231 prTitle := fmt .Sprintf ("[wl] %s" , title )
232232
233233 // Create git-native branch on fork + cross-fork PR to upstream.
234- prURL , err := createGitHubPR (ghPath , cfg .GitHubRepo , cfg .ForkOrg , cfg .ForkDB , branch , prTitle , mdBuf .String (), stdout )
234+ client := newGHClient (ghPath )
235+ prURL , err := createGitHubPR (client , cfg .GitHubRepo , cfg .ForkOrg , cfg .ForkDB , branch , prTitle , mdBuf .String (), stdout )
235236 if err != nil {
236237 return err
237238 }
@@ -240,113 +241,54 @@ func runGitHubPR(stdout io.Writer, cfg *federation.Config, doltPath, branch stri
240241 return nil
241242}
242243
243- func createGitHubPR (ghPath , upstreamRepo , forkOrg , forkDB , wlBranch , title , mdBody string , stdout io.Writer ) (string , error ) {
244+ func createGitHubPR (client GitHubPRClient , upstreamRepo , forkOrg , forkDB , wlBranch , title , mdBody string , stdout io.Writer ) (string , error ) {
244245 forkRepo := forkOrg + "/" + forkDB
245246 wantedID := extractWantedID (wlBranch )
246247 markerPath := ".wasteland/" + wantedID + ".md"
247248
248249 // 1. Get fork's default branch SHA.
249250 fmt .Fprintln (stdout , " Getting fork HEAD..." )
250- refData , err := ghAPICall ( ghPath , "GET" , fmt . Sprintf ( "repos/%s/git/ref/ heads/main" , forkRepo ), " " )
251+ headSHA , err := client . GetRef ( forkRepo , "heads/main" )
251252 if err != nil {
252253 return "" , fmt .Errorf ("getting fork HEAD: %w" , err )
253254 }
254- var ref struct {
255- Object struct {
256- SHA string `json:"sha"`
257- } `json:"object"`
258- }
259- if err := json .Unmarshal (refData , & ref ); err != nil {
260- return "" , fmt .Errorf ("parsing fork HEAD: %w" , err )
261- }
262- headSHA := ref .Object .SHA
263255
264256 // 2. Get base tree SHA from the commit.
265- commitData , err := ghAPICall ( ghPath , "GET" , fmt . Sprintf ( "repos/%s/git/commits/%s" , forkRepo , headSHA ), "" )
257+ baseTreeSHA , err := client . GetCommitTree ( forkRepo , headSHA )
266258 if err != nil {
267259 return "" , fmt .Errorf ("getting base commit: %w" , err )
268260 }
269- var commitObj struct {
270- Tree struct {
271- SHA string `json:"sha"`
272- } `json:"tree"`
273- }
274- if err := json .Unmarshal (commitData , & commitObj ); err != nil {
275- return "" , fmt .Errorf ("parsing base commit: %w" , err )
276- }
277- baseTreeSHA := commitObj .Tree .SHA
278261
279262 // 3. Create blob with marker file content.
280263 fmt .Fprintln (stdout , " Creating marker file..." )
281- blobBody , _ := json .Marshal (map [string ]string {
282- "content" : mdBody ,
283- "encoding" : "utf-8" ,
284- })
285- blobData , err := ghAPICall (ghPath , "POST" , fmt .Sprintf ("repos/%s/git/blobs" , forkRepo ), string (blobBody ))
264+ blobSHA , err := client .CreateBlob (forkRepo , mdBody , "utf-8" )
286265 if err != nil {
287266 return "" , fmt .Errorf ("creating blob: %w" , err )
288267 }
289- var blob struct {
290- SHA string `json:"sha"`
291- }
292- if err := json .Unmarshal (blobData , & blob ); err != nil {
293- return "" , fmt .Errorf ("parsing blob response: %w" , err )
294- }
295268
296269 // 4. Create tree with marker file.
297- treeBody , _ := json .Marshal (map [string ]interface {}{
298- "base_tree" : baseTreeSHA ,
299- "tree" : []map [string ]string {{
300- "path" : markerPath ,
301- "mode" : "100644" ,
302- "type" : "blob" ,
303- "sha" : blob .SHA ,
304- }},
305- })
306- treeData , err := ghAPICall (ghPath , "POST" , fmt .Sprintf ("repos/%s/git/trees" , forkRepo ), string (treeBody ))
270+ treeSHA , err := client .CreateTree (forkRepo , baseTreeSHA , []TreeEntry {{
271+ Path : markerPath ,
272+ Mode : "100644" ,
273+ Type : "blob" ,
274+ SHA : blobSHA ,
275+ }})
307276 if err != nil {
308277 return "" , fmt .Errorf ("creating tree: %w" , err )
309278 }
310- var tree struct {
311- SHA string `json:"sha"`
312- }
313- if err := json .Unmarshal (treeData , & tree ); err != nil {
314- return "" , fmt .Errorf ("parsing tree response: %w" , err )
315- }
316279
317280 // 5. Create commit on fork.
318281 fmt .Fprintln (stdout , " Creating commit..." )
319- newCommitBody , _ := json .Marshal (map [string ]interface {}{
320- "message" : fmt .Sprintf ("wl review: %s" , wlBranch ),
321- "tree" : tree .SHA ,
322- "parents" : []string {headSHA },
323- })
324- newCommitData , err := ghAPICall (ghPath , "POST" , fmt .Sprintf ("repos/%s/git/commits" , forkRepo ), string (newCommitBody ))
282+ commitSHA , err := client .CreateCommit (forkRepo , fmt .Sprintf ("wl review: %s" , wlBranch ), treeSHA , []string {headSHA })
325283 if err != nil {
326284 return "" , fmt .Errorf ("creating commit: %w" , err )
327285 }
328- var newCommit struct {
329- SHA string `json:"sha"`
330- }
331- if err := json .Unmarshal (newCommitData , & newCommit ); err != nil {
332- return "" , fmt .Errorf ("parsing commit response: %w" , err )
333- }
334286
335287 // 6. Create or update ref on fork.
336288 fmt .Fprintln (stdout , " Pushing branch to fork..." )
337- refBody , _ := json .Marshal (map [string ]string {
338- "ref" : "refs/heads/" + wlBranch ,
339- "sha" : newCommit .SHA ,
340- })
341- _ , err = ghAPICall (ghPath , "POST" , fmt .Sprintf ("repos/%s/git/refs" , forkRepo ), string (refBody ))
342- if err != nil {
289+ if err := client .CreateRef (forkRepo , "refs/heads/" + wlBranch , commitSHA ); err != nil {
343290 // Ref may already exist — force-update it.
344- updateBody , _ := json .Marshal (map [string ]interface {}{
345- "sha" : newCommit .SHA ,
346- "force" : true ,
347- })
348- _ , err = ghAPICall (ghPath , "PATCH" , fmt .Sprintf ("repos/%s/git/refs/heads/%s" , forkRepo , wlBranch ), string (updateBody ))
349- if err != nil {
291+ if err := client .UpdateRef (forkRepo , "heads/" + wlBranch , commitSHA , true ); err != nil {
350292 return "" , fmt .Errorf ("creating/updating ref: %w" , err )
351293 }
352294 }
@@ -355,33 +297,17 @@ func createGitHubPR(ghPath, upstreamRepo, forkOrg, forkDB, wlBranch, title, mdBo
355297 fmt .Fprintln (stdout , " Opening PR..." )
356298 head := forkOrg + ":" + wlBranch
357299
358- existingURL , existingNumber := findExistingPR ( ghPath , upstreamRepo , head )
300+ existingURL , existingNumber := client . FindPR ( upstreamRepo , head )
359301 if existingNumber != "" {
360- // Update existing PR body.
361- updateBody , _ := json .Marshal (map [string ]string {
362- "body" : mdBody ,
363- })
364- _ , _ = ghAPICall (ghPath , "PATCH" , fmt .Sprintf ("repos/%s/pulls/%s" , upstreamRepo , existingNumber ), string (updateBody ))
302+ _ = client .UpdatePR (upstreamRepo , existingNumber , map [string ]string {"body" : mdBody })
365303 return existingURL , nil
366304 }
367305
368- prBody , _ := json .Marshal (map [string ]string {
369- "title" : title ,
370- "body" : mdBody ,
371- "head" : head ,
372- "base" : "main" ,
373- })
374- prData , err := ghAPICall (ghPath , "POST" , fmt .Sprintf ("repos/%s/pulls" , upstreamRepo ), string (prBody ))
306+ prURL , err := client .CreatePR (upstreamRepo , title , mdBody , head , "main" )
375307 if err != nil {
376308 return "" , fmt .Errorf ("creating PR: %w" , err )
377309 }
378- var pr struct {
379- HTMLURL string `json:"html_url"`
380- }
381- if err := json .Unmarshal (prData , & pr ); err != nil {
382- return "" , fmt .Errorf ("parsing PR response: %w" , err )
383- }
384- return pr .HTMLURL , nil
310+ return prURL , nil
385311}
386312
387313// findExistingPR checks for an open PR on upstream with the given head ref.
0 commit comments