Skip to content

Commit fe07410

Browse files
committed
Fixed issues with DockerBuild.ps1.
1 parent 55cb55a commit fe07410

File tree

4 files changed

+115
-63
lines changed

4 files changed

+115
-63
lines changed

Build.ps1

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ if (-not $Interactive -or $BuildArgs)
127127
throw "Build succeeded but output DLL '$outputDll' not found."
128128
}
129129
}
130-
130+
131131
# Run the project using dotnet exec (faster than dotnet run)
132132
if (-not $outputDll -or -not (Test-Path $outputDll))
133133
{
@@ -149,6 +149,7 @@ if (-not $Interactive -or $BuildArgs)
149149
}
150150
}
151151

152-
if ( $Interactive ) {
152+
if ($Interactive)
153+
{
153154
Write-Host "Entering interactive PowerShell." -ForegroundColor Green
154155
}

DockerBuild.ps1

Lines changed: 100 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ param(
1616
[switch]$LoadEnvFromKeyVault, # Forces loading environment variables form the key vault.
1717
[switch]$StartVsmon, # Enable the remote debugger.
1818
[string]$Script = 'Build.ps1', # The build script to be executed inside Docker.
19+
[string]$Isolation = 'process', # Docker isolation mode (process or hyperv).
20+
[string]$Memory = '8g', # Docker memory limit.
1921
[Parameter(ValueFromRemainingArguments)]
2022
[string[]]$BuildArgs # Arguments passed to `Build.ps1` within the container (or Claude prompt if -Claude is specified).
2123
)
@@ -56,7 +58,7 @@ function New-EnvJson
5658
if (-not $envVariables.ContainsKey("NUGET_PACKAGES"))
5759
{
5860
$nugetPackages = $env:NUGET_PACKAGES
59-
if ([string]::IsNullOrEmpty($nugetPackages))
61+
if ( [string]::IsNullOrEmpty($nugetPackages))
6062
{
6163
$nugetPackages = Join-Path $env:USERPROFILE ".nuget\packages"
6264
}
@@ -153,7 +155,7 @@ function New-ClaudeEnvJson
153155

154156
# Add NUGET_PACKAGES with default if not set
155157
$nugetPackages = $env:NUGET_PACKAGES
156-
if ([string]::IsNullOrEmpty($nugetPackages))
158+
if ( [string]::IsNullOrEmpty($nugetPackages))
157159
{
158160
$nugetPackages = Join-Path $env:USERPROFILE ".nuget\packages"
159161
}
@@ -206,7 +208,7 @@ function Copy-McpServerToTemp
206208
if ($targetFrameworkDirs.Count -gt 1)
207209
{
208210
Write-Warning "Multiple target framework directories found in $debugDir"
209-
Write-Warning "Using the first one: $($targetFrameworkDirs[0].Name)"
211+
Write-Warning "Using the first one: $( $targetFrameworkDirs[0].Name )"
210212
}
211213

212214
$targetFrameworkDir = $targetFrameworkDirs[0].FullName
@@ -239,7 +241,7 @@ function Copy-McpServerToTemp
239241
throw "No executable (.exe) or assembly (.dll) found in $targetFrameworkDir"
240242
}
241243

242-
Write-Host "Found MCP server executable: $($executableFile.Name)" -ForegroundColor Cyan
244+
Write-Host "Found MCP server executable: $( $executableFile.Name )" -ForegroundColor Cyan
243245

244246
# Create temporary directory using hash of source directory
245247
# This ensures the same repo always uses the same temp path (avoiding firewall prompts)
@@ -319,7 +321,7 @@ if ($Claude -and -not $NoMcp)
319321

320322
Write-Host "Saving MCP server files before cleanup..." -ForegroundColor Cyan
321323
$mcpServerSnapshot = Copy-McpServerToTemp -SourceRootDir $PSScriptRoot
322-
Write-Host "MCP server files saved to: $($mcpServerSnapshot.TempDirectory)" -ForegroundColor Cyan
324+
Write-Host "MCP server files saved to: $( $mcpServerSnapshot.TempDirectory )" -ForegroundColor Cyan
323325
}
324326
catch
325327
{
@@ -409,7 +411,7 @@ if (-not $NoNuGetCache)
409411
{
410412
# Use NUGET_PACKAGES from environment or default to user profile
411413
$nugetCacheDir = $env:NUGET_PACKAGES
412-
if ([string]::IsNullOrEmpty($nugetCacheDir))
414+
if ( [string]::IsNullOrEmpty($nugetCacheDir))
413415
{
414416
$nugetCacheDir = Join-Path $env:USERPROFILE ".nuget\packages"
415417
}
@@ -485,7 +487,7 @@ if ($parentDir -and (Test-Path $parentDir) -and ($parentDirName -like "PostSharp
485487
{
486488
Write-Host "Detected product family directory: $parentDirName" -ForegroundColor Cyan
487489
$siblingDirs = Get-ChildItem -Path $parentDir -Directory -ErrorAction SilentlyContinue |
488-
Where-Object { $_.FullName -ne $SourceDirName }
490+
Where-Object { $_.FullName -ne $SourceDirName }
489491

490492
foreach ($sibling in $siblingDirs)
491493
{
@@ -503,7 +505,7 @@ $grandparentDir = Split-Path $parentDir -Parent
503505
if ($grandparentDir -and (Test-Path $grandparentDir))
504506
{
505507
$engineeringDirs = Get-ChildItem -Path $grandparentDir -Directory -Filter "PostSharp.Engineering*" -ErrorAction SilentlyContinue |
506-
Where-Object { $_.FullName -ne $SourceDirName }
508+
Where-Object { $_.FullName -ne $SourceDirName }
507509

508510
foreach ($engDir in $engineeringDirs)
509511
{
@@ -530,7 +532,7 @@ elseif (-not $env:IS_TEAMCITY_AGENT)
530532

531533
# Handle non-C: drive letters for Docker (Windows containers only have C: by default)
532534
# We mount X:\foo to C:\X\foo in the container, then use subst to create the X: drive
533-
$driveLetters = @{}
535+
$driveLetters = @{ }
534536

535537
function Get-ContainerPath($hostPath)
536538
{
@@ -601,7 +603,7 @@ foreach ($letter in $driveLetters.Keys | Sort-Object)
601603
}
602604
if ($driveLetters.Count -gt 0)
603605
{
604-
Write-Host "Drive letter mappings for container: $($driveLetters.Keys -join ', ')" -ForegroundColor Cyan
606+
Write-Host "Drive letter mappings for container: $( $driveLetters.Keys -join ', ' )" -ForegroundColor Cyan
605607
}
606608

607609
# Create Init.g.ps1 with git configuration (safe.directory and user identity)
@@ -621,7 +623,7 @@ if (`$gitUserEmail) {
621623
622624
# Configure git safe.directory for all mounted directories
623625
`$gitDirectories = @(
624-
$(($GitDirectories | ForEach-Object { " '$_'" }) -join ",`n")
626+
$( ($GitDirectories | ForEach-Object { " '$_'" }) -join ",`n" )
625627
)
626628
627629
foreach (`$dir in `$gitDirectories) {
@@ -675,13 +677,13 @@ if (-not $NoBuildImage -and -not $existingContainerId)
675677

676678
if ($Claude)
677679
{
678-
$Dockerfile = "Dockerfile.claude"
680+
$Dockerfile = "Dockerfile.claude"
679681
}
680682
else
681683
{
682-
$Dockerfile = "Dockerfile"
684+
$Dockerfile = "Dockerfile"
683685
}
684-
686+
685687

686688
Write-Host "Building the image with tag: $ImageTag" -ForegroundColor Green
687689
Get-Content -Raw $Dockerfile | docker build -t $ImageTag --build-arg MOUNTPOINTS="$mountPointsAsString" -f - $dockerContextDirectory
@@ -716,45 +718,54 @@ if (-not $BuildImage)
716718
$mcpPortFile = $null
717719
$mcpSecret = $null
718720
$mcpTempDir = $null
719-
if (-not $NoMcp) {
720-
try {
721+
if (-not $NoMcp)
722+
{
723+
try
724+
{
721725
# Check if MCP server snapshot was saved before cleanup
722-
if (-not $mcpServerSnapshot) {
726+
if (-not $mcpServerSnapshot)
727+
{
723728
throw "MCP server files were not saved before cleanup. Cannot start MCP server."
724729
}
725730

726731
Write-Host "Starting MCP approval server..." -ForegroundColor Green
727-
$mcpPortFile = Join-Path $env:TEMP "mcp-port-$([System.Guid]::NewGuid().ToString('N').Substring(0,8)).txt"
732+
$mcpPortFile = Join-Path $env:TEMP "mcp-port-$([System.Guid]::NewGuid().ToString('N').Substring(0, 8) ).txt"
728733

729734
# Generate 128-bit (16 byte) random secret for authentication
730735
$randomBytes = New-Object byte[] 16
731736
[Security.Cryptography.RandomNumberGenerator]::Fill($randomBytes)
732-
# Use URL-safe Base64 encoding (replace / with _, + with -, remove =)
733-
$mcpSecret = [Convert]::ToBase64String($randomBytes).Replace('/', '_').Replace('+', '-').TrimEnd('=')
737+
# Use hex encoding (alphanumeric only, URL-safe and command-line safe)
738+
$mcpSecret = [BitConverter]::ToString($randomBytes).Replace('-', '').ToLower()
734739
Write-Host "Generated MCP authentication secret" -ForegroundColor Cyan
735740

736741
# Use the MCP server snapshot saved before cleanup
737742
$mcpServerInfo = $mcpServerSnapshot
738743
$mcpTempDir = $mcpServerInfo.TempDirectory
739744

740745
# Build the command to run in the new tab
741-
if ($mcpServerInfo.IsExe) {
746+
if ($mcpServerInfo.IsExe)
747+
{
742748
# Run executable directly
743-
$mcpCommand = "& '$($mcpServerInfo.ExecutablePath)' tools mcp-server --port-file '$mcpPortFile' --secret '$mcpSecret'"
744-
} else {
749+
$mcpCommand = "& '$( $mcpServerInfo.ExecutablePath )' tools mcp-server --port-file '$mcpPortFile' --secret '$mcpSecret'"
750+
}
751+
else
752+
{
745753
# Run DLL with dotnet
746-
$mcpCommand = "dotnet '$($mcpServerInfo.ExecutablePath)' tools mcp-server --port-file '$mcpPortFile' --secret '$mcpSecret'"
754+
$mcpCommand = "dotnet '$( $mcpServerInfo.ExecutablePath )' tools mcp-server --port-file '$mcpPortFile' --secret '$mcpSecret'"
747755
}
748756

749757
# Try Windows Terminal first (wt.exe), fall back to conhost
750758
$wtPath = Get-Command wt.exe -ErrorAction SilentlyContinue
751-
if ($wtPath) {
759+
if ($wtPath)
760+
{
752761
# Open new tab in current Windows Terminal window
753762
# The -w 0 option targets the current window
754763
# Use single argument string for proper escaping
755764
$wtArgString = "-w 0 new-tab --title `"MCP Approval Server`" -- pwsh -NoExit -Command `"$mcpCommand`""
756765
$mcpServerProcess = Start-Process -FilePath "wt.exe" -ArgumentList $wtArgString -PassThru
757-
} else {
766+
}
767+
else
768+
{
758769
# Fallback: start in new console window
759770
$mcpServerProcess = Start-Process -FilePath "pwsh" `
760771
-ArgumentList "-NoExit", "-Command", $mcpCommand `
@@ -764,27 +775,32 @@ if (-not $BuildImage)
764775
# Wait for port file to be written (with timeout)
765776
$timeout = 30
766777
$elapsed = 0
767-
while (-not (Test-Path $mcpPortFile) -and $elapsed -lt $timeout) {
778+
while (-not (Test-Path $mcpPortFile) -and $elapsed -lt $timeout)
779+
{
768780
Start-Sleep -Milliseconds 500
769781
$elapsed += 0.5
770782
}
771783

772-
if (-not (Test-Path $mcpPortFile)) {
784+
if (-not (Test-Path $mcpPortFile))
785+
{
773786
throw "MCP server failed to start within $timeout seconds"
774787
}
775788

776789
$mcpPort = (Get-Content $mcpPortFile -Raw).Trim()
777790
Write-Host "MCP approval server running on port $mcpPort" -ForegroundColor Cyan
778791
}
779-
catch {
792+
catch
793+
{
780794
Write-Host "ERROR: Failed to start MCP approval server: $_" -ForegroundColor Red
781795
Write-Host "Continuing without MCP server support." -ForegroundColor Yellow
782796

783797
# Clean up on error
784-
if ($mcpServerProcess -and !$mcpServerProcess.HasExited) {
798+
if ($mcpServerProcess -and !$mcpServerProcess.HasExited)
799+
{
785800
Stop-Process -Id $mcpServerProcess.Id -Force -ErrorAction SilentlyContinue
786801
}
787-
if ($mcpTempDir -and (Test-Path $mcpTempDir)) {
802+
if ($mcpTempDir -and (Test-Path $mcpTempDir))
803+
{
788804
Remove-Item $mcpTempDir -Recurse -Force -ErrorAction SilentlyContinue
789805
}
790806

@@ -793,7 +809,9 @@ if (-not $BuildImage)
793809
$mcpSecret = $null
794810
$mcpTempDir = $null
795811
}
796-
} else {
812+
}
813+
else
814+
{
797815
Write-Host "Skipping MCP approval server (-NoMcp specified)." -ForegroundColor Yellow
798816
}
799817

@@ -855,14 +873,28 @@ if (-not $BuildImage)
855873
{
856874
# Non-interactive mode with prompt - no -it flags
857875
$dockerArgs = @()
858-
$mcpArg = if ($mcpPort) { " -McpPort $mcpPort" } else { "" }
876+
$mcpArg = if ($mcpPort)
877+
{
878+
" -McpPort $mcpPort"
879+
}
880+
else
881+
{
882+
""
883+
}
859884
$inlineScript = "${substCommandsInline}& c:\Init.g.ps1; ${copyClaudeJsonScript}cd '$SourceDirName'; & .\eng\RunClaude.ps1 -Prompt `"$ClaudePrompt`"$mcpArg"
860885
}
861886
else
862887
{
863888
# Interactive mode - requires TTY
864889
$dockerArgs = @("-it")
865-
$mcpArg = if ($mcpPort) { " -McpPort $mcpPort" } else { "" }
890+
$mcpArg = if ($mcpPort)
891+
{
892+
" -McpPort $mcpPort"
893+
}
894+
else
895+
{
896+
""
897+
}
866898
$inlineScript = "${substCommandsInline}& c:\Init.g.ps1; ${copyClaudeJsonScript}cd '$SourceDirName'; & .\eng\RunClaude.ps1$mcpArg"
867899
}
868900

@@ -876,58 +908,73 @@ if (-not $BuildImage)
876908
)
877909

878910
# Pass MCP secret to container if MCP server is running
879-
if ($mcpSecret) {
911+
if ($mcpSecret)
912+
{
880913
$envArgs += @("-e", "MCP_APPROVAL_SERVER_TOKEN=$mcpSecret")
881914
}
882915

883-
try {
916+
try
917+
{
884918
# Start new container with docker run
885-
Write-Host "Executing: docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -e HOME=$containerUserProfile -e USERPROFILE=$containerUserProfile -w $ContainerSourceDir $ImageTag `"$pwshPath`" -Command `"$inlineScript`"" -ForegroundColor Cyan
886-
docker run --rm --memory=12g $dockerArgs @volumeArgs @envArgs -w $ContainerSourceDir $ImageTag $pwshPath -Command $inlineScript
919+
Write-Host "Executing: docker run --rm --memory=$Memory --isolation=$Isolation $dockerArgsAsString $VolumeMappingsAsString -e HOME=$containerUserProfile -e USERPROFILE=$containerUserProfile -w $ContainerSourceDir $ImageTag `"$pwshPath`" -Command `"$inlineScript`"" -ForegroundColor Cyan
920+
docker run --rm --memory=$Memory --isolation=$Isolation $dockerArgs @volumeArgs @envArgs -w $ContainerSourceDir $ImageTag $pwshPath -Command $inlineScript
887921
$dockerExitCode = $LASTEXITCODE
888922
}
889-
finally {
923+
finally
924+
{
890925
# Cleanup MCP server after container exits (only if it was started)
891-
if ($mcpPort) {
926+
if ($mcpPort)
927+
{
892928
Write-Host "Stopping MCP approval server..." -ForegroundColor Cyan
893929

894930
# Find the process listening on the MCP port and kill it
895-
try {
931+
try
932+
{
896933
# Find PID using netstat
897934
$netstatOutput = netstat -ano | Select-String ":$mcpPort\s" | Select-Object -First 1
898-
if ($netstatOutput) {
935+
if ($netstatOutput)
936+
{
899937
$parts = $netstatOutput.Line.Trim() -split '\s+'
900938
$mcpPid = $parts[-1]
901-
if ($mcpPid -and $mcpPid -match '^\d+$') {
939+
if ($mcpPid -and $mcpPid -match '^\d+$')
940+
{
902941
Stop-Process -Id $mcpPid -Force -ErrorAction SilentlyContinue
903942
Write-Host "Stopped MCP server process (PID: $mcpPid)" -ForegroundColor Cyan
904943
}
905944
}
906-
} catch {
945+
}
946+
catch
947+
{
907948
Write-Host "Could not stop MCP server via port lookup: $_" -ForegroundColor Yellow
908949
}
909950

910951
# Fallback: try to find by command line
911952
$mcpProcesses = Get-Process -Name pwsh, dotnet -ErrorAction SilentlyContinue |
912-
Where-Object { $_.CommandLine -like "*mcp-server*" }
953+
Where-Object { $_.CommandLine -like "*mcp-server*" }
913954

914-
foreach ($proc in $mcpProcesses) {
915-
try {
955+
foreach ($proc in $mcpProcesses)
956+
{
957+
try
958+
{
916959
Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue
917-
Write-Host "Stopped MCP server process $($proc.Id)" -ForegroundColor Cyan
918-
} catch {
960+
Write-Host "Stopped MCP server process $( $proc.Id )" -ForegroundColor Cyan
961+
}
962+
catch
963+
{
919964
# Process may have already exited
920965
}
921966
}
922967
}
923968

924969
# Clean up port file
925-
if ($mcpPortFile -and (Test-Path $mcpPortFile)) {
970+
if ($mcpPortFile -and (Test-Path $mcpPortFile))
971+
{
926972
Remove-Item $mcpPortFile -ErrorAction SilentlyContinue
927973
}
928974

929975
# Clean up temporary MCP server directory
930-
if ($mcpTempDir -and (Test-Path $mcpTempDir)) {
976+
if ($mcpTempDir -and (Test-Path $mcpTempDir))
977+
{
931978
Write-Host "Cleaning up temporary MCP server directory: $mcpTempDir" -ForegroundColor Cyan
932979
Remove-Item $mcpTempDir -Recurse -Force -ErrorAction SilentlyContinue
933980
}
@@ -992,8 +1039,8 @@ if (-not $BuildImage)
9921039
else
9931040
{
9941041
# Start new container with docker run
995-
Write-Host "Executing: ``docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -w $ContainerSourceDir $ImageTag `"$pwshPath`" $pwshArgs -Command `"$inlineScript`"" -ForegroundColor Cyan
996-
docker run --rm --memory=12g $dockerArgs @volumeArgs -w $ContainerSourceDir $ImageTag $pwshPath $pwshArgs -Command $inlineScript
1042+
Write-Host "Executing: ``docker run --rm --memory=$Memory --isolation=$Isolation $dockerArgsAsString $VolumeMappingsAsString -w $ContainerSourceDir $ImageTag `"$pwshPath`" $pwshArgs -Command `"$inlineScript`"" -ForegroundColor Cyan
1043+
docker run --rm --memory=$Memory --isolation=$Isolation $dockerArgs @volumeArgs -w $ContainerSourceDir $ImageTag $pwshPath $pwshArgs -Command $inlineScript
9971044
}
9981045

9991046
if ($LASTEXITCODE -ne 0)

0 commit comments

Comments
 (0)