Private/Compile/Import-GovernanceSource.ps1
|
function Import-GovernanceSource { <# .SYNOPSIS Loads and parses a program's authored governance source (hierarchy + access + members + taxonomy + systems) from its programs/<program>/ folder, returning the raw model plus a source hash for provenance. #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$ProgramPath ) $manifestPath = Join-Path $ProgramPath 'manifest.yaml' $hierarchyPath = Join-Path $ProgramPath 'hierarchy.yaml' $accessPath = Join-Path $ProgramPath 'access.yaml' if (-not (Test-Path $manifestPath)) { throw "Manifest file not found: $manifestPath" } if (-not (Test-Path $hierarchyPath)) { throw "Hierarchy file not found: $hierarchyPath" } if (-not (Test-Path $accessPath)) { throw "Access file not found: $accessPath" } $manifestRaw = Get-Content -Path $manifestPath -Raw $hierarchyRaw = Get-Content -Path $hierarchyPath -Raw $accessRaw = Get-Content -Path $accessPath -Raw $manifest = ConvertFrom-Yaml $manifestRaw $hierarchy = ConvertFrom-Yaml $hierarchyRaw $access = ConvertFrom-Yaml $accessRaw # Membership: programs/<program>/members/<short>.yaml, keyed by file base name. $membersDir = Join-Path $ProgramPath 'members' $members = @{} $membersRaw = '' if (Test-Path $membersDir) { foreach ($file in Get-ChildItem -Path $membersDir -Filter '*.yaml' -File) { $raw = Get-Content -Path $file.FullName -Raw $membersRaw += $raw $members[$file.BaseName] = ConvertFrom-Yaml $raw } } # taxonomy.yaml: optional governed vocabularies (tags today; other controlled # value lists later). Separate from hierarchy.yaml because it is a flat list # of allowed strings, not part of the product/team tree. $taxonomyPath = Join-Path $ProgramPath 'taxonomy.yaml' $taxonomyRaw = '' $taxonomy = $null if (Test-Path $taxonomyPath) { $taxonomyRaw = Get-Content -Path $taxonomyPath -Raw $taxonomy = ConvertFrom-Yaml $taxonomyRaw } # systems.yaml: optional reusable systems — named sets of governed # sub-elements stamped onto teams via `systems:` in hierarchy.yaml. $systemsPath = Join-Path $ProgramPath 'systems.yaml' $systemsRaw = '' $systems = $null if (Test-Path $systemsPath) { $systemsRaw = Get-Content -Path $systemsPath -Raw $systems = ConvertFrom-Yaml $systemsRaw } $bytes = [System.Text.Encoding]::UTF8.GetBytes($manifestRaw + $hierarchyRaw + $accessRaw + $membersRaw + $taxonomyRaw + $systemsRaw) $stream = [System.IO.MemoryStream]::new($bytes) $hash = (Get-FileHash -InputStream $stream -Algorithm SHA256).Hash.ToLowerInvariant() # cadence.yaml: optional iteration cadence config. $cadencePath = Join-Path $ProgramPath 'cadence.yaml' $cadence = $null if (Test-Path $cadencePath) { $cadence = ConvertFrom-Yaml (Get-Content -Path $cadencePath -Raw) } # team-ids.yaml: auto-maintained state file mapping codePath -> ADO team GUID. # Allows teams to be found by stable codePath even after a rename. $teamIdsPath = Join-Path $ProgramPath 'team-ids.yaml' $teamIds = @{} if (Test-Path $teamIdsPath) { $parsed = ConvertFrom-Yaml (Get-Content -Path $teamIdsPath -Raw) if ($parsed -and $parsed.teams) { foreach ($k in $parsed.teams.Keys) { $teamIds[$k] = $parsed.teams[$k] } } } return @{ Manifest = $manifest Hierarchy = $hierarchy Access = $access Members = $members Hash = $hash Cadence = $cadence Taxonomy = $taxonomy Systems = $systems TeamIds = $teamIds TeamIdsPath = $teamIdsPath } } |