Private/Shared/Get-GithubRelease.ps1
#################################### # Get-GithubRelease.ps1 # #################################### # Version: 0.1.0 # Based on Invoke-GitHubReleaseFetcher by Jack Tracey: # Source: https://github.com/jtracey93/PublicScripts/blob/master/GitHub/PowerShell/Invoke-GitHubReleaseFetcher.ps1 <# .SYNOPSIS Checks for the releases of a GitHub repository and downloads the latest release or all releases and pulls it into a specified directory, one for each version. .DESCRIPTION Checks for the releases of a GitHub repository and downloads the latest release or all releases and pulls it into a specified directory, one for each version. .EXAMPLE .NOTES # Release notes 16/03/2023 - V0.1.0: - Initial release. #> function Get-GithubRelease { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1, HelpMessage = "Please the provide the full URL of the GitHub repository you wish to check for the latest release.")] [string] $githubRepoUrl, [Parameter(Mandatory = $false, Position = 2, HelpMessage = "The releases to download. Specify 'latest' to download the latest release. Defaults to the latest release.")] [array] $release = "latest", [Parameter(Mandatory = $true, Position = 3, HelpMessage = "The directory to download the releases to.")] [string] $targetDirectory, [Parameter(Mandatory = $false, Position = 4, HelpMessage = "Whether to just query the API and return the release versions.")] [switch] $queryOnly, [Parameter(Mandatory = $false, HelpMessage = "The source directory location of the modules. Defaults to root")] $moduleSourceFolder = ".", [Parameter(Mandatory = $true, HelpMessage = "The target directory location of the modules.")] $moduleTargetFolder, [Parameter(Mandatory = $false, HelpMessage = "The name of the release artifact in the target release. Defaults to standard release zip.")] $releaseArtifactName = "" ) $parentDirectory = $targetDirectory $targetPath = Join-Path $targetDirectory $moduleTargetFolder # Split Repo URL into parts $repoOrgPlusRepo = $githubRepoUrl.Split("/")[-2..-1] -join "/" Write-Verbose "=====> Checking for release on GitHub Repo: $repoOrgPlusRepo" # Get releases on repo $repoReleaseUrl = "https://api.github.com/repos/$repoOrgPlusRepo/releases/$release" if($release -ne "latest") { $repoReleaseUrl = "https://api.github.com/repos/$repoOrgPlusRepo/releases/tags/$release" } $releaseData = Invoke-RestMethod $repoReleaseUrl -SkipHttpErrorCheck -StatusCodeVariable "statusCode" Write-Verbose "Status code: $statusCode" if($statusCode -eq 404) { Write-Error "The release $release does not exist in the GitHub repository $githubRepoUrl - $repoReleaseUrl" throw "The release $release does not exist in the GitHub repository $githubRepoUrl - $repoReleaseUrl" } # Handle transient errors like throttling if($statusCode -ge 400 -and $statusCode -le 599) { Write-InformationColored "Retrying as got the Status Code $statusCode, which may be a transient error." -ForegroundColor Yellow -InformationAction Continue $releaseData = Invoke-RestMethod $repoReleaseUrl -RetryIntervalSec 3 -MaximumRetryCount 100 } if($statusCode -ne 200) { throw "Unable to query repository version, please check your internet connection and try again..." } $releaseTag = $releaseData.tag_name if($queryOnly) { return $releaseTag } # Check if directory exists Write-Verbose "=====> Checking if directory for releases exists: $targetPath" if (!(Test-Path $targetPath)) { Write-Verbose "Directory does not exist for releases, will now create: $targetPath" New-Item -ItemType Directory -Path $targetPath | Out-String | Write-Verbose } # Check the directory for this release $targetVersionPath = Join-Path $targetPath $releaseTag Write-Verbose "===> Checking if directory for release version exists: $targetVersionPath" if (!(Test-Path $targetVersionPath)) { Write-Verbose "Directory does not exist for release $releaseTag, will now create: $targetVersionPath" New-Item -ItemType Directory -Path $targetVersionPath | Out-String | Write-Verbose } Write-Verbose "===> Checking if any content exists inside of $targetVersionPath" $contentTargetVersionPath = Get-ChildItem -Path $targetVersionPath -Recurse -ErrorAction SilentlyContinue if ($null -eq $contentTargetVersionPath) { Write-Verbose "===> Pulling and extracting release $releaseTag into $targetVersionPath" New-Item -ItemType Directory -Path "$targetVersionPath/tmp" | Out-String | Write-Verbose $targetPathForZip = "$targetVersionPath/tmp/$releaseTag.zip" # Get the artifact url if($releaseArtifactName -ne "") { $releaseArtifactUrl = $releaseData.assets | Where-Object { $_.name -eq $releaseArtifactName } | Select-Object -ExpandProperty browser_download_url } else { $releaseArtifactUrl = $releaseData.zipball_url } Write-Verbose "===> Downloading the release artifact $releaseArtifactUrl from the GitHub repository $repoOrgPlusRepo" Invoke-WebRequest -Uri $releaseArtifactUrl -OutFile $targetPathForZip -RetryIntervalSec 3 -MaximumRetryCount 100 | Out-String | Write-Verbose if(!(Test-Path $targetPathForZip)) { Write-InformationColored "Failed to download the release $releaseTag from the GitHub repository $repoOrgPlusRepo" -ForegroundColor Red -InformationAction Continue throw } $targetPathForExtractedZip = "$targetVersionPath/tmp/extracted" Expand-Archive -Path $targetPathForZip -DestinationPath $targetPathForExtractedZip | Out-String | Write-Verbose $extractedSubFolder = $targetPathForExtractedZip if($releaseArtifactName -eq "") { $extractedSubFolder = (Get-ChildItem -Path $targetPathForExtractedZip -Directory).FullName } Write-Verbose "===> Copying all extracted contents into $targetVersionPath from $($extractedSubFolder)/$moduleSourceFolder/*." Copy-Item -Path "$($extractedSubFolder)/$moduleSourceFolder/*" -Destination "$targetVersionPath" -Recurse -Force | Out-String | Write-Verbose Remove-Item -Path "$targetVersionPath/tmp" -Force -Recurse Write-InformationColored "The directory for $targetVersionPath has been created and populated." -ForegroundColor Green -InformationAction Continue } else { Write-InformationColored "The directory for $targetVersionPath already exists and has content in it, so we are not overwriting it." -ForegroundColor Green -InformationAction Continue Write-Verbose "===> Content already exists in $releaseDirectory. Skipping" } # Check and replace the .env file release version if it is Bicep $envFilePath = Join-Path -Path $parentDirectory -ChildPath ".env" if (Test-Path $envFilePath) { Write-Verbose "===> Replacing the .env file release version with $releaseTag" (Get-Content $envFilePath) -replace "UPSTREAM_RELEASE_VERSION=.*", "UPSTREAM_RELEASE_VERSION=$releaseTag" | Set-Content $envFilePath } return $releaseTag } # SIG # Begin signature block # MIIoPQYJKoZIhvcNAQcCoIIoLjCCKCoCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAAVmOiiSXWHNtI # Byi8YZXtrk91+pCSq1NzoFZSQPq216CCDYUwggYDMIID66ADAgECAhMzAAAEhJji # EuB4ozFdAAAAAASEMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM1WhcNMjYwNjE3MTgyMTM1WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDtekqMKDnzfsyc1T1QpHfFtr+rkir8ldzLPKmMXbRDouVXAsvBfd6E82tPj4Yz # aSluGDQoX3NpMKooKeVFjjNRq37yyT/h1QTLMB8dpmsZ/70UM+U/sYxvt1PWWxLj # MNIXqzB8PjG6i7H2YFgk4YOhfGSekvnzW13dLAtfjD0wiwREPvCNlilRz7XoFde5 # KO01eFiWeteh48qUOqUaAkIznC4XB3sFd1LWUmupXHK05QfJSmnei9qZJBYTt8Zh # ArGDh7nQn+Y1jOA3oBiCUJ4n1CMaWdDhrgdMuu026oWAbfC3prqkUn8LWp28H+2S # LetNG5KQZZwvy3Zcn7+PQGl5AgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUBN/0b6Fh6nMdE4FAxYG9kWCpbYUw # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwNTM2MjAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # AGLQps1XU4RTcoDIDLP6QG3NnRE3p/WSMp61Cs8Z+JUv3xJWGtBzYmCINmHVFv6i # 8pYF/e79FNK6P1oKjduxqHSicBdg8Mj0k8kDFA/0eU26bPBRQUIaiWrhsDOrXWdL # m7Zmu516oQoUWcINs4jBfjDEVV4bmgQYfe+4/MUJwQJ9h6mfE+kcCP4HlP4ChIQB # UHoSymakcTBvZw+Qst7sbdt5KnQKkSEN01CzPG1awClCI6zLKf/vKIwnqHw/+Wvc # Ar7gwKlWNmLwTNi807r9rWsXQep1Q8YMkIuGmZ0a1qCd3GuOkSRznz2/0ojeZVYh # ZyohCQi1Bs+xfRkv/fy0HfV3mNyO22dFUvHzBZgqE5FbGjmUnrSr1x8lCrK+s4A+ # bOGp2IejOphWoZEPGOco/HEznZ5Lk6w6W+E2Jy3PHoFE0Y8TtkSE4/80Y2lBJhLj # 27d8ueJ8IdQhSpL/WzTjjnuYH7Dx5o9pWdIGSaFNYuSqOYxrVW7N4AEQVRDZeqDc # fqPG3O6r5SNsxXbd71DCIQURtUKss53ON+vrlV0rjiKBIdwvMNLQ9zK0jy77owDy # XXoYkQxakN2uFIBO1UNAvCYXjs4rw3SRmBX9qiZ5ENxcn/pLMkiyb68QdwHUXz+1 # fI6ea3/jjpNPz6Dlc/RMcXIWeMMkhup/XEbwu73U+uz/MIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGg4wghoKAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAASEmOIS4HijMV0AAAAA # BIQwDQYJYIZIAWUDBAIBBQCggbAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIB/j # e563Edd6Ldkx9P4suSYlZAMmipT0Ik9K7toNZX9MMEQGCisGAQQBgjcCAQwxNjA0 # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEcgBpodHRwczovL3d3dy5taWNyb3NvZnQu # Y29tIDANBgkqhkiG9w0BAQEFAASCAQAN367aRfoY4EYTeajfIMrFBSDby3+SBFdp # 2zYYY3/qDXfxrCCxktQaSkHju3UkcpAScA0qRFQ42aegrlTGzuS82Vr1ijKg6lpy # Dlij6FEoFuDcS3RjnVQRM2vSIIsvPcK07Syc81v1uPb0DLHOc5JGy2ZcWIR6pvhb # rBLo0OmIx3Q0mnGdqpb6joV5pd/4/NsNXo+C9U9EDfxIG6Wg69ofUMSxzzChoQgg # EiTtE5zSFWyVDeRxqF1uDEvcB7NpFwMK58dtUBaRuVJliMQLLcKXYeHQQvlv6lLo # MQVPvqxcyMr75UtoaYVqE1ZE5IQRf2BuO3rn04qzIJKlIHgkHhZboYIXljCCF5IG # CisGAQQBgjcDAwExgheCMIIXfgYJKoZIhvcNAQcCoIIXbzCCF2sCAQMxDzANBglg # hkgBZQMEAgEFADCCAVEGCyqGSIb3DQEJEAEEoIIBQASCATwwggE4AgEBBgorBgEE # AYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEIF1tI/zvr9aj7YFPSrtjUnSVAqfgnb0q # tniFFXUrwvfqAgZoo6N6Vy0YEjIwMjUwOTE2MTE0NzE0LjQ5WjAEgAIB9KCB0aSB # zjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UE # CxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVs # ZCBUU1MgRVNOOjg5MDAtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt # ZS1TdGFtcCBTZXJ2aWNloIIR7TCCByAwggUIoAMCAQICEzMAAAIOLMsofZUgdWMA # AQAAAg4wDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw # MTAwHhcNMjUwMTMwMTk0MzAzWhcNMjYwNDIyMTk0MzAzWjCByzELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFt # ZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjg5MDAt # MDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEArObe4kbV7dIW3qPTBO/G # WIyKN7GkLljARUO1+LPb6KGEQAUzn9qaEx2rcfhMJwVBgdVdrfxOjMLEDZmOV6TP # ++Wgq2XcQJ61faOE7ubAXqW233obKzlkQSBqCROj7VqHdQqxXoZtXYs942Nx/Iha # 4e56nn54mdUp23FjzMjSMbhhc6UIgwPhOWEt95njKml8IXW9NQpbspof9xCr5J4+ # HSKUGRFjjzN48W0VQGDeSdrTq2JCXHQ8dJdNlfzWHdapL1AYD8ayr4quZM+xOgGz # onwg0jAYHJ/1+0UMOt9EJM6oadJA1Nqnov2qPSB5rrkXlxI546YE7K+AG99yAgCj # GMTkHvp+cKhFXBPTk8oZlmSUuQJ1lE54qJOJoMDjQVkNQyzhhZGcF099+CDwqneP # 9/y3fyLYs4rLclGWLJpfwuGYXQC2732MM799TsX/DU5leSBsVnR55Nh4YeG580yq # LBGg6yb0DIkPpaKIzO3+W4HcgQZ2EAZufv4ibMcPJNtu8xdo2zSPjsLPBy3mRrfL # eridnlYzQ9QdGLYLAT9HLAZZ5yPuPnby2EbdHAKsOj4mEs+RUmXG6YtMXQB/43d3 # c8hgK28i7qOvR7oHxhBG/7DNO63KD9aN3GfHljG+PjCAfHrjm+Q1Tw5xHBYuDQ7p # GDPdYNQ7f6iHpPq7RPPFUvECAwEAAaOCAUkwggFFMB0GA1UdDgQWBBSFcURpUhGR # PtREiulBiO2DXBCI2zAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBf # BgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmww # bAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29m # dC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0El # MjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUF # BwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEAdeC9ky/i/Dly # 8Zxkmpdod9JmexbARaKImJFFTmNORfaZ8D01bnxAxlhKTTctjn2lB1iDqEP/f648 # DtIUtkqQdAczAJNoMs/djRljqVm6QXTL660Q6YlmYv7i0uGRnUZ9z9g3HGJpZDT/ # r2kQF757/pqduyoCO/ZifYRsgkG77TCI5G2KC6iu7Be1moZ/ay419cuUCS+JbxMt # 0JgPSkQY+enBL/5QL8w6u3koqkav6QsqsnPLs5kPEnilslrug41APb4vOELJi46j # xgpx+HD8oPrfeUaVvu97J4XsNYglfsF7tkcTJ1oOxLA+Xi5CRy7M1CD3flwpQ/hU # 71dNxn6ww35PuOX5R/3ikWXNzFGbZ4SyYz8L9yqCg0nFuIlekmwkcnGD5KqFgax3 # +0rwwOxqx9lDrc9VmtZNu7HWYKRuv3PQqiiPAl+b4GmvgO6GB2+GQY+0vLvLIMcF # iux4Fg0Qcjh9woibuCyfId04kZEQK5h0adJWzX9YgCri/POiChPddr9MquebfIzM # YwVO7qC7K2FSKCpM4frAJIJKRjqGS9ePnZcVTPdQWr82uJDg01JcM2/kqV7Eqlcf # J7geqoVMu6aqYMMNauEjYQMRZxcbMYk5WqC++RjcT0etOZSdll3obRIu//mHyarx # /r56nKago8kPYTWlc7jhB1+DMrqnI8IwggdxMIIFWaADAgECAhMzAAAAFcXna54C # m0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZp # Y2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMy # MjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV # BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0B # AQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51 # yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY # 6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9 # cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN # 7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDua # Rr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74 # kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2 # K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5 # TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZk # i1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9Q # BXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3Pmri # Lq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUC # BBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJl # pxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9y # eS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUA # YgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU # 1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2Ny # bC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIw # MTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0w # Ni0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/yp # b+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulm # ZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM # 9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECW # OKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4 # FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3Uw # xTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPX # fx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVX # VAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGC # onsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU # 5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEG # ahC0HVUzWLOhcGbyoYIDUDCCAjgCAQEwgfmhgdGkgc4wgcsxCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVy # aWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo4OTAwLTA1 # RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIj # CgEBMAcGBSsOAwIaAxUASuh2P2Vi5znDBELI5AwKAfyWVgiggYMwgYCkfjB8MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNy # b3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAOxzscYw # IhgPMjAyNTA5MTYwOTUyMDZaGA8yMDI1MDkxNzA5NTIwNlowdzA9BgorBgEEAYRZ # CgQBMS8wLTAKAgUA7HOxxgIBADAKAgEAAgImIwIB/zAHAgEAAgISKjAKAgUA7HUD # RgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6Eg # oQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IBAQAsywdwrq+LtXxctC0jSbHh # 2f6pmBPJlLUWrWoF6GF2oG3mYoswL/Db+W/4/GWqbaXCI/IvTprpw3BmqPgl8Hix # e/yKtJyYSY9NNtFDTSRNgx4pQW4qMLVGLVw8be13eH4Pz3ideH5/UNuEsQaejM0E # 9FK1Ia+80uvpnuFXB9MjIzizYHAxpdaQwqPaO4s7CRUpP3ztxFh18UTxjvxXRWxC # rVMODv367FIa29ob0qbWSGwcUk3OXgGLHlNdMjVuE1EPtp9xHMTw5Afks1M8S2ly # yt87SRshkYvlRgeJo1h5HszISyisI9xNlLR4sWPvRvQursPxRPZ2V4XiKiTjcdda # MYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 # b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMA # AAIOLMsofZUgdWMAAQAAAg4wDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJ # AzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgU7pwA1SA8Ns4/s9dmoZB # I9PLO0cXU+WT3J7MQsrMhJswgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCAB # dB1zJfDpgZCtuu5saGykoocDnT9HlDV0DMqT808ShjCBmDCBgKR+MHwxCzAJBgNV # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m # dCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAACDizLKH2VIHVjAAEAAAIOMCIEIOEH # Fqnjki4QJ1f8QmWeqq/73DtchmszMBYKRWFRy+KuMA0GCSqGSIb3DQEBCwUABIIC # AHwSSzOSgypOwnHNNOURfUpIzF1q6sLKMUhigUgElywsxRaAW2YDRXXo+Uckc7W9 # tqI4kuDDRySTjMOZFfV0TDdW6V98+uT6F3m0thFbkiGarMdxnQyvT/mttwjAydR/ # vkONaoOISte344WqET1faIk2OrqS/PJSa5gYHJMxGUtmyRR81s9jTCodsiifBwz8 # VsoQ/gl1aA+2maiWEAgoTrtis8gSE+h8OJJ3POqXXEzC2TQwjJNoqOdGnQyrC0eh # 2KM/th7GfTVCIA+OZfp4kchSl5GFrDnUjQsuIFcp9G7pX5ekTUXJ0EG8SPnq/p/A # OQy5nzO7Y2VHY2CkTPXU7exrjwk+FUCcLok0rFckoeX37f1mpMe+E0aJaQ6d0xH2 # SBFAd0KdjOJuXoXB0UNGafBCQfr0Y34lGlMR6nw6/P5UPwEQmy2Fiw/aP+2ZHXnV # e2q45x1Yz2j/oq5QJ2Y5U7CYHQTVQV+WYpAPYdVj1CrZVdHuQGSdQ6sXy79d7odt # j3MohWtEB3jkWLZ0ow16eCoEhE7/20BvG5AOFK+xxZyHz3KFgGeV/w5A1caJOlkT # +K73yaU1ZN8YU+6TdFbH6frEIlbjUgPp0d1J1zos1cFPXmNumboJBSnQgbTzuB2u # UK0/79Bk4L2fBx5dIGxbkY6pLxEUFBS2IqEyFtzR8G0U # SIG # End signature block |