@@ -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" ;
@@ -54,11 +54,14 @@ import type {
5454 GitStateSnapshot ,
5555 GitSyncStatus ,
5656 OpenPrOutput ,
57+ PrActionType ,
58+ PrDetailsByUrlOutput ,
5759 PrStatusOutput ,
5860 PublishOutput ,
5961 PullOutput ,
6062 PushOutput ,
6163 SyncOutput ,
64+ UpdatePrByUrlOutput ,
6265} from "./schemas" ;
6366
6467const fsPromises = fs . promises ;
@@ -837,10 +840,10 @@ export class GitService extends TypedEventEmitter<GitServiceEvents> {
837840 }
838841
839842 public async getPrChangedFiles ( prUrl : string ) : Promise < ChangedFile [ ] > {
840- const match = prUrl . match ( / g i t h u b \. c o m \/ ( [ ^ / ] + ) \/ ( [ ^ / ] + ) \/ p u l l \/ ( \d + ) / ) ;
841- if ( ! match ) return [ ] ;
843+ const pr = parsePrUrl ( prUrl ) ;
844+ if ( ! pr ) return [ ] ;
842845
843- const [ , owner , repo , number ] = match ;
846+ const { owner, repo, number } = pr ;
844847
845848 try {
846849 const result = await execGh ( [
@@ -907,6 +910,78 @@ export class GitService extends TypedEventEmitter<GitServiceEvents> {
907910 }
908911 }
909912
913+ public async getPrDetailsByUrl (
914+ prUrl : string ,
915+ ) : Promise < PrDetailsByUrlOutput | null > {
916+ const pr = parsePrUrl ( prUrl ) ;
917+ if ( ! pr ) return null ;
918+
919+ try {
920+ const result = await execGh ( [
921+ "api" ,
922+ `repos/${ pr . owner } /${ pr . repo } /pulls/${ pr . number } ` ,
923+ "--jq" ,
924+ "{state,merged,draft}" ,
925+ ] ) ;
926+
927+ if ( result . exitCode !== 0 ) {
928+ log . warn ( "Failed to fetch PR details" , {
929+ prUrl,
930+ error : result . stderr || result . error ,
931+ } ) ;
932+ return null ;
933+ }
934+
935+ const data = JSON . parse ( result . stdout ) as {
936+ state : string ;
937+ merged : boolean ;
938+ draft : boolean ;
939+ } ;
940+
941+ return data ;
942+ } catch ( error ) {
943+ log . warn ( "Failed to fetch PR details" , { prUrl, error } ) ;
944+ return null ;
945+ }
946+ }
947+
948+ public async updatePrByUrl (
949+ prUrl : string ,
950+ action : PrActionType ,
951+ ) : Promise < UpdatePrByUrlOutput > {
952+ const pr = parsePrUrl ( prUrl ) ;
953+ if ( ! pr ) {
954+ return { success : false , message : "Invalid PR URL" } ;
955+ }
956+
957+ try {
958+ const args =
959+ action === "draft"
960+ ? [ "pr" , "ready" , "--undo" , String ( pr . number ) ]
961+ : [ "pr" , action , String ( pr . number ) ] ;
962+
963+ const result = await execGh ( [
964+ ...args ,
965+ "--repo" ,
966+ `${ pr . owner } /${ pr . repo } ` ,
967+ ] ) ;
968+
969+ if ( result . exitCode !== 0 ) {
970+ const errorMsg = result . stderr || result . error || "Unknown error" ;
971+ log . warn ( "Failed to update PR" , { prUrl, action, error : errorMsg } ) ;
972+ return { success : false , message : errorMsg } ;
973+ }
974+
975+ return { success : true , message : result . stdout } ;
976+ } catch ( error ) {
977+ log . warn ( "Failed to update PR" , { prUrl, action, error } ) ;
978+ return {
979+ success : false ,
980+ message : error instanceof Error ? error . message : "Unknown error" ,
981+ } ;
982+ }
983+ }
984+
910985 public async getBranchChangedFiles (
911986 repo : string ,
912987 branch : string ,
0 commit comments