@@ -60,6 +60,31 @@ interface ProbeResult {
6060 detail : string ;
6161}
6262
63+ export function probeFailureDetail ( stderr : string , exitCode : number ) : string {
64+ const lines = stderr
65+ . split ( "\n" )
66+ . map ( ( line ) => line . trim ( ) )
67+ . filter ( ( line ) => line && ! / ^ R u n ' d o c k e r r u n - - h e l p ' f o r m o r e i n f o r m a t i o n \. ? $ / . test ( line ) ) ;
68+ return lines . at ( - 1 ) ?? `exit ${ exitCode } ` ;
69+ }
70+
71+ export function composeNetworkName ( configText : string ) : string | null {
72+ try {
73+ const config = JSON . parse ( configText ) as {
74+ name ?: unknown ;
75+ networks ?: Record < string , { name ?: unknown } | null > ;
76+ } ;
77+ const explicitName = config . networks ?. openmapx ?. name ;
78+ if ( typeof explicitName === "string" && explicitName . trim ( ) ) return explicitName . trim ( ) ;
79+ if ( typeof config . name === "string" && config . name . trim ( ) ) {
80+ return `${ config . name . trim ( ) } _openmapx` ;
81+ }
82+ } catch {
83+ // Fall back to the conventional reference-deployment network below.
84+ }
85+ return null ;
86+ }
87+
6388/**
6489 * Probe image: a small, pinned curl container. curl's ENTRYPOINT is `curl`, so
6590 * everything after the image name is curl flags. `-f` turns non-2xx responses
@@ -87,12 +112,7 @@ async function runDeepProbe(serviceId: string, network: string): Promise<ProbeRe
87112 const result = await dockerRun ( buildProbeArgs ( network , url ) ) ;
88113
89114 if ( result . exitCode !== 0 ) {
90- const stderr =
91- result . stderr
92- . split ( "\n" )
93- . filter ( ( line ) => line . trim ( ) )
94- . slice ( - 1 ) [ 0 ] ?? "" ;
95- return { status : "fail" , detail : stderr . trim ( ) || `exit ${ result . exitCode } ` } ;
115+ return { status : "fail" , detail : probeFailureDetail ( result . stderr , result . exitCode ) } ;
96116 }
97117 if ( probe . expect && ! result . stdout . toLowerCase ( ) . includes ( probe . expect . toLowerCase ( ) ) ) {
98118 return { status : "fail" , detail : `response missing "${ probe . expect } "` } ;
@@ -101,20 +121,13 @@ async function runDeepProbe(serviceId: string, network: string): Promise<ProbeRe
101121}
102122
103123async function detectComposeNetwork ( ) : Promise < string > {
104- // docker-compose names networks `<project>_<name>`. Our compose declares one
105- // network called `openmapx`, so the project prefix is the only variable.
106- const result = await dockerCompose ( [ "config" , "--services" ] ) ;
124+ // Read the network name from this checkout's rendered config. `compose ls`
125+ // lists every project on the host and its first row may belong to an
126+ // unrelated deployment (for example the docs stack).
127+ const result = await dockerCompose ( [ "config" , "--format" , "json" ] ) ;
107128 if ( result . exitCode === 0 ) {
108- const inspect = await dockerCompose ( [ "ls" , "--format" , "json" ] ) ;
109- if ( inspect . exitCode === 0 && inspect . stdout . trim ( ) ) {
110- try {
111- const rows = JSON . parse ( inspect . stdout ) as Array < { Name ?: string } > ;
112- const project = rows . find ( ( r ) => r . Name ) ?. Name ;
113- if ( project ) return `${ project } _openmapx` ;
114- } catch {
115- // fall through
116- }
117- }
129+ const name = composeNetworkName ( result . stdout ) ;
130+ if ( name ) return name ;
118131 }
119132 return "docker_openmapx" ;
120133}
0 commit comments