From 7ab4473c4a5e300924371400f83626a78582f719 Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Sun, 15 Sep 2024 09:08:50 +1000 Subject: [PATCH 1/9] Add Get-GitHubRepoTag --- Evergreen/Evergreen.json | 7 + Evergreen/Shared/Get-GitHubRepoRelease.ps1 | 4 - Evergreen/Shared/Get-GitHubRepoTag.ps1 | 215 +++++++++++++++++++++ 3 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 Evergreen/Shared/Get-GitHubRepoTag.ps1 diff --git a/Evergreen/Evergreen.json b/Evergreen/Evergreen.json index 3acf287a..a8ffb439 100644 --- a/Evergreen/Evergreen.json +++ b/Evergreen/Evergreen.json @@ -40,6 +40,13 @@ "upload_url", "url", "zipball_url" + ], + "GitHubTags": [ + "name", + "commit", + "zipball_url", + "tarball_url", + "node_id" ] }, "Uri": { diff --git a/Evergreen/Shared/Get-GitHubRepoRelease.ps1 b/Evergreen/Shared/Get-GitHubRepoRelease.ps1 index cedd2d8d..1c19c574 100644 --- a/Evergreen/Shared/Get-GitHubRepoRelease.ps1 +++ b/Evergreen/Shared/Get-GitHubRepoRelease.ps1 @@ -203,10 +203,6 @@ function Get-GitHubRepoRelease { } Write-Output -InputObject $PSObject } - # Write-Verbose -Message "$($MyInvocation.MyCommand): Matching platform 'Windows' against: $($PSObject.Platform)." - # if ($PSObject.Platform -eq "Windows") { - # Write-Output -InputObject $PSObject - # } } else { Write-Verbose -Message "$($MyInvocation.MyCommand): Skip: $($asset.browser_download_url)." diff --git a/Evergreen/Shared/Get-GitHubRepoTag.ps1 b/Evergreen/Shared/Get-GitHubRepoTag.ps1 new file mode 100644 index 00000000..e9a3cd0a --- /dev/null +++ b/Evergreen/Shared/Get-GitHubRepoTag.ps1 @@ -0,0 +1,215 @@ +function Get-GitHubRepoTag { + <# + .SYNOPSIS + Calls the GitHub Tags API passed via $Uri, validates the response and returns a formatted object + Example: https://api.github.com/repos/PowerShell/PowerShell/releases/latest + + TODO: support Basic or OAuth authentication to GitHub + #> + [OutputType([System.Management.Automation.PSObject])] + [CmdletBinding(SupportsShouldProcess = $false)] + param ( + [Parameter(Mandatory = $true, Position = 0)] + [ValidateScript( { + if ($_ -match "^(https://api\.github\.com/repos/)([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)(/tags)") { + $true + } + else { + throw "'$_' must be in the format 'https://api.github.com/repos/user/repository/tags'. Replace 'user' with the user or organisation and 'repository' with the target repository name." + } + })] + [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 + ) + + begin { + $RateLimit = Get-GitHubRateLimit + } + + process { + if ($RateLimit.remaining -eq 0) { + # We're rate limited, so output a special object + [PSCustomObject] @{ + Version = "RateLimited" + URI = "https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting" + } | Write-Output + } + else { + try { + # Retrieve the releases from the GitHub API + # Use TLS for connections + Write-Verbose -Message "$($MyInvocation.MyCommand): Set TLS to 1.2." + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + + # Invoke the GitHub releases REST API + # Note that the API performs rate limiting. + # https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#get-the-latest-release + $params = @{ + ContentType = "application/vnd.github.v3+json" + ErrorAction = "Stop" + MaximumRedirection = 0 + DisableKeepAlive = $true + UseBasicParsing = $true + UserAgent = "github-aaronparker-evergreen" + Uri = $Uri + } + if (Test-ProxyEnv) { + $params.Proxy = $script:EvergreenProxy + } + if (Test-ProxyEnv -Creds) { + $params.ProxyCredential = $script:EvergreenProxyCreds + } + # If GITHUB_TOKEN or GH_TOKEN exists, let's add that to the API request + if (Test-Path -Path "env:GITHUB_TOKEN") { + $params.Headers = @{ Authorization = "token $env:GITHUB_TOKEN" } + } + elseif (Test-Path -Path "env:GH_TOKEN") { + $params.Headers = @{ Authorization = "token $env:GH_TOKEN" } + } + + # Output the parameters when using -Verbose + foreach ($tag in $params.GetEnumerator()) { + Write-Verbose -Message "$($MyInvocation.MyCommand): Invoke-WebRequest parameter: $($tag.name): $($tag.value)." + } + + Write-Verbose -Message "$($MyInvocation.MyCommand): Get GitHub release from: $Uri." + $tags = Invoke-RestMethod @params + } + catch { + throw $_ + } + + if ($null -eq $script:resourceStrings.Properties.GitHub) { + Write-Warning -Message "$($MyInvocation.MyCommand): Unable to validate tag against GitHub releases property object because we can't find the module resource." + } + else { + # Validate that $tags has the expected properties + Write-Verbose -Message "$($MyInvocation.MyCommand): Validating GitHub tag object." + foreach ($tag in $tags) { + + # Compare the GitHub release object with properties that we expect + $params = @{ + ReferenceObject = $script:resourceStrings.Properties.GitHubTags + DifferenceObject = (Get-Member -InputObject $tag -MemberType NoteProperty) + PassThru = $true + ErrorAction = "Continue" + } + $missingProperties = Compare-Object @params + + # Throw an error for missing properties + if ($null -ne $missingProperties) { + Write-Verbose -Message "$($MyInvocation.MyCommand): Validated successfully." + } + else { + Write-Verbose -Message "$($MyInvocation.MyCommand): Validation failed." + $missingProperties | ForEach-Object { + throw [System.Management.Automation.ValidationMetadataException]::New("$($MyInvocation.MyCommand): Property: '$_' missing") + } + } + } + } + + # Build and array of the latest release and download URLs + Write-Verbose -Message "$($MyInvocation.MyCommand): Found $($tags.count) tags." + Write-Verbose -Message "$($MyInvocation.MyCommand): Found $($tags.assets.count) asset/s." + + if ($PSBoundParameters.ContainsKey("ReturnVersionOnly")) { + if ($Uri -match "^*tags$") { + try { + # Uri matches tags fo the repo; find the latest tag + $Version = [RegEx]::Match($tags[0].name, $MatchVersion).Captures.Groups[1].Value + } + catch { + Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number as-is, returning: $($tags[0].$VersionTag)." + $Version = $tags[0].name + } + } + else { + try { + # Uri matches releases for the repo; return just the version string + $Version = [RegEx]::Match($tags[0].$VersionTag, $MatchVersion).Captures.Groups[1].Value + } + catch { + Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number as-is, returning: $($tags[0].$VersionTag)." + $Version = $tag.$VersionTag + } + } + + if ($PSBoundParameters.ContainsKey("VersionReplace")) { + # Replace string in version + $Version = $Version -replace $res.Get.VersionReplace[0], $res.Get.VersionReplace[1] + } + + # Build the output object + $PSObject = [PSCustomObject] @{ + Version = $Version + } + Write-Output -InputObject $PSObject + } + else { + foreach ($tag in $tags) { + foreach ($asset in $tag.assets) { + + # Filter downloads by matching the RegEx in the manifest. The the RegEx may perform includes and excludes + Write-Verbose -Message "$($MyInvocation.MyCommand): Match $Filter to $($asset.browser_download_url)." + if ($asset.browser_download_url -match $Filter) { + Write-Verbose -Message "$($MyInvocation.MyCommand): Building Windows release output object with: $($asset.browser_download_url)." + + # Capture the version string from the specified release tag + try { + Write-Verbose -Message "$($MyInvocation.MyCommand): Matching version number against: $($tag.$VersionTag)." + $Version = [RegEx]::Match($tag.$VersionTag, $MatchVersion).Captures.Groups[1].Value + Write-Verbose -Message "$($MyInvocation.MyCommand): Found version number: $Version." + } + catch { + Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number, returning: $($tag.$VersionTag)." + $Version = $tag.$VersionTag + } + + if ($PSBoundParameters.ContainsKey("VersionReplace")) { + # Replace string in version + Write-Verbose -Message "$($MyInvocation.MyCommand): Replace $($res.Get.VersionReplace[0])." + $Version = $Version -replace $res.Get.VersionReplace[0], $res.Get.VersionReplace[1] + } + + # Build the output object + if ((Get-Platform -String $asset.browser_download_url) -eq "Windows") { + $PSObject = [PSCustomObject] @{ + Version = $Version + Date = ConvertTo-DateTime -DateTime $tag.created_at -Pattern "MM/dd/yyyy HH:mm:ss" + Size = $asset.size + #Platform = Get-Platform -String $asset.browser_download_url + Architecture = Get-Architecture -String $(Split-Path -Path $asset.browser_download_url -Leaf) + InstallerType = Get-InstallerType -String $asset.browser_download_url + Type = [System.IO.Path]::GetExtension($asset.browser_download_url).Split(".")[-1] + URI = $asset.browser_download_url + } + Write-Output -InputObject $PSObject + } + } + else { + Write-Verbose -Message "$($MyInvocation.MyCommand): Skip: $($asset.browser_download_url)." + } + } + } + } + } + } +} From 62fc09cb4b613bf643ec8931916c13169d62cf96 Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Mon, 23 Sep 2024 09:29:59 +1000 Subject: [PATCH 2/9] Add ConvertTo-DotNetVersionClass #717 --- Evergreen/Evergreen.psd1 | 12 ++-- Evergreen/Private/Convert-Segment.ps1 | 16 +++++ .../Public/ConvertTo-DotNetVersionClass.ps1 | 67 +++++++++++++++++++ 3 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 Evergreen/Private/Convert-Segment.ps1 create mode 100644 Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 diff --git a/Evergreen/Evergreen.psd1 b/Evergreen/Evergreen.psd1 index c4481795..f0d76771 100644 --- a/Evergreen/Evergreen.psd1 +++ b/Evergreen/Evergreen.psd1 @@ -69,10 +69,10 @@ PowerShellVersion = '3.0' # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = @('Export-EvergreenApp', 'Export-EvergreenManifest', - 'Find-EvergreenApp', 'Get-EvergreenApp', 'Get-EvergreenAppFromApi', - 'Get-EvergreenAppFromLibrary', 'Get-EvergreenEndpointFromApi', - 'Get-EvergreenLibrary', 'New-EvergreenLibrary', 'Save-EvergreenApp', +FunctionsToExport = @('Export-EvergreenApp', 'Export-EvergreenManifest', + 'Find-EvergreenApp', 'Get-EvergreenApp', 'Get-EvergreenAppFromApi', 'ConvertTo-DotNetVersionClass', + 'Get-EvergreenAppFromLibrary', 'Get-EvergreenEndpointFromApi', + 'Get-EvergreenLibrary', 'New-EvergreenLibrary', 'Save-EvergreenApp', 'Start-EvergreenLibraryUpdate', 'Test-EvergreenApp') # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. @@ -82,8 +82,8 @@ CmdletsToExport = @() # VariablesToExport = @() # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. -AliasesToExport = 'sea', 'gea', 'fea', 'tea', 'iea', 'Invoke-EvergreenLibraryUpdate', - 'Get-EvergreenLibraryApp', 'Invoke-EvergreenApp', +AliasesToExport = 'sea', 'gea', 'fea', 'tea', 'iea', 'Invoke-EvergreenLibraryUpdate', + 'Get-EvergreenLibraryApp', 'Invoke-EvergreenApp', 'Get-EvergreenEndpoint' # DSC resources to export from this module diff --git a/Evergreen/Private/Convert-Segment.ps1 b/Evergreen/Private/Convert-Segment.ps1 new file mode 100644 index 00000000..3c6e2d61 --- /dev/null +++ b/Evergreen/Private/Convert-Segment.ps1 @@ -0,0 +1,16 @@ +function Convert-Segment { + param ( + [System.String] $Segment + ) + + if ($Segment -match '^\d+$') { + return [System.Int32]$Segment + } + else { + $Normalized = 0 + foreach ($Char in $Segment.ToCharArray()) { + $Normalized = $Normalized * 100 + [System.Int32][System.Char]$Char + } + return $Normalized + } +} diff --git a/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 b/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 new file mode 100644 index 00000000..87a0d78b --- /dev/null +++ b/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 @@ -0,0 +1,67 @@ +function ConvertTo-DotNetVersionClass { + <# + .SYNOPSIS + Converts a version string to a standard .NET compliant Version class. + + .DESCRIPTION + The ConvertTo-DotNetVersionClass function takes a version string as input and converts it into a .NET Version class. + It normalizes the segments of the version string, ensuring it has exactly four segments by either summing excess segments + or padding with zeros if there are fewer than four segments. + + .PARAMETER Version + A version string to convert to a standard .NET compliant version class. + + .EXAMPLE + PS> ConvertTo-DotNetVersionClass -Version "1.2.3.4" + 1.2.3.4 + + .EXAMPLE + PS> ConvertTo-DotNetVersionClass -Version "1.2.3" + 1.2.3.0 + + .EXAMPLE + PS> ConvertTo-DotNetVersionClass -Version "1.2.3.4.5" + 1.2.3.9 + + .NOTES + If the conversion to a .NET Version class fails, the function will return the normalized version string as a string. + #> + param ( + [Parameter( + Mandatory = $true, + Position = 0, + ValueFromPipeline, + HelpMessage = "A version string to convert to a standard .NET compliant version class.")] + [System.String] $Version + ) + + process { + # Split the version string into segments and initialise an array + $Segments = $Version -split '[.\-_+]' + $NormalizedSegments = @() + + # Normalize each segment + foreach ($Segment in $Segments) { + $NormalizedSegments += @(Convert-Segment -Segment $Segment) + } + + # If the number of segments is greater than 4, sum the last segments + if ($NormalizedSegments.Count -gt 4) { + $NormalizedSegments = $NormalizedSegments[0..2] + ($NormalizedSegments[3..($NormalizedSegments.Count - 1)] | Measure-Object -Sum).Sum + } + + # If the number of segments is less than 4, pad with zeros + while ($NormalizedSegments.Count -lt 4) { + $NormalizedSegments += 0 + } + + # Return the version as a .NET Version class + try { + return [System.Version]($NormalizedSegments -join ".") + } + catch { + Write-Warning -Message "Failed to convert version string '$Version' to a .NET Version class." + return ($NormalizedSegments -join ".") + } + } +} From c929ef4d4014f91d324b3a35af4d28d112d8bdca Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Mon, 23 Sep 2024 10:59:45 +1000 Subject: [PATCH 3/9] ConvertTo-DotNetVersionClass Add ValueFromPipelineByPropertyName, add tests --- .../Public/ConvertTo-DotNetVersionClass.ps1 | 1 + .../ConvertTo-DotNetVersionClass.Tests.ps1 | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 diff --git a/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 b/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 index 87a0d78b..7b8ea816 100644 --- a/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 +++ b/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 @@ -31,6 +31,7 @@ function ConvertTo-DotNetVersionClass { Mandatory = $true, Position = 0, ValueFromPipeline, + ValueFromPipelineByPropertyName, HelpMessage = "A version string to convert to a standard .NET compliant version class.")] [System.String] $Version ) diff --git a/tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 b/tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 new file mode 100644 index 00000000..cabb743a --- /dev/null +++ b/tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 @@ -0,0 +1,32 @@ +<# + .SYNOPSIS + Public Pester function tests. +#> +[OutputType()] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "", Justification = "This OK for the tests files.")] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "", Justification = "Outputs to log host.")] +param () + +BeforeDiscovery { +} + +BeforeAll { +} + +Describe -Tag "Convert" -Name "ConvertTo-DotNetVersionClass" { + BeforeAll { + $App = Get-EvergreenApp -Name "MicrosoftOneDrive" + } + + It "Should return a valid .NET version class" { + { $App[0] | ConvertTo-DotNetVersionClass } | Should -BeOfType [System.Version] + } + + It "Should return a string for a version number that fails to convert" { + { ConvertTo-DotNetVersionClass -Version "v22-build1" } | Should -BeOfType [System.String] + } + + It "Should return the expected string when converting a version string" { + ConvertTo-DotNetVersionClass -Version "v22-build1" | Should -BeExactly "1185050.991806090049.0.0" + } +} From e2539884ee27639dee4afe5bfc40f4379e1aeea1 Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Mon, 23 Sep 2024 12:55:00 +1000 Subject: [PATCH 4/9] Update ConvertTo-DotNetVersionClass.Tests.ps1 --- tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 b/tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 index cabb743a..37a50753 100644 --- a/tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 +++ b/tests/Public/ConvertTo-DotNetVersionClass.Tests.ps1 @@ -19,11 +19,11 @@ Describe -Tag "Convert" -Name "ConvertTo-DotNetVersionClass" { } It "Should return a valid .NET version class" { - { $App[0] | ConvertTo-DotNetVersionClass } | Should -BeOfType [System.Version] + ($App[0] | ConvertTo-DotNetVersionClass) | Should -BeOfType [System.Version] } It "Should return a string for a version number that fails to convert" { - { ConvertTo-DotNetVersionClass -Version "v22-build1" } | Should -BeOfType [System.String] + ConvertTo-DotNetVersionClass -Version "v22-build1" | Should -BeOfType [System.String] } It "Should return the expected string when converting a version string" { From 507d118b0ad29770688ba22d16a96f340b037afa Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Wed, 25 Sep 2024 18:31:46 +1000 Subject: [PATCH 5/9] Update Get-GitHubRepoTag.ps1 Working version #544 --- Evergreen/Shared/Get-GitHubRepoTag.ps1 | 119 +++---------------------- 1 file changed, 12 insertions(+), 107 deletions(-) diff --git a/Evergreen/Shared/Get-GitHubRepoTag.ps1 b/Evergreen/Shared/Get-GitHubRepoTag.ps1 index e9a3cd0a..e5239fd0 100644 --- a/Evergreen/Shared/Get-GitHubRepoTag.ps1 +++ b/Evergreen/Shared/Get-GitHubRepoTag.ps1 @@ -1,10 +1,8 @@ function Get-GitHubRepoTag { <# .SYNOPSIS - Calls the GitHub Tags API passed via $Uri, validates the response and returns a formatted object - Example: https://api.github.com/repos/PowerShell/PowerShell/releases/latest - - TODO: support Basic or OAuth authentication to GitHub + Calls the GitHub Tags API passed via $Uri and returns the tags for the repository + Example: https://api.github.com/repos/PowerShell/PowerShell/tags #> [OutputType([System.Management.Automation.PSObject])] [CmdletBinding(SupportsShouldProcess = $false)] @@ -15,28 +13,10 @@ function Get-GitHubRepoTag { $true } else { - throw "'$_' must be in the format 'https://api.github.com/repos/user/repository/tags'. Replace 'user' with the user or organisation and 'repository' with the target repository name." + throw "'$_' must be in the format 'https://api.github.com/repos/user/tags'. Replace 'user' with the user or organisation and 'repository' with the target repository name." } })] - [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 + [System.String] $Uri ) begin { @@ -96,8 +76,8 @@ function Get-GitHubRepoTag { throw $_ } - if ($null -eq $script:resourceStrings.Properties.GitHub) { - Write-Warning -Message "$($MyInvocation.MyCommand): Unable to validate tag against GitHub releases property object because we can't find the module resource." + if ($null -eq $script:resourceStrings.Properties.GitHubTags) { + Write-Warning -Message "$($MyInvocation.MyCommand): Unable to validate tag against GitHub tags property object because we can't find the module resource." } else { # Validate that $tags has the expected properties @@ -115,7 +95,7 @@ function Get-GitHubRepoTag { # Throw an error for missing properties if ($null -ne $missingProperties) { - Write-Verbose -Message "$($MyInvocation.MyCommand): Validated successfully." + Write-Verbose -Message "$($MyInvocation.MyCommand): Validated tag object successfully." } else { Write-Verbose -Message "$($MyInvocation.MyCommand): Validation failed." @@ -128,87 +108,12 @@ function Get-GitHubRepoTag { # Build and array of the latest release and download URLs Write-Verbose -Message "$($MyInvocation.MyCommand): Found $($tags.count) tags." - Write-Verbose -Message "$($MyInvocation.MyCommand): Found $($tags.assets.count) asset/s." - - if ($PSBoundParameters.ContainsKey("ReturnVersionOnly")) { - if ($Uri -match "^*tags$") { - try { - # Uri matches tags fo the repo; find the latest tag - $Version = [RegEx]::Match($tags[0].name, $MatchVersion).Captures.Groups[1].Value - } - catch { - Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number as-is, returning: $($tags[0].$VersionTag)." - $Version = $tags[0].name - } - } - else { - try { - # Uri matches releases for the repo; return just the version string - $Version = [RegEx]::Match($tags[0].$VersionTag, $MatchVersion).Captures.Groups[1].Value - } - catch { - Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number as-is, returning: $($tags[0].$VersionTag)." - $Version = $tag.$VersionTag - } - } - if ($PSBoundParameters.ContainsKey("VersionReplace")) { - # Replace string in version - $Version = $Version -replace $res.Get.VersionReplace[0], $res.Get.VersionReplace[1] - } - - # Build the output object - $PSObject = [PSCustomObject] @{ - Version = $Version - } - Write-Output -InputObject $PSObject - } - else { - foreach ($tag in $tags) { - foreach ($asset in $tag.assets) { - - # Filter downloads by matching the RegEx in the manifest. The the RegEx may perform includes and excludes - Write-Verbose -Message "$($MyInvocation.MyCommand): Match $Filter to $($asset.browser_download_url)." - if ($asset.browser_download_url -match $Filter) { - Write-Verbose -Message "$($MyInvocation.MyCommand): Building Windows release output object with: $($asset.browser_download_url)." - - # Capture the version string from the specified release tag - try { - Write-Verbose -Message "$($MyInvocation.MyCommand): Matching version number against: $($tag.$VersionTag)." - $Version = [RegEx]::Match($tag.$VersionTag, $MatchVersion).Captures.Groups[1].Value - Write-Verbose -Message "$($MyInvocation.MyCommand): Found version number: $Version." - } - catch { - Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number, returning: $($tag.$VersionTag)." - $Version = $tag.$VersionTag - } - - if ($PSBoundParameters.ContainsKey("VersionReplace")) { - # Replace string in version - Write-Verbose -Message "$($MyInvocation.MyCommand): Replace $($res.Get.VersionReplace[0])." - $Version = $Version -replace $res.Get.VersionReplace[0], $res.Get.VersionReplace[1] - } - - # Build the output object - if ((Get-Platform -String $asset.browser_download_url) -eq "Windows") { - $PSObject = [PSCustomObject] @{ - Version = $Version - Date = ConvertTo-DateTime -DateTime $tag.created_at -Pattern "MM/dd/yyyy HH:mm:ss" - Size = $asset.size - #Platform = Get-Platform -String $asset.browser_download_url - Architecture = Get-Architecture -String $(Split-Path -Path $asset.browser_download_url -Leaf) - InstallerType = Get-InstallerType -String $asset.browser_download_url - Type = [System.IO.Path]::GetExtension($asset.browser_download_url).Split(".")[-1] - URI = $asset.browser_download_url - } - Write-Output -InputObject $PSObject - } - } - else { - Write-Verbose -Message "$($MyInvocation.MyCommand): Skip: $($asset.browser_download_url)." - } - } - } + # Output the tags object + foreach ($tag in $tags) { + [PSCustomObject]@{ + Tag = $tag.name + } | Write-Output } } } From 5f35791d8d3220ebc31cb31040d073089b1657c7 Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Wed, 25 Sep 2024 18:32:13 +1000 Subject: [PATCH 6/9] Update Get-AWSCLI.ps1 Update to use Get-GitHubRepoTag #544 --- Evergreen/Apps/Get-AWSCLI.ps1 | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/Evergreen/Apps/Get-AWSCLI.ps1 b/Evergreen/Apps/Get-AWSCLI.ps1 index 2710d3f3..9add113d 100644 --- a/Evergreen/Apps/Get-AWSCLI.ps1 +++ b/Evergreen/Apps/Get-AWSCLI.ps1 @@ -15,24 +15,17 @@ function Get-AWSCLI { $res = (Get-FunctionResource -AppName ("$($MyInvocation.MyCommand)".Split("-"))[1]) ) - # Get latest version and download latest release via GitHub API - $params = @{ - Uri = $res.Get.Update.Uri - ContentType = $res.Get.Update.ContentType - ReturnObject = "Content" - } + # Get the latest version of AWS CLI via the latest tag on the repository + $Tags = Get-GitHubRepoTag -Uri $res.Get.Update.Uri - # Get only latest version tag from GitHub API - $Content = ((Invoke-EvergreenWebRequest @params | ConvertFrom-Json).name | ForEach-Object { New-Object -TypeName "System.Version" ($_) } | Sort-Object -Descending | Select-Object -First 1 | ForEach-Object {("{0}.{1}.{2}" -f $_.Major,$_.Minor,$_.Build)}) + # Select the latest version + $Version = $Tags | Sort-Object -Property @{ Expression = { [System.Version]$_.Tag }; Descending = $true } | Select-Object -First 1 - if ($null -ne $Content) { - $Content | ForEach-Object { - $PSObject = [PSCustomObject] @{ - Version = $_ - Type = "msi" - URI = $res.Get.Download.Uri -replace $res.Get.Download.ReplaceText, $_ - } - Write-Output -InputObject $PSObject - } + # Output the version and download URL + $PSObject = [PSCustomObject] @{ + Version = $Version.Tag + Type = "msi" + URI = $res.Get.Download.Uri -replace $res.Get.Download.ReplaceText, $Version.Tag } + Write-Output -InputObject $PSObject } From c93eca324b5cb955edf68b681985c4514454980b Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Wed, 25 Sep 2024 21:44:45 +1000 Subject: [PATCH 7/9] Update Get-GitHubRepoTag.ps1 Add match version #544 --- Evergreen/Shared/Get-GitHubRepoTag.ps1 | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Evergreen/Shared/Get-GitHubRepoTag.ps1 b/Evergreen/Shared/Get-GitHubRepoTag.ps1 index e5239fd0..1c794fe7 100644 --- a/Evergreen/Shared/Get-GitHubRepoTag.ps1 +++ b/Evergreen/Shared/Get-GitHubRepoTag.ps1 @@ -16,7 +16,11 @@ function Get-GitHubRepoTag { throw "'$_' must be in the format 'https://api.github.com/repos/user/tags'. Replace 'user' with the user or organisation and 'repository' with the target repository name." } })] - [System.String] $Uri + [System.String] $Uri, + + [Parameter(Mandatory = $false, Position = 1)] + [ValidateNotNullOrEmpty()] + [System.String] $MatchVersion = "(\d+(\.\d+){1,4}).*" ) begin { @@ -70,7 +74,7 @@ function Get-GitHubRepoTag { } Write-Verbose -Message "$($MyInvocation.MyCommand): Get GitHub release from: $Uri." - $tags = Invoke-RestMethod @params + $Tags = Invoke-RestMethod @params } catch { throw $_ @@ -82,7 +86,7 @@ function Get-GitHubRepoTag { else { # Validate that $tags has the expected properties Write-Verbose -Message "$($MyInvocation.MyCommand): Validating GitHub tag object." - foreach ($tag in $tags) { + foreach ($tag in $Tags) { # Compare the GitHub release object with properties that we expect $params = @{ @@ -108,11 +112,20 @@ function Get-GitHubRepoTag { # Build and array of the latest release and download URLs Write-Verbose -Message "$($MyInvocation.MyCommand): Found $($tags.count) tags." + foreach ($Tag in $Tags) { + + try { + # Uri matches tags for the repo; find the latest tag + $Version = [RegEx]::Match($Tag.name, $MatchVersion).Captures.Groups[1].Value + } + catch { + Write-Verbose -Message "$($MyInvocation.MyCommand): Failed to match version number, returning as-is: $($Tag.name)." + $Version = $Tag.name + } - # Output the tags object - foreach ($tag in $tags) { + # Output the tags object [PSCustomObject]@{ - Tag = $tag.name + Tag = $Version } | Write-Output } } From 991ca5f2f4e0a37cd0d057875059169e8f83c6e3 Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Wed, 25 Sep 2024 21:45:03 +1000 Subject: [PATCH 8/9] Update npcap to use Get-GitHubRepoTag #544 --- Evergreen/Apps/Get-Npcap.ps1 | 36 +++++++++++++--------------------- Evergreen/Manifests/Npcap.json | 3 ++- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/Evergreen/Apps/Get-Npcap.ps1 b/Evergreen/Apps/Get-Npcap.ps1 index 36e128bc..245552fb 100644 --- a/Evergreen/Apps/Get-Npcap.ps1 +++ b/Evergreen/Apps/Get-Npcap.ps1 @@ -1,4 +1,4 @@ -Function Get-Npcap { +function Get-Npcap { <# .SYNOPSIS Returns the latest Npcap version number and download. @@ -8,34 +8,26 @@ Function Get-Npcap { E-mail: jms@du.se #> [OutputType([System.Management.Automation.PSObject])] - [CmdletBinding(SupportsShouldProcess = $False)] + [CmdletBinding(SupportsShouldProcess = $false)] param ( - [Parameter(Mandatory = $False, Position = 0)] + [Parameter(Mandatory = $false, Position = 0)] [ValidateNotNull()] [System.Management.Automation.PSObject] $res = (Get-FunctionResource -AppName ("$($MyInvocation.MyCommand)".Split("-"))[1]) ) + # Get the latest version via the latest tag on the repository + $Tags = Get-GitHubRepoTag -Uri $res.Get.Update.Uri - # Get latest version and download latest release via GitHub API - $params = @{ - Uri = $res.Get.Update.Uri - ContentType = $res.Get.Update.ContentType - ReturnObject = "Content" - } - - # Get only latest version tag from GitHub API - $Content = ((Invoke-EvergreenWebRequest @params | ConvertFrom-Json).name -replace "v",""| ForEach-Object { New-Object -TypeName "System.Version" ($_) } | Sort-Object -Descending | Select-Object -First 1 | ForEach-Object {("{0}.{1}" -f $_.Major,$_.Minor)}) + # Select the latest version + $Version = $Tags | Sort-Object -Property @{ Expression = { [System.Version]$_.Tag }; Descending = $true } | Select-Object -First 1 - if ($null -ne $Content) { - $Content | ForEach-Object { - $PSObject = [PSCustomObject] @{ - Version = $_ - Type = "exe" - URI = $res.Get.Download.Uri -replace $res.Get.Download.ReplaceText, $_ - } - Write-Output -InputObject $PSObject - } + # Output the version and download URL + $PSObject = [PSCustomObject] @{ + Version = $Version.Tag + Type = Get-FileType -File $res.Get.Download.Uri + URI = $res.Get.Download.Uri -replace $res.Get.Download.ReplaceText, $Version.Tag } -} + Write-Output -InputObject $PSObject +} diff --git a/Evergreen/Manifests/Npcap.json b/Evergreen/Manifests/Npcap.json index c39f66a0..fbfaa861 100644 --- a/Evergreen/Manifests/Npcap.json +++ b/Evergreen/Manifests/Npcap.json @@ -4,7 +4,8 @@ "Get": { "Update": { "Uri": "https://api.github.com/repos/nmap/npcap/tags", - "ContentType": "application/json; charset=utf-8" + "ContentType": "application/json; charset=utf-8", + "MatchVersion": "(\\d+(\\.\\d+){1,4}).*" }, "Download": { "Uri": "https://npcap.com/dist/npcap-#version.exe", From 4aecebdcca323ec11c52eaf5f1177ff91b6b9466 Mon Sep 17 00:00:00 2001 From: Aaron Parker Date: Thu, 26 Sep 2024 09:52:26 +1000 Subject: [PATCH 9/9] Update help --- .../Public/ConvertTo-DotNetVersionClass.ps1 | 26 +---- Evergreen/en-US/Evergreen-help.xml | 110 ++++++++++++++++-- .../en-US/ConvertTo-DotNetVersionClass.md | 85 ++++++++++++++ docs/help/en-US/Export-EvergreenApp.md | 2 +- docs/help/en-US/Export-EvergreenManifest.md | 2 +- docs/help/en-US/Find-EvergreenApp.md | 2 +- docs/help/en-US/Get-EvergreenApp.md | 2 +- docs/help/en-US/Get-EvergreenAppFromApi.md | 2 +- .../en-US/Get-EvergreenEndpointFromApi.md | 2 +- docs/help/en-US/Get-EvergreenLibrary.md | 2 +- docs/help/en-US/Get-EvergreenLibraryApp.md | 2 +- docs/help/en-US/New-EvergreenLibrary.md | 2 +- docs/help/en-US/Save-EvergreenApp.md | 2 +- .../en-US/Start-EvergreenLibraryUpdate.md | 2 +- docs/help/en-US/Test-EvergreenApp.md | 2 +- 15 files changed, 196 insertions(+), 49 deletions(-) create mode 100644 docs/help/en-US/ConvertTo-DotNetVersionClass.md diff --git a/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 b/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 index 7b8ea816..b34672f1 100644 --- a/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 +++ b/Evergreen/Public/ConvertTo-DotNetVersionClass.ps1 @@ -1,30 +1,6 @@ function ConvertTo-DotNetVersionClass { <# - .SYNOPSIS - Converts a version string to a standard .NET compliant Version class. - - .DESCRIPTION - The ConvertTo-DotNetVersionClass function takes a version string as input and converts it into a .NET Version class. - It normalizes the segments of the version string, ensuring it has exactly four segments by either summing excess segments - or padding with zeros if there are fewer than four segments. - - .PARAMETER Version - A version string to convert to a standard .NET compliant version class. - - .EXAMPLE - PS> ConvertTo-DotNetVersionClass -Version "1.2.3.4" - 1.2.3.4 - - .EXAMPLE - PS> ConvertTo-DotNetVersionClass -Version "1.2.3" - 1.2.3.0 - - .EXAMPLE - PS> ConvertTo-DotNetVersionClass -Version "1.2.3.4.5" - 1.2.3.9 - - .NOTES - If the conversion to a .NET Version class fails, the function will return the normalized version string as a string. + .EXTERNALHELP Evergreen-help.xml #> param ( [Parameter( diff --git a/Evergreen/en-US/Evergreen-help.xml b/Evergreen/en-US/Evergreen-help.xml index d96294ab..7ee650a0 100644 --- a/Evergreen/en-US/Evergreen-help.xml +++ b/Evergreen/en-US/Evergreen-help.xml @@ -1,5 +1,91 @@  + + + ConvertTo-DotNetVersionClass + ConvertTo + DotNetVersionClass + + Converts a version string to a standard .NET compliant Version class. + + + + The ConvertTo-DotNetVersionClass function takes a version string as input and converts it into a .NET Version class. It normalizes the segments of the version string, ensuring it has exactly four segments by either summing excess segments or padding with zeros if there are fewer than four segments. + If the conversion to a .NET Version class fails, the function will return the normalized version string as a string. + + + + ConvertTo-DotNetVersionClass + + Version + + A version string to convert to a standard .NET compliant version class. + + String + + String + + + None + + + + + + Version + + A version string to convert to a standard .NET compliant version class. + + String + + String + + + None + + + + + + + Site: https://stealthpuppy.com/evergreen + Author: Aaron Parker + Twitter: @stealthpuppy + + + + + -------------------------- EXAMPLE 1 -------------------------- + ConvertTo-DotNetVersionClass -Version "1.2.3.4" +1.2.3.4 + + + + + + -------------------------- EXAMPLE 2 -------------------------- + ConvertTo-DotNetVersionClass -Version "1.2.3" +1.2.3.0 + + + + + + -------------------------- EXAMPLE 3 -------------------------- + ConvertTo-DotNetVersionClass -Version "1.2.3.4.5" +1.2.3.9 + + + + + + + + Export application version information + https://stealthpuppy.com/evergreen/convertversion/ + + + Export-EvergreenApp @@ -126,7 +212,7 @@ - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -218,7 +304,7 @@ Export-EvergreenApp -InputObject $OneDrive -Path "C:\Evergreen\OneDrive\Microsof - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -308,7 +394,7 @@ Export-EvergreenApp -InputObject $OneDrive -Path "C:\Evergreen\OneDrive\Microsof - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -561,7 +647,7 @@ Export-EvergreenApp -InputObject $OneDrive -Path "C:\Evergreen\OneDrive\Microsof - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -710,7 +796,7 @@ URI : https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservi - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -817,7 +903,7 @@ URI : https://msedge.sf.dl.delivery.mp.microsoft.com/filestreamingservi - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -967,7 +1053,7 @@ c.1password.com - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -1088,7 +1174,7 @@ c.1password.com - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -1277,7 +1363,7 @@ Architecture : x64 - Site: https://stealthpuppy.com Author: Aaron Parker Twitter: @stealthpuppy + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -1700,7 +1786,7 @@ Architecture : x64 - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -1887,7 +1973,7 @@ Architecture : x64 - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy @@ -2153,7 +2239,7 @@ Architecture : x64 - Site: https://stealthpuppy.com + Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy diff --git a/docs/help/en-US/ConvertTo-DotNetVersionClass.md b/docs/help/en-US/ConvertTo-DotNetVersionClass.md new file mode 100644 index 00000000..be72802b --- /dev/null +++ b/docs/help/en-US/ConvertTo-DotNetVersionClass.md @@ -0,0 +1,85 @@ +--- +external help file: Evergreen-help.xml +Module Name: Evergreen +online version: +schema: 2.0.0 +--- + +# ConvertTo-DotNetVersionClass + +## SYNOPSIS +Converts a version string to a standard .NET compliant Version class. + +## SYNTAX + +``` +ConvertTo-DotNetVersionClass [-Version] [-ProgressAction ] [] +``` + +## DESCRIPTION +The ConvertTo-DotNetVersionClass function takes a version string as input and converts it into a .NET Version class. +It normalizes the segments of the version string, ensuring it has exactly four segments by either summing excess segments +or padding with zeros if there are fewer than four segments. + +If the conversion to a .NET Version class fails, the function will return the normalized version string as a string. + +## EXAMPLES + +### EXAMPLE 1 + +``` +ConvertTo-DotNetVersionClass -Version "1.2.3.4" +1.2.3.4 +``` + +### EXAMPLE 2 + +``` +ConvertTo-DotNetVersionClass -Version "1.2.3" +1.2.3.0 +``` + +### EXAMPLE 3 + +``` +ConvertTo-DotNetVersionClass -Version "1.2.3.4.5" +1.2.3.9 +``` + +## PARAMETERS + +### -Version + +A version string to convert to a standard .NET compliant version class. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +Site: https://stealthpuppy.com/evergreen + +Author: Aaron Parker + +Twitter: @stealthpuppy + +## RELATED LINKS + +[Export application version information](https://stealthpuppy.com/evergreen/convertversion/) diff --git a/docs/help/en-US/Export-EvergreenApp.md b/docs/help/en-US/Export-EvergreenApp.md index 563f02a0..05a66995 100644 --- a/docs/help/en-US/Export-EvergreenApp.md +++ b/docs/help/en-US/Export-EvergreenApp.md @@ -114,7 +114,7 @@ Export-EvergreenApp accepts the output from Get-EvergreenApp. ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Export-EvergreenManifest.md b/docs/help/en-US/Export-EvergreenManifest.md index 029d80ca..8c03980d 100644 --- a/docs/help/en-US/Export-EvergreenManifest.md +++ b/docs/help/en-US/Export-EvergreenManifest.md @@ -64,7 +64,7 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Find-EvergreenApp.md b/docs/help/en-US/Find-EvergreenApp.md index 42c49c14..3b8231e8 100644 --- a/docs/help/en-US/Find-EvergreenApp.md +++ b/docs/help/en-US/Find-EvergreenApp.md @@ -83,7 +83,7 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Get-EvergreenApp.md b/docs/help/en-US/Get-EvergreenApp.md index c175fbae..ee8e7f39 100644 --- a/docs/help/en-US/Get-EvergreenApp.md +++ b/docs/help/en-US/Get-EvergreenApp.md @@ -246,7 +246,7 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Get-EvergreenAppFromApi.md b/docs/help/en-US/Get-EvergreenAppFromApi.md index a4b50bca..6923f58f 100644 --- a/docs/help/en-US/Get-EvergreenAppFromApi.md +++ b/docs/help/en-US/Get-EvergreenAppFromApi.md @@ -83,7 +83,7 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Get-EvergreenEndpointFromApi.md b/docs/help/en-US/Get-EvergreenEndpointFromApi.md index 84cbf189..756b4070 100644 --- a/docs/help/en-US/Get-EvergreenEndpointFromApi.md +++ b/docs/help/en-US/Get-EvergreenEndpointFromApi.md @@ -104,7 +104,7 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Get-EvergreenLibrary.md b/docs/help/en-US/Get-EvergreenLibrary.md index 43e07966..a9a483c3 100644 --- a/docs/help/en-US/Get-EvergreenLibrary.md +++ b/docs/help/en-US/Get-EvergreenLibrary.md @@ -94,7 +94,7 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Get-EvergreenLibraryApp.md b/docs/help/en-US/Get-EvergreenLibraryApp.md index cdc93022..c453ddb5 100644 --- a/docs/help/en-US/Get-EvergreenLibraryApp.md +++ b/docs/help/en-US/Get-EvergreenLibraryApp.md @@ -119,7 +119,7 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/New-EvergreenLibrary.md b/docs/help/en-US/New-EvergreenLibrary.md index 78849d9f..63c25192 100644 --- a/docs/help/en-US/New-EvergreenLibrary.md +++ b/docs/help/en-US/New-EvergreenLibrary.md @@ -121,7 +121,7 @@ New-EvergreenLibrary accepts string parameters. ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker Twitter: @stealthpuppy diff --git a/docs/help/en-US/Save-EvergreenApp.md b/docs/help/en-US/Save-EvergreenApp.md index 75d33f5c..23b807ed 100644 --- a/docs/help/en-US/Save-EvergreenApp.md +++ b/docs/help/en-US/Save-EvergreenApp.md @@ -250,7 +250,7 @@ Provides a list of paths of the downloaded target files. ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Start-EvergreenLibraryUpdate.md b/docs/help/en-US/Start-EvergreenLibraryUpdate.md index 6f6c2e75..047654d3 100644 --- a/docs/help/en-US/Start-EvergreenLibraryUpdate.md +++ b/docs/help/en-US/Start-EvergreenLibraryUpdate.md @@ -135,7 +135,7 @@ Start-EvergreenLibraryUpdate accepts a string parameter. ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker diff --git a/docs/help/en-US/Test-EvergreenApp.md b/docs/help/en-US/Test-EvergreenApp.md index d5fee4de..9e5315db 100644 --- a/docs/help/en-US/Test-EvergreenApp.md +++ b/docs/help/en-US/Test-EvergreenApp.md @@ -194,7 +194,7 @@ Provides a list URLs and a true/false result. ## NOTES -Site: https://stealthpuppy.com +Site: https://stealthpuppy.com/evergreen Author: Aaron Parker