From c6e12c1764a27145885e511b63b7bd25415b7e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6tz=20Jensen?= Date: Thu, 9 Jul 2026 22:39:51 +0200 Subject: [PATCH 1/2] Add fscCompileNugetForce setting and fix NuGet cache size check - Add fscCompileNugetForce setting (default $true) to keep the original force-download behaviour; set $false to reuse already downloaded packages and keep them during cleanup for faster repeated local builds. - Drive the compiler NuGet downloads and packages-folder cleanup off the new setting in Invoke-FSCCompile. - Fix Get-FSCPSNuget size comparison: read the blob size from the PSFSize '.Size' property instead of '.Length' (which returned 1 and forced a re-download every run), and log the correct local size. Co-Authored-By: Claude Opus 4.8 --- fscps.tools/functions/get-fscpsnuget.ps1 | 8 ++++++-- .../internal/configurations/configuration.ps1 | 1 + .../internal/functions/invoke-fsccompile.ps1 | 20 ++++++++++++++----- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/fscps.tools/functions/get-fscpsnuget.ps1 b/fscps.tools/functions/get-fscpsnuget.ps1 index 63a40ae..d01af99 100644 --- a/fscps.tools/functions/get-fscpsnuget.ps1 +++ b/fscps.tools/functions/get-fscpsnuget.ps1 @@ -164,10 +164,14 @@ function Get-FSCPSNuget { if(!$download) { $blobFile = Get-FSCPSAzureStorageFile -Name $packageName - $blobSize = $blobFile.Length + # Get-FSCPSAzureStorageFile exposes the blob size as a PSFSize on the 'Size' + # property (the underlying 'Length' is renamed). Reading '.Length' here returns + # the PowerShell scalar length (1), which never matches the real file size and + # forced a re-download every run. Cast the PSFSize to bytes for a correct compare. + $blobSize = [long]$blobFile.Size $localSize = (Get-Item $destinationNugetFilePath).length Write-PSFMessage -Level Verbose -Message "BlobSize is: $blobSize" - Write-PSFMessage -Level Verbose -Message "LocalSize is: $blobSize" + Write-PSFMessage -Level Verbose -Message "LocalSize is: $localSize" $download = $blobSize -ne $localSize } diff --git a/fscps.tools/internal/configurations/configuration.ps1 b/fscps.tools/internal/configurations/configuration.ps1 index 293b156..8040daf 100644 --- a/fscps.tools/internal/configurations/configuration.ps1 +++ b/fscps.tools/internal/configurations/configuration.ps1 @@ -49,6 +49,7 @@ Set-PSFConfig -FullName 'fscps.tools.settings.all.buildVersion' -Value '' -Initi Set-PSFConfig -FullName 'fscps.tools.settings.all.solutionName' -Value '' -Initialize -Description '' Set-PSFConfig -FullName 'fscps.tools.settings.all.enableBuildCaching' -Value $false -Initialize -Description '' Set-PSFConfig -FullName 'fscps.tools.settings.all.cleanupAfterBuild' -Value $true -Initialize -Description 'Cleanup build cache after build' +Set-PSFConfig -FullName 'fscps.tools.settings.all.fscCompileNugetForce' -Value $true -Initialize -Description 'Force a fresh download of the D365FSC compiler NuGet packages on every compile (default behaviour). Set to $false to reuse already downloaded packages and keep them during cleanup, for faster repeated local builds.' Set-PSFConfig -FullName 'fscps.tools.settings.all.msBuildParameters' -Value '' -Initialize -Description 'Additional MSBuild command-line arguments appended to the compile step (e.g. /MaxCpuCount:16 /p:BuildInParallel=true).' Set-PSFConfig -FullName 'fscps.tools.settings.all.exportModel' -Value $false -Initialize -Description 'Option to generate axmodel file. IMPORTANT!!! generatePackages option should be set to True' Set-PSFConfig -FullName 'fscps.tools.settings.all.uploadPackageToLCS' -Value $false -Initialize -Description 'Option to upload the generated package to the LCS after the build and generate process. IMPORTANT!!! generatePackages option should be set to True' diff --git a/fscps.tools/internal/functions/invoke-fsccompile.ps1 b/fscps.tools/internal/functions/invoke-fsccompile.ps1 index d8c2dd5..33ec4f2 100644 --- a/fscps.tools/internal/functions/invoke-fsccompile.ps1 +++ b/fscps.tools/internal/functions/invoke-fsccompile.ps1 @@ -100,6 +100,13 @@ function Invoke-FSCCompile { } $settings = Get-FSCPSSettings @CMDOUT + # Whether to force a fresh NuGet download every run. Defaults to $true (original + # behaviour). When set to $false the already downloaded packages are reused and + # kept during cleanup, which speeds up repeated local builds. + try { $nugetForce = [System.Convert]::ToBoolean($settings.fscCompileNugetForce) } + catch { $nugetForce = $true } + Write-PSFMessage -Level Important -Message "fscCompileNugetForce: $nugetForce" + if([string]::IsNullOrEmpty($Version)) { $Version = $settings.buildVersion @@ -293,10 +300,10 @@ function Invoke-FSCCompile { Convert-FSCPSTextToAscii -Text "Download NuGet packages" -Font "Term" -BorderType DoubleDots -HorizontalLayout ControlledSmushing -ScreenWigth 160 -Padding 2 $null = Test-PathExists -Path $NuGetPackagesPath -Type Container -Create @CMDOUT - $null = Get-FSCPSNuget -Version $PlatformVersion -Type PlatformCompilerPackage -Path $NuGetPackagesPath -Force @CMDOUT - $null = Get-FSCPSNuget -Version $PlatformVersion -Type PlatformDevALM -Path $NuGetPackagesPath -Force @CMDOUT - $null = Get-FSCPSNuget -Version $ApplicationVersion -Type ApplicationDevALM -Path $NuGetPackagesPath -Force @CMDOUT - $null = Get-FSCPSNuget -Version $ApplicationVersion -Type ApplicationSuiteDevALM -Path $NuGetPackagesPath -Force @CMDOUT + $null = Get-FSCPSNuget -Version $PlatformVersion -Type PlatformCompilerPackage -Path $NuGetPackagesPath -Force:$nugetForce @CMDOUT + $null = Get-FSCPSNuget -Version $PlatformVersion -Type PlatformDevALM -Path $NuGetPackagesPath -Force:$nugetForce @CMDOUT + $null = Get-FSCPSNuget -Version $ApplicationVersion -Type ApplicationDevALM -Path $NuGetPackagesPath -Force:$nugetForce @CMDOUT + $null = Get-FSCPSNuget -Version $ApplicationVersion -Type ApplicationSuiteDevALM -Path $NuGetPackagesPath -Force:$nugetForce @CMDOUT Write-PSFMessage -Level Important -Message "Complete" $responseObject.NUGETS_FOLDER = $NuGetPackagesPath @@ -757,7 +764,10 @@ function Invoke-FSCCompile { Remove-Item -Path $SolutionBuildFolderPath -Recurse -Force -ErrorAction SilentlyContinue } } - if($NuGetPackagesPath) + # Only remove the downloaded NuGet packages when we are forcing a fresh + # download every run (fscCompileNugetForce). When caching is enabled + # (fscCompileNugetForce = $false) keep them so the next build can reuse them. + if($nugetForce -and $NuGetPackagesPath) { if (Test-Path -Path $NuGetPackagesPath -ErrorAction SilentlyContinue) { From 34d1a603f3913b45c1b767a5519f7f80cf8be18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6tz=20Jensen?= Date: Thu, 9 Jul 2026 22:41:09 +0200 Subject: [PATCH 2/2] Document fscCompileNugetForce setting Co-Authored-By: Claude Opus 4.8 --- wiki/settings.md | 1 + 1 file changed, 1 insertion(+) diff --git a/wiki/settings.md b/wiki/settings.md index a5561c3..b3adbcc 100644 --- a/wiki/settings.md +++ b/wiki/settings.md @@ -64,6 +64,7 @@ The settings file can be everywhere and provided to the fscps.tools through the | versionStrategy | This value means the version of the NuGet packages that will be taken to build the D365FSC code. GA - the NuGets from the GA version of the FSC will be taken (e.g. 10.0.39). Latest - latest available packages. Values: GA/Latest | FSCM | All | GA | | cleanupNugets | Cleanup Commerce compiled NuGet packages with microsoft artifacts | Commerce | All | false | | cleanupAfterBuild | Cleanup build cache after build | All | All | true | +| fscCompileNugetForce | Force a fresh download of the D365FSC compiler NuGet packages on every compile (default behaviour). Set to false to reuse already downloaded packages and keep them during cleanup, for faster repeated local builds. | FSCM | All | true | | cleanupCSUPackage | Cleanup CSU (Commerce Scale Unit) package after build | Commerce | All | false | | solutionName | Name of the solution | All | All | "" | | artifactsPath | The destination artifacts path | All | All | "" |