Skip to content

Instantly share code, notes, and snippets.

@bew
Created January 17, 2024 18:21
Show Gist options
  • Select an option

  • Save bew/ac0aa9ade8dfa88c1f9ed5f4ae91db28 to your computer and use it in GitHub Desktop.

Select an option

Save bew/ac0aa9ade8dfa88c1f9ed5f4ae91db28 to your computer and use it in GitHub Desktop.

Revisions

  1. bew created this gist Jan 17, 2024.
    75 changes: 75 additions & 0 deletions 0_Powershell-Testing-Utils.ps1
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,75 @@
    # This module defines helper functions to help with local/CI testing PowerShell code,
    # like checking pwsh version, installing up necessary modules..

    function Assert-PowerShellVersion {
    param(
    [Parameter(Mandatory)]
    [string]$MinimumVersion
    )
    if ($PSVersionTable.PSVersion -le [System.Version]$MinimumVersion) {
    throw "PowerShell minimum version $MinimumVersion is required, current version is: $($PSVersionTable.PSVersion)"
    }
    }

    function Check-VersionAgainstConstraints {
    param(
    [Parameter(Mandatory, Position = 0)]
    [System.Version]$givenVersion,
    [Parameter(Mandatory, Position = 1)]
    [hashtable]$VersionConstraints
    )
    Set-StrictMode -Off # Disabled locally, to ease check for missing properties
    [System.Version]$min = $VersionConstraints.MinimumVersion ?? "0.0.0"
    [System.Version]$max = $VersionConstraints.MaximumVersion # allow $null
    if (!$max) {
    $min -le $givenVersion
    }
    else {
    $min -le $givenVersion -and $givenVersion -le $max
    }
    }

    function Ensure-AllModulesAvailable {
    param(
    [Parameter(Mandatory, Position = 0)]
    [hashtable]$modulesToCheck
    )
    foreach ($moduleName in $modulesToCheck.Keys) {
    # Wrap the loop body with a re-throwing try-catch, to ensure an error in the loop is
    # correctly propagated and stops the script.
    # (In PowerShell7 (@2024-01), a cmd failing with an error in a loop will just print the
    # error and ignore it, continuing as normal :/)
    try {
    Ensure-ModuleAvailable $moduleName -VersionConstraints $modulesToCheck[$moduleName]
    }
    catch {
    throw $_
    }
    }
    }

    function Ensure-ModuleAvailable {
    param(
    [Parameter(Mandatory, Position = 0)]
    [string]$Name,
    [Parameter(Mandatory, HelpMessage = "Version constraints with fields like `MinimumVersion`, `MaximumVersion`. Must be compatible to being passed to 'Install-Module' & 'Import-Module'")]
    [hashtable]$VersionConstraints
    )
    # Check the module is installed, and the version constraints are respected
    Write-Host "Checking module '$Name'"
    # NOTE: since there is no way to easily check that a package following version constraints is installed
    # we have to get all versions of a given package and check the versions ourselves..
    $module = (
    Get-Module -Name $Name -ListAvailable
    | Where-Object { Check-VersionAgainstConstraints $_.Version $VersionConstraints }
    | Select-Object -Last 1
    )
    if ($module) {
    Write-Host " 👍 Module '$Name' is already installed"
    }
    else {
    Write-Host " ❌ Module '$Name' is not installed or not at correct version"
    Write-Host " 👉 Installing module '$Name' with version constraints: $($VersionConstraints | ConvertTo-Json -Compress -Depth 10)"
    Install-Module -Name $Name -Force -Scope CurrentUser -SkipPublisherCheck @VersionConstraints
    }
    }
    12 changes: 12 additions & 0 deletions Example-usage.ps1
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    Set-StrictMode -Version 3.0; $ErrorActionPreference = "Stop" # Ensure sane behavior

    Import-Module $PSScriptRoot\..\..\powershell-modules\Pwsh-Testing-Utils.ps1 -force

    # Require PowerShell 7 (version 5 is OLD!)
    Assert-PowerShellVersion -MinimumVersion "7.0.0"

    # Ensure required modules are installed for tests
    Ensure-AllModulesAvailable @{
    "Pester" = @{ MinimumVersion = "5.2.0" }
    "Az" = @{ MinimumVersion = "11.2.0" }
    }