@@ -5,17 +5,10 @@ interface PR {
55 title : string
66}
77
8- interface Repo {
9- nameWithOwner : string
10- }
11-
12- interface HeadRepo {
13- nameWithOwner : string
14- }
15-
16- interface PRHead {
17- headRefName : string
18- headRepository : HeadRepo
8+ interface RunResult {
9+ exitCode : number
10+ stdout : string
11+ stderr : string
1912}
2013
2114async function main ( ) {
@@ -29,12 +22,6 @@ async function main() {
2922 const prs : PR [ ] = JSON . parse ( prsResult . stdout )
3023 console . log ( `Found ${ prs . length } open contributor PRs` )
3124
32- const repoResult = await $ `gh repo view --json nameWithOwner` . nothrow ( )
33- if ( repoResult . exitCode !== 0 ) {
34- throw new Error ( `Failed to fetch repo info: ${ repoResult . stderr } ` )
35- }
36- const repo : Repo = JSON . parse ( repoResult . stdout )
37-
3825 console . log ( "Fetching latest dev branch..." )
3926 const fetchDev = await $ `git fetch origin dev` . nothrow ( )
4027 if ( fetchDev . exitCode !== 0 ) {
@@ -53,75 +40,52 @@ async function main() {
5340 for ( const pr of prs ) {
5441 console . log ( `\nProcessing PR #${ pr . number } : ${ pr . title } ` )
5542
56- const headResult = await $ `gh pr view ${ pr . number } --json headRefName,headRepository` . nothrow ( )
57- if ( headResult . exitCode !== 0 ) {
58- console . log ( ` Failed to get head info` )
59- skipped . push ( { number : pr . number , reason : `Failed to get head info: ${ headResult . stderr } ` } )
60- continue
61- }
62- const head : PRHead = JSON . parse ( headResult . stdout )
63-
64- // Get the diff from GitHub compare API
65- console . log ( ` Getting diff...` )
66- const compare = `${ repo . nameWithOwner } /compare/dev...${ head . headRepository . nameWithOwner } :${ head . headRefName } `
67- const diffResult = await $ `gh api -H Accept:application/vnd.github.v3.diff repos/${ compare } ` . nothrow ( )
68- if ( diffResult . exitCode !== 0 ) {
69- console . log ( ` Failed to get diff: ${ diffResult . stderr } ` )
70- console . log ( ` Compare: ${ compare } ` )
71- skipped . push ( { number : pr . number , reason : `Failed to get diff: ${ diffResult . stderr } ` } )
72- continue
73- }
74-
75- if ( ! diffResult . stdout . trim ( ) ) {
76- console . log ( ` No changes, skipping` )
77- skipped . push ( { number : pr . number , reason : "No changes" } )
43+ console . log ( " Fetching PR head..." )
44+ const fetch = await run ( [ "git" , "fetch" , "origin" , `pull/${ pr . number } /head:pr/${ pr . number } ` ] )
45+ if ( fetch . exitCode !== 0 ) {
46+ console . log ( ` Failed to fetch PR head: ${ fetch . stderr } ` )
47+ skipped . push ( { number : pr . number , reason : `Fetch failed: ${ fetch . stderr } ` } )
7848 continue
7949 }
8050
81- // Try to apply the diff
82- console . log ( ` Applying...` )
83- const apply = await Bun . spawn ( [ "git" , "apply" , "--3way" ] , {
84- stdin : new TextEncoder ( ) . encode ( diffResult . stdout ) ,
85- stdout : "pipe" ,
86- stderr : "pipe" ,
87- } )
88- const applyExit = await apply . exited
89- const applyStderr = await Bun . readableStreamToText ( apply . stderr )
90-
91- if ( applyExit !== 0 ) {
92- console . log ( ` Failed to apply (conflicts)` )
51+ console . log ( " Merging..." )
52+ const merge = await run ( [ "git" , "merge" , "--no-commit" , "--no-ff" , `pr/${ pr . number } ` ] )
53+ if ( merge . exitCode !== 0 ) {
54+ console . log ( " Failed to merge (conflicts)" )
55+ await $ `git merge --abort` . nothrow ( )
9356 await $ `git checkout -- .` . nothrow ( )
9457 await $ `git clean -fd` . nothrow ( )
9558 skipped . push ( { number : pr . number , reason : "Has conflicts" } )
9659 continue
9760 }
9861
99- // Stage and commit
62+ const mergeHead = await $ `git rev-parse -q --verify MERGE_HEAD` . nothrow ( )
63+ if ( mergeHead . exitCode !== 0 ) {
64+ console . log ( " No changes, skipping" )
65+ skipped . push ( { number : pr . number , reason : "No changes" } )
66+ continue
67+ }
68+
10069 const add = await $ `git add -A` . nothrow ( )
10170 if ( add . exitCode !== 0 ) {
102- console . log ( ` Failed to stage` )
71+ console . log ( " Failed to stage" )
10372 await $ `git checkout -- .` . nothrow ( )
10473 await $ `git clean -fd` . nothrow ( )
10574 skipped . push ( { number : pr . number , reason : "Failed to stage" } )
10675 continue
10776 }
10877
10978 const commitMsg = `Apply PR #${ pr . number } : ${ pr . title } `
110- const commit = await Bun . spawn ( [ "git" , "commit" , "-m" , commitMsg ] , {
111- stdout : "pipe" ,
112- stderr : "pipe" ,
113- } )
114- const commitExit = await commit . exited
115- const commitStderr = await Bun . readableStreamToText ( commit . stderr )
116- if ( commitExit !== 0 ) {
117- console . log ( ` Failed to commit: ${ commitStderr } ` )
79+ const commit = await run ( [ "git" , "commit" , "-m" , commitMsg ] )
80+ if ( commit . exitCode !== 0 ) {
81+ console . log ( ` Failed to commit: ${ commit . stderr } ` )
11882 await $ `git checkout -- .` . nothrow ( )
11983 await $ `git clean -fd` . nothrow ( )
120- skipped . push ( { number : pr . number , reason : `Commit failed: ${ commitStderr } ` } )
84+ skipped . push ( { number : pr . number , reason : `Commit failed: ${ commit . stderr } ` } )
12185 continue
12286 }
12387
124- console . log ( ` Applied successfully` )
88+ console . log ( " Applied successfully" )
12589 applied . push ( pr . number )
12690 }
12791
@@ -145,6 +109,18 @@ main().catch((err) => {
145109 process . exit ( 1 )
146110} )
147111
112+ async function run ( args : string [ ] , stdin ?: Uint8Array ) : Promise < RunResult > {
113+ const proc = Bun . spawn ( args , {
114+ stdin : stdin ?? "inherit" ,
115+ stdout : "pipe" ,
116+ stderr : "pipe" ,
117+ } )
118+ const exitCode = await proc . exited
119+ const stdout = await new Response ( proc . stdout ) . text ( )
120+ const stderr = await new Response ( proc . stderr ) . text ( )
121+ return { exitCode, stdout, stderr }
122+ }
123+
148124function $ ( strings : TemplateStringsArray , ...values : unknown [ ] ) {
149125 const cmd = strings . reduce ( ( acc , str , i ) => acc + str + ( values [ i ] ?? "" ) , "" )
150126 return {
0 commit comments