Skip to content

Commit 5b4aae9

Browse files
gfraiteurclaude
andcommitted
Refactor DockerBuild.ps1 to eliminate redundancy between Claude and normal build modes.
Moved common setup before conditional blocks: - PowerShell path detection ($pwshPath) - Init.g.ps1 call setup ($initCall) - Volume args construction from VolumeMappings - Volume mappings string for display Conditional blocks now only handle mode-specific parameters: - Claude mode: MCP server setup, Claude-specific volume mounts, RunClaude.ps1 script - Normal mode: Build.ps1 arguments and script path resolution Single docker execution section after conditional blocks: - Handles both docker exec (existing container) and docker run (new container) - Properly wraps in try/finally only when MCP cleanup is needed - Unified exit code handling Result: Eliminated ~100 lines of duplicate code while maintaining all functionality. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent b725a5e commit 5b4aae9

File tree

3 files changed

+111
-96
lines changed

3 files changed

+111
-96
lines changed

src/PostSharp.Engineering.BuildTools/Dependencies/Model/DependenciesConfigurationFile.cs renamed to src/PostSharp.Engineering.BuildTools/Build/Files/DependenciesConfigurationFile.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) SharpCrafters s.r.o. See the LICENSE.md file in the root directory of this repository root for details.
22

33
using PostSharp.Engineering.BuildTools.Build;
4+
using PostSharp.Engineering.BuildTools.Build.Files;
45
using PostSharp.Engineering.BuildTools.Build.MSBuild;
56
using PostSharp.Engineering.BuildTools.Utilities;
67
using Spectre.Console;

src/PostSharp.Engineering.BuildTools/Dependencies/Model/VersionFile.cs renamed to src/PostSharp.Engineering.BuildTools/Build/Files/VersionFile.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
namespace PostSharp.Engineering.BuildTools.Dependencies.Model;
1616

1717
/// <summary>
18-
/// Represents then information of <c>Versions.props</c>.
18+
/// Represents then information of <c>Versions.Debug.g.props</c>.
1919
/// </summary>
2020
public class VersionFile
2121
{

src/PostSharp.Engineering.BuildTools/Resources/DockerBuild.ps1

Lines changed: 109 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,18 @@ else
10871087
# Run the build within the container
10881088
if (-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
}
14521466
else

0 commit comments

Comments
 (0)