Install-RequiredModule.ps1

<#PSScriptInfo
 
.VERSION 4.0.0
 
.GUID 6083ddaa-3951-4482-a9f7-fe115ddf8021
 
.AUTHOR Joel 'Jaykul' Bennett
 
.COMPANYNAME PoshCode
 
.COPYRIGHT Copyright 2019, Joel Bennett
 
.TAGS Install Modules Development ModuleBuilder
 
.LICENSEURI https://github.com/PoshCode/ModuleBuilder/blob/master/LICENSE
 
.PROJECTURI https://github.com/PoshCode/ModuleBuilder/
 
.ICONURI https://github.com/PoshCode/ModuleBuilder/blobl/resources/images/install.png
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
    4.0.0 Breaking change: require the -Destination to start empty (allow -CleanDestination to clear it)
          Fix for adding the destination to PSModulePath multiple times
          Started testing this so I can ship it to PowerShellGet
    3.0.0 Breaking change: switch -SkipImport to -Import -- inverting the logic to NOT import by default
          Add -Destination parameter to support installing in a local tool path
    2.0.1 Squash mistaken "InstallError" message caused by Select-Object -First
          Clean up output that was unexpected
    2.0.0 Breaking change: use NuGetVersion to support wildcards like 3.*
          Improve the error messages around aborted or failed installs
    1.0.1 Fix "Version '3.4.0' of module 'Pester' is already installed"
    1.0.0 This is the first public release - it probably doesn't work right
 
.PRIVATEDATA
 
#>


<#
.SYNOPSIS
    Installs (and imports) modules listed in RequiredModules.psd1
.DESCRIPTION
    Parses a RequiredModules.psd1 listing modules and attempts to import those modules.
    If it can't find the module in the PSModulePath, attempts to install it from PowerShellGet.
 
    The RequiredModules list looks like this (uses nuget version range syntax):
    @{
        "PowerShellGet" = "2.0.4"
        "Configuration" = "[1.3.1,2.0)"
        "Pester" = "[4.4.2,4.7.0]"
    }
 
    https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards
 
.EXAMPLE
    Install-RequiredModule
 
    Runs the install interactively:
    - reads the default 'RequiredModules.psd1' from the current folder
    - prompts for each module that needs to be installed
.EXAMPLE
    Save-Script Install-RequiredModule -Path .
    .\Install-RequiredModule.ps1 -Path .\RequiredModules.psd1 -Confirm:$false
 
    This example shows how to use this in a build where you're downloading the script
    and then running it in automation (without "confirm" prompting)
#>

using namespace NuGet.Versioning
using namespace Microsoft.PowerShell.Commands
# NOTE: Requires -Module PowerShellGet is missing here because we assume the version included in PowerShell 5+ is good enough
# If you need a higher version (which you very well may) you should put that at the top of your RequiredModules manifest

