@@ -708,6 +708,72 @@ describe("GitHubSourceControlProvider.getChangeRequest", () => {
708708} ) ;
709709
710710describe ( "GitHubSourceControlProvider writes" , ( ) => {
711+ it . effect ( "creates an App fork PR without granting fork edits and pins the acting token" , ( ) => {
712+ let current = "before" ;
713+ const posts : Array < GitHubRest . GitHubRestInput > = [ ] ;
714+ const pinnedTokens : Array < string | null > = [ ] ;
715+ const { layer, graphqlCalls } = harness ( {
716+ remotes :
remotesOutput ( [ "origin" , "[email protected] :acme/web.git" ] ) , 717+ api : {
718+ credential : ( host ) =>
719+ Effect . succeed ( {
720+ token : Redacted . make ( current ) ,
721+ fingerprint : `${ host } :${ current } ` ,
722+ } ) ,
723+ rest : ( input ) =>
724+ Effect . gen ( function * ( ) {
725+ if ( input . method === "POST" ) {
726+ const pinned = yield * GitHubRequestPolicy . PinnedGitHubCredential ;
727+ pinnedTokens . push ( pinned === null ? null : Redacted . value ( pinned . token ) ) ;
728+ posts . push ( input ) ;
729+ return restResponse ( { number : 1 } , 201 ) ;
730+ }
731+ current = "after" ;
732+ return yield * Effect . fail (
733+ new GitHubRequestPolicy . GitHubApiResponseError ( {
734+ host : input . host ,
735+ operation : "getViewer" ,
736+ status : 403 ,
737+ } ) ,
738+ ) ;
739+ } ) ,
740+ } ,
741+ graphql : ( ) =>
742+ new Response (
743+ encodeJson ( {
744+ data : { viewer : { login : "example[bot]" , databaseId : 123 } } ,
745+ } ) ,
746+ { headers : { "content-type" : "application/json" } } ,
747+ ) ,
748+ } ) ;
749+ return Effect . gen ( function * ( ) {
750+ const fs = yield * FileSystem . FileSystem ;
751+ const bodyFile = yield * fs . makeTempFileScoped ( { suffix : ".md" } ) ;
752+ yield * fs . writeFileString ( bodyFile , "Body" ) ;
753+ const provider = yield * GitHubSourceControlProvider . make ;
754+ yield * provider . createChangeRequest ( {
755+ cwd : "/repo" ,
756+ baseRefName : "main" ,
757+ headSelector : "other:feature" ,
758+ title : "Title" ,
759+ bodyFile,
760+ } ) ;
761+ assert . strictEqual ( posts . length , 1 ) ;
762+ assert . deepStrictEqual ( posts [ 0 ] ?. body , {
763+ base : "main" ,
764+ head : "other:feature" ,
765+ title : "Title" ,
766+ body : "Body" ,
767+ maintainer_can_modify : false ,
768+ } ) ;
769+ assert . deepStrictEqual ( pinnedTokens , [ "before" ] ) ;
770+ assert . deepStrictEqual (
771+ graphqlCalls . map ( ( call ) => call . authorization ) ,
772+ [ "Bearer before" ] ,
773+ ) ;
774+ } ) . pipe ( Effect . provide ( Layer . merge ( layer , NodeServices . layer ) ) , Effect . scoped ) ;
775+ } ) ;
776+
711777 it . effect ( "creates a cross-repository pull request with an owner:branch head" , ( ) => {
712778 const requests : Array < GitHubRest . GitHubRestInput > = [ ] ;
713779 const { layer } = harness ( {
@@ -718,6 +784,7 @@ describe("GitHubSourceControlProvider writes", () => {
718784 api : {
719785 rest : ( input ) =>
720786 Effect . sync ( ( ) => {
787+ if ( input . path === "user" ) return restResponse ( { login : "me" } ) ;
721788 requests . push ( input ) ;
722789 return restResponse ( { number : 1 } , 201 ) ;
723790 } ) ,
@@ -1742,6 +1809,7 @@ it.effect.each([
17421809 api : {
17431810 rest : ( input ) =>
17441811 Effect . sync ( ( ) => {
1812+ if ( input . path === "user" ) return restResponse ( { login : "me" } ) ;
17451813 targets . push ( `${ input . host } /${ input . path } ` ) ;
17461814 return restResponse ( {
17471815 full_name : expected ,
0 commit comments