@@ -10,7 +10,9 @@ import { Effect, Either } from "effect"
1010import { Buffer } from "node:buffer"
1111import { spawn } from "node:child_process"
1212import { randomUUID } from "node:crypto"
13+ import { existsSync } from "node:fs"
1314import type { IncomingMessage , Server as HttpServer } from "node:http"
15+ import os from "node:os"
1416import type { Duplex } from "node:stream"
1517import { WebSocket , WebSocketServer , type RawData } from "ws"
1618
@@ -140,7 +142,13 @@ type ContainerNetworkEntry = {
140142 readonly name : string
141143}
142144
143- const dockerGitApiContainerName = ( ) : string => process . env [ "DOCKER_GIT_API_CONTAINER_NAME" ] ?. trim ( ) || "docker-git-api"
145+ const dockerGitApiContainerName = ( ) : string =>
146+ process . env [ "DOCKER_GIT_API_CONTAINER_NAME" ] ?. trim ( ) || os . hostname ( ) . trim ( ) || "docker-git-api"
147+
148+ const isContainerizedController = ( ) : boolean => {
149+ const configuredName = process . env [ "DOCKER_GIT_API_CONTAINER_NAME" ] ?. trim ( )
150+ return ( configuredName !== undefined && configuredName . length > 0 ) || existsSync ( "/.dockerenv" )
151+ }
144152
145153const parseContainerNetworkEntries = ( output : string ) : ReadonlyArray < ContainerNetworkEntry > =>
146154 output
@@ -150,9 +158,23 @@ const parseContainerNetworkEntries = (output: string): ReadonlyArray<ContainerNe
150158 . map ( ( [ name , ipAddress ] ) => ( { name, ipAddress } ) )
151159
152160const selectReachableProjectNetwork = (
161+ projectEntries : ReadonlyArray < ContainerNetworkEntry > ,
162+ controllerEntries : ReadonlyArray < ContainerNetworkEntry >
163+ ) : ContainerNetworkEntry | null =>
164+ projectEntries . find ( ( entry ) =>
165+ entry . name !== "bridge" && controllerEntries . some ( ( controllerEntry ) => controllerEntry . name === entry . name )
166+ ) ??
167+ projectEntries . find ( ( entry ) =>
168+ controllerEntries . some ( ( controllerEntry ) => controllerEntry . name === entry . name )
169+ ) ??
170+ null
171+
172+ const selectFallbackProjectNetwork = (
153173 entries : ReadonlyArray < ContainerNetworkEntry >
154174) : ContainerNetworkEntry | null =>
155- entries . find ( ( entry ) => entry . name !== "bridge" ) ?? entries [ 0 ] ?? null
175+ isContainerizedController ( )
176+ ? entries . find ( ( entry ) => entry . name === "bridge" ) ?? entries [ 0 ] ?? null
177+ : null
156178
157179const inspectContainerNetworks = (
158180 containerName : string
@@ -177,7 +199,7 @@ const connectContainerToNetwork = (
177199 containerName : string
178200) =>
179201 networkName === "bridge"
180- ? Effect . void
202+ ? Effect . succeed ( true )
181203 : runCommandCapture (
182204 {
183205 cwd : process . cwd ( ) ,
@@ -187,23 +209,36 @@ const connectContainerToNetwork = (
187209 [ 0 ] ,
188210 ( exitCode ) => new CommandFailedError ( { command : `docker network connect ${ networkName } ` , exitCode } )
189211 ) . pipe (
190- Effect . asVoid ,
191- Effect . orElseSucceed ( ( ) => void 0 )
212+ Effect . as ( true ) ,
213+ Effect . orElseSucceed ( ( ) => false )
192214 )
193215
194216const resolveControllerReachableProject = (
195217 projectItem : ProjectItem
196218) =>
197219 Effect . gen ( function * ( _ ) {
220+ const controllerContainer = dockerGitApiContainerName ( )
198221 const networkEntries = yield * _ ( inspectContainerNetworks ( projectItem . containerName ) . pipe ( Effect . orElseSucceed ( ( ) => [ ] ) ) )
222+ const controllerNetworks = yield * _ ( inspectContainerNetworks ( controllerContainer ) . pipe ( Effect . orElseSucceed ( ( ) => [ ] ) ) )
223+ const alreadyReachable = selectReachableProjectNetwork ( networkEntries , controllerNetworks )
224+ if ( alreadyReachable !== null ) {
225+ return {
226+ ...projectItem ,
227+ ipAddress : alreadyReachable . ipAddress
228+ }
229+ }
199230 yield * _ (
200231 Effect . forEach (
201232 networkEntries . filter ( ( entry ) => entry . name !== "bridge" ) ,
202- ( entry ) => connectContainerToNetwork ( entry . name , dockerGitApiContainerName ( ) ) ,
233+ ( entry ) => connectContainerToNetwork ( entry . name , controllerContainer ) ,
203234 { discard : true }
204235 )
205236 )
206- const preferredNetwork = selectReachableProjectNetwork ( networkEntries )
237+ const refreshedControllerNetworks = yield * _ (
238+ inspectContainerNetworks ( controllerContainer ) . pipe ( Effect . orElseSucceed ( ( ) => [ ] ) )
239+ )
240+ const preferredNetwork = selectReachableProjectNetwork ( networkEntries , refreshedControllerNetworks ) ??
241+ selectFallbackProjectNetwork ( networkEntries )
207242 if ( preferredNetwork === null ) {
208243 return projectItem
209244 }
0 commit comments