@@ -3,10 +3,43 @@ 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+ import constants from './constants.js' ;
10+ var fp = require ( "find-free-port" )
811
912const uploadDomToS3ViaEnv = process . env . USE_LAMBDA_INTERNAL || false ;
13+
14+ // Helper function to find an available port
15+ async function findAvailablePort ( server : FastifyInstance , startPort : number , log : Logger ) : Promise < number > {
16+ let currentPort = startPort ;
17+
18+ // If the default port gives error, use find-free-port with range 49100-60000
19+ try {
20+ await server . listen ( { port : currentPort } ) ;
21+ return currentPort ;
22+ } catch ( error : any ) {
23+ if ( error . code === 'EADDRINUSE' ) {
24+ log . debug ( `Port ${ currentPort } is in use, finding available port in range 49100-60000` ) ;
25+
26+ // Use find-free-port to get an available port in the specified range
27+ const availablePorts = await fp ( constants . MIN_PORT_RANGE , constants . MAX_PORT_RANGE ) ;
28+ if ( availablePorts . length > 0 ) {
29+ const freePort = availablePorts [ 0 ] ;
30+ await server . listen ( { port : freePort } ) ;
31+ log . debug ( `Found and started server on port ${ freePort } ` ) ;
32+ return freePort ;
33+ } else {
34+ throw new Error ( 'No available ports found in range 49100-60000' ) ;
35+ }
36+ } else {
37+ // If it's not a port conflict error, rethrow it
38+ throw error ;
39+ }
40+ }
41+ }
42+
1043export default async ( ctx : Context ) : Promise < FastifyInstance < Server , IncomingMessage , ServerResponse > > => {
1144
1245 const server : FastifyInstance < Server , IncomingMessage , ServerResponse > = fastify ( {
@@ -307,12 +340,21 @@ export default async (ctx: Context): Promise<FastifyInstance<Server, IncomingMes
307340 }
308341 } ) ;
309342
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 } ` ;
343+ // Use the helper function to find and start server on available port
344+ if ( ctx . sourceCommand && ctx . sourceCommand === 'exec-start' ) {
345+
346+ await server . listen ( { port : ctx . options . port } ) ;
347+ let { port } = server . addresses ( ) [ 0 ] ;
348+ process . env . SMARTUI_SERVER_ADDRESS = `http://localhost:${ port } ` ;
349+ process . env . CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${ port } ` ;
350+ ctx . log . debug ( `Server started successfully on port ${ port } ` ) ;
351+
352+ } else {
353+ const actualPort = await findAvailablePort ( server , ctx . options . port , ctx . log ) ;
354+ process . env . SMARTUI_SERVER_ADDRESS = `http://localhost:${ actualPort } ` ;
355+ process . env . CYPRESS_SMARTUI_SERVER_ADDRESS = `http://localhost:${ actualPort } ` ;
356+ ctx . log . debug ( `Server started successfully on port ${ actualPort } ` ) ;
357+ }
316358
317359 return server ;
318360}
0 commit comments