@@ -12,6 +12,26 @@ import { tryBuildGithubCompareUrl, withGithubAskpassEnv } from "./github-auth.js
1212
1313type StateRepoEnv = FileSystem . FileSystem | Path . Path | CommandExecutor . CommandExecutor
1414
15+ const withOriginPushUrlOverride = ( originUrl : string | null , args : ReadonlyArray < string > ) : ReadonlyArray < string > => {
16+ const trimmed = originUrl ?. trim ( ) ?? ""
17+ if ( trimmed . length === 0 ) {
18+ return args
19+ }
20+ // Use a per-command config override so token-based pushes use HTTPS even when the repo has an SSH pushurl.
21+ // This keeps the repo config unchanged while avoiding non-interactive SSH host key / passphrase prompts.
22+ return [ "-c" , `remote.origin.pushurl=${ trimmed } ` , ...args ]
23+ }
24+
25+ const resolveSyncMessage = ( value : string | null ) : string => {
26+ const trimmed = value ?. trim ( ) ?? ""
27+ return trimmed . length > 0 ? trimmed : defaultSyncMessage
28+ }
29+
30+ const logOpenPr = ( originUrl : string , baseBranch : string , prBranch : string , compareUrl : string | null ) =>
31+ compareUrl
32+ ? Effect . log ( `Open PR: ${ compareUrl } ` )
33+ : Effect . log ( `Open PR from '${ prBranch } ' into '${ baseBranch } ' (origin: ${ originUrl } ).` )
34+
1535const commitAllIfNeeded = (
1636 root : string ,
1737 message : string ,
@@ -68,6 +88,7 @@ const rebaseOntoOriginIfPossible = (
6888const pushToNewBranch = (
6989 root : string ,
7090 baseBranch : string ,
91+ originPushUrlOverride : string | null ,
7192 env : GitAuthEnv
7293) : Effect . Effect < string , CommandFailedError | PlatformError , CommandExecutor . CommandExecutor > =>
7394 Effect . gen ( function * ( _ ) {
@@ -77,7 +98,9 @@ const pushToNewBranch = (
7798 const timestamp = yield * _ ( Effect . sync ( ( ) => new Date ( ) . toISOString ( ) . replaceAll ( ":" , "-" ) . replaceAll ( "." , "-" ) ) )
7899 const branch = sanitizeBranchComponent ( `state-sync/${ baseBranch } /${ timestamp } -${ headShort } ` )
79100
80- yield * _ ( git ( root , [ "push" , "origin" , `HEAD:refs/heads/${ branch } ` ] , env ) )
101+ yield * _ (
102+ git ( root , withOriginPushUrlOverride ( originPushUrlOverride , [ "push" , "origin" , `HEAD:refs/heads/${ branch } ` ] ) , env )
103+ )
81104 return branch
82105 } )
83106
@@ -93,41 +116,42 @@ export const runStateSyncOps = (
93116 root : string ,
94117 originUrl : string ,
95118 message : string | null ,
96- env : GitAuthEnv
119+ env : GitAuthEnv ,
120+ options ?: { readonly originPushUrlOverride ?: string | null }
97121) : Effect . Effect < void , CommandFailedError | PlatformError , StateRepoEnv > =>
98122 Effect . gen ( function * ( _ ) {
123+ const originPushUrlOverride = options ?. originPushUrlOverride ?? null
99124 yield * _ ( normalizeLegacyStateProjects ( root ) )
100- const commitMessage = message && message . trim ( ) . length > 0 ? message . trim ( ) : defaultSyncMessage
101- yield * _ ( commitAllIfNeeded ( root , commitMessage , env ) )
125+ yield * _ ( commitAllIfNeeded ( root , resolveSyncMessage ( message ) , env ) )
102126
103127 const branch = yield * _ ( getCurrentBranch ( root , env ) )
104128 const baseBranch = resolveBaseBranch ( branch )
105129
106130 const rebaseResult = yield * _ ( rebaseOntoOriginIfPossible ( root , baseBranch , env ) )
107131 if ( rebaseResult === "conflict" ) {
108- const prBranch = yield * _ ( pushToNewBranch ( root , baseBranch , env ) )
132+ const prBranch = yield * _ ( pushToNewBranch ( root , baseBranch , originPushUrlOverride , env ) )
109133 const compareUrl = tryBuildGithubCompareUrl ( originUrl , baseBranch , prBranch )
110134
111135 yield * _ ( Effect . logWarning ( `State sync needs manual merge: pushed changes to branch '${ prBranch } '.` ) )
112- yield * ( compareUrl
113- ? _ ( Effect . log ( `Open PR: ${ compareUrl } ` ) )
114- : _ ( Effect . log ( `Open PR from '${ prBranch } ' into '${ baseBranch } ' (origin: ${ originUrl } ).` ) ) )
136+ yield * _ ( logOpenPr ( originUrl , baseBranch , prBranch , compareUrl ) )
115137 return
116138 }
117139
118- const pushExit = yield * _ ( gitExitCode ( root , [ "push" , "-u" , "origin" , "HEAD" ] , env ) )
140+ const pushExit = yield * _ (
141+ gitExitCode (
142+ root ,
143+ withOriginPushUrlOverride ( originPushUrlOverride , [ "push" , "-u" , "origin" , "HEAD" ] ) ,
144+ env
145+ )
146+ )
119147 if ( pushExit === successExitCode ) {
120148 return
121149 }
122150
123- const prBranch = yield * _ ( pushToNewBranch ( root , baseBranch , env ) )
151+ const prBranch = yield * _ ( pushToNewBranch ( root , baseBranch , originPushUrlOverride , env ) )
124152 const compareUrl = tryBuildGithubCompareUrl ( originUrl , baseBranch , prBranch )
125153 yield * _ ( Effect . logWarning ( `State push failed (exit ${ pushExit } ); pushed changes to branch '${ prBranch } '.` ) )
126- if ( compareUrl ) {
127- yield * _ ( Effect . log ( `Open PR: ${ compareUrl } ` ) )
128- return
129- }
130- yield * _ ( Effect . log ( `Open PR from '${ prBranch } ' into '${ baseBranch } ' (origin: ${ originUrl } ).` ) )
154+ yield * _ ( logOpenPr ( originUrl , baseBranch , prBranch , compareUrl ) )
131155 } ) . pipe ( Effect . asVoid )
132156
133157export const runStateSyncWithToken = (
@@ -136,4 +160,7 @@ export const runStateSyncWithToken = (
136160 originUrl : string ,
137161 message : string | null
138162) : Effect . Effect < void , CommandFailedError | PlatformError , StateRepoEnv > =>
139- withGithubAskpassEnv ( token , ( env ) => runStateSyncOps ( root , originUrl , message , env ) )
163+ withGithubAskpassEnv (
164+ token ,
165+ ( env ) => runStateSyncOps ( root , originUrl , message , env , { originPushUrlOverride : originUrl } )
166+ )
0 commit comments