sdwheeler.ReleaseInfo.psm1
|
#------------------------------------------------------- #region Private functions #------------------------------------------------------- function GetGraphQLQuery { param( [string]$org, [string]$repo, [string]$after ) $GraphQLQuery = @" query { repository(name: "$repo", owner: "$org") { releases(first: 100, after: $after, orderBy: {field: CREATED_AT, direction: DESC}) { nodes { publishedAt name tagName url } pageInfo { hasNextPage endCursor } } } } "@ return $GraphQLQuery } #------------------------------------------------------- $eolCategories = (Invoke-RestMethod https://endoflife.date/api/v1/categories).result #------------------------------------------------------- #endregion module variables #------------------------------------------------------- #region Public functions #------------------------------------------------------- function Find-PmcPackages { <# .SYNOPSIS Gets information about PowerShell packages from the Microsoft Package Cache (PMC). .DESCRIPTION Gets information about PowerShell packages that are published to https://packages.microsoft.com. By default, packages for all supported distributions are returned, but you can filter by specific distribution(s) using the -Distribution parameter. .PARAMETER Distribution The distribution(s) to filter by. Valid values are 'debian', 'ubuntu', 'rhel', 'azurelinux'. You can specify multiple values for this parameter. If not specified, packages for all supported distributions are returned. #> param( [ValidateSet('debian', 'ubuntu', 'rhel', 'azurelinux')] [string[]]$Distribution ) if ($IsWindows) { $gitcmd = Get-Command git -ErrorAction SilentlyContinue $gitroot = $gitcmd.Path -replace 'cmd\\git.exe', '' $toolpath = Join-Path $gitroot 'usr\bin\gzip.exe' $gzipcmd = Get-Command $toolpath -ErrorAction SilentlyContinue } else { $gzipcmd = Get-Command gzip -ErrorAction SilentlyContinue } if ($null -eq $gzipcmd) { Write-Error 'gzip command not found' return } if (Test-Path "$env:temp\repodata") { $null = Remove-Item -Path "$env:temp\repodata" -Recurse -Force $null = New-Item -ItemType Directory -Path "$env:temp\repodata" } else { $null = New-Item -ItemType Directory -Path "$env:temp\repodata" } $pmcVersionInfo = Get-Content -Path "$PSScriptRoot\PmcVersionInfo.json" | ConvertFrom-Json $versions = $pmcVersionInfo.versions $debrepos = $pmcVersionInfo.debrepos $rpmrepos = $pmcVersionInfo.rpmrepos if ($null -ne $Distribution) { $repolist = foreach ($distro in $Distribution) { $debrepos | Where-Object { $_.distro -like "$distro*" } } } else { $repolist = $debrepos } # Download and parse DEB package information foreach ($repo in $repolist) { # Get package metadata $lines = (Invoke-RestMethod -Uri $repo.packages) -split '\n' | Select-String -Pattern '^Package:|^Version:|^Filename:' | Select-Object -ExpandProperty Line # Filter and select package information $packages = @() for ($i = 0; $i -lt $lines.Count; $i += 3) { $pkg = [pscustomobject]($lines[$i..($i + 2)] | ConvertFrom-Yaml) if ($pkg.Package -match '^powershell' -and $pkg.Version -match '^7\.\d+') { $packages += $pkg } } # Normalize version strings $packages | ForEach-Object { $_.Version = $_.Version -replace '-1.ubuntu.\d\d.\d\d|-1.deb', '' } # Enumerate stable packages foreach ($ver in $versions.stable) { $package = $packages | Where-Object { $_.Version -like $ver -and $_.Package -eq 'powershell'} | Sort-Object {[semver]($_.Version)} -Descending | Select-Object -First 1 if ($package) { [pscustomobject]@{ PSTypeName = 'PmcData' distro = $repo.distro version = [semver]$package.Version channel = 'stable' processor = $repo.processor package = ($package.Filename -split '/')[-1] } } } # Enumerate lts packages foreach ($ver in $versions.lts) { $package = $packages | Where-Object { $_.Version -like $ver -and $_.Package -eq 'powershell-lts'} | Sort-Object {[semver]($_.Version)} -Descending | Select-Object -First 1 if ($package) { [pscustomobject]@{ PSTypeName = 'PmcData' distro = $repo.distro version = [semver]$package.Version channel = 'lts' processor = $repo.processor package = ($package.Filename -split '/')[-1] } } } # Enumerate preview packages foreach ($ver in $versions.preview) { $package = $packages | Where-Object { $_.Version -like $ver -and $_.Package -eq 'powershell-preview'} | Sort-Object {[semver]($_.Version)} -Descending | Select-Object -First 1 if ($package) { [pscustomobject]@{ PSTypeName = 'PmcData' distro = $repo.distro version = [semver]$package.Version channel = 'preview' processor = $repo.processor package = ($package.Filename -split '/')[-1] } } } } # RPM-based packages have XML metadata if ($null -ne $Distribution) { $repolist = foreach ($distro in $Distribution) { $rpmrepos | Where-Object { $_.distro -like "$distro*" } } } else { $repolist = $rpmrepos } # Download and parse RPM package information foreach ($repo in $repolist) { # Get repo metadata $xml = [xml](Invoke-WebRequest -Uri $repo.mdxml).Content $primarypath = ($xml.repomd.data | Where-Object type -eq primary).location.href # Get package metadata $primaryurl = $repo.mdxml -replace 'repodata/repomd.xml', $primarypath Invoke-WebRequest -Uri $primaryurl -OutFile "$env:temp\$primarypath" $primary = [xml](& $gzipcmd -d -c "$env:temp\$primarypath") # Filter and select package information $packages = $primary.metadata.package | Where-Object { $_.name -match '^powershell' -and $_.version.ver -match '^7\.\d+' } $results = @() # Enumerate stable packages foreach ($ver in $versions.stable) { $package = $packages | Where-Object { $_.version.ver -like $ver -and $_.name -eq 'powershell'} | Sort-Object {[semver]($_.version.ver -replace '_','-')} -Descending | Select-Object -First 1 if ($package) { $results += [pscustomobject]@{ PSTypeName = 'PmcData' distro = $repo.distro version = [semver]$package.version.ver channel = 'stable' processor = $repo.processor package = ($package.location.href -split '/')[-1] } } } # Enumerate lts packages foreach ($ver in $versions.lts) { $package = $packages | Where-Object { $_.version.ver -like $ver -and $_.name -eq 'powershell-lts'} | Sort-Object {[semver]($_.version.ver -replace '_','-')} -Descending | Select-Object -First 1 if ($package) { $results += [pscustomobject]@{ PSTypeName = 'PmcData' distro = $repo.distro version = [semver]$package.version.ver channel = 'lts' processor = $repo.processor package = ($package.location.href -split '/')[-1] } } } # Enumerate preview packages foreach ($ver in $versions.preview) { $package = $packages | Where-Object { $_.version.ver -like $ver -and $_.name -eq 'powershell-preview'} | Sort-Object {[semver]($_.version.ver -replace '_','-')} -Descending | Select-Object -First 1 if ($package) { $results += [pscustomobject]@{ PSTypeName = 'PmcData' distro = $repo.distro version = [semver]($package.version.ver -replace '_','-') channel = 'preview' processor = $repo.processor package = ($package.location.href -split '/')[-1] } } } $results | Sort-Object distro, version, channel, processor } } #------------------------------------------------------- function Find-DotnetDockerInfo { <# .SYNOPSIS Gets information about .NET SDK Docker images that have PowerShell installed from the dotnet/dotnet-docker repository. .DESCRIPTION Gets information about .NET SDK Docker images that have PowerShell installed from the dotnet/dotnet-docker repository. You must have a local clone of the repository to use this command, and you must specify the path to the repository with the -Path parameter. The command extracts the information from the Dockerfile images in the src/sdk directory. .PARAMETER Path The path to the local clone of the dotnet/dotnet-docker repository. #> param( [string]$Path = 'D:\Git\PS-Src\dotnet-docker\src\sdk' ) $images = Get-ChildItem -Path $Path -Include dockerfile -Recurse | Select-String 'powershell_version[\n\s]*=|POWERSHELL_DISTRIBUTION_CHANNEL' | Select-Object Path, Line | Group-Object Path | Where-Object Count -ge 2 $results = foreach ($image in $images) { $psver = $os = '' $imagePath = $image.Group.Path[0] -replace [regex]::Escape($Path), '' foreach ($line in $image.Group.Line) { $value = if ($line -match '.+=([^\s]+)') { $Matches[1] } if ($line -like '*powershell_version*') { $psver = $value } else { $os = $value -replace 'PSDocker-DotnetSDK-','' } } if ($psver -ge '7.4') { $parts = $imagePath -split [regex]::Escape([System.IO.Path]::DirectorySeparatorChar) [pscustomobject]@{ PSTypeName = 'DockerInfo' family = switch -wildcard ($parts[2]) { '*mariner*' { 'Mariner' } '*azure*' { 'AzureLinux' } '*nano*' { 'Windows' } '*windows*' { 'Windows' } '*jammy*' { 'Ubuntu' } '*noble*' { 'Ubuntu' } '*resolute*' { 'Ubuntu' } '*alpine*' { 'Alpine' } '*bookworm*' { 'Debian' } '*trixie*' { 'Debian' } } os = if ($os -ne '') { $os } else { $parts[2] } dotnetver = [version]$parts[1] arch = $parts[3] psver = $psver } } } $results | Sort-Object family, os, dotnetver, arch } #------------------------------------------------------- function Find-DockerImages { <# .SYNOPSIS Gets information about PowerShell-based Docker images from the Microsoft Container Registry (MAR). .DESCRIPTION Gets information about PowerShell-based Docker images from MAR. By default, images for all supported distributions are returned, but you can filter by specific distribution(s) using the -Distribution parameter. .PARAMETER Distribution The distribution(s) to filter by. Valid values are 'debian', 'ubuntu', 'rhel', 'azurelinux', 'alpine', 'windows'. You can specify multiple values for this parameter. If not specified, images for all supported distributions are returned. .NOTES These Docker images are no longer maintained. Use the .NET SDK Docker images instead. #> param( [ValidateSet('debian', 'ubuntu', 'rhel', 'azurelinux', 'alpine', 'windows')] [string[]]$Distribution = ( 'debian', 'ubuntu', 'rhel', 'azurelinux', 'alpine', 'windows' ) ) $baseUrl = 'https://mcr.microsoft.com/api/v1/catalog/powershell' $supportedTags = Invoke-RestMethod "$baseUrl/details?reg=mar" | Select-Object -ExpandProperty supportedTags $allTags = Invoke-RestMethod "$baseUrl/tags?reg=mar" $images = $allTags | Where-Object name -in $supportedTags foreach ($i in $images) { if ($i.operatingSystem -eq 'linux') { switch -Regex ($i.name) { 'alpine' { $i.operatingSystem = 'alpine' } 'debian' { $i.operatingSystem = 'debian' } 'ubuntu' { $i.operatingSystem = 'ubuntu' } 'azurelinux' { $i.operatingSystem = 'azurelinux' } 'ubi' { $i.operatingSystem = 'rhel' } } } } $images | Where-Object operatingSystem -in $Distribution | Sort-Object -Property operatingSystem, name | Select-Object -Property name, operatingSystem, architecture, @{n='modifiedDate';e={'{0:yyyy-MM-dd}' -f $_.lastModifiedDate}} } #------------------------------------------------------- function Get-OSEndOfLife { <# .SYNOPSIS Gets end of life information for operating systems supported by PowerShell from https://endoflife.date. .DESCRIPTION Gets end of life information for operating systems supported by PowerShell.By default, all supported operating systems are included, but you can filter by specific operating system. The command only shows the supported versions. If you want the whole release history, use the Get-EndOfLife command. .PARAMETER OS The operating system to query. You can use tab completion with the parameter to see available operating systems. .EXAMPLE Get-OSEndOfLife macos os cycle latest codename support eol extendedSupport lts -- ----- ------ -------- ------- --- --------------- --- macos 26 26.3 Tahoe False False macos 15 15.7.4 Sequoia False False macos 14 14.8.4 Sonoma False False #> param ( [Parameter(Position = 0)] [ArgumentCompletions('alpine', 'debian', 'macos', 'rhel', 'ubuntu', 'wincli', 'winsrv')] [string[]]$OS = ('alpine', 'debian', 'macos', 'rhel', 'ubuntu', 'wincli', 'winsrv') ) $links = [ordered]@{ alpine = 'https://endoflife.date/api/alpine.json' centos = 'https://endoflife.date/api/centos.json' debian = 'https://endoflife.date/api/debian.json' macos = 'https://endoflife.date/api/macos.json' opensuse = 'https://endoflife.date/api/opensuse.json' rhel = 'https://endoflife.date/api/rhel.json' ubuntu = 'https://endoflife.date/api/ubuntu.json' wincli = 'https://endoflife.date/api/windows.json' winsrv = 'https://endoflife.date/api/windows-server.json' } $today = '{0:yyyy-MM-dd}' -f (Get-Date) $results = $links.GetEnumerator().Where({$_.Name -in $OS}) | ForEach-Object -Parallel { $name = $_.Name (Invoke-RestMethod $_.Value) | Where-Object { $_.eol -gt $using:today -or $_.eol -eq $false } | ForEach-Object { [pscustomobject]@{ PSTypeName = 'EolData' os = $name cycle = $_.cycle latest = $_.latest codename = $_.codename releaseDate = $_.releaseDate latestReleaseDate = $_.latestReleaseDate support = $_.support eol = $_.eol extendedSupport = $_.extendedSupport lts = $_.lts link = $_.link } } } $results | Sort-Object os } #------------------------------------------------------- function Get-EndOfLife { <# .SYNOPSIS Gets end of life information for products from https://endoflife.date. .DESCRIPTION Gets end of life information for products from https://endoflife.date. When you specify a Category, the command return a list of products in that category. Use that information to find the product name. When you specify a product name, the command returns all of its releases for that product. .PARAMETER Name The name of the product to query. The command uses regular expression matching for that value. .PARAMETER Category The category to query. The parameter supports wildcards. You can use tab completion with the parameter to see available categories. .EXAMPLE Get-EndOfLife -Category standard name category product uri ---- -------- ------- --- pci-dss standard PCI-DSS https://endoflife.date/api/v1/products/pci-dss tls standard TLS https://endoflife.date/api/v1/products/tls .EXAMPLE Get-EndOfLife debian product release codename releaseDate isEol isLts eolDate name ------- ------- -------- ----------- ----- ----- ------- ---- Debian 13 Trixie 2025-08-09 False False 2028-08-09 debian Debian 12 Bookworm 2023-06-10 False False 2026-06-10 debian Debian 11 Bullseye 2021-08-14 True False 2024-08-14 debian Debian 10 Buster 2019-07-06 True False 2022-09-10 debian Debian 9 Stretch 2017-06-17 True False 2020-07-18 debian Debian 8 Jessie 2015-04-25 True False 2018-06-17 debian Debian 7 Wheezy 2013-05-04 True False 2016-04-25 debian Debian 6 Squeeze 2011-02-06 True False 2014-05-31 debian Debian 5 Lenny 2009-02-14 True False 2012-02-06 debian Debian 4 Etch 2007-04-08 True False 2010-02-15 debian Debian 3.1 Sarge 2005-06-06 True False 2008-03-31 debian Debian 3.0 Woody 2002-07-19 True False 2006-06-30 debian Debian 2.2 Potato 2000-08-15 True False 2003-06-30 debian Debian 2.1 Slink 1999-03-09 True False 2000-09-30 debian Debian 2.0 Hamm 1998-07-24 True False 1999-02-15 debian Debian 1.3 Bo 1997-07-02 True False 1998-12-08 debian Debian 1.2 Rex 1996-12-12 True False 1997-10-23 debian Debian 1.1 Buzz 1996-06-17 True False 1996-12-12 debian #> [CmdletBinding(DefaultParameterSetName='ByName')] param ( [Parameter(Position = 0, ParameterSetName='ByName')] [string[]]$Name, [Parameter(ParameterSetName='ListCategories')] [SupportsWildcards()] [string[]]$Category ) if ($Category.Count -ne 0) { $categories = foreach ($cat in $Category) { ($eolCategories | Where-Object name -like $cat).uri } if ($Category -ne '') { foreach ($cat in $categories) { (Invoke-RestMethod $cat).result | Sort-Object -Property label, category | Select-Object -Property name, category, @{n='product'; e={$_.label}}, uri } return } } if ($Name.Count -ne 0) { $products = (Invoke-RestMethod https://endoflife.date/api/v1/products).result foreach ($n in $Name) { $plist = $products | Where-Object name -match $n if ($plist.Count -lt 1) { Write-Warning "Product '$n' not found." continue } foreach ($p in $plist) { $item = (Invoke-RestMethod $p.uri).result foreach ($release in $item.releases) { [pscustomobject]@{ PSTypeName = 'EolProductData' product = $item.label release = $release.name codename = $release.codename releaseDate = $release.releaseDate isEol = $release.isEol isLts = $release.isLts eolDate = $release.eolFrom name = $item.name } } } } } } #------------------------------------------------------- function Get-DSCReleaseHistory { <# .SYNOPSIS Gets release history for DSC releases. .DESCRIPTION Gets release history for DSC v3 releases. By default, only the latest release for each major.minor version is returned, but this can be modified with the available parameters. This command uses the GitHub GraphQL API to query release information. To use this command, a GitHub personal access token is required. The token should be stored in an environment variable named GITHUB_TOKEN. .PARAMETER AllVersions If specified, all releases are returned. Otherwise, only the latest release for each major.minor version is returned. #> param( [switch]$AllVersions ) $query = GetGraphQLQuery -org 'PowerShell' -repo 'DSC' -after 'null' $irmSplat = @{ Headers = @{ Authorization = "bearer $env:GITHUB_TOKEN" Accept = 'application/vnd.github.v4.json' } Uri = 'https://api.github.com/graphql' Body = @{ query = $query } | ConvertTo-Json -Compress Method = 'POST' } $hasNextPage = $true $history = while ($hasNextPage) { $result = Invoke-RestMethod @irmSplat $result.data.repository.releases.nodes | Select-Object @{n = 'Version'; e = { $_.tagName.Substring(0, 4) } }, @{n = 'Tag'; e = { $_.tagName } }, @{n = 'Date'; e = { '{0:yyyy-MM-dd}' -f $_.publishedAt } } $hasNextPage = $result.data.repository.releases.pageInfo.hasNextPage $after = '"',$result.data.repository.releases.pageInfo.endCursor,'"' -join '' $query = GetGraphQLQuery -org 'PowerShell' -repo 'PowerShell' -after $after $irmSplat.Body = @{ query = $query} | ConvertTo-Json -Compress } if ($AllVersions) { $history } else { $history | Group-Object Version | Sort-Object Name -Descending | ForEach-Object { $_.Group | Select-Object -First 1 } } } #------------------------------------------------------- function Get-PSReleaseHistory { <# .SYNOPSIS Gets release history for PowerShell releases. .DESCRIPTION Gets release history for PowerShell releases. By default, only the latest release for each major.minor version is returned, but this can be modified with the available parameters. This command uses the GitHub GraphQL API to query release information. To use this command, a GitHub personal access token is required. The token should be stored in an environment variable named GITHUB_TOKEN. .PARAMETER Version The major.minor version to filter by (e.g. '7.5'). If not specified, the latest release for each major.minor version are returned. .PARAMETER Current If specified, only releases for the currently running version ofPowerShell are returned. .PARAMETER GeneralAvailability If specified, only GA releases (i.e. tags that end with '.0') are returned. .PARAMETER All If specified, all releases are returned. .EXAMPLE Get-PSReleaseHistory Version Tag ReleaseDate DotnetVersion SupportType EndOfSupport ------- --- ----------- ------------- ----------- ------------ v7.6 v7.6.0-rc.1 2026-02-20 .NET 10.0 Preview v7.5 v7.5.4 2025-10-20 .NET 9.0 STS 2026-05-12 v7.4 v7.4.13 2025-10-20 .NET 8.0 LTS 2026-11-10 v7.3 v7.3.12 2024-04-11 .NET 7.0 STS 2024-05-08 v7.2 v7.2.24 2024-10-22 .NET 6.0 LTS 2024-11-08 v7.1 v7.1.7 2022-04-26 .NET 5.0 STS 2022-05-08 v7.0 v7.0.13 2022-10-20 .NET Core 3.1 LTS 2022-12-03 v6.2 v6.2.7 2020-07-16 .NET Core 2.1 STS 2020-09-04 v6.1 v6.1.6 2019-09-12 .NET Core 2.1 STS 2019-09-28 v6.0 v6.0.5 2018-11-13 .NET Core 2.0 STS 2019-02-13 #> [CmdletBinding(DefaultParameterSetName = 'ByVersion')] param( [Parameter(ParameterSetName = 'ByVersion', Position = 0)] [string]$Version, [Parameter(ParameterSetName = 'Current')] [switch]$Current, [Parameter(ParameterSetName = 'ByVersion')] [Parameter(ParameterSetName = 'Current')] [Alias('GA')] [switch]$GeneralAvailability, [Parameter(ParameterSetName = 'ShowAll')] [switch]$All ) $history = @() $lifecycle = Get-Content -Path $PSScriptRoot\PowerShellLifecycle.jsonc | ConvertFrom-Json -AsHashtable $query = GetGraphQLQuery -org 'PowerShell' -repo 'PowerShell' -after 'null' $irmSplat = @{ Headers = @{ Authorization = "bearer $env:GITHUB_TOKEN" Accept = 'application/vnd.github.v4.json' } Uri = 'https://api.github.com/graphql' Body = @{ query = $query} | ConvertTo-Json -Compress Method = 'POST' } $hasNextPage = $true while ($hasNextPage) { $irmSplat.Body = @{ query = $query} | ConvertTo-Json -Compress $result = Invoke-RestMethod @irmSplat $result.data.repository.releases.nodes | Where-Object tagName -gt 'v5.1' | ForEach-Object { $history += [pscustomobject]@{ PSTypeName = 'ReleaseInfoData' Version = $_.tagName.Substring(0, 4) Tag = $_.tagName ReleaseDate = '{0:yyyy-MM-dd}' -f $_.publishedAt DotnetVersion = $lifecycle[$_.tagName.Substring(0, 4)].Dotnet SupportType = if ($_.tagName -like '*-*') { 'Preview' } else { $lifecycle[$_.tagName.Substring(0, 4)].Support } EndOfSupport = $lifecycle[$_.tagName.Substring(0, 4)].EndOfSupport ReleaseUrl = $_.url } } $hasNextPage = $result.data.repository.releases.pageInfo.hasNextPage $after = '"',$result.data.repository.releases.pageInfo.endCursor,'"' -join '' $query = GetGraphQLQuery -org 'PowerShell' -repo 'PowerShell' -after $after } switch ($PSCmdlet.ParameterSetName) { 'ByVersion' { if ($Version -eq '') { $groupedByVersion = $history | Group-Object Version | Sort-Object Name -Descending if ($GeneralAvailability) { $groupedByVersion | ForEach-Object { $_.Group | Where-Object Tag -Like '*.0' } } else { $groupedByVersion | ForEach-Object { $_.Group | Select-Object -First 1 } } } else { if ($GeneralAvailability) { $history | Where-Object Version -EQ $Version | Where-Object Tag -Like '*.0' } else { $history | Where-Object Version -EQ $Version } } break } 'Current' { $Version = ('v{0}' -f $PSVersionTable.PSVersion.ToString().SubString(0, 3)) if ($GeneralAvailability) { $history | Where-Object Version -EQ $Version | Where-Object Tag -Like '*.0' } else { $history | Where-Object Version -EQ $Version } break } 'ShowAll' { $history } } } #------------------------------------------------------- function Get-PSReleasePackage { <# .SYNOPSIS Gets release assets for a given PowerShell release tag. .DESCRIPTION Gets release assets for a given PowerShell release tag. If a file name is specified, only the asset with that name is downloaded. Otherwise, all assets are listed. This command uses the GitHub REST API to query release information. To use this command, a GitHub personal access token is required. The token should be stored in an environment variable named GITHUB_TOKEN. .PARAMETER Tag The release tag to query. .PARAMETER FileName The name of the asset to download. If not specified, the command lists the available assets. .PARAMETER OutputPath The directory to which assets will be downloaded. Defaults to the current directory. .EXAMPLE Get-PSReleasePackage v7.5.4 PowerShell-7.5.4-win-x64.msi This example downloads PowerShell-7.5.4-win-x64.msi to the current directory. #> param( [Parameter(Mandatory, Position = 0)] [ValidatePattern('^v\d\.\d+\.\d+(-\p{L}+\.?\d*)?$')] [string]$Tag, [Parameter(Position = 1)] [string[]]$FileName, [Parameter(Position = 2)] [string]$OutputPath = '.' ) try { $irmSplat = @{ Headers = @{ Accept = 'application/vnd.github.v4.json' Authorization = "bearer $env:GITHUB_TOKEN" } Uri = "https://api.github.com/repos/PowerShell/PowerShell/releases/tags/$tag" ErrorAction = 'Stop' } $release = Invoke-RestMethod @irmSplat if ($release.assets.Count -eq 0) { Write-Warning "No assets found for release '$Tag'." return } } catch { Write-Error ("Error fetching release tag '$Tag'." + [Environment]::NewLine + $_.Exception.Message) } if ($FileName.Count -eq 0) { $release.assets | Select-Object name, size, browser_download_url } else { $release.assets | Where-Object name -in $FileName | ForEach-Object { $outputFile = Join-Path $OutputPath $_.name Invoke-WebRequest -Uri $_.browser_download_url -OutFile $outputFile Get-Item $outputFile } } } #------------------------------------------------------- #endregion Public functions #------------------------------------------------------- #region Argument completers #------------------------------------------------------- $sbEOLCategories = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $eolCategories | Where-Object { $_.name -like "$wordToComplete*" } | Select-Object -ExpandProperty name } Register-ArgumentCompleter -CommandName Get-EndOfLife -ParameterName Category -ScriptBlock $sbEOLCategories #------------------------------------------------------- #endregion Argument completers #------------------------------------------------------- |