[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")]
param(
    # The path to a metadata file listing required modules. Defaults to "RequiredModules.psd1" (in the current working directory).
    [Parameter(Position = 0)]
    [Alias("Path")]
    [string]$RequiredModulesFile = "RequiredModules.psd1",


    # If set, the local tools Destination path will be cleared and recreated
    [Parameter(ParameterSetName = "LocalTools")]
    [Switch]$CleanDestination,

    # If set, saves the modules to a local path rather than installing them to the scope
    [Parameter(ParameterSetName="LocalTools", Position = 0)]
    [string]$Destination,

    # The scope in which to install the modules (defaults to "CurrentUser")
    [ValidateSet("CurrentUser", "AllUsers")]
    $Scope = "CurrentUser",

    # If set, the modules are download or installed but not imported
    [Switch]$Import
)

begin {
    Write-Progress "Installing Required Modules from $RequiredModulesFile" -Id 0
    # we use this little hack to ensure NuGet types are available
    if (-not ("NuGet.Versioning.VersionRange" -as [Type])) {
        $EncodedCompressedFile = '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'

        $UncompressedFileBytes = [byte[]]::new(52488)
        $DeflatedStream = [System.IO.Compression.DeflateStream]::new(
            [IO.MemoryStream][Convert]::FromBase64String($EncodedCompressedFile),
            [IO.Compression.CompressionMode]::Decompress)
        $null = $DeflatedStream.Read($UncompressedFileBytes, 0, 52488)
        $null = [Reflection.Assembly]::Load($UncompressedFileBytes)

    }

    filter GetModuleVersion {
        # PowerShell does the wrong thing with MaximumVersion so we get all versions and check them
        [CmdletBinding()]param(
            [AllowNull()][string]$Destination,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][string]$Name,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][VersionRange]$Version
        )
        Write-Progress "Searching PSModulePath for '$Name' module with version '$Version'" -Id 1 -ParentId 0
        $Found = (Get-Module $Name -ListAvailable -Verbose:$false).Where({
                    (!$Destination -or $_.ModuleBase.ToUpperInvariant().StartsWith($Destination.ToUpperInvariant())) -and
                    (
                        ($Version.Float -and $Version.Float.Satisfies($_.Version.ToString())) -or
                        (!$Version.Float -and $Version.Satisfies($_.Version.ToString()))
                    )
                    # Get returns modules in PSModulePath and then Version order, you're not necessarily getting the highest valid version
                }, "First", 1)
        if (-not $Found) {
            Write-Warning "Unable to find module '$Name' installed with version '$Version'"
        } else {
            Write-Verbose "Found '$Name' installed already with version '$($Found.Version)'"
            $Found
        }
    }

    filter FindModuleVersion {
        # PowerShellGet also does the wrong thing with MaximumVersion so we get all versions and check them
        [CmdletBinding()]param(
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][string]$Name,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][VersionRange]$Version
        )
        Write-Progress "Searching PSRepository for '$Name' module with version '$Version'" -Id 1 -ParentId 0

        $Found = (Find-Module -Name $Name -AllVersions -Verbose:$false ).Where({
                    ($Version.Float -and $Version.Float.Satisfies($_.Version.ToString())) -or
                    (!$Version.Float -and $Version.Satisfies($_.Version.ToString()))
                }, "First", 1)

        if (-not $Found) {
            Write-Warning "Unable to resolve dependency '$Name' with version '$Version'"
        } else {
            Write-Verbose "Found '$Name' to install with version '$($Found.Version)'"
            $Found
        }
    }

    function ImportRequiredModulesFile {
        # Load a requirements file
        [CmdletBinding()]param(
            $RequiredModulesFile
        )

        $RequiredModulesFile = Convert-Path $RequiredModulesFile
        Write-Progress "Loading Required Module list from '$RequiredModulesFile'" -Id 1 -ParentId 0
        $LocalizedData = @{
            BaseDirectory = [IO.Path]::GetDirectoryName($RequiredModulesFile)
            FileName = [IO.Path]::GetFileNameWithoutExtension($RequiredModulesFile)
        }
        (Import-LocalizedData @LocalizedData).GetEnumerator().ForEach({
            [PSCustomObject]@{
                Name = $_.Key
                Version = [VersionRange]$_.Value
            }
        })
    }

    filter InstallModuleVersion {
        [CmdletBinding()]param(
            [AllowNull()][string]$Destination,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][string]$Name,
            [Parameter(ValueFromPipelineByPropertyName, Mandatory)][string]$Version # This has to stay [string]
        )
        Write-Progress "Installing module '$($Name)' with version '$($Version)' from the PSGallery"
        if ($Destination) {
            Save-Module -Name $Name -RequiredVersion $Version -Path $Destination
        } else {
            $Preferences = @{
                Verbose            = $VerbosePreference -eq "Continue"
                Confirm            = $ConfirmPreference -ne "None"
                Scope              = $Scope
                Repository         = "PSGallery"
                SkipPublisherCheck = $true
                AllowClobber       = $true
                RequiredVersion    = $Version
                Name               = $Name
            }

            # Install missing modules with -AllowClobber and -SkipPublisherCheck because PowerShellGet requires both
            Install-Module @Preferences -ErrorAction Stop
        }

        if (GetModuleVersion @PSBoundParameters -WarningAction SilentlyContinue) {
            $PSCmdlet.WriteInformation("Installed module '$($Name)' with version '$($Version)' from the PSGallery", "PSHOST")
        } else {
            $PSCmdlet.WriteError(
                [System.Management.Automation.ErrorRecord]::new(
                    [Exception]::new("Failed to install module '$($Name)' with version '$($Version)' from the PSGallery"),
                    "InstallModuleDidnt",
                    "NotInstalled", $module))
        }
    }

    function Install-RequiredModule {
        [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "High")]
        param(
            # The path to a metadata file listing required modules. Defaults to "RequiredModules.psd1" (in the current working directory).
            [Parameter(Position = 0)]
            [Alias("Path")]
            [string]$RequiredModulesFile = "RequiredModules.psd1",


            # If set, the local tools Destination path will be cleared and recreated
            [Parameter(ParameterSetName = "LocalTools")]
            [Switch]$CleanDestination,

            # If set, saves the modules to a local path rather than installing them to the scope
            [Parameter(ParameterSetName = "LocalTools", Position = 0)]
            [string]$Destination,

            # The scope in which to install the modules (defaults to "CurrentUser")
            [ValidateSet("CurrentUser", "AllUsers")]
            $Scope = "CurrentUser",

            # If set, the modules are download or installed but not imported
            [Switch]$Import
        )

        if (-Not (Test-Path $RequiredModulesFile -PathType Leaf)) {
            $PSCmdlet.WriteError(
                [System.Management.Automation.ErrorRecord]::new(
                    [Exception]::new("RequiredModules file '$($RequiredModulesFile)' not found."),
                    "RequiredModules.psd1 Not Found",
                    "ResourceUnavailable", $RequiredModulesFile))
            return
        }

        if ($Destination) {
            if (-not (Test-Path $Destination -PathType Container)) {
                New-Item $Destination -ItemType Directory
            }
            if (-not $CleanDestination) {
                if (Get-ChildItem $Destination) {
                    $PSCmdlet.WriteError(
                        [System.Management.Automation.ErrorRecord]::new(
                            [Exception]::new("Destination folder '$($Destination)' not empty."),
                            "Destination Not Empty",
                            "ResourceUnavailable", $Destination))
                    return
                }
            }
            if ($CleanDestination -and (Get-ChildItem $Destination)) {
                Write-Warning "CleanDestination specified: Removing $($Destination) and all it's children:"
                try {
                    Remove-Item $Destination -Recurse -ErrorAction Stop # No -Force -- if this fails, you should handle it yourself
                    New-Item $Destination -ItemType Directory
                } catch {
                    $PSCmdlet.WriteError(
                        [System.Management.Automation.ErrorRecord]::new(
                            [Exception]::new("Failed to clean destination folder '$($Destination)'"),
                            "Destination Cannot Be Emptied",
                            "ResourceUnavailable", $Destination))
                    return
                }
            }
        }

        Write-Progress "Verifying PSRepository trust" -Id 1 -ParentId 0

        # Force Policy to Trusted so we can install without prompts and without -Force which is bad
        # TODO: Add support for all registered PSRepositories
        if ('Trusted' -ne ($Policy = (Get-PSRepository PSGallery).InstallationPolicy)) {
            Set-PSRepository PSGallery -InstallationPolicy Trusted
        }

        if ($Destination) {
            # make sure we don't do this multiple times
            $RealDestination = Convert-Path $Destination
            if (-not ($Env:PSModulePath.Split([IO.Path]::PathSeparator) -contains $RealDestination)) {
                $Env:PSModulePath = $RealDestination + [IO.Path]::PathSeparator + $Env:PSModulePath
            }
        }

        try {
            ImportRequiredModulesFile $RequiredModulesFile -OV Modules |
                Where-Object { -not ($_ | GetModuleVersion -WarningAction SilentlyContinue) } |
                FindModuleVersion |
                InstallModuleVersion -Destination:$Destination -ErrorVariable InstallErrors
        } finally {
            # Put Policy back so we don't needlessly change environments permanently
            if ('Trusted' -ne $Policy) {
                Set-PSRepository PSGallery -InstallationPolicy $Policy
            }
        }
        Write-Progress "Importing Modules" -Id 1 -ParentId 0

        if ($Import) {
            Remove-Module $Modules.Name -Force
            $Modules | GetModuleVersion | Import-Module -Passthru -Verbose:$false
        } elseif ($InstallErrors) {
            Write-Warning "Module import skipped because of install errors"
            Wait-Debugger
        } else {
            Write-Warning "Module import skipped"
        }

        Write-Progress "Done" -Id 0 -Completed
    }
}
end {
    Install-RequiredModule @PSBoundParameters
}