Build-ModuleManifest.ps1
|
# Build-ModuleManifest.ps1 [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$ModulePath = $PSScriptRoot ) $psd1Path = Join-Path $ModulePath "cloudstack-ps.psd1" $psm1Path = Join-Path $ModulePath "cloudstack-ps.psm1" $publicPath = Join-Path $ModulePath "Public" $allFunctions = @() $allAliases = @() # Function to extract function names from a file function Get-FunctionsFromFile { param([string]$FilePath) $ast = [System.Management.Automation.Language.Parser]::ParseFile( $FilePath, [ref]$null, [ref]$null ) $functions = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true) | ForEach-Object { $_.Name } return $functions } # Extract names from backwards-compatibility 'Set-Alias -Name <old> -Value <new>' calls function Get-AliasesFromFile { param([string]$FilePath) $ast = [System.Management.Automation.Language.Parser]::ParseFile( $FilePath, [ref]$null, [ref]$null ) $commands = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.CommandAst] }, $true) | Where-Object { $_.GetCommandName() -eq 'Set-Alias' } $aliases = foreach ($command in $commands) { $elements = $command.CommandElements for ($i = 0; $i -lt $elements.Count - 1; $i++) { if ($elements[$i] -is [System.Management.Automation.Language.CommandParameterAst] -and $elements[$i].ParameterName -eq 'Name') { $elements[$i + 1].Value } } } return $aliases } # Check .psm1 file if (Test-Path $psm1Path) { Write-Host "Scanning cloudstack.psm1..." -ForegroundColor Cyan $psm1Functions = Get-FunctionsFromFile -FilePath $psm1Path if ($psm1Functions) { Write-Host " Found $($psm1Functions.Count) functions in .psm1" -ForegroundColor Gray $allFunctions += $psm1Functions } $allAliases += Get-AliasesFromFile -FilePath $psm1Path } # Check Public folder if (Test-Path $publicPath) { Write-Host "Scanning Public folder..." -ForegroundColor Cyan $publicFiles = Get-ChildItem -Path $publicPath -Filter "*.ps1" -File foreach ($file in $publicFiles) { Write-Host " Scanning $($file.Name)..." -ForegroundColor Gray $fileFunctions = Get-FunctionsFromFile -FilePath $file.FullName if ($fileFunctions) { Write-Host " Found: $($fileFunctions -join ', ')" -ForegroundColor DarkGray $allFunctions += $fileFunctions } $fileAliases = Get-AliasesFromFile -FilePath $file.FullName if ($fileAliases) { Write-Host " Aliases: $($fileAliases -join ', ')" -ForegroundColor DarkGray $allAliases += $fileAliases } } } # Remove duplicates and sort $allFunctions = $allFunctions | Select-Object -Unique | Sort-Object $allAliases = $allAliases | Select-Object -Unique | Sort-Object Write-Host "`nTotal functions found: $($allFunctions.Count)" -ForegroundColor Cyan $allFunctions | ForEach-Object { Write-Host " - $_" -ForegroundColor White } Write-Host "`nTotal aliases found: $($allAliases.Count)" -ForegroundColor Cyan $allAliases | ForEach-Object { Write-Host " - $_" -ForegroundColor White } if ($allFunctions.Count -eq 0) { Write-Warning "No functions found! Check your module structure." exit 1 } # BUILD THE MANIFEST FROM SCRATCH Write-Host "`nBuilding module manifest..." -ForegroundColor Cyan # Create the functions and aliases array strings $functionsString = ($allFunctions | ForEach-Object { " '$_'" }) -join ",`n" $aliasesString = ($allAliases | ForEach-Object { " '$_'" }) -join ",`n" # Build the complete manifest content - USE LOWERCASE cloudstack.psm1 $manifestContent = @" @{ RootModule = 'cloudstack-ps.psm1' ModuleVersion = '0.0.1' GUID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890' Author = 'Tyler Verkade' CompanyName = 'US Signal Company' Copyright = '(c) 2026. All rights reserved.' Description = 'PowerShell module for interacting with Apache CloudStack API' PowerShellVersion = '5.1' FunctionsToExport = @( $functionsString ) CmdletsToExport = @() VariablesToExport = @() # Deprecated pre-1.1.0 names, kept so existing scripts keep working. AliasesToExport = @( $aliasesString ) PrivateData = @{ PSData = @{ Tags = @('CloudStack', 'API', 'Cloud') ReleaseNotes = 'Renamed functions that used unapproved PowerShell verbs. Old names remain available as aliases.' } } } "@ # Write the manifest. 'Out-File -Encoding UTF8' means UTF-8 *with* BOM on # Windows PowerShell 5.1 and *without* on PowerShell 6+, and a BOM-less file # containing non-ASCII is read as the ANSI code page by 5.1, which corrupts it. # Go through .NET so the encoding is the same on every host. $utf8WithBom = New-Object System.Text.UTF8Encoding($true) [System.IO.File]::WriteAllText($psd1Path, $manifestContent, $utf8WithBom) Write-Host "✓ Module manifest created!" -ForegroundColor Green # Test the manifest Write-Host "`nTesting module manifest..." -ForegroundColor Cyan try { $null = Test-ModuleManifest -Path $psd1Path -ErrorAction Stop Write-Host "✓ Manifest is valid!" -ForegroundColor Green Write-Host " Functions exported: $($allFunctions.Count)" -ForegroundColor Cyan } catch { Write-Error "Manifest validation failed: $_" exit 1 } |