Dependency/Install-Dependency.ps1
#Requires -Version 5.0 using namespace System.Collections.Generic <# .SYNOPSIS .EXAMPLE .DESCRIPTION .NOTES #> function Install-Dependency { [CmdletBinding()] Param( [Parameter()] [PSCustomObject] # All required dependencies for the application $DependencyConfig, [Parameter()] [PSCustomObject] # Repository configuration providing passwords for each repo $RepositoryConfig, [Parameter(ParameterSetName = "DependencyPath", Mandatory)] [Alias('DependencyPath')] [string[]] $DependencyPaths, [Parameter(ParameterSetName = "ScriptName", Mandatory)] [Alias('ScriptName')] [string[]] $ScriptNames, [Parameter()] [string] # The destination folder to install to (if required). If not provided uses the current working directory. Will create Depend-Nuget and Depend-WebDownload folders below this folder. $DestinationFolder, [parameter()] [switch] # By default we won't install if already installed. Force will first remove then install again $Force, [parameter()] [switch] # Automatically import after install $Import, # if set will force the scope (useful for server installation where you want installation to be for all users) [Parameter()] [ValidateSet('', 'AllUsers', 'CurrentUser')] [String] $ForceScope ) try { Set-StrictMode -Version 2 $ErrorActionPreference = "Stop" # get the dependencies asked for $dependencySplat = @{ DestinationFolder = $DestinationFolder } if ($DependencyPaths) { $dependencySplat.Add('DependencyPaths', $DependencyPaths) } if ($ScriptNames) { $dependencySplat.Add('ScriptNames', $ScriptNames) } if ($DependencyConfig) { $dependencySplat.Add('DependencyConfig', $DependencyConfig) } $groupedDependencies = Get-Dependency @dependencySplat if ($ScriptNames) { Write-Host "Installing Dependencies for Scripts: $([string]::Join(', ', $ScriptNames))" } elseif ($DependencyPaths) { Write-Host "Installing Dependencies for Dependency Paths: $([string]::Join(', ', $DependencyPaths))" } # install them foreach ($typeGroup in $groupedDependencies) { if ($typeGroup.Name -eq 'PackageProvider') { foreach ($dependency in $typeGroup.Group) { $splat = @{ Name = $Dependency.name RequiredVersion = $Dependency.Version Force = $Force } Install-DependencyPSPackageProvider } } elseif ($typeGroup.Name -eq 'WebDownload') { foreach ($dependency in $typeGroup.Group) { $splat = @{ Name = $Dependency.name Version = $Dependency.Version Url = $Dependency.Url Destination = $Dependency.destination Force = $Force } Install-DependencyWebDownload @splat } } elseif ($typeGroup.Name -eq 'Module') { foreach ($dependency in $typeGroup.Group) { $splat = @{ Name = $Dependency.name RequiredVersion = $Dependency.Version Force = $Force # ForceImport = [bool]$Dependency.PSObject.Properties['forceImport'] } if ($Dependency.PSObject.Properties['preRelease']) { $splat.Add('PreRelease', $Dependency.PreRelease) } if ($Dependency.PSObject.Properties['allowClobber']) { $splat.Add('AllowClobber', $Dependency.AllowClobber) } if ($ForceScope) { $splat.Add('ForceScope', $ForceScope) } elseif ($Dependency.PSObject.Properties['ForceScope']) { $splat.Add('ForceScope', $Dependency.ForceScope) } if ($Dependency.PSObject.Properties['Repository']) { $splat.Add('Repository', $Dependency.Repository) if ($RepositoryConfig -and $RepositoryConfig.HasProperties() -and $RepositoryConfig.PSObject.Properties[$Dependency.Repository] -and $RepositoryConfig."$($Dependency.Repository)".PSObject.Properties['AdoArtifact'] ) { $artifactConfig = $RepositoryConfig."$($Dependency.Repository)".AdoArtifact ("Artifact Configuration for this Repository" + ($artifactConfig | Format-List | Out-String)) | Write-Verbose if ($artifactConfig.PSObject.Properties['Password']) { $splat.Add('Credential', (Get-CredentialSilently -Username $artifactConfig.Username -Password $artifactConfig.Password)) } } } Install-DependencyPSModule @splat } } elseif ($typeGroup.Name -eq 'Nuget') { $splat = @{ # TODO put nuget in the path so we don't need to absolute it NugetPath = (Join-Path (Split-Path -Parent -Path $typeGroup.Group[0].Destination) 'Depend-WebDownload\NuGet\nuget.exe') Destination = $typeGroup.Group[0].destination } # Install-DependencyNuget @splat $typeGroup.Group | Format-List | Out-String | Write-Verbose $nuGetConfigTemplate = @" <!-- DO NOT CHANGE THIS: This is autogenerated by Install-Dependency so anything you do here will be undone. Use dependencies.global.json to control what gets installed by which script--> <packages>$($typeGroup.Group | Foreach-Object { [string]::format("`n`t<package id=""{0}"" version=""{1}"" />",$_.Name,$_.version)}) </packages> "@ $nuGetConfigFolderName = "Install-Dependency-Nuget$(([IO.Path]::GetFileNameWithoutExtension([IO.Path]::GetRandomFileName())))" $nuGetConfigFolder = "$(Join-Path ($env:TMP) $nuGetConfigFolderName)" try { $null = New-Item -ItemType Directory $nuGetConfigFolder -Force $nuGetConfigPath = Join-Path $nuGetConfigFolder "packages.config" Write-Verbose "Generated File: $nuGetConfigPath `n----------------------------`n$nuGetConfigTemplate`n----------------------------" $null = New-Item -ItemType File -Path $nuGetConfigPath -Value $nuGetConfigTemplate -Force Install-DependencyNuget -ConfigPath $nuGetConfigPath @splat } finally { Remove-Item $nuGetConfigFolder -force -recurse -ErrorAction 'SilentlyContinue' # cleanup, although with whatif this will error so ignore it } } else { Write-Error "Type $($typeGroup.Name) not expected. No installer known" } } if ($Import) { & Import-Dependency @dependencySplat } } catch { throw } } |