Shared/Get-GitLabRepoRelease.ps1
|
function Get-GitLabRepoRelease { <# .SYNOPSIS Calls the GitLab Releases API passed via $Uri, validates the response and returns a formatted object. Supported examples: - https://gitlab.com/api/v4/projects/:id/releases/latest - https://gitlab.com/api/v4/projects/:id/releases - https://gitlab.com/api/v4/projects/:id/repository/tags TODO: support Basic or OAuth authentication to GitLab #> [OutputType([System.Management.Automation.PSObject])] [CmdletBinding(SupportsShouldProcess = $false)] param ( [Parameter(Mandatory = $true, Position = 0)] [ValidateScript({ if ($_ -match "^https://gitlab\.com/api/v4/projects/[^/]+/(releases(?:/latest)?|repository/tags)/?$") { $true } else { throw "'$_' must be in the format 'https://gitlab.com/api/v4/projects/:id/releases/latest', '.../releases', or '.../repository/tags'. Replace ':id' with the project ID." } })] [System.String] $Uri, [Parameter(Mandatory = $false, Position = 1)] [ValidateNotNullOrEmpty()] [System.String] $MatchVersion = "(\d+(\.\d+){1,4}).*", [Parameter(Mandatory = $false, Position = 2)] [ValidateNotNullOrEmpty()] [System.String] $VersionTag = "tag_name", [Parameter(Mandatory = $false, Position = 3)] [ValidateNotNullOrEmpty()] [System.String] $Filter = "\.exe$|\.msi$|\.msp$|\.zip$", [Parameter(Mandatory = $false, Position = 4)] [System.Array] $VersionReplace, [Parameter()] [System.Management.Automation.SwitchParameter] $ReturnVersionOnly ) process { try { # Retrieve releases/tags from GitLab API Write-Verbose -Message "$($MyInvocation.MyCommand): Set TLS to 1.2." [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 $params = @{ ContentType = "application/json" ErrorAction = "Stop" MaximumRedirection = 0 DisableKeepAlive = $true UseBasicParsing = $true UserAgent = (Get-EvergreenUserAgent) Uri = $Uri } if (Test-ProxyEnv) { $params.Proxy = $script:EvergreenProxy } if (Test-ProxyEnv -Creds) { $params.ProxyCredential = $script:EvergreenProxyCreds } # GitLab token support (PAT or bearer token) if (Test-Path -Path "env:GITLAB_TOKEN") { $params.Headers = @{ "PRIVATE-TOKEN" = $env:GITLAB_TOKEN } } foreach ($item in $params.GetEnumerator()) { Write-Verbose -Message "$($MyInvocation.MyCommand): Invoke-RestMethod parameter: $($item.Name): $($item.Value)." } Write-Verbose -Message "$($MyInvocation.MyCommand): Get GitLab data from: $Uri." $apiResponse = Invoke-RestMethod @params } catch { throw $_ } # Normalize to array for consistent handling $release = if ($apiResponse -is [System.Array]) { $apiResponse } else { @($apiResponse) } if ($null -eq $script:resourceStrings.Properties.GitLab) { Write-Warning -Message "$($MyInvocation.MyCommand): Unable to validate release against GitLab releases property object because module resources were not found." } else { Write-Verbose -Message "$($MyInvocation.MyCommand): Validating GitLab release object." foreach ($item in $release) { $compareParams = @{ ReferenceObject = $script:resourceStrings.Properties.GitLab DifferenceObject = (Get-Member -InputObject $item -MemberType NoteProperty).Name PassThru = $true ErrorAction = "Continue" } $missingProperties = Compare-Object @compareParams | Where-Object { $_.SideIndicator -eq "<=" } if ($null -eq $missingProperties) { Write-Verbose -Message "$($MyInvocation.MyCommand): Validated successfully." } else { Write-Verbose -Message "$($MyInvocation.MyCommand): Validation failed." foreach ($missingProperty in $missingProperties) { throw [System.Management.Automation.ValidationMetadataException]::New("$($MyInvocation.MyCommand): Property '$missingProperty' missing") } } } } Write-Verbose -Message "$($MyInvocation.MyCommand): Found $($release.Count) release/tag item(s)." if ($PSBoundParameters.ContainsKey("ReturnVersionOnly")) { $firstItem = $release | Select-Object -First 1 try { if ($Uri -match "/repository/tags/?$") { $sourceValue = $firstItem.name } else { $sourceValue = $firstItem.$VersionTag } $Version = [System.Text.RegularExpressions.Regex]::Match($sourceValue, $MatchVersion).Groups[1].Value if ([System.String]::IsNullOrWhiteSpace($Version)) { $Version = $sourceValue } } catch { Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number as-is, returning source value." $Version = $sourceValue } if ($PSBoundParameters.ContainsKey("VersionReplace")) { $Version = $Version -replace $VersionReplace[0], $VersionReplace[1] } [PSCustomObject] @{ Version = $Version } | Write-Output return } foreach ($item in $release) { $assetLinks = @() if ($null -ne $item.assets -and $null -ne $item.assets.links) { $assetLinks += $item.assets.links } if ($null -ne $item.assets -and $null -ne $item.assets.sources) { $assetLinks += $item.assets.sources } Write-Verbose -Message "$($MyInvocation.MyCommand): Found $($assetLinks.Count) asset link(s)." if ($assetLinks.Count -eq 0) { Write-Warning -Message "$($MyInvocation.MyCommand): No assets found for this release." continue } foreach ($asset in $assetLinks) { $downloadUri = if ($null -ne $asset.direct_asset_url -and -not [System.String]::IsNullOrWhiteSpace($asset.direct_asset_url)) { $asset.direct_asset_url } else { $asset.url } if ([System.String]::IsNullOrWhiteSpace($downloadUri)) { continue } Write-Verbose -Message "$($MyInvocation.MyCommand): Match $Filter to $downloadUri." if ($downloadUri -notmatch $Filter) { Write-Verbose -Message "$($MyInvocation.MyCommand): Skip as asset does not match filter: $downloadUri." continue } if ((Get-Platform -String $downloadUri) -ne "Windows") { Write-Verbose -Message "$($MyInvocation.MyCommand): Skip as asset is not for Windows: $downloadUri." continue } try { Write-Verbose -Message "$($MyInvocation.MyCommand): Matching version number against: $($item.$VersionTag)." $Version = [System.Text.RegularExpressions.Regex]::Match($item.$VersionTag, $MatchVersion).Groups[1].Value if ([System.String]::IsNullOrWhiteSpace($Version)) { $Version = $item.$VersionTag } Write-Verbose -Message "$($MyInvocation.MyCommand): Found version number: $Version." } catch { Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number, returning: $($item.$VersionTag)." $Version = $item.$VersionTag } if ($PSBoundParameters.ContainsKey("VersionReplace")) { Write-Verbose -Message "$($MyInvocation.MyCommand): Replace $($VersionReplace[0])." $Version = $Version -replace $VersionReplace[0], $VersionReplace[1] } $dateValue = if ($null -ne $item.released_at) { $item.released_at } else { $item.created_at } $leafName = Split-Path -Path $downloadUri -Leaf $typeValue = [System.IO.Path]::GetExtension($leafName).TrimStart(".") [PSCustomObject] @{ Version = $Version Date = ConvertTo-DateTime -DateTime $dateValue -Pattern "MM/dd/yyyy HH:mm:ss" Architecture = Get-Architecture -String $leafName InstallerType = Get-InstallerType -String $downloadUri Type = $typeValue URI = $downloadUri } | Write-Output } } } } |