11/**
22 * Integration Test Environment Orchestrator
33 *
4- * Co-authored by Claude (Opus 4.6).
5- *
64 * Spins up the full ENSNode stack against the ens-test-env devnet, runs
75 * monorepo-level integration tests, then tears everything down.
86 *
1715 * - testcontainers for Postgres (dynamic port, built-in health check) and devnet
1816 * (fixed ports required — ensTestEnvChain hardcodes localhost:8545).
1917 * - execa for child process management — automatic cleanup on parent exit,
20- * forceKillAfterDelay (10s SIGKILL fallback), env inheritance via extendEnv .
18+ * forceKillAfterDelay (10s SIGKILL fallback), env inherited from parent .
2119 * - Services run from source (pnpm start/serve) rather than Docker so that
2220 * CI tests the actual code in the PR.
2321 * - ENSRainbow database is downloaded via the existing shell script and
@@ -131,29 +129,29 @@ function logError(msg: string) {
131129 console . error ( `[ci] ERROR: ${ msg } ` ) ;
132130}
133131
134- async function waitForHealth ( url : string , timeoutMs : number , label : string ) : Promise < void > {
132+ async function waitForHealth ( url : string , timeoutMs : number , serviceName : string ) : Promise < void > {
135133 const start = Date . now ( ) ;
136134 while ( Date . now ( ) - start < timeoutMs ) {
137135 checkAborted ( ) ;
138136 try {
139137 const res = await fetch ( url , { signal : AbortSignal . timeout ( 5_000 ) } ) ;
140138 if ( res . ok ) {
141- log ( `${ label } is healthy` ) ;
139+ log ( `${ serviceName } is healthy` ) ;
142140 return ;
143141 }
144- log ( `${ label } health check returned ${ res . status } , retrying...` ) ;
142+ log ( `${ serviceName } health check returned ${ res . status } , retrying...` ) ;
145143 } catch { }
146144 await new Promise ( ( r ) => setTimeout ( r , 1000 ) ) ;
147145 }
148- throw new Error ( `${ label } did not become healthy within ${ timeoutMs / 1000 } s` ) ;
146+ throw new Error ( `${ serviceName } did not become healthy within ${ timeoutMs / 1000 } s` ) ;
149147}
150148
151149function spawnService (
152150 command : string ,
153151 args : string [ ] ,
154152 cwd : string ,
155153 env : Record < string , string > ,
156- label : string ,
154+ serviceName : string ,
157155) : ResultPromise {
158156 const subprocess = spawn ( command , args , {
159157 cwd,
@@ -167,19 +165,19 @@ function spawnService(
167165
168166 subprocess . stdout ?. on ( "data" , ( data : Buffer ) => {
169167 for ( const line of data . toString ( ) . split ( "\n" ) . filter ( Boolean ) ) {
170- console . log ( `[${ label } ] ${ line } ` ) ;
168+ console . log ( `[${ serviceName } ] ${ line } ` ) ;
171169 }
172170 } ) ;
173171
174172 subprocess . stderr ?. on ( "data" , ( data : Buffer ) => {
175173 for ( const line of data . toString ( ) . split ( "\n" ) . filter ( Boolean ) ) {
176- console . error ( `[${ label } ] ${ line } ` ) ;
174+ console . error ( `[${ serviceName } ] ${ line } ` ) ;
177175 }
178176 } ) ;
179177
180178 subprocess . then ( ( result ) => {
181179 if ( result . failed && ! result . isTerminated ) {
182- setAborted ( `${ label } exited with code ${ result . exitCode } ` ) ;
180+ setAborted ( `${ serviceName } exited with code ${ result . exitCode } ` ) ;
183181 }
184182 } ) ;
185183
@@ -219,8 +217,18 @@ async function pollIndexingStatus(timeoutMs: number): Promise<void> {
219217 throw new Error ( `Indexing did not complete within ${ timeoutMs / 1000 } s` ) ;
220218}
221219
220+ function logVersions ( ) {
221+ log ( "Software versions:" ) ;
222+ log ( ` Node.js: ${ process . version } ` ) ;
223+ log ( ` pnpm: ${ execaSync ( "pnpm" , [ "--version" ] ) . stdout . trim ( ) } ` ) ;
224+ log ( ` Docker: ${ execaSync ( "docker" , [ "--version" ] ) . stdout . trim ( ) } ` ) ;
225+ log ( ` Postgres image: ${ POSTGRES_IMAGE } ` ) ;
226+ log ( ` Devnet image: ${ DEVNET_IMAGE } ` ) ;
227+ }
228+
222229async function main ( ) {
223230 log ( "Starting integration test environment..." ) ;
231+ logVersions ( ) ;
224232
225233 // Phase 1: Start Postgres + Devnet in parallel
226234 log ( "Starting Postgres and devnet..." ) ;
0 commit comments