Modules/businessdev.ALbuild.Pipeline/Private/Read-AdoPipelineYaml.ps1

function Read-AdoPipelineYaml {
    <#
    .SYNOPSIS
        Reads an Azure DevOps pipeline YAML file into an ordered dictionary.
    .DESCRIPTION
        Internal helper for the local pipeline runner. Ensures the 'powershell-yaml' module is
        available (installing it for the current user on demand, mirroring the task bootstrap), then
        parses the file order-preservingly so step order is retained. If the document uses 'extends'
        to reference another template, that template is followed (relative to the entry file).
    .PARAMETER Path
        The pipeline YAML file.
    .OUTPUTS
        System.Collections.IDictionary
    #>

    [CmdletBinding()]
    [OutputType([System.Collections.IDictionary])]
    param(
        [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string] $Path
    )

    if (-not (Test-Path -LiteralPath $Path)) { throw "Pipeline file '$Path' does not exist." }

    if (-not (Get-Module -ListAvailable -Name 'powershell-yaml')) {
        Write-ALbuildLog -Level Information 'Installing powershell-yaml from the PowerShell Gallery...'
        Install-Module -Name 'powershell-yaml' -Scope CurrentUser -Force -AllowClobber
    }
    Import-Module -Name 'powershell-yaml' -ErrorAction Stop

    $document = ConvertFrom-Yaml -Yaml (Get-Content -LiteralPath $Path -Raw) -Ordered

    # Follow an 'extends' reference to the actual template (relative to the entry file).
    if ($document.Contains('extends')) {
        $templateRef = $document['extends']['template']
        if ($templateRef) {
            $templatePath = ($templateRef -split '@', 2)[0]
            $resolved = Join-Path (Split-Path -Parent $Path) $templatePath
            if (Test-Path -LiteralPath $resolved) {
                Write-ALbuildLog -Level Information "Following extends template '$templatePath'."
                return Read-AdoPipelineYaml -Path $resolved
            }
            Write-ALbuildLog -Level Warning "Could not resolve extends template '$templateRef'; using the entry file as-is."
        }
    }

    return $document
}