@@ -460,6 +460,7 @@ private async Task PullContainerAsync(IExecutionContext executionContext, Contai
460460 }
461461 }
462462
463+ [ System . Diagnostics . CodeAnalysis . SuppressMessage ( "Maintainability" , "CA1505:Avoid unmaintainable code" , Justification = "Complex container startup logic with multiple fallback paths" ) ]
463464 private async Task StartContainerAsync ( IExecutionContext executionContext , ContainerInfo container )
464465 {
465466 Trace . Entering ( ) ;
@@ -526,8 +527,10 @@ private async Task StartContainerAsync(IExecutionContext executionContext, Conta
526527 }
527528
528529 bool useNode20ToStartContainer = AgentKnobs . UseNode20ToStartContainer . GetValue ( executionContext ) . AsBoolean ( ) ;
530+ bool useNode24ToStartContainer = AgentKnobs . UseNode24ToStartContainer . GetValue ( executionContext ) . AsBoolean ( ) ;
529531 bool useAgentNode = false ;
530532
533+ string labelContainerStartupUsingNode24 = "container-startup-using-node-24" ;
531534 string labelContainerStartupUsingNode20 = "container-startup-using-node-20" ;
532535 string labelContainerStartupUsingNode16 = "container-startup-using-node-16" ;
533536 string labelContainerStartupFailed = "container-startup-failed" ;
@@ -540,6 +543,7 @@ string containerNodePath(string nodeFolder)
540543 string nodeContainerPath = containerNodePath ( NodeHandler . NodeFolder ) ;
541544 string node16ContainerPath = containerNodePath ( NodeHandler . Node16Folder ) ;
542545 string node20ContainerPath = containerNodePath ( NodeHandler . Node20_1Folder ) ;
546+ string node24ContainerPath = containerNodePath ( NodeHandler . Node24Folder ) ;
543547
544548 if ( container . IsJobContainer )
545549 {
@@ -573,7 +577,20 @@ string useDoubleQuotes(string value)
573577 else
574578 {
575579 useAgentNode = true ;
576- string sleepCommand = useNode20ToStartContainer ? $ "'{ node20ContainerPath } ' --version && echo '{ labelContainerStartupUsingNode20 } ' && { nodeSetInterval ( node20ContainerPath ) } || '{ node16ContainerPath } ' --version && echo '{ labelContainerStartupUsingNode16 } ' && { nodeSetInterval ( node16ContainerPath ) } || echo '{ labelContainerStartupFailed } '" : nodeSetInterval ( nodeContainerPath ) ;
580+ string sleepCommand ;
581+
582+ if ( useNode24ToStartContainer )
583+ {
584+ sleepCommand = $ "'{ node24ContainerPath } ' --version && echo '{ labelContainerStartupUsingNode24 } ' && { nodeSetInterval ( node24ContainerPath ) } || '{ node20ContainerPath } ' --version && echo '{ labelContainerStartupUsingNode20 } ' && { nodeSetInterval ( node20ContainerPath ) } || '{ node16ContainerPath } ' --version && echo '{ labelContainerStartupUsingNode16 } ' && { nodeSetInterval ( node16ContainerPath ) } || echo '{ labelContainerStartupFailed } '";
585+ }
586+ else if ( useNode20ToStartContainer )
587+ {
588+ sleepCommand = $ "'{ node20ContainerPath } ' --version && echo '{ labelContainerStartupUsingNode20 } ' && { nodeSetInterval ( node20ContainerPath ) } || '{ node16ContainerPath } ' --version && echo '{ labelContainerStartupUsingNode16 } ' && { nodeSetInterval ( node16ContainerPath ) } || echo '{ labelContainerStartupFailed } '";
589+ }
590+ else
591+ {
592+ sleepCommand = nodeSetInterval ( nodeContainerPath ) ;
593+ }
577594 container . ContainerCommand = PlatformUtil . RunningOnWindows ? $ "cmd.exe /c call { useDoubleQuotes ( sleepCommand ) } " : $ "bash -c \" { sleepCommand } \" ";
578595 container . ResultNodePath = nodeContainerPath ;
579596 }
@@ -609,7 +626,7 @@ string useDoubleQuotes(string value)
609626
610627 executionContext . Warning ( $ "Docker container { container . ContainerId } is not in running state.") ;
611628 }
612- else if ( useAgentNode && useNode20ToStartContainer )
629+ else if ( useAgentNode && ( useNode20ToStartContainer || useNode24ToStartContainer ) )
613630 {
614631 bool containerStartupCompleted = false ;
615632 int containerStartupTimeoutInMilliseconds = 10000 ;
@@ -622,7 +639,14 @@ string useDoubleQuotes(string value)
622639
623640 foreach ( string logLine in containerLogs )
624641 {
625- if ( logLine . Contains ( labelContainerStartupUsingNode20 ) )
642+ if ( logLine . Contains ( labelContainerStartupUsingNode24 ) )
643+ {
644+ executionContext . Debug ( "Using Node 24 for container startup." ) ;
645+ containerStartupCompleted = true ;
646+ container . ResultNodePath = node24ContainerPath ;
647+ break ;
648+ }
649+ else if ( logLine . Contains ( labelContainerStartupUsingNode20 ) )
626650 {
627651 executionContext . Debug ( "Using Node 20 for container startup." ) ;
628652 containerStartupCompleted = true ;
@@ -931,8 +955,29 @@ string useDoubleQuotes(string value)
931955 if ( PlatformUtil . RunningOnLinux )
932956 {
933957 bool useNode20InUnsupportedSystem = AgentKnobs . UseNode20InUnsupportedSystem . GetValue ( executionContext ) . AsBoolean ( ) ;
958+ bool useNode24InUnsupportedSystem = AgentKnobs . UseNode24InUnsupportedSystem . GetValue ( executionContext ) . AsBoolean ( ) ;
934959
935- if ( ! useNode20InUnsupportedSystem )
960+ if ( ! useNode24InUnsupportedSystem )
961+ {
962+ var node24 = container . TranslateToContainerPath ( Path . Combine ( HostContext . GetDirectory ( WellKnownDirectory . Externals ) , NodeHandler . Node24Folder , "bin" , $ "node{ IOUtil . ExeExtension } ") ) ;
963+
964+ string node24TestCmd = $ "bash -c \" { node24 } -v\" ";
965+ List < string > node24VersionOutput = await DockerExec ( executionContext , container . ContainerId , node24TestCmd , noExceptionOnError : true ) ;
966+
967+ container . NeedsNode20Redirect = WorkerUtilities . IsCommandResultGlibcError ( executionContext , node24VersionOutput , out string node24InfoLine ) ;
968+
969+ if ( container . NeedsNode20Redirect )
970+ {
971+ PublishTelemetry (
972+ executionContext ,
973+ new Dictionary < string , string >
974+ {
975+ { "ContainerNode24to20Fallback" , container . NeedsNode20Redirect . ToString ( ) }
976+ }
977+ ) ;
978+ }
979+ }
980+ else if ( ! useNode20InUnsupportedSystem )
936981 {
937982 var node20 = container . TranslateToContainerPath ( Path . Combine ( HostContext . GetDirectory ( WellKnownDirectory . Externals ) , NodeHandler . Node20_1Folder , "bin" , $ "node{ IOUtil . ExeExtension } ") ) ;
938983
@@ -953,6 +998,19 @@ string useDoubleQuotes(string value)
953998 }
954999 }
9551000
1001+ if ( ! container . NeedsNode20Redirect )
1002+ {
1003+ container . ResultNodePath = container . TranslateToContainerPath ( Path . Combine ( HostContext . GetDirectory ( WellKnownDirectory . Externals ) , NodeHandler . Node24Folder , "bin" , $ "node{ IOUtil . ExeExtension } ") ) ;
1004+ }
1005+ else if ( ! container . NeedsNode16Redirect )
1006+ {
1007+ container . ResultNodePath = container . TranslateToContainerPath ( Path . Combine ( HostContext . GetDirectory ( WellKnownDirectory . Externals ) , NodeHandler . Node20_1Folder , "bin" , $ "node{ IOUtil . ExeExtension } ") ) ;
1008+ }
1009+ else
1010+ {
1011+ container . ResultNodePath = container . TranslateToContainerPath ( Path . Combine ( HostContext . GetDirectory ( WellKnownDirectory . Externals ) , NodeHandler . Node16Folder , "bin" , $ "node{ IOUtil . ExeExtension } ") ) ;
1012+ }
1013+
9561014 }
9571015
9581016 if ( ! string . IsNullOrEmpty ( containerUserName ) )
0 commit comments