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 } # sources.yaml: optional pre-migration source locations per codePath — # where each incoming team lives TODAY, consumed only by preflight. The # raw text joins the hash last so programs without one keep their hash. $sourcesPath = Join-Path $ProgramPath 'sources.yaml' $sourcesRaw = '' $sources = $null $sourceLabels = $null # optional `labels:` — engagement fields attached per preflight check id (ADR-008) $sourceReporting = $null # optional `reporting:` — how the rendered fix report is framed (ADR-009) $sourceScope = $null # optional `scope:` — the migration query narrowing what is validated (ADR-010) if (Test-Path $sourcesPath) { $sourcesRaw = Get-Content -Path $sourcesPath -Raw $parsed = ConvertFrom-Yaml $sourcesRaw if ($parsed -and $parsed.sources) { $sources = $parsed.sources } if ($parsed -and $parsed.labels) { $sourceLabels = $parsed.labels } if ($parsed -and $parsed.reporting) { $sourceReporting = $parsed.reporting } if ($parsed -and $parsed.scope) { $sourceScope = $parsed.scope } } $bytes = [System.Text.Encoding]::UTF8.GetBytes($manifestRaw + $hierarchyRaw + $accessRaw + $membersRaw + $taxonomyRaw + $systemsRaw + $sourcesRaw) $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 Sources = $sources SourceLabels = $sourceLabels SourceReporting = $sourceReporting SourceScope = $sourceScope TeamIds = $teamIds TeamIdsPath = $teamIdsPath } } |