Modules/businessdev.ALbuild.Core/Public/Get-ALbuildScratchFolder.ps1

function Get-ALbuildScratchFolder {
    <#
    .SYNOPSIS
        The folder ALbuild uses for large short-lived working files.
 
    .DESCRIPTION
        The system TEMP folder is the wrong place for the payloads ALbuild handles. Two reasons, both
        measured on build agents:
 
        Space. A symbol merge folder can hold a full copy of the first-party symbols, and an expanded
        .app is the whole package. TEMP lives on the system drive, which on a build agent is the
        smallest one - on 2026-09-03 the runtime sweep filled C: on two agents and took them offline.
        A server usually has a large data drive; this is how ALbuild is told to use it.
 
        Path length. The per-user TEMP path is deep ('C:\Users\<account>\AppData\Local\Temp'), and the
        DevOps task runs under Windows PowerShell 5.1, which enforces MAX_PATH hard. The default here
        sits under BaseFolder, which is deliberately a short root ('C:\alb\temp').
 
        Resolution order: the ALBUILD_SCRATCH environment variable, then an explicit ScratchFolder
        setting, then '<BaseFolder>\temp' - so pointing BaseFolder at a data drive moves the working
        files too - and finally the system TEMP folder. Placement never fails a build: if the configured folder cannot be
        created, this falls back to TEMP rather than throwing.
 
    .PARAMETER Name
        Optional leaf to append. The folder itself is NOT created for a leaf - callers create what
        they need, because most of them want a folder and some want a file.
 
    .EXAMPLE
        Set-ALbuildConfig -Settings @{ ScratchFolder = 'G:\alb\temp' } -Persist
 
        Puts the working files on a data drive with room, machine-wide.
 
    .OUTPUTS
        System.String
    #>

    [CmdletBinding()]
    [OutputType([string])]
    param(
        [string] $Name
    )

    $root = $null
    $fromEnv = [System.Environment]::GetEnvironmentVariable('ALBUILD_SCRATCH')
    if (-not [string]::IsNullOrWhiteSpace($fromEnv)) { $root = $fromEnv }

    if (-not $root) {
        try {
            $configured = Get-ALbuildConfig -Name 'ScratchFolder'
            if (-not [string]::IsNullOrWhiteSpace($configured)) { $root = "$configured" }
        }
        catch { $root = $null }
    }

    if (-not $root) {
        # Derived, not baked in: a machine that persisted BaseFolder = 'G:\alb' must scratch on G:.
        try {
            $base = Get-ALbuildConfig -Name 'BaseFolder'
            if (-not [string]::IsNullOrWhiteSpace($base)) { $root = Join-Path -Path "$base" -ChildPath 'temp' }
        }
        catch { $root = $null }
    }

    if (-not $root) { $root = [System.IO.Path]::GetTempPath() }

    try {
        if (-not (Test-Path -LiteralPath $root)) {
            New-Item -ItemType Directory -Path $root -Force -ErrorAction Stop | Out-Null
        }
    }
    catch {
        Write-ALbuildLog -Level Warning "The scratch folder '$root' could not be created ($($_.Exception.Message)); using the system TEMP folder."
        $root = [System.IO.Path]::GetTempPath()
    }

    if ($PSBoundParameters.ContainsKey('Name') -and -not [string]::IsNullOrWhiteSpace($Name)) {
        return (Join-Path -Path $root -ChildPath $Name)
    }
    return $root
}