@@ -28,7 +28,7 @@ import { CommitSaga } from "@posthog/git/sagas/commit";
2828import { DiscardFileChangesSaga } from "@posthog/git/sagas/discard" ;
2929import { PullSaga } from "@posthog/git/sagas/pull" ;
3030import { PushSaga } from "@posthog/git/sagas/push" ;
31- import { parseGitHubUrl } from "@posthog/git/utils" ;
31+ import { parseGitHubUrl , parsePrUrl } from "@posthog/git/utils" ;
3232import { inject , injectable } from "inversify" ;
3333import { MAIN_TOKENS } from "../../di/tokens" ;
3434import { logger } from "../../utils/logger" ;
@@ -55,11 +55,14 @@ import type {
5555 GitStateSnapshot ,
5656 GitSyncStatus ,
5757 OpenPrOutput ,
58+ PrActionType ,
59+ PrDetailsByUrlOutput ,
5860 PrStatusOutput ,
5961 PublishOutput ,
6062 PullOutput ,
6163 PushOutput ,
6264 SyncOutput ,
65+ UpdatePrByUrlOutput ,
6366} from "./schemas" ;
6467
6568const fsPromises = fs . promises ;
@@ -865,10 +868,10 @@ export class GitService extends TypedEventEmitter<GitServiceEvents> {
865868 }
866869
867870 public async getPrChangedFiles ( prUrl : string ) : Promise < ChangedFile [ ] > {
868- const match = prUrl . match ( / g i t h u b \. c o m \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) \/ p u l l \/ ( \d + ) / ) ;
869- if ( ! match ) return [ ] ;
871+ const pr = parsePrUrl ( prUrl ) ;
872+ if ( ! pr ) return [ ] ;
870873
871- const [ , owner , repo , number ] = match ;
874+ const { owner, repo, number } = pr ;
872875
873876 try {
874877 const result = await execGh ( [
@@ -935,6 +938,78 @@ export class GitService extends TypedEventEmitter<GitServiceEvents> {
935938 }
936939 }
937940
941+ public async getPrDetailsByUrl (
942+ prUrl : string ,
943+ ) : Promise < PrDetailsByUrlOutput | null > {
944+ const pr = parsePrUrl ( prUrl ) ;
945+ if ( ! pr ) return null ;
946+
947+ try {
948+ const result = await execGh ( [
949+ "api" ,
950+ `repos/${ pr . owner } /${ pr . repo } /pulls/${ pr . number } ` ,
951+ "--jq" ,
952+ "{state,merged,draft}" ,
953+ ] ) ;
954+
955+ if ( result . exitCode !== 0 ) {
956+ log . warn ( "Failed to fetch PR details" , {
957+ prUrl,
958+ error : result . stderr || result . error ,
959+ } ) ;
960+ return null ;
961+ }
962+
963+ const data = JSON . parse ( result . stdout ) as {
964+ state : string ;
965+ merged : boolean ;
966+ draft : boolean ;
967+ } ;
968+
969+ return data ;
970+ } catch ( error ) {
971+ log . warn ( "Failed to fetch PR details" , { prUrl, error } ) ;
972+ return null ;
973+ }
974+ }
975+
976+ public async updatePrByUrl (
977+ prUrl : string ,
978+ action : PrActionType ,
979+ ) : Promise < UpdatePrByUrlOutput > {
980+ const pr = parsePrUrl ( prUrl ) ;
981+ if ( ! pr ) {
982+ return { success : false , message : "Invalid PR URL" } ;
983+ }
984+
985+ try {
986+ const args =
987+ action === "draft"
988+ ? [ "pr" , "ready" , "--undo" , String ( pr . number ) ]
989+ : [ "pr" , action , String ( pr . number ) ] ;
990+
991+ const result = await execGh ( [
992+ ...args ,
993+ "--repo" ,
994+ `${ pr . owner } /${ pr . repo } ` ,
995+ ] ) ;
996+
997+ if ( result . exitCode !== 0 ) {
998+ const errorMsg = result . stderr || result . error || "Unknown error" ;
999+ log . warn ( "Failed to update PR" , { prUrl, action, error : errorMsg } ) ;
1000+ return { success : false , message : errorMsg } ;
1001+ }
1002+
1003+ return { success : true , message : result . stdout } ;
1004+ } catch ( error ) {
1005+ log . warn ( "Failed to update PR" , { prUrl, action, error } ) ;
1006+ return {
1007+ success : false ,
1008+ message : error instanceof Error ? error . message : "Unknown error" ,
1009+ } ;
1010+ }
1011+ }
1012+
9381013 public async getBranchChangedFiles (
9391014 repo : string ,
9401015 branch : string ,
0 commit comments