internal/Get-MtMaesterConfig.ps1

function Get-MtMaesterConfig {
    <#
    .SYNOPSIS
    Reads the Maester config from (usually from the root of the ./tests directory)

    .DESCRIPTION
    This also uses the ./custom/maester-config.json file if it exists and
    merges the settings, allowing users to override the default settings.

    .EXAMPLE
    $maesterConfig = Get-MtMaesterConfig -ConfigFilePath 'C:\path\to\maester-config.json'
    #>

    [CmdletBinding()]
    [OutputType([object])]
    param(
        # Path to the Maester config file or the directory containing the config file (maester-config.json).
        [Parameter(Mandatory = $true)]
        $Path,

        # Optional tenant ID. When provided, looks for maester-config.{TenantId}.json first,
        # then falls back to maester-config.json.
        [Parameter(Mandatory = $false)]
        [string] $TenantId
    )

    Write-Verbose "Getting Maester config from $Path"

    # Helper to find a config file by name in a directory, walking up to 5 parent levels
    function Find-ConfigFile {
        param([string]$SearchPath, [string]$FileName)

        if (Test-Path $SearchPath -PathType Container) {
            $candidate = Join-Path -Path $SearchPath -ChildPath $FileName
            if (Test-Path -Path $candidate) { return $candidate }

            # Check tests subfolder
            $testsCandidate = Join-Path -Path $SearchPath -ChildPath "tests/$FileName"
            if (Test-Path -Path $testsCandidate) { return $testsCandidate }

            # Walk up to 5 parent directories
            $currentDir = $SearchPath
            for ($i = 1; $i -le 5; $i++) {
                $parentDir = Split-Path -Path $currentDir -Parent
                if ($parentDir -eq $currentDir -or [string]::IsNullOrEmpty($parentDir)) { break }
                $currentDir = $parentDir
                $candidate = Join-Path -Path $currentDir -ChildPath $FileName
                if (Test-Path -Path $candidate) { return $candidate }
            }
        }

        return $null
    }

    $ConfigFilePath = $null

    try {
        # If a valid TenantId (GUID) is provided, look for tenant-specific config first
        $isValidTenantId = $TenantId -as [guid]
        if ($isValidTenantId) {
            $tenantFileName = "maester-config.$TenantId.json"
            $ConfigFilePath = Find-ConfigFile -SearchPath $Path -FileName $tenantFileName
            if ($ConfigFilePath) {
                Write-Verbose "Found tenant-specific config: $ConfigFilePath"
            } else {
                Write-Verbose "No tenant-specific config ($tenantFileName) found. Falling back to default."
            }
        }

        # Fall back to the default maester-config.json
        if (-not $ConfigFilePath) {
            # If Path is a direct file reference, use it as-is (preserves original behavior)
            if (Test-Path -Path $Path -PathType Leaf) {
                $ConfigFilePath = $Path
            } else {
                $ConfigFilePath = Find-ConfigFile -SearchPath $Path -FileName 'maester-config.json'
            }
        }
    } catch {
        Write-Verbose "Error while trying to seek the config file: $_"
    }

    if (-not $ConfigFilePath -or -not (Test-Path -Path $ConfigFilePath)) {
        # If we didn't find it anywhere, let's use the default config file
        Write-Verbose "Config file not found. Using default config file."
        $ConfigFilePath = Join-Path (Get-MtMaesterTestFolderPath) -ChildPath 'maester-config.json'
        if (-not (Test-Path -Path $ConfigFilePath)) {
            Write-Warning "Default config file not found at $ConfigFilePath. Please provide a valid path to the config file."
            return $null
        }
    }

    Write-Verbose "Loading Maester config from: $ConfigFilePath"
    $maesterConfig = Get-Content -Path $ConfigFilePath -Raw | ConvertFrom-Json

    # Store the source file name so the report can show which config was loaded
    $configFileName = Split-Path -Path $ConfigFilePath -Leaf
    Add-Member -InputObject $maesterConfig -MemberType NoteProperty -Name 'ConfigSource' -Value $configFileName

    # Add a new property called TestSettingsHash to the config object with Id as the key for faster access
    Add-Member -InputObject $maesterConfig -MemberType NoteProperty -Name 'TestSettingsHash' -Value @{}

    foreach ($testSetting in $maesterConfig.TestSettings) {
        $maesterConfig.TestSettingsHash.Add($testSetting.Id, $testSetting)
    }

    # Read the custom config file if it exists
    $customConfigPath = Join-Path -Path (Split-Path -Path $ConfigFilePath -Parent) -ChildPath 'Custom' | Join-Path -ChildPath 'maester-config.json'
    if (Test-Path $customConfigPath) {
        Write-Verbose "Custom config file found at $customConfigPath. Merging with main config."
        $customConfig = Get-Content -Path $customConfigPath -Raw | ConvertFrom-Json

        # Go through each GlobalSetting in custom and override the main config if it exists, otherwise append
        foreach ($property in $customConfig.GlobalSettings.PSObject.Properties) {
            if ($maesterConfig.GlobalSettings.PSObject.Properties.Name -contains $property.Name) {
                Write-Verbose "Updating GlobalSetting `"$($property.Name)`" from custom config."
                $maesterConfig.GlobalSettings.$($property.Name) = $property.Value
            } else {
                Write-Verbose "Adding GlobalSetting `"$($property.Name)`" from custom config."
                Add-Member -InputObject $maesterConfig.GlobalSettings -MemberType NoteProperty -Name $property.Name -Value $property.Value
            }
        }

        # Go through each TestSetting in custom and override the main config if it exists
        foreach ($customSetting in $customConfig.TestSettings) {
            $mainTestSetting = $maesterConfig.TestSettingsHash[$customSetting.Id]
            if ($mainTestSetting) {
                Write-Verbose "Updating TestSetting with Id $($customSetting.Id) from custom config."
                # Update the existing properties (right now only Severity is supported)
                $mainTestSetting.Severity = $customSetting.Severity
            }
        }
    } else {
        Write-Verbose "No custom config file found. Using main config only."
    }

    return $maesterConfig
}