diff --git a/src/classes/public/Config/GitHubConfig.ps1 b/src/classes/public/Config/GitHubConfig.ps1 index 32a7b5bfc..fbd86f1ae 100644 --- a/src/classes/public/Config/GitHubConfig.ps1 +++ b/src/classes/public/Config/GitHubConfig.ps1 @@ -26,6 +26,12 @@ # The default value for the 'per_page' API parameter used in 'GET' functions that support paging. [int] $PerPage + # The default value for retry count. + [int] $RetryCount + + # The default value for retry interval in seconds. + [int] $RetryInterval + # Simple parameterless constructor GitHubConfig() {} diff --git a/src/formats/GitHubContext.Format.ps1xml b/src/formats/GitHubContext.Format.ps1xml index 5897f2b75..824682b99 100644 --- a/src/formats/GitHubContext.Format.ps1xml +++ b/src/formats/GitHubContext.Format.ps1xml @@ -1,7 +1,6 @@ - GitHubContextTableView @@ -42,8 +41,6 @@ - - GitHubContextListView diff --git a/src/formats/GitHubWebhook.Format.ps1xml b/src/formats/GitHubWebhook.Format.ps1xml index c5b96100e..d8e2eed0d 100644 --- a/src/formats/GitHubWebhook.Format.ps1xml +++ b/src/formats/GitHubWebhook.Format.ps1xml @@ -1,7 +1,6 @@ - GitHubWebhookTable @@ -79,8 +78,6 @@ - - GitHubWebhookList diff --git a/src/formats/GitHubWebhookRedelivery.Format.ps1xml b/src/formats/GitHubWebhookRedelivery.Format.ps1xml index dab55ba4c..1e87f79c2 100644 --- a/src/formats/GitHubWebhookRedelivery.Format.ps1xml +++ b/src/formats/GitHubWebhookRedelivery.Format.ps1xml @@ -1,7 +1,6 @@ - GitHubWebhookRedeliveryTable @@ -60,8 +59,6 @@ - - GitHubWebhookRedeliveryList diff --git a/src/functions/private/Auth/Cli/Connect-GithubCli.ps1 b/src/functions/private/Auth/Cli/Connect-GithubCli.ps1 index ccba21046..dd77bdf7d 100644 --- a/src/functions/private/Auth/Cli/Connect-GithubCli.ps1 +++ b/src/functions/private/Auth/Cli/Connect-GithubCli.ps1 @@ -42,12 +42,17 @@ } process { - $Context.Token | ConvertFrom-SecureString -AsPlainText | gh auth login --with-token --hostname $Context.HostName + $return = ($Context.Token | ConvertFrom-SecureString -AsPlainText | gh auth login --with-token --hostname $Context.HostName) 2>&1 + $return = $return -join [System.Environment]::NewLine if ($LASTEXITCODE -ne 0) { - Write-Warning 'Unable to log on with the GitHub Cli.' + if ($return.Contains('GITHUB_TOKEN environment variable is being used for authentication')) { + Write-Debug $return + } else { + Write-Warning "Unable to log on with the GitHub Cli. ($LASTEXITCODE)" + Write-Warning "$($return)" + } $Global:LASTEXITCODE = 0 Write-Debug "Resetting LASTEXITCODE: $LASTEXITCODE" - return } } diff --git a/src/functions/private/Auth/Context/Resolve-GitHubContextSetting.ps1 b/src/functions/private/Auth/Context/Resolve-GitHubContextSetting.ps1 index 32f3868cb..4b8d8ec7b 100644 --- a/src/functions/private/Auth/Context/Resolve-GitHubContextSetting.ps1 +++ b/src/functions/private/Auth/Context/Resolve-GitHubContextSetting.ps1 @@ -41,6 +41,5 @@ if ([string]::IsNullOrEmpty($Value)) { $Value = $Context.$Name } - Write-Debug "$Name`: [$Value]" return $Value } diff --git a/src/functions/public/API/Invoke-GitHubAPI.ps1 b/src/functions/public/API/Invoke-GitHubAPI.ps1 index ea42a67c4..b135faff9 100644 --- a/src/functions/public/API/Invoke-GitHubAPI.ps1 +++ b/src/functions/public/API/Invoke-GitHubAPI.ps1 @@ -81,6 +81,20 @@ filter Invoke-GitHubAPI { [Parameter()] [string] $ApiVersion, + # Specifies how many times PowerShell retries a connection when a failure code between 400 and 599, inclusive or 304 is received. + [Parameter()] + [int] $RetryCount = $script:GitHub.Config.RetryCount, + + # Specifies the interval between retries for the connection when a failure code between 400 and 599, inclusive or 304 is received. + # When the failure code is 429 and the response includes the Retry-After property in its headers, the cmdlet uses that value for the retry + # interval, even if this parameter is specified. + [Parameter()] + [int] $RetryInterval = $script:GitHub.Config.RetryInterval, + + # The number of results per page for paginated GitHub API responses. + [Parameter()] + [int] $PerPage, + # The context to run the command in. Used to get the details for the API call. # Can be either a string or a GitHubContext object. [Parameter()] @@ -92,20 +106,26 @@ filter Invoke-GitHubAPI { Write-Debug "[$stackPath] - Start" $Context = Resolve-GitHubContext -Context $Context Write-Debug 'Invoking GitHub API...' - Write-Debug 'Parameters:' - Get-FunctionParameter | Format-List | Out-String -Stream | ForEach-Object { Write-Debug $_ } Write-Debug 'Parent function parameters:' Get-FunctionParameter -Scope 1 | Format-List | Out-String -Stream | ForEach-Object { Write-Debug $_ } + Write-Debug 'Parameters:' + Get-FunctionParameter | Format-List | Out-String -Stream | ForEach-Object { Write-Debug $_ } } process { $Token = $Context.Token - Write-Debug "Token: [$Token]" $HttpVersion = Resolve-GitHubContextSetting -Name 'HttpVersion' -Value $HttpVersion -Context $Context $ApiBaseUri = Resolve-GitHubContextSetting -Name 'ApiBaseUri' -Value $ApiBaseUri -Context $Context $ApiVersion = Resolve-GitHubContextSetting -Name 'ApiVersion' -Value $ApiVersion -Context $Context $TokenType = Resolve-GitHubContextSetting -Name 'TokenType' -Value $TokenType -Context $Context + [pscustomobject]@{ + Token = $Token + HttpVersion = $HttpVersion + ApiBaseUri = $ApiBaseUri + ApiVersion = $ApiVersion + TokenType = $TokenType + } | Format-List | Out-String -Stream | ForEach-Object { Write-Debug $_ } $jwt = $null switch ($TokenType) { 'ghu' { @@ -132,32 +152,39 @@ filter Invoke-GitHubAPI { } $APICall = @{ - Uri = $Uri - Method = [string]$Method - Headers = $Headers - Authentication = 'Bearer' - Token = $Token - ContentType = $ContentType - InFile = $UploadFilePath - OutFile = $DownloadFilePath - HttpVersion = [string]$HttpVersion + Uri = $Uri + Method = [string]$Method + Headers = $Headers + Authentication = 'Bearer' + Token = $Token + ContentType = $ContentType + InFile = $UploadFilePath + OutFile = $DownloadFilePath + HttpVersion = [string]$HttpVersion + MaximumRetryCount = $RetryCount + RetryIntervalSec = $RetryInterval } $APICall | Remove-HashtableEntry -NullOrEmptyValues - if ($Body) { - # Use body to create the query string for certain situations - if ($Method -eq 'GET') { - # If body conatins 'per_page' and its is null, set it to $context.PerPage - if ($Body['per_page'] -eq 0) { - Write-Debug "Setting per_page to the default value in context [$($Context.PerPage)]." - $Body['per_page'] = $Context.PerPage - } - $APICall.Uri = New-Uri -BaseUri $Uri -Query $Body -AsString - } elseif ($Body -is [string]) { - # Use body to create the form data - $APICall.Body = $Body - } else { + if ($Method -eq 'GET') { + if (-not $Body) { + $Body = @{} + } + + if ($PSBoundParameters.ContainsKey('PerPage')) { + Write-Debug "Using provided PerPage parameter value [$PerPage]." + $Body['per_page'] = $PerPage + } elseif (-not $Body.ContainsKey('per_page') -or $Body['per_page'] -eq 0) { + Write-Debug "Setting per_page to the default value in context [$($Context.PerPage)]." + $Body['per_page'] = $Context.PerPage + } + + $APICall.Uri = New-Uri -BaseUri $Uri -Query $Body -AsString + } elseif ($Body) { + if ($Body -is [hashtable]) { $APICall.Body = $Body | ConvertTo-Json -Depth 100 + } else { + $APICall.Body = $Body } } @@ -289,7 +316,7 @@ filter Invoke-GitHubAPI { $APICall.Headers = $APICall.Headers | ConvertTo-Json $APICall.Method = $APICall.Method.ToString() - Write-Warning @" + $exception = @" ---------------------------------- Error details: @@ -300,7 +327,7 @@ $($errorResult | Format-List | Out-String -Stream | ForEach-Object { " $_`n" $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( - [System.Exception]::new('GitHub API call failed. See error details above.'), + [System.Exception]::new($exception), 'GitHubAPIError', [System.Management.Automation.ErrorCategory]::InvalidOperation, $errorResult diff --git a/src/functions/public/Auth/Connect-GitHubAccount.ps1 b/src/functions/public/Auth/Connect-GitHubAccount.ps1 index 99ce6bd02..8390f272a 100644 --- a/src/functions/public/Auth/Connect-GitHubAccount.ps1 +++ b/src/functions/public/Auth/Connect-GitHubAccount.ps1 @@ -320,7 +320,6 @@ clean { Remove-Variable -Name tokenResponse -ErrorAction SilentlyContinue Remove-Variable -Name context -ErrorAction SilentlyContinue - Remove-Variable -Name contextData -ErrorAction SilentlyContinue Remove-Variable -Name Token -ErrorAction SilentlyContinue [System.GC]::Collect() } diff --git a/src/variables/private/GitHub.ps1 b/src/variables/private/GitHub.ps1 index 9ca9b6847..8b9b77b19 100644 --- a/src/variables/private/GitHub.ps1 +++ b/src/variables/private/GitHub.ps1 @@ -17,6 +17,8 @@ ApiVersion = '2022-11-28' HttpVersion = '2.0' PerPage = 100 + RetryCount = 0 + RetryInterval = 1 } Config = $null Event = $null diff --git a/tests/TEMPLATE.ps1 b/tests/TEMPLATE.ps1 index 087ab37d6..f9d18a136 100644 --- a/tests/TEMPLATE.ps1 +++ b/tests/TEMPLATE.ps1 @@ -71,6 +71,7 @@ Describe 'As a GitHub App - Enterprise (APP_ENT)' { BeforeAll { Connect-GitHubAccount -ClientID $env:TEST_APP_ENT_CLIENT_ID -PrivateKey $env:TEST_APP_ENT_PRIVATE_KEY $owner = 'psmodule-test-org3' + Connect-GitHubApp -Organization $owner -Default } AfterAll { Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount @@ -84,6 +85,7 @@ Describe 'As a GitHub App - Organization (APP_ORG)' { BeforeAll { Connect-GitHubAccount -ClientID $env:TEST_APP_ORG_CLIENT_ID -PrivateKey $env:TEST_APP_ORG_PRIVATE_KEY $owner = 'psmodule-test-org' + Connect-GitHubApp -Organization $owner -Default } AfterAll { Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount