@@ -3,10 +3,44 @@ import path from 'path';
33import fastify , { FastifyInstance , RouteShorthandOptions } from 'fastify' ;
44import { readFileSync , truncate } from 'fs'
55import { Context } from '../types.js'
6+ import { Logger } from 'winston'
67import { validateSnapshot } from './schemaValidation.js'
78import { pingIntervalId , startPollingForTunnel , stopTunnelHelper , isTunnelPolling } from './utils.js' ;
9+ var fp = require ( "find-free-port" )
810
911const uploadDomToS3ViaEnv = process . env . USE_LAMBDA_INTERNAL || false ;
12+
13+ // Helper function to find an available port
14+ async function findAvailablePort ( server : FastifyInstance , startPort : number , log : Logger ) : Promise < number > {
15+ let currentPort = startPort ;
16+ let attempts = 0 ;
17+ let maxAttempts = 10 ;
18+
19+ // If the default port gives error, use find-free-port with range 49100-60000
20+ try {
21+ await server . listen ( { port : currentPort } ) ;
22+ return currentPort ;
23+ } catch ( error : any ) {
24+ if ( error . code === 'EADDRINUSE' ) {
25+ log . debug ( `Port ${ currentPort } is in use, finding available port in range 49100-60000` ) ;
26+
27+ // Use find-free-port to get an available port in the specified range
28+ const availablePorts = await fp ( 49100 , 60000 ) ;
29+ if ( availablePorts . length > 0 ) {
30+ const freePort = availablePorts [ 0 ] ;
31+ await server . listen ( { port : freePort } ) ;
32+ log . debug ( `Found and started server on port ${ freePort } ` ) ;
33+ return freePort ;
34+ } else {
35+ throw new Error ( 'No available ports found in range 49100-60000' ) ;
36+ }
37+ } else {
38+ // If it's not a port conflict error, rethrow it
39+ throw error ;
40+ }
41+ }
42+ }
43+
1044export default async ( ctx : Context ) : Promise < FastifyInstance < Server , IncomingMessage , ServerResponse > > => {
1145
1246 const server : FastifyInstance < Server , IncomingMessage , ServerResponse > = fastify ( {
@@ -307,12 +341,21 @@ export default async (ctx: Context): Promise<FastifyInstance<Server, IncomingMes
307341 }
308342 } ) ;
309343
310-
311- await server . listen ( { port : ctx . options . port } ) ;
312- // store server's address for SDK
313- let { port } = server . addresses ( ) [ 0 ] ;
314- process . env . SMARTUI_SERVER_ADDRESS = `http://localhost:${ port } ` ;
315- process . env . CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${ port } ` ;
344+ // Use the helper function to find and start server on available port
345+ if ( ctx . sourceCommand && ctx . sourceCommand === 'exec-start' ) {
346+
347+ await server . listen ( { port : ctx . options . port } ) ;
348+ let { port } = server . addresses ( ) [ 0 ] ;
349+ process . env . SMARTUI_SERVER_ADDRESS = `http://localhost:${ port } ` ;
350+ process . env . CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${ port } ` ;
351+ ctx . log . debug ( `Server started successfully on port ${ port } ` ) ;
352+
353+ } else {
354+ const actualPort = await findAvailablePort ( server , ctx . options . port , ctx . log ) ;
355+ process . env . SMARTUI_SERVER_ADDRESS = `http://localhost:${ actualPort } ` ;
356+ process . env . CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${ actualPort } ` ;
357+ ctx . log . debug ( `Server started successfully on port ${ actualPort } ` ) ;
358+ }
316359
317360 return server ;
318361}
0 commit comments