@@ -1087,6 +1087,18 @@ else
10871087# Run the build within the container
10881088if (-not $BuildImage )
10891089{
1090+ # Common setup for both Claude and normal build modes
1091+ $pwshPath = if ($IsUnix ) { ' /usr/bin/pwsh' } else { ' C:\Program Files\PowerShell\7\pwsh.exe' }
1092+ $initCall = if (-not $NoInit ) { " & c:\docker-context\Init.g.ps1; " } else { " " }
1093+
1094+ # Convert volume mappings to docker args format (interleave "-v" flags)
1095+ $volumeArgs = @ ()
1096+ foreach ($mapping in $VolumeMappings )
1097+ {
1098+ $volumeArgs += @ (" -v" , $mapping )
1099+ }
1100+ $VolumeMappingsAsString = ($VolumeMappings | ForEach-Object { " -v $_ " }) -join " "
1101+
10901102 if ($Claude )
10911103 {
10921104 # Start MCP approval server on host with dynamic port in new terminal tab
@@ -1199,13 +1211,6 @@ if (-not $BuildImage)
11991211 # Container will have its own Claude profile (no mount, no copy from host)
12001212 $hostUserProfile = if ($IsUnix ) { $env: HOME } else { $env: USERPROFILE }
12011213
1202- # Convert volume mappings to docker args format (interleave "-v" flags)
1203- $volumeArgs = @ ()
1204- foreach ($mapping in $VolumeMappings )
1205- {
1206- $volumeArgs += @ (" -v" , $mapping )
1207- }
1208-
12091214 # Mount Claude sessions directory to preserve history (but not plugins)
12101215 $hostClaudeSessions = Join-Path $hostUserProfile " .claude\.sessions"
12111216 $containerClaudeSessions = Join-Path $containerUserProfile " .claude\.sessions"
@@ -1226,8 +1231,6 @@ if (-not $BuildImage)
12261231 $volumeArgs += @ (" -v" , " ${hostClaudeProjects} :${containerClaudeProjects} " )
12271232 Write-Host " Mounting Claude projects directory: $hostClaudeProjects " - ForegroundColor Cyan
12281233
1229- $VolumeMappingsAsString = ($VolumeMappings | ForEach-Object { " -v $_ " }) -join " "
1230-
12311234 # Extract Claude prompt from remaining arguments if present
12321235 # Usage: -Claude for interactive, -Claude "prompt" for non-interactive
12331236 $ClaudePrompt = $null
@@ -1237,9 +1240,6 @@ if (-not $BuildImage)
12371240 }
12381241
12391242 # Build inline script: subst drives, copy claude.json, cd to source, run Claude
1240- # Conditionally include Init.g.ps1 call
1241- $initCall = if (-not $NoInit ) { " & c:\docker-context\Init.g.ps1; " } else { " " }
1242-
12431243 if ($ClaudePrompt )
12441244 {
12451245 # Non-interactive mode with prompt - no -it flags
@@ -1269,9 +1269,6 @@ if (-not $BuildImage)
12691269 $inlineScript = " ${substCommandsInline}${initCall} cd '$SourceDirName '; & .\eng\RunClaude.ps1$mcpArg "
12701270 }
12711271
1272- $dockerArgsAsString = $dockerArgs -join " "
1273- $pwshPath = if ($IsUnix ) { ' /usr/bin/pwsh' } else { ' C:\Program Files\PowerShell\7\pwsh.exe' }
1274-
12751272 # Environment variables to pass to container
12761273 $envArgs = @ ()
12771274
@@ -1281,21 +1278,91 @@ if (-not $BuildImage)
12811278 $envArgs += @ (" -e" , " MCP_APPROVAL_SERVER_TOKEN=$mcpSecret " )
12821279 }
12831280
1284- try
1281+ # No pwshArgs for Claude mode
1282+ $pwshArgs = $null
1283+ $needsMcpCleanup = $true
1284+ }
1285+ else
1286+ {
1287+ # Run standard build mode
1288+ # Delete now and not in the container because it's much faster and lock error messages are more relevant.
1289+ Write-Host " Building the product in the container." - ForegroundColor Green
1290+
1291+ # Prepare Build.ps1 arguments
1292+ if ($StartVsmon )
12851293 {
1286- # Start new container with docker run
1287- $envArgsAsString = ($envArgs -join " " )
1288- Write-Host " Executing: docker run --rm --memory=$Memory --cpus=$Cpus $isolationArg $dockerArgsAsString $VolumeMappingsAsString $envArgsAsString -w $ContainerSourceDir $ImageTag `" $pwshPath `" -Command `" $inlineScript `" " - ForegroundColor Cyan
1294+ $BuildArgs = @ (" -StartVsmon" ) + $BuildArgs
1295+ }
12891296
1290- # Build docker command with proper argument handling (avoid empty strings)
1291- $dockerCmd = @ (' run' , ' --rm' , " --memory=$Memory " , " --cpus=$Cpus " )
1292- if ($isolationArg ) { $dockerCmd += $isolationArg }
1293- $dockerCmd += $dockerArgs
1294- $dockerCmd += $volumeArgs
1295- $dockerCmd += $envArgs
1296- $dockerCmd += @ (' -w' , $ContainerSourceDir , $ImageTag , $pwshPath , ' -Command' , $inlineScript )
1297+ if ($Interactive )
1298+ {
1299+ $pwshArgs = " -NoExit"
1300+ $BuildArgs = @ (" -Interactive" ) + $BuildArgs
1301+ $dockerArgs = @ (" -it" )
1302+ $pwshExitCommand = " "
1303+ }
1304+ else
1305+ {
1306+ $pwshArgs = " -NonInteractive"
1307+ $dockerArgs = @ ()
1308+ $pwshExitCommand = " exit `$ LASTEXITCODE`;"
1309+ }
12971310
1298- & docker @dockerCmd
1311+ $buildArgsString = $BuildArgs -join " "
1312+
1313+ # Build inline script: subst drives, run init, cd to source, run build
1314+ # Get full script path (combine with container source dir if relative)
1315+ if ([System.IO.Path ]::IsPathRooted($Script ))
1316+ {
1317+ $scriptFullPath = $Script
1318+ }
1319+ else
1320+ {
1321+ $scriptFullPath = Join-Path $ContainerSourceDir $Script
1322+ }
1323+ $scriptInvocation = " & '$scriptFullPath '"
1324+ $inlineScript = " ${substCommandsInline}${initCall} cd '$SourceDirName '; $scriptInvocation $buildArgsString ; $pwshExitCommand "
1325+
1326+ # No environment args for normal build
1327+ $envArgs = @ ()
1328+ $needsMcpCleanup = $false
1329+ }
1330+
1331+ # Common docker execution for both modes
1332+ $dockerArgsAsString = $dockerArgs -join " "
1333+ $envArgsAsString = ($envArgs -join " " )
1334+
1335+ # Wrap in try/finally only if MCP cleanup is needed
1336+ if ($needsMcpCleanup )
1337+ {
1338+ try
1339+ {
1340+ # Execute docker command
1341+ if ($existingContainerId )
1342+ {
1343+ # Reuse existing container with docker exec
1344+ Write-Host " Executing: `` docker exec $existingContainerId $dockerArgsAsString -w $ContainerSourceDir $ImageTag `" $pwshPath `" $pwshArgs -Command `" $inlineScript `" " - ForegroundColor Cyan
1345+ docker exec $dockerArgs - w $ContainerSourceDir $existingContainerId $pwshPath $pwshArgs - Command $inlineScript
1346+ }
1347+ else
1348+ {
1349+ # Start new container with docker run
1350+ Write-Host " Executing: docker run --rm --memory=$Memory --cpus=$Cpus $isolationArg $dockerArgsAsString $VolumeMappingsAsString $envArgsAsString -w $ContainerSourceDir $ImageTag `" $pwshPath `" $pwshArgs -Command `" $inlineScript `" " - ForegroundColor Cyan
1351+
1352+ # Build docker command with proper argument handling (avoid empty strings)
1353+ $dockerCmd = @ (' run' , ' --rm' , " --memory=$Memory " , " --cpus=$Cpus " )
1354+ if ($isolationArg ) { $dockerCmd += $isolationArg }
1355+ $dockerCmd += $dockerArgs
1356+ $dockerCmd += $volumeArgs
1357+ $dockerCmd += $envArgs
1358+ if ($pwshArgs ) {
1359+ $dockerCmd += @ (' -w' , $ContainerSourceDir , $ImageTag , $pwshPath , $pwshArgs , ' -Command' , $inlineScript )
1360+ } else {
1361+ $dockerCmd += @ (' -w' , $ContainerSourceDir , $ImageTag , $pwshPath , ' -Command' , $inlineScript )
1362+ }
1363+
1364+ & docker @dockerCmd
1365+ }
12991366 $dockerExitCode = $LASTEXITCODE
13001367 }
13011368 finally
@@ -1357,96 +1424,43 @@ if (-not $BuildImage)
13571424 Remove-Item $mcpTempDir - Recurse - Force - ErrorAction SilentlyContinue
13581425 }
13591426 }
1360-
1361- if ($dockerExitCode -ne 0 )
1362- {
1363- Write-Host " Docker run (Claude) failed with exit code $dockerExitCode " - ForegroundColor Red
1364- exit $dockerExitCode
1365- }
13661427 }
13671428 else
13681429 {
1369- # Run standard build mode
1370- # Delete now and not in the container because it's much faster and lock error messages are more relevant.
1371- Write-Host " Building the product in the container." - ForegroundColor Green
1372-
1373- # Prepare Build.ps1 arguments
1374- if ($StartVsmon )
1375- {
1376- $BuildArgs = @ (" -StartVsmon" ) + $BuildArgs
1377- }
1378-
1379- if ($Interactive )
1380- {
1381- $pwshArgs = " -NoExit"
1382- $BuildArgs = @ (" -Interactive" ) + $BuildArgs
1383- $dockerArgs = @ (" -it" )
1384- $pwshExitCommand = " "
1385- }
1386- else
1387- {
1388- $pwshArgs = " -NonInteractive"
1389- $dockerArgs = @ ()
1390- $pwshExitCommand = " exit `$ LASTEXITCODE`;"
1391- }
1392-
1393- $buildArgsString = $BuildArgs -join " "
1394-
1395- # Convert volume mappings to docker args format (interleave "-v" flags)
1396- $volumeArgs = @ ()
1397- foreach ($mapping in $VolumeMappings )
1398- {
1399- $volumeArgs += @ (" -v" , $mapping )
1400- }
1401- $VolumeMappingsAsString = ($VolumeMappings | ForEach-Object { " -v $_ " }) -join " "
1402- $dockerArgsAsString = $dockerArgs -join " "
1403-
1404- # Build inline script: subst drives, run init, cd to source, run build
1405- # Conditionally include Init.g.ps1 call
1406- $initCall = if (-not $NoInit ) { " & c:\docker-context\Init.g.ps1; " } else { " " }
1407-
1408- # Get full script path (combine with container source dir if relative)
1409- if ([System.IO.Path ]::IsPathRooted($Script ))
1410- {
1411- $scriptFullPath = $Script
1412- }
1413- else
1414- {
1415- $scriptFullPath = Join-Path $ContainerSourceDir $Script
1416- }
1417- $scriptInvocation = " & '$scriptFullPath '"
1418- $inlineScript = " ${substCommandsInline}${initCall} cd '$SourceDirName '; $scriptInvocation $buildArgsString ; $pwshExitCommand "
1419-
1420- $pwshPath = if ($IsUnix ) { ' /usr/bin/pwsh' } else { ' C:\Program Files\PowerShell\7\pwsh.exe' }
1421-
1422- # Build docker command arguments
1430+ # Execute docker command (no MCP cleanup needed)
14231431 if ($existingContainerId )
14241432 {
14251433 # Reuse existing container with docker exec
14261434 Write-Host " Executing: `` docker exec $existingContainerId $dockerArgsAsString -w $ContainerSourceDir $ImageTag `" $pwshPath `" $pwshArgs -Command `" $inlineScript `" " - ForegroundColor Cyan
14271435 docker exec $dockerArgs - w $ContainerSourceDir $existingContainerId $pwshPath $pwshArgs - Command $inlineScript
1428-
14291436 }
14301437 else
14311438 {
14321439 # Start new container with docker run
1433- Write-Host " Executing: `` docker run --rm --memory=$Memory --cpus=$Cpus $isolationArg $dockerArgsAsString $VolumeMappingsAsString -w $ContainerSourceDir $ImageTag `" $pwshPath `" $pwshArgs -Command `" $inlineScript `" " - ForegroundColor Cyan
1440+ Write-Host " Executing: `` docker run --rm --memory=$Memory --cpus=$Cpus $isolationArg $dockerArgsAsString $VolumeMappingsAsString $envArgsAsString -w $ContainerSourceDir $ImageTag `" $pwshPath `" $pwshArgs -Command `" $inlineScript `" " - ForegroundColor Cyan
14341441
14351442 # Build docker command with proper argument handling (avoid empty strings)
14361443 $dockerCmd = @ (' run' , ' --rm' , " --memory=$Memory " , " --cpus=$Cpus " )
14371444 if ($isolationArg ) { $dockerCmd += $isolationArg }
14381445 $dockerCmd += $dockerArgs
14391446 $dockerCmd += $volumeArgs
1440- $dockerCmd += @ (' -w' , $ContainerSourceDir , $ImageTag , $pwshPath , $pwshArgs , ' -Command' , $inlineScript )
1447+ $dockerCmd += $envArgs
1448+ if ($pwshArgs ) {
1449+ $dockerCmd += @ (' -w' , $ContainerSourceDir , $ImageTag , $pwshPath , $pwshArgs , ' -Command' , $inlineScript )
1450+ } else {
1451+ $dockerCmd += @ (' -w' , $ContainerSourceDir , $ImageTag , $pwshPath , ' -Command' , $inlineScript )
1452+ }
14411453
14421454 & docker @dockerCmd
14431455 }
1456+ $dockerExitCode = $LASTEXITCODE
1457+ }
14441458
1445- if ( $LASTEXITCODE -ne 0 )
1446- {
1447- Write-Host " Container failed with exit code $LASTEXITCODE " - ForegroundColor Red
1448- exit $LASTEXITCODE
1449- }
1459+ # Check exit code
1460+ if ( $dockerExitCode -ne 0 )
1461+ {
1462+ Write-Host " Container failed with exit code $dockerExitCode " - ForegroundColor Red
1463+ exit $dockerExitCode
14501464 }
14511465}
14521466else
0 commit comments