From c40c08609fdae1bc12a350ac771a66d2a5e38143 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 10 Jul 2026 20:46:33 +0200 Subject: [PATCH] Add PSMA library, action, dispatcher, tests and CI --- .github/workflows/CI.yml | 101 ++++++++++++++++++ action.yml | 64 +++++++++++ src/PSMA/PSMA.psd1 | 24 +++++ src/PSMA/PSMA.psm1 | 17 +++ src/PSMA/functions/private/Get-PSMAInput.ps1 | 23 ++++ .../functions/private/Get-PSMAModuleName.ps1 | 17 +++ src/PSMA/functions/private/Set-PSMAOutput.ps1 | 23 ++++ src/PSMA/functions/private/Write-PSMALog.ps1 | 30 ++++++ .../public/Build-PSMADocumentation.ps1 | 16 +++ .../functions/public/Build-PSMAModule.ps1 | 26 +++++ .../functions/public/Get-PSMACodeCoverage.ps1 | 16 +++ .../functions/public/Get-PSMASettings.ps1 | 25 +++++ .../functions/public/Get-PSMATestResult.ps1 | 16 +++ src/PSMA/functions/public/Initialize-PSMA.ps1 | 20 ++++ .../functions/public/Publish-PSMAModule.ps1 | 21 ++++ .../functions/public/Resolve-PSMAVersion.ps1 | 18 ++++ src/PSMA/functions/public/Test-PSMAModule.ps1 | 17 +++ src/main.ps1 | 38 +++++++ tests/PSMA.Tests.ps1 | 71 ++++++++++++ 19 files changed, 583 insertions(+) create mode 100644 .github/workflows/CI.yml create mode 100644 action.yml create mode 100644 src/PSMA/PSMA.psd1 create mode 100644 src/PSMA/PSMA.psm1 create mode 100644 src/PSMA/functions/private/Get-PSMAInput.ps1 create mode 100644 src/PSMA/functions/private/Get-PSMAModuleName.ps1 create mode 100644 src/PSMA/functions/private/Set-PSMAOutput.ps1 create mode 100644 src/PSMA/functions/private/Write-PSMALog.ps1 create mode 100644 src/PSMA/functions/public/Build-PSMADocumentation.ps1 create mode 100644 src/PSMA/functions/public/Build-PSMAModule.ps1 create mode 100644 src/PSMA/functions/public/Get-PSMACodeCoverage.ps1 create mode 100644 src/PSMA/functions/public/Get-PSMASettings.ps1 create mode 100644 src/PSMA/functions/public/Get-PSMATestResult.ps1 create mode 100644 src/PSMA/functions/public/Initialize-PSMA.ps1 create mode 100644 src/PSMA/functions/public/Publish-PSMAModule.ps1 create mode 100644 src/PSMA/functions/public/Resolve-PSMAVersion.ps1 create mode 100644 src/PSMA/functions/public/Test-PSMAModule.ps1 create mode 100644 src/main.ps1 create mode 100644 tests/PSMA.Tests.ps1 diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 0000000..dd47156 --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,101 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + Test-Module: + name: Test module (Pester) + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Run Pester + shell: pwsh + run: | + $config = New-PesterConfiguration + $config.Run.Path = 'tests' + $config.Run.Exit = $true + $config.Output.Verbosity = 'Detailed' + Invoke-Pester -Configuration $config + + Action-Test: + name: Action-Test (modes at branch) + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Settings + id: settings + uses: ./ + with: + Mode: Settings + Name: PSMATest + + - name: Version + id: version + uses: ./ + with: + Mode: Version + Version: 1.2.3 + + - name: Build + id: build + uses: ./ + with: + Mode: Build + Name: PSMATest + Version: 1.2.3 + + - name: Verify outputs + shell: pwsh + env: + SETTINGS: ${{ steps.settings.outputs.Settings }} + VERSION: ${{ steps.version.outputs.Version }} + MODULEPATH: ${{ steps.build.outputs.ModulePath }} + run: | + Write-Host "Settings = $env:SETTINGS" + Write-Host "Version = $env:VERSION" + Write-Host "ModulePath = $env:MODULEPATH" + if ($env:VERSION -ne '1.2.3') { throw "Version output = '$env:VERSION', expected '1.2.3'." } + $manifest = Join-Path $env:MODULEPATH 'PSMATest.psd1' + if (-not (Test-Path $manifest)) { throw "Manifest not found at $manifest." } + $actual = (Import-PowerShellDataFile $manifest).ModuleVersion + if ($actual -ne '1.2.3') { throw "Manifest ModuleVersion = '$actual', expected '1.2.3'." } + Write-Host 'Action-Test passed.' + + Lint: + name: Lint (PSScriptAnalyzer) + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: PSScriptAnalyzer + shell: pwsh + run: | + $findings = Invoke-ScriptAnalyzer -Path . -Recurse -Severity Error + $findings | Format-Table -AutoSize | Out-String | Write-Host + if ($findings) { throw "$($findings.Count) error-level finding(s)." } diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..2ab7ec8 --- /dev/null +++ b/action.yml @@ -0,0 +1,64 @@ +name: PSMA +description: PSModule Actions — one action and one library, dispatched by Mode. +author: PSModule + +inputs: + Mode: + description: | + The task to run. One of: Settings, Version, Build, Test, CodeCoverage, + TestResults, Document, Publish. + required: true + Name: + description: Module name. Defaults to the repository name. + required: false + default: '' + Version: + description: Module version to stamp (Build) or publish (Publish). + required: false + default: '' + Prerelease: + description: Prerelease label (Build / Publish). + required: false + default: '' + SettingsPath: + description: Path to the settings file (Settings). + required: false + default: .github/PSModule.yml + APIKey: + description: PowerShell Gallery API key (Publish). + required: false + default: '' + WorkingDirectory: + description: The working directory the script runs from. + required: false + default: '.' + +outputs: + Settings: + description: The resolved settings as JSON (Settings). + value: ${{ steps.psma.outputs.Settings }} + Version: + description: The resolved version (Version). + value: ${{ steps.psma.outputs.Version }} + ModulePath: + description: Path to the built module (Build). + value: ${{ steps.psma.outputs.ModulePath }} + Passed: + description: Whether the tests passed (Test). + value: ${{ steps.psma.outputs.Passed }} + +runs: + using: composite + steps: + - name: PSMA + id: psma + shell: pwsh + working-directory: ${{ inputs.WorkingDirectory }} + env: + PSMODULE_PSMA_INPUT_Mode: ${{ inputs.Mode }} + PSMODULE_PSMA_INPUT_Name: ${{ inputs.Name }} + PSMODULE_PSMA_INPUT_Version: ${{ inputs.Version }} + PSMODULE_PSMA_INPUT_Prerelease: ${{ inputs.Prerelease }} + PSMODULE_PSMA_INPUT_SettingsPath: ${{ inputs.SettingsPath }} + PSMODULE_PSMA_INPUT_APIKey: ${{ inputs.APIKey }} + run: ${{ github.action_path }}/src/main.ps1 diff --git a/src/PSMA/PSMA.psd1 b/src/PSMA/PSMA.psd1 new file mode 100644 index 0000000..8fb212c --- /dev/null +++ b/src/PSMA/PSMA.psd1 @@ -0,0 +1,24 @@ +@{ + RootModule = 'PSMA.psm1' + ModuleVersion = '0.1.0' + GUID = 'a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d' + Author = 'PSModule' + CompanyName = 'PSModule' + Copyright = '(c) 2026 PSModule. All rights reserved.' + Description = 'Internal library backing the PSMA action - all framework action logic in one module.' + PowerShellVersion = '7.4' + FunctionsToExport = @( + 'Initialize-PSMA' + 'Get-PSMASettings' + 'Resolve-PSMAVersion' + 'Build-PSMAModule' + 'Test-PSMAModule' + 'Get-PSMACodeCoverage' + 'Get-PSMATestResult' + 'Build-PSMADocumentation' + 'Publish-PSMAModule' + ) + CmdletsToExport = @() + VariablesToExport = @() + AliasesToExport = @() +} diff --git a/src/PSMA/PSMA.psm1 b/src/PSMA/PSMA.psm1 new file mode 100644 index 0000000..5dd740f --- /dev/null +++ b/src/PSMA/PSMA.psm1 @@ -0,0 +1,17 @@ +<# + .SYNOPSIS + Root module for the PSMA library. + + .DESCRIPTION + Dot-sources every private (shared) and public (per-mode) function, then exports + the public functions. Private helpers stay internal but are reused by every mode. +#> + +$private = @(Get-ChildItem -Path (Join-Path $PSScriptRoot 'functions' 'private') -Filter '*.ps1' -ErrorAction SilentlyContinue) +$public = @(Get-ChildItem -Path (Join-Path $PSScriptRoot 'functions' 'public') -Filter '*.ps1' -ErrorAction SilentlyContinue) + +foreach ($file in @($private + $public)) { + . $file.FullName +} + +Export-ModuleMember -Function $public.BaseName diff --git a/src/PSMA/functions/private/Get-PSMAInput.ps1 b/src/PSMA/functions/private/Get-PSMAInput.ps1 new file mode 100644 index 0000000..1d74115 --- /dev/null +++ b/src/PSMA/functions/private/Get-PSMAInput.ps1 @@ -0,0 +1,23 @@ +function Get-PSMAInput { + <# + .SYNOPSIS + Reads an action input from the environment with an optional default. + + .DESCRIPTION + Inputs are passed by action.yml as PSMODULE_PSMA_INPUT_ environment + variables. Shared by every mode so input handling is defined once. + #> + [CmdletBinding()] + [OutputType([string])] + param( + [Parameter(Mandatory)] + [string] $Name, + + [Parameter()] + [string] $Default = '' + ) + + $value = [Environment]::GetEnvironmentVariable("PSMODULE_PSMA_INPUT_$Name") + if ([string]::IsNullOrEmpty($value)) { return $Default } + $value +} diff --git a/src/PSMA/functions/private/Get-PSMAModuleName.ps1 b/src/PSMA/functions/private/Get-PSMAModuleName.ps1 new file mode 100644 index 0000000..df1f888 --- /dev/null +++ b/src/PSMA/functions/private/Get-PSMAModuleName.ps1 @@ -0,0 +1,17 @@ +function Get-PSMAModuleName { + <# + .SYNOPSIS + Resolves the module name from the Name input, falling back to the repository name. + + .DESCRIPTION + Shared context helper reused by the modes that need the module name. + #> + [CmdletBinding()] + [OutputType([string])] + param() + + $name = Get-PSMAInput -Name 'Name' + if (-not [string]::IsNullOrEmpty($name)) { return $name } + if ($env:GITHUB_REPOSITORY) { return ($env:GITHUB_REPOSITORY -split '/')[-1] } + 'UnknownModule' +} diff --git a/src/PSMA/functions/private/Set-PSMAOutput.ps1 b/src/PSMA/functions/private/Set-PSMAOutput.ps1 new file mode 100644 index 0000000..c1d8c99 --- /dev/null +++ b/src/PSMA/functions/private/Set-PSMAOutput.ps1 @@ -0,0 +1,23 @@ +function Set-PSMAOutput { + <# + .SYNOPSIS + Writes a GitHub Actions step output. + + .DESCRIPTION + Shared output writer used by every mode. No-ops safely when not running inside + a GitHub Actions runner (e.g. during local tests). + #> + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] $Name, + + [Parameter()] + [string] $Value = '' + ) + + if ($env:GITHUB_OUTPUT) { + "$Name=$Value" | Add-Content -Path $env:GITHUB_OUTPUT + } + Write-Verbose "output: $Name=$Value" +} diff --git a/src/PSMA/functions/private/Write-PSMALog.ps1 b/src/PSMA/functions/private/Write-PSMALog.ps1 new file mode 100644 index 0000000..53e92ba --- /dev/null +++ b/src/PSMA/functions/private/Write-PSMALog.ps1 @@ -0,0 +1,30 @@ +function Write-PSMALog { + <# + .SYNOPSIS + Emits a collapsible log group around a block of work. + + .DESCRIPTION + Shared grouped-logging helper reused by every mode so diagnostics read the same + way across all action calls. Falls back to a plain line when no block is given. + #> + [CmdletBinding()] + param( + [Parameter(Mandatory, Position = 0)] + [string] $Title, + + [Parameter(Position = 1)] + [scriptblock] $ScriptBlock + ) + + if (-not $ScriptBlock) { + Write-Host $Title + return + } + + Write-Host "::group::$Title" + try { + & $ScriptBlock + } finally { + Write-Host '::endgroup::' + } +} diff --git a/src/PSMA/functions/public/Build-PSMADocumentation.ps1 b/src/PSMA/functions/public/Build-PSMADocumentation.ps1 new file mode 100644 index 0000000..b950835 --- /dev/null +++ b/src/PSMA/functions/public/Build-PSMADocumentation.ps1 @@ -0,0 +1,16 @@ +function Build-PSMADocumentation { + <# + .SYNOPSIS + Builds the module documentation. + + .DESCRIPTION + PORT FROM: PSModule/Document-PSModule - generate the PSModule-flavored docs. The + scaffold logs a placeholder. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Build-PSMADocumentation' { + Write-Host 'Documentation step (scaffold).' + } +} diff --git a/src/PSMA/functions/public/Build-PSMAModule.ps1 b/src/PSMA/functions/public/Build-PSMAModule.ps1 new file mode 100644 index 0000000..c75c8ad --- /dev/null +++ b/src/PSMA/functions/public/Build-PSMAModule.ps1 @@ -0,0 +1,26 @@ +function Build-PSMAModule { + <# + .SYNOPSIS + Builds the module and its manifest. + + .DESCRIPTION + PORT FROM: PSModule/Build-PSModule - assemble the module and stamp the manifest. + The scaffold writes a stub manifest so the build/test/publish pipeline can be + exercised end to end. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Build-PSMAModule' { + $name = Get-PSMAModuleName + $version = Get-PSMAInput -Name 'Version' -Default '0.0.0' + $outputRoot = Join-Path (Get-Location) 'outputs' 'module' $name + + New-Item -ItemType Directory -Path $outputRoot -Force | Out-Null + $manifest = Join-Path $outputRoot "$name.psd1" + "@{ ModuleVersion = '$version' }" | Set-Content -Path $manifest + + Set-PSMAOutput -Name 'ModulePath' -Value $outputRoot + Write-Host "Built stub module '$name' $version at: $outputRoot" + } +} diff --git a/src/PSMA/functions/public/Get-PSMACodeCoverage.ps1 b/src/PSMA/functions/public/Get-PSMACodeCoverage.ps1 new file mode 100644 index 0000000..8a5e755 --- /dev/null +++ b/src/PSMA/functions/public/Get-PSMACodeCoverage.ps1 @@ -0,0 +1,16 @@ +function Get-PSMACodeCoverage { + <# + .SYNOPSIS + Gathers code coverage from a Pester run. + + .DESCRIPTION + PORT FROM: PSModule/Get-PesterCodeCoverage - aggregate coverage and compare it to + the target. The scaffold logs a placeholder. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Get-PSMACodeCoverage' { + Write-Host 'Code coverage step (scaffold).' + } +} diff --git a/src/PSMA/functions/public/Get-PSMASettings.ps1 b/src/PSMA/functions/public/Get-PSMASettings.ps1 new file mode 100644 index 0000000..74ff6e3 --- /dev/null +++ b/src/PSMA/functions/public/Get-PSMASettings.ps1 @@ -0,0 +1,25 @@ +function Get-PSMASettings { + <# + .SYNOPSIS + Resolves the framework settings and run conditions. + + .DESCRIPTION + PORT FROM: PSModule/Get-PSModuleSettings - read the settings file, merge defaults, + and compute the Run.* conditions. The scaffold emits a minimal settings object. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Get-PSMASettings' { + $path = Get-PSMAInput -Name 'SettingsPath' -Default '.github/PSModule.yml' + Write-Host "Settings path: $path" + + $settings = [ordered]@{ + Name = Get-PSMAModuleName + Run = [ordered]@{} + } + $json = $settings | ConvertTo-Json -Compress -Depth 10 + Set-PSMAOutput -Name 'Settings' -Value $json + Write-Host "Settings: $json" + } +} diff --git a/src/PSMA/functions/public/Get-PSMATestResult.ps1 b/src/PSMA/functions/public/Get-PSMATestResult.ps1 new file mode 100644 index 0000000..5ea561f --- /dev/null +++ b/src/PSMA/functions/public/Get-PSMATestResult.ps1 @@ -0,0 +1,16 @@ +function Get-PSMATestResult { + <# + .SYNOPSIS + Gathers and reports Pester test results. + + .DESCRIPTION + PORT FROM: PSModule/Get-PesterTestResults - aggregate results across test runs and + write the step summary. The scaffold logs a placeholder. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Get-PSMATestResult' { + Write-Host 'Test results step (scaffold).' + } +} diff --git a/src/PSMA/functions/public/Initialize-PSMA.ps1 b/src/PSMA/functions/public/Initialize-PSMA.ps1 new file mode 100644 index 0000000..0120b91 --- /dev/null +++ b/src/PSMA/functions/public/Initialize-PSMA.ps1 @@ -0,0 +1,20 @@ +function Initialize-PSMA { + <# + .SYNOPSIS + Prepares the runner for the PSMA library (replaces Install-PSModuleHelpers). + + .DESCRIPTION + One shared bootstrap, run once at the top of every action call, that makes the + dependencies the modes rely on available. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Initialize-PSMA' { + Write-Host "PowerShell $($PSVersionTable.PSVersion)" + # PORT FROM: PSModule/Install-PSModuleHelpers - install/import the shared modules the + # real actions depend on (the PSModule 'GitHub' module for LogGroup / Write-GitHubNotice / + # Set-GitHubStepSummary, 'Pester', 'PSScriptAnalyzer', etc.). + Write-Host 'PSMA library loaded.' + } +} diff --git a/src/PSMA/functions/public/Publish-PSMAModule.ps1 b/src/PSMA/functions/public/Publish-PSMAModule.ps1 new file mode 100644 index 0000000..cd7478d --- /dev/null +++ b/src/PSMA/functions/public/Publish-PSMAModule.ps1 @@ -0,0 +1,21 @@ +function Publish-PSMAModule { + <# + .SYNOPSIS + Publishes the module. + + .DESCRIPTION + PORT FROM: PSModule/Publish-PSModule - publish to the PowerShell Gallery and create + the GitHub release. The scaffold warns when no API key is present and no-ops. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Publish-PSMAModule' { + $apiKey = Get-PSMAInput -Name 'APIKey' + if ([string]::IsNullOrEmpty($apiKey)) { + Write-Host '::warning::No APIKey provided; skipping publish (scaffold).' + return + } + Write-Host 'Publish step (scaffold).' + } +} diff --git a/src/PSMA/functions/public/Resolve-PSMAVersion.ps1 b/src/PSMA/functions/public/Resolve-PSMAVersion.ps1 new file mode 100644 index 0000000..4657237 --- /dev/null +++ b/src/PSMA/functions/public/Resolve-PSMAVersion.ps1 @@ -0,0 +1,18 @@ +function Resolve-PSMAVersion { + <# + .SYNOPSIS + Resolves the next module version. + + .DESCRIPTION + PORT FROM: PSModule/Resolve-PSModuleVersion - compute the next version from the + pull request, labels, and existing tags. The scaffold echoes the Version input. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Resolve-PSMAVersion' { + $version = Get-PSMAInput -Name 'Version' -Default '0.0.0' + Set-PSMAOutput -Name 'Version' -Value $version + Write-Host "Resolved version: $version" + } +} diff --git a/src/PSMA/functions/public/Test-PSMAModule.ps1 b/src/PSMA/functions/public/Test-PSMAModule.ps1 new file mode 100644 index 0000000..d821987 --- /dev/null +++ b/src/PSMA/functions/public/Test-PSMAModule.ps1 @@ -0,0 +1,17 @@ +function Test-PSMAModule { + <# + .SYNOPSIS + Runs the module test harness. + + .DESCRIPTION + PORT FROM: PSModule/Test-PSModule - run the Pester + PSScriptAnalyzer harness and + surface results. The scaffold reports a pass. + #> + [CmdletBinding()] + param() + + Write-PSMALog 'Test-PSMAModule' { + Set-PSMAOutput -Name 'Passed' -Value 'true' + Write-Host 'Tests passed (scaffold).' + } +} diff --git a/src/main.ps1 b/src/main.ps1 new file mode 100644 index 0000000..131ba9a --- /dev/null +++ b/src/main.ps1 @@ -0,0 +1,38 @@ +#Requires -Version 7.4 + +<# + .SYNOPSIS + PSMA control script. + + .DESCRIPTION + Loads the single bundled PSMA library and dispatches to the function that + implements the requested Mode. This is the only entry point the action calls. +#> + +[CmdletBinding()] +param() + +$ErrorActionPreference = 'Stop' + +# Load the single bundled library — reused by every mode. +Import-Module (Join-Path $PSScriptRoot 'PSMA' 'PSMA.psd1') -Force + +# Shared bootstrap (replaces the Install-PSModuleHelpers action). +Initialize-PSMA + +$mode = $env:PSMODULE_PSMA_INPUT_Mode +Write-Host "PSMA: dispatching mode '$mode'" + +switch ($mode) { + 'Settings' { Get-PSMASettings } + 'Version' { Resolve-PSMAVersion } + 'Build' { Build-PSMAModule } + 'Test' { Test-PSMAModule } + 'CodeCoverage' { Get-PSMACodeCoverage } + 'TestResults' { Get-PSMATestResult } + 'Document' { Build-PSMADocumentation } + 'Publish' { Publish-PSMAModule } + default { + throw "Unknown PSMA mode: '$mode'. Valid modes: Settings, Version, Build, Test, CodeCoverage, TestResults, Document, Publish." + } +} diff --git a/tests/PSMA.Tests.ps1 b/tests/PSMA.Tests.ps1 new file mode 100644 index 0000000..8453149 --- /dev/null +++ b/tests/PSMA.Tests.ps1 @@ -0,0 +1,71 @@ +#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0.0' } + +Describe 'PSMA library' { + BeforeAll { + $script:ModulePath = Join-Path $PSScriptRoot '..' 'src' 'PSMA' 'PSMA.psd1' + Import-Module $script:ModulePath -Force + } + + AfterAll { + Remove-Module PSMA -Force -ErrorAction SilentlyContinue + } + + Context 'Module surface' { + It 'exports a public function for every mode' { + $expected = @( + 'Get-PSMASettings' + 'Resolve-PSMAVersion' + 'Build-PSMAModule' + 'Test-PSMAModule' + 'Get-PSMACodeCoverage' + 'Get-PSMATestResult' + 'Build-PSMADocumentation' + 'Publish-PSMAModule' + ) + $exported = (Get-Command -Module PSMA).Name + foreach ($fn in $expected) { + $exported | Should -Contain $fn + } + } + } + + Context 'Shared helpers (reused across every mode)' { + It 'Get-PSMAInput returns the default when the env var is not set' { + InModuleScope PSMA { + Get-PSMAInput -Name 'DefinitelyNotSet' -Default 'fallback' | Should -Be 'fallback' + } + } + + It 'Get-PSMAInput reads the PSMODULE_PSMA_INPUT_ env var' { + $env:PSMODULE_PSMA_INPUT_Sample = 'hello' + try { + InModuleScope PSMA { + Get-PSMAInput -Name 'Sample' | Should -Be 'hello' + } + } finally { + Remove-Item Env:PSMODULE_PSMA_INPUT_Sample -ErrorAction SilentlyContinue + } + } + } + + Context 'Build mode' { + It 'writes a stub manifest with the requested version' { + $env:PSMODULE_PSMA_INPUT_Name = 'PSMATest' + $env:PSMODULE_PSMA_INPUT_Version = '1.2.3' + $work = Join-Path ([IO.Path]::GetTempPath()) ([guid]::NewGuid().Guid) + New-Item -ItemType Directory -Path $work | Out-Null + Push-Location $work + try { + Build-PSMAModule + $manifest = Join-Path $work 'outputs' 'module' 'PSMATest' 'PSMATest.psd1' + $manifest | Should -Exist + (Import-PowerShellDataFile $manifest).ModuleVersion | Should -Be '1.2.3' + } finally { + Pop-Location + Remove-Item $work -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item Env:PSMODULE_PSMA_INPUT_Name -ErrorAction SilentlyContinue + Remove-Item Env:PSMODULE_PSMA_INPUT_Version -ErrorAction SilentlyContinue + } + } + } +}