99 [switch ]$NoClean , # Does not clean up.
1010 [switch ]$NoNuGetCache , # Does not mount the host nuget cache in the container.
1111 [switch ]$KeepEnv , # Does not override the env.g.json file.
12+ [switch ]$Claude , # Run Claude CLI instead of Build.ps1.
13+ [string ]$ClaudePrompt , # Optional prompt for Claude (non-interactive mode).
1214 [string ]$ImageName , # Image name (defaults to a name based on the directory).
1315 [string ]$BuildAgentPath = ' C:\BuildAgent' ,
1416 [switch ]$LoadEnvFromKeyVault , # Forces loading environment variables form the key vault.
@@ -93,6 +95,51 @@ function New-EnvJson
9395 return $jsonPath
9496}
9597
98+ # Function to create Claude-specific env.g.json with filtered/renamed variables
99+ function New-ClaudeEnvJson
100+ {
101+ $claudeEnv = @ { }
102+
103+ # CLAUDE_GITHUB_TOKEN -> GITHUB_TOKEN (renamed)
104+ if ($env: CLAUDE_GITHUB_TOKEN )
105+ {
106+ $claudeEnv [" GITHUB_TOKEN" ] = $env: CLAUDE_GITHUB_TOKEN
107+ }
108+
109+ # Preserved variables
110+ if ($env: ANTHROPIC_API_KEY )
111+ {
112+ $claudeEnv [" ANTHROPIC_API_KEY" ] = $env: ANTHROPIC_API_KEY
113+ }
114+ if ($env: IS_POSTSHARP_OWNED )
115+ {
116+ $claudeEnv [" IS_POSTSHARP_OWNED" ] = $env: IS_POSTSHARP_OWNED
117+ }
118+ if ($env: IS_TEAMCITY_AGENT )
119+ {
120+ $claudeEnv [" IS_TEAMCITY_AGENT" ] = $env: IS_TEAMCITY_AGENT
121+ }
122+
123+ # Convert to JSON and save
124+ $jsonPath = Join-Path $dockerContextDirectory " env.g.json"
125+
126+ # Write a test JSON file with GUID first
127+ @ { guid = [System.Guid ]::NewGuid().ToString() } | ConvertTo-Json | Set-Content - Path $jsonPath - Encoding UTF8
128+
129+ # Check if secrets file is tracked by git
130+ $gitStatus = git status -- porcelain $jsonPath 2> $null
131+ if ($LASTEXITCODE -eq 0 -and -not [string ]::IsNullOrWhiteSpace($gitStatus ))
132+ {
133+ Write-Error " Secrets file '$jsonPath ' is tracked by git. Please add it to .gitignore first."
134+ exit 1
135+ }
136+
137+ $claudeEnv | ConvertTo-Json - Depth 10 | Set-Content - Path $jsonPath - Encoding UTF8
138+ Write-Host " Created Claude secrets file: $jsonPath " - ForegroundColor Cyan
139+
140+ return $jsonPath
141+ }
142+
96143if ($env: RUNNING_IN_DOCKER )
97144{
98145 Write-Error " Already running in Docker."
@@ -139,29 +186,38 @@ Write-Host "Preparing context and mounts." -ForegroundColor Green
139186# Create secrets JSON file.
140187if (-not $KeepEnv )
141188{
142- if (-not $ env: ENG_USERNAME )
189+ if ($Claude )
143190 {
144- $env: ENG_USERNAME = $env: USERNAME
191+ # Use Claude-specific environment variables (filtered and renamed)
192+ New-ClaudeEnvJson
145193 }
146-
147- # Add git identity to environment
148- if ($env: IS_TEAMCITY_AGENT )
194+ else
149195 {
150- # On TeamCity agents, check if the environment variables are set.
151- if (-not $env: GIT_USER_EMAIL -or -not $ env: GIT_USER_NAME )
196+ # Use standard build environment variables
197+ if (-not $env: ENG_USERNAME )
152198 {
153- Write-Error " On TeamCity agents, the GIT_USER_EMAIL and GIT_USER_NAME environment variables must be set."
154- exit 1
199+ $env: ENG_USERNAME = $env: USERNAME
200+ }
201+
202+ # Add git identity to environment
203+ if ($env: IS_TEAMCITY_AGENT )
204+ {
205+ # On TeamCity agents, check if the environment variables are set.
206+ if (-not $env: GIT_USER_EMAIL -or -not $env: GIT_USER_NAME )
207+ {
208+ Write-Error " On TeamCity agents, the GIT_USER_EMAIL and GIT_USER_NAME environment variables must be set."
209+ exit 1
210+ }
211+ }
212+ else
213+ {
214+ # On developer machines, use the current git user.
215+ $env: GIT_USER_EMAIL = git config -- global user.email
216+ $env: GIT_USER_NAME = git config -- global user.name
155217 }
156- }
157- else
158- {
159- # On developer machines, use the current git user.
160- $env: GIT_USER_EMAIL = git config -- global user.email
161- $env: GIT_USER_NAME = git config -- global user.name
162- }
163218
164- New-EnvJson - EnvironmentVariableList $EnvironmentVariables
219+ New-EnvJson - EnvironmentVariableList $EnvironmentVariables
220+ }
165221}
166222
167223# Get the source directory name from $PSScriptRoot
@@ -179,9 +235,9 @@ if (-not (Test-Path $dockerContextDirectory))
179235
180236
181237# Prepare volume mappings
182- $VolumeMappings = @ (" -v" , " ${SourceDirName} :${SourceDirName} " )
183- $MountPoints = @ ($SourceDirName , " c:\packages" )
184- $GitDirectories = @ ($SourceDirName )
238+ $VolumeMappings = @ (" -v" , " ${SourceDirName} :${SourceDirName} " )
239+ $MountPoints = @ ($SourceDirName , " c:\packages" )
240+ $GitDirectories = @ ($SourceDirName )
185241
186242# Define static Git system directory for mapping. This used by Teamcity as an LFS parent repo.
187243$gitSystemDir = " $BuildAgentPath \system\git"
@@ -281,60 +337,89 @@ docker ps -q --filter "ancestor=$ImageTag" | ForEach-Object {
281337# Building the image.
282338if (-not $NoBuildImage )
283339{
284- Write-Host " Building the image with tag: $ImageTag " - ForegroundColor Green
340+ Write-Host " Building the base image with tag: $ImageTag " - ForegroundColor Green
285341 Get-Content - Raw Dockerfile | docker build - t $ImageTag -- build-arg GITDIRS= " $gitDirectoriesAsString " -- build-arg MOUNTPOINTS= " $mountPointsAsString " -f - $dockerContextDirectory
286342 if ($LASTEXITCODE -ne 0 )
287343 {
288344 Write-Host " Docker build failed with exit code $LASTEXITCODE " - ForegroundColor Red
289345 exit $LASTEXITCODE
290346 }
347+
348+ # Build Claude image if requested
349+ if ($Claude )
350+ {
351+ $ClaudeImageTag = " $ImageTag -claude"
352+ Write-Host " Building the Claude image with tag: $ClaudeImageTag " - ForegroundColor Green
353+
354+ if (-not (Test-Path " Dockerfile.claude" ))
355+ {
356+ Write-Error " Dockerfile.claude not found. Make sure generate-scripts was run with a NodeJs component."
357+ exit 1
358+ }
359+
360+ Get-Content - Raw Dockerfile.claude | docker build - t $ClaudeImageTag -- build-arg BASE_IMAGE= " $ImageTag " -f - $dockerContextDirectory
361+ if ($LASTEXITCODE -ne 0 )
362+ {
363+ Write-Host " Docker build (Claude) failed with exit code $LASTEXITCODE " - ForegroundColor Red
364+ exit $LASTEXITCODE
365+ }
366+
367+ # Use Claude image for the run
368+ $ImageTag = $ClaudeImageTag
369+ }
291370}
292371else
293372{
294373 Write-Host " Skipping image build (-NoBuildImage specified)." - ForegroundColor Yellow
374+
375+ # If Claude mode and skipping build, use the Claude image tag
376+ if ($Claude )
377+ {
378+ $ImageTag = " $ImageTag -claude"
379+ }
295380}
296381
297382
298383# Run the build within the container
299384if (-not $BuildImage )
300385{
301386
302- # Delete now and not in the container because it's much faster and lock error messages are more relevant.
303- Write-Host " Building the product in the container." - ForegroundColor Green
387+ # Delete now and not in the container because it's much faster and lock error messages are more relevant.
388+ Write-Host " Building the product in the container." - ForegroundColor Green
304389
305- # Prepare Build.ps1 arguments
306- if ($StartVsmon )
307- {
308- $BuildArgs = @ (" -StartVsmon" ) + $BuildArgs
309- }
390+ # Prepare Build.ps1 arguments
391+ if ($StartVsmon )
392+ {
393+ $BuildArgs = @ (" -StartVsmon" ) + $BuildArgs
394+ }
310395
311- if ($Interactive )
312- {
313- $pwshArgs = " -NoExit"
314- $BuildArgs = @ (" -Interactive" ) + $BuildArgs
315- $dockerArgs = @ (" -it" )
316- $pwshExitCommand = " "
317- }
318- else
319- {
320- $pwshArgs = " -NonInteractive"
321- $dockerArgs = @ ()
396+ if ($Interactive )
397+ {
398+ $pwshArgs = " -NoExit"
399+ $BuildArgs = @ (" -Interactive" ) + $BuildArgs
400+ $dockerArgs = @ (" -it" )
401+ $pwshExitCommand = " "
402+ }
403+ else
404+ {
405+ $pwshArgs = " -NonInteractive"
406+ $dockerArgs = @ ()
322407 $pwshExitCommand = " exit `$ LASTEXITCODE`;"
323- }
408+ }
324409
325- $buildArgsString = $BuildArgs -join " "
326- $VolumeMappingsAsString = $VolumeMappings -join " "
327- $dockerArgsAsString = $dockerArgs -join " "
410+ $buildArgsString = $BuildArgs -join " "
411+ $VolumeMappingsAsString = $VolumeMappings -join " "
412+ $dockerArgsAsString = $dockerArgs -join " "
328413
329414
330415 Write-Host " Executing: `` docker run --rm --memory=12g $dockerArgsAsString $VolumeMappingsAsString -w $SourceDirName $ImageTag pwsh $pwshArgs -Command `" & .\$Script $buildArgsString `; $pwshExitCommand `" " - ForegroundColor Cyan
331416
332417 docker run -- rm -- memory= 12g $dockerArgs @VolumeMappings - w $SourceDirName @dockerArgs $ImageTag pwsh $pwshArgs - Command " & .\$Script $buildArgsString `; $pwshExitCommand ; "
333- if ($LASTEXITCODE -ne 0 )
334- {
335- Write-Host " Docker run (build) failed with exit code $LASTEXITCODE " - ForegroundColor Red
336- exit $LASTEXITCODE
337- }
418+ if ($LASTEXITCODE -ne 0 )
419+ {
420+ Write-Host " Docker run (build) failed with exit code $LASTEXITCODE " - ForegroundColor Red
421+ exit $LASTEXITCODE
422+ }
338423
339424}
340425else
0 commit comments