From e8f19f23e3e48b818c9d5c5312d4911b0268a0a7 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Wed, 13 May 2020 13:18:39 -0700 Subject: [PATCH 01/15] Add support for gists Adds full support for all gist related API's (core and comments) as described in https://developer.github.com/v3/gists/ and https://developer.github.com/v3/gists/comments/. * No tests yet. * Test-GitHubGistStarred doesn't appear to be working right, despite being coded against the proper API spec. --- GitHubCore.ps1 | 9 + GitHubGistComments.ps1 | 323 ++++++++++++++ GitHubGists.ps1 | 881 +++++++++++++++++++++++++++++++++++++++ PowerShellForGitHub.psd1 | 19 + 4 files changed, 1232 insertions(+) create mode 100644 GitHubGistComments.ps1 create mode 100644 GitHubGists.ps1 diff --git a/GitHubCore.ps1 b/GitHubCore.ps1 index 02c887fd..4ea6fabd 100644 --- a/GitHubCore.ps1 +++ b/GitHubCore.ps1 @@ -329,6 +329,15 @@ function Invoke-GHRestMethod $finalResult = $finalResult | ConvertFrom-Json } } + catch [InvalidOperationException] + { + # In some cases, the returned data might have two different keys of the same characters + # but different casing (this can happen with gists with two files named 'a.txt' and 'A.txt'). + # PowerShell 6 introduced the -AsHashtable switch to work around this issue, but this + # module wants to be compatible down to PowerShell 4, so we're unable to use that feature. + Write-Log -Message 'The returned object likely contains keys that differ only in casing. Unable to convert to an object. Returning the raw JSON as a fallback.' -Level Warning + $finalResult = $finalResult + } catch [ArgumentException] { # The content must not be JSON (which is a legitimate situation). diff --git a/GitHubGistComments.ps1 b/GitHubGistComments.ps1 new file mode 100644 index 00000000..6640d36b --- /dev/null +++ b/GitHubGistComments.ps1 @@ -0,0 +1,323 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +function Get-GitHubGistComment +{ +<# + .SYNOPSIS + Retrieves comments for a specific gist from GitHub. + + .DESCRIPTION + Retrieves comments for a specific gist from GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific gist that you wish to retrieve the comments for. + + .PARAMETER CommentId + The ID of the specific comment on the gist that you wish to retrieve. + + .PARAMETER MediaType + The format in which the API will return the body of the comment. + + Raw - Return the raw markdown body. Response will include body. This is the default if you do not pass any specific media type. + Text - Return a text only representation of the markdown body. Response will include body_text. + Html - Return HTML rendered from the body's markdown. Response will include body_html. + Full - Return raw, text and HTML representations. Response will include body, body_text, and body_html. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + Get-GitHubGistComment -Id 6cad326836d38bd3a7ae + + Gets all comments on octocat's "hello_world.rb" gist. + + .EXAMPLE + Get-GitHubGistComment -Id 6cad326836d38bd3a7ae -CommentId 1507813 + + Gets comment 1507813 from octocat's "hello_world.rb" gist. +#> + [CmdletBinding(SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [Alias('GistId')] + [string] $Id, + + [string] $CommentId, + + [ValidateSet('Raw', 'Text', 'Html', 'Full')] + [string] $MediaType = 'Raw', + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{} + + $uriFragment = [String]::Empty + $description = [String]::Empty + + if ([String]::IsNullOrWhiteSpace($CommentId)) + { + $uriFragment = "gists/$Id/comments" + $description = "Getting comments for gist $Id" + } + else + { + $telemetryProperties['SpecifiedCommentId'] = $true + + $uriFragment = "gists/$Id/comments/$CommentId" + $description = "Getting comment $CommentId for gist $Id" + } + + $params = @{ + 'UriFragment' = $uriFragment + 'Description' = $description + 'AccessToken' = $AccessToken + 'AcceptHeader' = (Get-MediaAcceptHeader -MediaType $MediaType -AsJson) + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + $result = Invoke-GHRestMethodMultipleResult @params + + return $result +} + +function Remove-GitHubGistComment +{ +<# + .SYNOPSIS + Removes/deletes a comment from a gist on GitHub. + + .DESCRIPTION + Removes/deletes a comment from a gist on GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific gist that you wish to remove the comment from. + + .PARAMETER CommentId + The ID of the comment to remove from the gist. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + Remove-GitHubGist -Id 6cad326836d38bd3a7ae + + Removes octocat's "hello_world.rb" gist (assuming you have permission). + + .EXAMPLE + Remove-GitHubGist -Id 6cad326836d38bd3a7ae -Confirm:$false + + Removes octocat's "hello_world.rb" gist (assuming you have permission). + Will not prompt for confirmation, as -Confirm:$false was specified. +#> + [CmdletBinding( + SupportsShouldProcess, + ConfirmImpact="High")] + [Alias('Delete-GitHubGist')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [Alias('GistId')] + [ValidateNotNullOrEmpty()] + [string] $Id, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $CommentId, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + if ($PSCmdlet.ShouldProcess($CommentId, "Delete comment from gist $Id")) + { + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id/comments/$CommentId" + 'Method' = 'Delete' + 'Description' = "Removing comment $CommentId from gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params + } +} + +function New-GitHubGistComment +{ +<# + .SYNOPSIS + Creates a new comment on the specified gist from GitHub. + + .DESCRIPTION + Creates a new comment on the specified gist from GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific gist that you wish to add the comment to. + + .PARAMETER Comment + The text of the comment that you wish to leave on the gist. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + New-GitHubGistComment -Id 6cad326836d38bd3a7ae -Comment 'Hello World' + + Adds a new comment of "Hello World" to octocat's "hello_world.rb" gist. +#> + [CmdletBinding(SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [Alias('GistId')] + [ValidateNotNullOrEmpty()] + [string] $Id, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $Comment, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $hashBody = @{ + 'body' = $Comment + } + + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id/comments" + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Method' = 'Post' + 'Description' = "Creating new comment on gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params +} + +function Set-GitHubGistComment +{ + <# + .SYNOPSIS + Edits a comment on the specified gist from GitHub. + + .DESCRIPTION + Edits a comment on the specified gist from GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the gist that the comment is on. + + .PARAMETER CommentId + The ID of the comment that you wish to edit. + + .PARAMETER Comment + The new text of the comment that you wish to leave on the gist. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + New-GitHubGistComment -Id 6cad326836d38bd3a7ae -Comment 'Hello World' + + Adds a new comment of "Hello World" to octocat's "hello_world.rb" gist. +#> + [CmdletBinding(SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [Alias('GistId')] + [ValidateNotNullOrEmpty()] + [string] $Id, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $CommentId, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $Comment, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $hashBody = @{ + 'body' = $Comment + } + + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id/comments/$CommentId" + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Method' = 'Patch' + 'Description' = "Creating new comment on gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params +} diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 new file mode 100644 index 00000000..84cbf5d1 --- /dev/null +++ b/GitHubGists.ps1 @@ -0,0 +1,881 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +function Get-GitHubGist +{ +<# + .SYNOPSIS + Retrieves gist information from GitHub. + + .DESCRIPTION + Retrieves gist information from GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific gist that you wish to retrieve. + + .PARAMETER Sha + The specific revision of the gist that you wish to retrieve. + + .PARAMETER Forks + Gets the forks of the specified gist. + + .PARAMETER Commits + Gets the commits of the specified gist. + + .PARAMETER UserName + Gets public gists for the specified user. + + .PARAMETER Current + Gets the authenticated user's gists. + + .PARAMETER Starred + Gets the authenticated user's starred gists. + + .PARAMETER Public + Gets public gists sorted by most recently updated to least recently updated. + The results will be limited to the first 3000. + + .PARAMETER Since + Only gists updated at or after this time are returned. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + Get-GitHubGist -Starred + + Gets all starred gists for the current authenticated user. + + .EXAMPLE + Get-GitHubGist -Public -Since ((Get-Date).AddDays(-2)) + + Gets all public gists that have been updated within the past two days. + + .EXAMPLE + Get-GitHubGist -Id 6cad326836d38bd3a7ae + + Gets octocat's "hello_world.rb" gist. +#> + [CmdletBinding( + SupportsShouldProcess, + DefaultParameterSetName='Current')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter( + Mandatory, + ParameterSetName='Id')] + [string] $Id, + + [Parameter(ParameterSetName='Id')] + [string] $Sha, + + [Parameter(ParameterSetName='Id')] + [switch] $Forks, + + [Parameter(ParameterSetName='Id')] + [switch] $Commits, + + [Parameter(ParameterSetName='User')] + [string] $UserName, + + [Parameter(ParameterSetName='Current')] + [switch] $Current, + + [Parameter(ParameterSetName='Current')] + [switch] $Starred, + + [Parameter(ParameterSetName='Public')] + [switch] $Public, + + [Parameter(ParameterSetName='User')] + [Parameter(ParameterSetName='Current')] + [Parameter(ParameterSetName='Public')] + [DateTime] $Since, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{} + + $uriFragment = [String]::Empty + $description = [String]::Empty + + if ($PSCmdlet.ParameterSetName -eq 'Id') + { + $telemetryProperties['ById'] = $true + + if ([String]::IsNullOrWhiteSpace($Sha)) + { + if ($Forks) + { + $uriFragment = "gists/$Id/forks" + $description = "Getting forks of gist $Id" + } + elseif ($Commits) + { + $uriFragment = "gists/$Id/commits" + $description = "Getting commits of gist $Id" + } + else + { + $uriFragment = "gists/$Id" + $description = "Getting gist $Id" + } + } + else + { + if ($Forks -or $Commits) + { + $message = 'Cannot check for forks or commits of a specific SHA. Do not specify SHA if you want to list out forks or commits.' + Write-Log -Message $message -Level Error + throw $message + } + + $telemetryProperties['SpecifiedSha'] = $true + + $uriFragment = "gists/$Id/$Sha" + $description = "Getting gist $Id with specified Sha" + } + } + elseif ($PSCmdlet.ParameterSetName -eq 'User') + { + $telemetryProperties['ByUserName'] = $true + + $uriFragment = "users/$UserName/gists" + $description = "Getting public gists for $UserName" + } + elseif ($PSCmdlet.ParameterSetName -eq 'Current') + { + $telemetryProperties['CurrentUser'] = $true + + if (Test-GitHubAuthenticationConfigured) + { + if ($Starred) + { + $uriFragment = 'gists/starred' + $description = 'Getting starred gists for current authenticated user' + } + else + { + $uriFragment = 'gists' + $description = 'Getting gists for current authenticated user' + } + } + else + { + if ($Starred) + { + $message = 'Starred can only be specified for authenticated users. Either call Set-GitHubAuthentication first, or provide a value for the AccessToken parameter.' + Write-Log -Message $message -Level Error + throw $message + } + + $description = 'Getting public gists' + } + } + elseif ($PSCmdlet.ParameterSetName -eq 'Public') + { + $telemetryProperties['Public'] = $true + + $uriFragment = "gists/public" + $description = 'Getting public gists' + } + + $getParams = @() + $sinceFormattedTime = [String]::Empty + if ($null -ne $Since) + { + $sinceFormattedTime = $Since.ToUniversalTime().ToString('o') + $getParams += "since=$sinceFormattedTime" + } + + $params = @{ + 'UriFragment' = $uriFragment + '?' + ($getParams -join '&') + 'Description' = $description + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + $result = Invoke-GHRestMethodMultipleResult @params + + if ($result.truncated -eq $true) + { + $message = @" +Response has been truncated. The API will only return the first 3000 gist results, +the first 300 files within an individual gist, and the first 1 Mb of an individual file. +If the file has been truncated, you can call (Invoke-WebRequest -UseBasicParsing -Method Get -Uri ).Content) +where is the value of raw_url for the file in question. Be aware that for files larger +than 10 Mb, you''ll need to clone the gist via the URL provided by git_pull_url. +"@ + Write-Log -Message $message -Level Warning + } + + return $result +} + +function Remove-GitHubGist +{ +<# + .SYNOPSIS + Removes/deletes a gist from GitHub. + + .DESCRIPTION + Removes/deletes a gist from GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific gist that you wish to retrieve. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + Remove-GitHubGist -Id 6cad326836d38bd3a7ae + + Removes octocat's "hello_world.rb" gist (assuming you have permission). + + .EXAMPLE + Remove-GitHubGist -Id 6cad326836d38bd3a7ae -Confirm:$false + + Removes octocat's "hello_world.rb" gist (assuming you have permission). + Will not prompt for confirmation, as -Confirm:$false was specified. +#> + [CmdletBinding( + SupportsShouldProcess, + ConfirmImpact="High")] + [Alias('Delete-GitHubGist')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $Id, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + if ($PSCmdlet.ShouldProcess($Id, "Delete gist")) + { + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id" + 'Method' = 'Delete' + 'Description' = "Removing gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params + } +} + +function Copy-GitHubGist +{ +<# + .SYNOPSIS + Forks a gist from GitHub. + + .DESCRIPTION + Forks a gist from GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific gist that you wish to fork. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + Copy-GitHubGist -Id 6cad326836d38bd3a7ae + + Forks octocat's "hello_world.rb" gist. + + .EXAMPLE + Fork-GitHubGist -Id 6cad326836d38bd3a7ae + + Forks octocat's "hello_world.rb" gist. This is using the alias for the command. + The result is the same whether you use Copy-GitHubGist or Fork-GitHubGist. +#> + [CmdletBinding(SupportsShouldProcess)] + [Alias('Fork-GitHubGist')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $Id, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id/forks" + 'Method' = 'Post' + 'Description' = "Forking gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params +} + +function Add-GitHubGistStar +{ +<# + .SYNOPSIS + Star a gist from GitHub. + + .DESCRIPTION + Star a gist from GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific Gist that you wish to star. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + Add-GitHubGistStar -Id 6cad326836d38bd3a7ae + + STars octocat's "hello_world.rb" gist. + + .EXAMPLE + Star-GitHubGist -Id 6cad326836d38bd3a7ae + + Stars octocat's "hello_world.rb" gist. This is using the alias for the command. + The result is the same whether you use Add-GitHubGistStar or Star-GitHubGist. +#> + [CmdletBinding(SupportsShouldProcess)] + [Alias('Star-GitHubGist')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $Id, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id/star" + 'Method' = 'Put' + 'Description' = "Starring gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params +} + +function Remove-GitHubGistStar +{ +<# + .SYNOPSIS + Unstar a gist from GitHub. + + .DESCRIPTION + Unstar a gist from GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific gist that you wish to unstar. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + Remove-GitHubGistStar -Id 6cad326836d38bd3a7ae + + Unstars octocat's "hello_world.rb" gist. + + .EXAMPLE + Unstar-GitHubGist -Id 6cad326836d38bd3a7ae + + Unstars octocat's "hello_world.rb" gist. This is using the alias for the command. + The result is the same whether you use Remove-GitHubGistStar or Unstar-GitHubGist. +#> + [CmdletBinding(SupportsShouldProcess)] + [Alias('Unstar-GitHubGist')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $Id, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id/star" + 'Method' = 'Delete' + 'Description' = "Unstarring gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params +} + +function Test-GitHubGistStar +{ +<# + .SYNOPSIS + Checks if a gist from GitHub is starred. + + .DESCRIPTION + Checks if a gist from GitHub is starred. + Will return $false if it isn't starred, as well as if it couldn't be checked + (due to permissions or non-existence). + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID of the specific gist that you wish to check. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .OUTPUTS + [bool] If the gist was both found and determined to be starred. + + .EXAMPLE + Test-GitHubGistStar -Id 6cad326836d38bd3a7ae + + Returns $true if the gist is starred, or $false if isn't starred or couldn't be checked + (due to permissions or non-existence). + + .NOTES + For some reason, this does not currently seem to be working correctly + (even though it matches the spec: https://developer.github.com/v3/gists/#check-if-a-gist-is-starred). +#> + [CmdletBinding(SupportsShouldProcess)] + [OutputType([bool])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $Id, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id/star" + 'Method' = 'Get' + 'Description' = "Checking if gist $Id is starred" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'ExtendedResult' = $true + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + try + { + $response = Invoke-GHRestMethod @params + return $response.StatusCode -eq 204 + } + catch + { + return $false + } +} + +function New-GitHubGist +{ +<# + .SYNOPSIS + Creates a new gist on GitHub. + + .DESCRIPTION + Creates a new gist on GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER File + An array of filepaths that should be part of this gist. + Use this when you have multiple files that should be part of a gist, or when you simply + want to reference an existing file on disk. + + .PARAMETER Content + The content of a single file that should be part of the gist. + + .PARAMETER FileName + The name of the file that Content should be stored in within the newly created gist. + + .PARAMETER Description + A descriptive name for this gist. + + .PARAMETER Public + When specified, the gist will be public and available for anyone to see. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + New-GitHubGist -Content 'Body of my file.' -FileName 'sample.txt' -Description 'This is my gist!' -Public + + Creates a new public gist with a single file named 'sample.txt' that has the body of "Body of my file." + + .EXAMPLE + New-GitHubGist -File 'c:\files\foo.txt' -Description 'This is my gist!' + + Creates a new private gist with a single file named 'foo.txt'. Will populate it with the + content of the file at c:\files\foo.txt. + + .EXAMPLE + New-GitHubGist -File ('c:\files\foo.txt', 'c:\other\bar.txt', 'c:\octocat.ps1') -Description 'This is my gist!' + + Creates a new private gist with a three files named 'foo.txt', 'bar.txt' and 'octocat.ps1'. + Each will be populated with the content from the file on disk at the specified location. +#> + [CmdletBinding( + SupportsShouldProcess, + DefaultParameterSetName='Content')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter( + Mandatory, + ParameterSetName='FileRef')] + [string[]] $File, + + [Parameter( + Mandatory, + ParameterSetName='Content')] + [ValidateNotNullOrEmpty()] + [string] $Content, + + [Parameter( + Mandatory, + ParameterSetName='Content')] + [ValidateNotNullOrEmpty()] + [string] $FileName, + + [string] $Description, + + [switch] $Public, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{} + + $files = @{} + if ($PSCmdlet.ParameterSetName -eq 'Content') + { + $files[$FileName] = @{ 'content' = $Content } + } + else + { + foreach ($path in $File) + { + $path = Resolve-UnverifiedPath -Path $path + if (-not (Test-Path -Path $path)) + { + $message = "Specified file [$path] could not be found or was inaccessible." + Write-Log -Message $message -Level Error + throw $message + } + + $content = Get-Content -Path $path -Raw -Encoding UTF8 + $fileName = (Get-Item -Path $path).Name + + if ($files.ContainsKey($fileName)) + { + $message = "You have specified more than one file with the same name [$fileName]. gists don't have a concept of directory structures, so please ensure each file has a unique name." + Write-Log -Message $message -Level Error + throw $message + } + + $files[$fileName] = @{ 'content' = $Content } + } + } + + $hashBody = @{ + 'description' = $Description + 'public' = $Public.ToBool() + 'files' = $files + } + + $params = @{ + 'UriFragment' = "gists" + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Method' = 'Post' + 'Description' = "Creating a new gist" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params +} + +function Set-GitHubGist +{ +<# + .SYNOPSIS + Updates a gist on GitHub. + + .DESCRIPTION + Updates a gist on GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Id + The ID for the gist to update. + + .PARAMETER Update + A hashtable of files to update in the gist. + The key should be the name of the file in the gist as it exists right now. + The value should be another hashtable with the following optional key/value pairs: + fileName - Specify a new name here if you want to rename the file. + filePath - Specify a path to a file on disk if you wish to update the contents of the + file in the gist with the contents of the specified file. + Should not be specified if you use 'content' (below) + content - Directly specify the raw content that the file in the gist should be updated with. + Should not be used if you use 'filePath' (above). + + .PARAMETER Delete + A list of filenames that should be removed from this gist. + + .PARAMETER Description + New description for this gist. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .EXAMPLE + Set-GitHubGist -Id 6cad326836d38bd3a7ae -Description 'This is my newer description' + + Updates the description for the specified gist. + + .EXAMPLE + Set-GitHubGist -Id 6cad326836d38bd3a7ae -Delete 'hello_world.rb' + + Deletes the 'hello_world.rb' file from the specified gist. + + .EXAMPLE + Set-GitHubGist -Id 6cad326836d38bd3a7ae -Delete 'hello_world.rb' -Description 'This is my newer description' + + Deletes the 'hello_world.rb' file from the specified gist and updates the description. + + .EXAMPLE + Set-GitHubGist -Id 6cad326836d38bd3a7ae -Update @{'hello_world.rb' = @{ 'fileName' = 'hello_universe.rb' }} + + Renames the 'hello_world.rb' file in the specified gist to be 'hello_universe.rb'. + + .EXAMPLE + Set-GitHubGist -Id 6cad326836d38bd3a7ae -Update @{'hello_world.rb' = @{ 'fileName' = 'hello_universe.rb' }} + + Renames the 'hello_world.rb' file in the specified gist to be 'hello_universe.rb'. +#> + [CmdletBinding( + SupportsShouldProcess, + DefaultParameterSetName='Content')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + param( + [Parameter(Mandatory)] + [string] $Id, + + [hashtable] $Update, + + [string[]] $Delete, + + [string] $Description, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + + $telemetryProperties = @{} + + $files = @{} + + # Mark the files that should be deleted. + foreach ($toDelete in $Delete) + { + $files[$toDelete] = $null + } + + # Then figure out which ones need content updates and/or file renames + if ($null -ne $Update) + { + foreach ($toUpdate in $Update.GetEnumerator()) + { + $currentFileName = $toUpdate.Key + + $providedContent = $toUpdate.Value.Content + $providedFileName = $toUpdate.Value.FileName + $providedFilePath = $toUpdate.Value.FilePath + + if (-not [String]::IsNullOrWhiteSpace($providedContent)) + { + $files[$currentFileName] = @{ 'content' = $providedContent } + } + + if (-not [String]::IsNullOrWhiteSpace($providedFilePath)) + { + if (-not [String]::IsNullOrWhiteSpace($providedContent)) + { + $message = "When updating a file [$currentFileName], you cannot provide both a path to a file [$providedPath] and the raw content." + Write-Log -Message $message -Level Error + throw $message + } + + $providedPath = Resolve-Path -Path $providedPath + if (-not (Test-Path -Path $providedPath)) + { + $message = "Specified file [$providedPath] could not be found or was inaccessible." + Write-Log -Message $message -Level Error + throw $message + } + + $newContent = Get-Content -Path $providedFilePath -Raw -Encoding UTF8 + $files[$currentFileName] = @{ 'content' = $newContent } + } + + # The user has chosen to rename the file. + if (-not [String]::IsNullOrWhiteSpace($providedFileName)) + { + $files[$currentFileName] = @{ 'filename' = $providedFileName } + } + } + } + + $hashBody = @{} + if (-not [String]::IsNullOrWhiteSpace($Description)) { $hashBody['description'] = $Description } + if ($files.Keys.count -gt 0) { $hashBody['files'] = $files } + + $params = @{ + 'UriFragment' = "gists/$Id" + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Method' = 'Patch' + 'Description' = "Updating gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + try + { + return Invoke-GHRestMethod @params + } + catch + { + if ($_.Exception.Message -like '*(422)*') + { + $message = 'This error can happen if you try to delete a file that doesn''t exist. Be aware that casing matters. ''A.txt'' is not the same as ''a.txt''.' + Write-Log -Message $message -Level Warning + } + + throw + } +} \ No newline at end of file diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 3063585b..1f396483 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -32,6 +32,8 @@ 'GitHubCore.ps1', 'GitHubContents.ps1', 'GitHubEvents.ps1', + 'GitHubGistComments.ps1', + 'GitHubGists.ps1', 'GitHubIssueComments.ps1', 'GitHubIssues.ps1', 'GitHubLabels.ps1', @@ -59,9 +61,11 @@ FunctionsToExport = @( 'Add-GitHubAssignee', 'Add-GitHubIssueLabel', + 'Add-GitHubGistStar', 'Backup-GitHubConfiguration', 'Clear-GitHubAuthentication', 'ConvertFrom-GitHubMarkdown', + 'Copy-GitHubGist', 'Disable-GitHubRepositorySecurityFix', 'Disable-GitHubRepositoryVulnerabilityAlert', 'Enable-GitHubRepositorySecurityFix', @@ -73,6 +77,8 @@ 'Get-GitHubContent', 'Get-GitHubEmoji', 'Get-GitHubEvent', + 'Get-GitHubGist', + 'Get-GitHubGistComment', 'Get-GitHubGitIgnore', 'Get-GitHubIssue', 'Get-GitHubIssueComment', @@ -115,6 +121,7 @@ 'Move-GitHubProjectCard', 'Move-GitHubProjectColumn', 'Move-GitHubRepositoryOwnership', + 'New-GitHubGist', 'New-GitHubIssue', 'New-GitHubIssueComment', 'New-GitHubLabel', @@ -130,6 +137,10 @@ 'New-GitHubRepositoryBranch', 'New-GitHubRepositoryFork', 'Remove-GitHubAssignee', + 'Remove-GitHubComment', + 'Remove-GitHubGist', + 'Remove-GitHubGistComment', + 'Remove-GitHubGistStar', 'Remove-GitHubIssueComment', 'Remove-GitHubIssueLabel', 'Remove-GitHubLabel', @@ -148,6 +159,8 @@ 'Set-GitHubAuthentication', 'Set-GitHubConfiguration', 'Set-GitHubContent', + 'Set-GitHubGist', + 'Set-GitHubGistComment', 'Set-GitHubIssue', 'Set-GitHubIssueComment', 'Set-GitHubIssueLabel', @@ -165,6 +178,7 @@ 'Split-GitHubUri', 'Test-GitHubAssignee', 'Test-GitHubAuthenticationConfigured', + 'Test-GitHubGistStar', 'Test-GitHubOrganizationMember', 'Test-GitHubRepositoryVulnerabilityAlert', 'Unlock-GitHubIssue' @@ -174,6 +188,8 @@ 'Delete-GitHubAsset', 'Delete-GitHubBranch', 'Delete-GitHubComment', + 'Delete-GitHubGist', + 'Delete-GitHubGistComment', 'Delete-GitHubIssueComment', 'Delete-GitHubLabel', 'Delete-GitHubMilestone', @@ -185,6 +201,7 @@ 'Delete-GitHubReleaseAsset', 'Delete-GitHubRepository', 'Delete-GitHubRepositoryBranch', + 'Fork-GitHubGist', 'Get-GitHubAsset', 'Get-GitHubBranch', 'Get-GitHubComment', @@ -197,7 +214,9 @@ 'Remove-GitHubComment', 'Set-GitHubAsset', 'Set-GitHubComment', + 'Star-GitHubGist', 'Transfer-GitHubRepositoryOwnership' + 'Unstar-GitHubGist' 'Update-GitHubIssue', 'Update-GitHubLabel', 'Update-GitHubCurrentUser', From 92d380d5ba4b9a05f54b17206d1eae53c862adff Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Thu, 9 Jul 2020 17:23:43 -0700 Subject: [PATCH 02/15] Add format file and some initial pipelining work --- Formatters/GitHubGists.Format.ps1xml | 62 ++++++++++++++++++ GitHubGists.ps1 | 96 ++++++++++++++++++++++++---- PowerShellForGitHub.psd1 | 1 + 3 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 Formatters/GitHubGists.Format.ps1xml diff --git a/Formatters/GitHubGists.Format.ps1xml b/Formatters/GitHubGists.Format.ps1xml new file mode 100644 index 00000000..ed79b631 --- /dev/null +++ b/Formatters/GitHubGists.Format.ps1xml @@ -0,0 +1,62 @@ + + + + + + GitHub.Gist + + GitHub.Gist + + + + + + + + + + + + + + + + + + + + + + + + + + + id + + + description + + + public + + + + ($_.files | + Get-Member -MemberType NoteProperty | + Select-Object -ExpandProperty Name) -join ', ' + + + + created_at + + + updated_at + + + + + + + + diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 index 84cbf5d1..4d1f49d8 100644 --- a/GitHubGists.ps1 +++ b/GitHubGists.ps1 @@ -1,7 +1,13 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -function Get-GitHubGist +@{ + GitHubGistTypeName = 'GitHub.Gist' + }.GetEnumerator() | ForEach-Object { + Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value + } + +filter Get-GitHubGist { <# .SYNOPSIS @@ -50,6 +56,12 @@ function Get-GitHubGist the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.Gist + + .OUTPUTS + GitHub.Gist + .EXAMPLE Get-GitHubGist -Starred @@ -66,14 +78,16 @@ function Get-GitHubGist Gets octocat's "hello_world.rb" gist. #> [CmdletBinding( - SupportsShouldProcess, - DefaultParameterSetName='Current')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + DefaultParameterSetName='Current', + PositionalBinding = $false)] param( [Parameter( Mandatory, - ParameterSetName='Id')] - [string] $Id, + ValueFromPipelineByPropertyName, + ParameterSetName='Id', + Position = 1)] + [Alias('GistId')] + [int64] $Id, [Parameter(ParameterSetName='Id')] [string] $Sha, @@ -225,10 +239,10 @@ than 10 Mb, you''ll need to clone the gist via the URL provided by git_pull_url. Write-Log -Message $message -Level Warning } - return $result + return ($result | Add-GitHubGistAdditionalProperties) } -function Remove-GitHubGist +filter Remove-GitHubGist { <# .SYNOPSIS @@ -252,6 +266,9 @@ function Remove-GitHubGist the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.Gist + .EXAMPLE Remove-GitHubGist -Id 6cad326836d38bd3a7ae @@ -265,11 +282,14 @@ function Remove-GitHubGist #> [CmdletBinding( SupportsShouldProcess, - ConfirmImpact="High")] + ConfirmImpact = 'High')] [Alias('Delete-GitHubGist')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] param( - [Parameter(Mandatory)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] [string] $Id, @@ -297,7 +317,7 @@ function Remove-GitHubGist } } -function Copy-GitHubGist +filter Copy-GitHubGist { <# .SYNOPSIS @@ -878,4 +898,56 @@ function Set-GitHubGist throw } -} \ No newline at end of file +} + + +filter Add-GitHubGistAdditionalProperties +{ +<# + .SYNOPSIS + Adds type name and additional properties to ease pipelining to GitHub Gist objects. + + .PARAMETER InputObject + The GitHub object to add additional properties to. + + .PARAMETER TypeName + The type that should be assigned to the object. + + .INPUTS + [PSCustomObject] + + .OUTPUTS + GitHub.Gist +#> + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] + param( + [Parameter( + Mandatory, + ValueFromPipeline)] + [AllowNull()] + [AllowEmptyCollection()] + [PSCustomObject[]] $InputObject, + + [ValidateNotNullOrEmpty()] + [string] $TypeName = $script:GitHubGistTypeName + ) + + foreach ($item in $InputObject) + { + $item.PSObject.TypeNames.Insert(0, $TypeName) + + if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) + { + Add-Member -InputObject $item -Name 'GistId' -Value $item.id -MemberType NoteProperty -Force + $null = Add-GitHubUserAdditionalProperties -InputObject $item.owner + foreach ($fork in $item.forks) + { + Add-Member -InputObject $fork -Name 'GistId' -Value $fork.id -MemberType NoteProperty -Force + $null = Add-GitHubUserAdditionalProperties -InputObject $fork.user + } + } + + Write-Output $item + } +} diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 1f396483..f35151e9 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -15,6 +15,7 @@ # Format files (.ps1xml) to be loaded when importing this module FormatsToProcess = @( + 'Formatters/GitHubGists.Format.ps1xml', 'Formatters/GitHubReleases.Format.ps1xml' 'Formatters/GitHubRepositories.Format.ps1xml' ) From b9f1bde03a846bdb02932851e315168a3baa9f3f Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Fri, 10 Jul 2020 16:55:50 -0700 Subject: [PATCH 03/15] Finish pipeline work and start adding tests --- GitHubGists.ps1 | 216 ++++++++++++++++++++++++------------ Tests/GitHubGists.tests.ps1 | 33 ++++++ 2 files changed, 181 insertions(+), 68 deletions(-) create mode 100644 Tests/GitHubGists.tests.ps1 diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 index 4d1f49d8..4014c5eb 100644 --- a/GitHubGists.ps1 +++ b/GitHubGists.ps1 @@ -80,6 +80,7 @@ filter Get-GitHubGist [CmdletBinding( DefaultParameterSetName='Current', PositionalBinding = $false)] + [OutputType({$script:GitHubGistTypeName})] param( [Parameter( Mandatory, @@ -282,13 +283,14 @@ filter Remove-GitHubGist #> [CmdletBinding( SupportsShouldProcess, + PositionalBinding = $false, ConfirmImpact = 'High')] [Alias('Delete-GitHubGist')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] param( [Parameter( Mandatory, - ValueFromPipelineByPropertyName)] + ValueFromPipelineByPropertyName, + Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] [string] $Id, @@ -300,21 +302,23 @@ filter Remove-GitHubGist Write-InvocationLog -Invocation $MyInvocation - if ($PSCmdlet.ShouldProcess($Id, "Delete gist")) + if (-not $PSCmdlet.ShouldProcess($Id, "Delete gist")) { - $telemetryProperties = @{} - $params = @{ - 'UriFragment' = "gists/$Id" - 'Method' = 'Delete' - 'Description' = "Removing gist $Id" - 'AccessToken' = $AccessToken - 'TelemetryEventName' = $MyInvocation.MyCommand.Name - 'TelemetryProperties' = $telemetryProperties - 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) - } + return + } - return Invoke-GHRestMethod @params + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$Id" + 'Method' = 'Delete' + 'Description' = "Removing gist $Id" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } + + return Invoke-GHRestMethod @params } filter Copy-GitHubGist @@ -341,6 +345,12 @@ filter Copy-GitHubGist the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.Gist + + .OUTPUTS + GitHub.Gist + .EXAMPLE Copy-GitHubGist -Id 6cad326836d38bd3a7ae @@ -352,11 +362,17 @@ filter Copy-GitHubGist Forks octocat's "hello_world.rb" gist. This is using the alias for the command. The result is the same whether you use Copy-GitHubGist or Fork-GitHubGist. #> - [CmdletBinding(SupportsShouldProcess)] + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false)] + [OutputType({$script:GitHubGistTypeName})] [Alias('Fork-GitHubGist')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] param( - [Parameter(Mandatory)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] [string] $Id, @@ -367,6 +383,11 @@ filter Copy-GitHubGist Write-InvocationLog -Invocation $MyInvocation + if (-not $PSCmdlet.ShouldProcess($Id, "Forking gist")) + { + return + } + $telemetryProperties = @{} $params = @{ 'UriFragment' = "gists/$Id/forks" @@ -378,10 +399,10 @@ filter Copy-GitHubGist 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return Invoke-GHRestMethod @params + return (Invoke-GHRestMethod @params | Add-GitHubGistAdditionalProperties) } -function Add-GitHubGistStar +filter Add-GitHubGistStar { <# .SYNOPSIS @@ -405,6 +426,9 @@ function Add-GitHubGistStar the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.Gist + .EXAMPLE Add-GitHubGistStar -Id 6cad326836d38bd3a7ae @@ -416,11 +440,16 @@ function Add-GitHubGistStar Stars octocat's "hello_world.rb" gist. This is using the alias for the command. The result is the same whether you use Add-GitHubGistStar or Star-GitHubGist. #> - [CmdletBinding(SupportsShouldProcess)] + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false)] [Alias('Star-GitHubGist')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] param( - [Parameter(Mandatory)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] [string] $Id, @@ -431,6 +460,11 @@ function Add-GitHubGistStar Write-InvocationLog -Invocation $MyInvocation + if (-not $PSCmdlet.ShouldProcess($Id, "Starring gist")) + { + return + } + $telemetryProperties = @{} $params = @{ 'UriFragment' = "gists/$Id/star" @@ -445,7 +479,7 @@ function Add-GitHubGistStar return Invoke-GHRestMethod @params } -function Remove-GitHubGistStar +filter Remove-GitHubGistStar { <# .SYNOPSIS @@ -469,6 +503,9 @@ function Remove-GitHubGistStar the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.Gist + .EXAMPLE Remove-GitHubGistStar -Id 6cad326836d38bd3a7ae @@ -480,11 +517,16 @@ function Remove-GitHubGistStar Unstars octocat's "hello_world.rb" gist. This is using the alias for the command. The result is the same whether you use Remove-GitHubGistStar or Unstar-GitHubGist. #> - [CmdletBinding(SupportsShouldProcess)] + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false)] [Alias('Unstar-GitHubGist')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] param( - [Parameter(Mandatory)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] [string] $Id, @@ -495,6 +537,11 @@ function Remove-GitHubGistStar Write-InvocationLog -Invocation $MyInvocation + if (-not $PSCmdlet.ShouldProcess($Id, "Unstarring gist")) + { + return + } + $telemetryProperties = @{} $params = @{ 'UriFragment' = "gists/$Id/star" @@ -509,7 +556,7 @@ function Remove-GitHubGistStar return Invoke-GHRestMethod @params } -function Test-GitHubGistStar +filter Test-GitHubGistStar { <# .SYNOPSIS @@ -535,8 +582,11 @@ function Test-GitHubGistStar the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.Gist + .OUTPUTS - [bool] If the gist was both found and determined to be starred. + Boolean indicating if the gist was both found and determined to be starred. .EXAMPLE Test-GitHubGistStar -Id 6cad326836d38bd3a7ae @@ -548,11 +598,14 @@ function Test-GitHubGistStar For some reason, this does not currently seem to be working correctly (even though it matches the spec: https://developer.github.com/v3/gists/#check-if-a-gist-is-starred). #> - [CmdletBinding(SupportsShouldProcess)] + [CmdletBinding(PositionalBinding = $false)] [OutputType([bool])] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] param( - [Parameter(Mandatory)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] [string] $Id, @@ -586,7 +639,7 @@ function Test-GitHubGistStar } } -function New-GitHubGist +filter New-GitHubGist { <# .SYNOPSIS @@ -643,23 +696,28 @@ function New-GitHubGist #> [CmdletBinding( SupportsShouldProcess, - DefaultParameterSetName='Content')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + DefaultParameterSetName='FileRef', + PositionalBinding = $false)] + [OutputType({$script:GitHubGistTypeName})] param( [Parameter( Mandatory, - ParameterSetName='FileRef')] + ValueFromPipeline, + ParameterSetName='FileRef', + Position = 1)] [string[]] $File, [Parameter( Mandatory, - ParameterSetName='Content')] + ParameterSetName='Content', + Position = 1)] [ValidateNotNullOrEmpty()] [string] $Content, [Parameter( Mandatory, - ParameterSetName='Content')] + ParameterSetName='Content', + Position = 2)] [ValidateNotNullOrEmpty()] [string] $FileName, @@ -672,16 +730,12 @@ function New-GitHubGist [switch] $NoStatus ) - Write-InvocationLog -Invocation $MyInvocation - - $telemetryProperties = @{} - - $files = @{} - if ($PSCmdlet.ParameterSetName -eq 'Content') + begin { - $files[$FileName] = @{ 'content' = $Content } + $files = @{} } - else + + process { foreach ($path in $File) { @@ -707,27 +761,44 @@ function New-GitHubGist } } - $hashBody = @{ - 'description' = $Description - 'public' = $Public.ToBool() - 'files' = $files - } + end + { + Write-InvocationLog -Invocation $MyInvocation - $params = @{ - 'UriFragment' = "gists" - 'Body' = (ConvertTo-Json -InputObject $hashBody) - 'Method' = 'Post' - 'Description' = "Creating a new gist" - 'AccessToken' = $AccessToken - 'TelemetryEventName' = $MyInvocation.MyCommand.Name - 'TelemetryProperties' = $telemetryProperties - 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) - } + $telemetryProperties = @{} - return Invoke-GHRestMethod @params + if ($PSCmdlet.ParameterSetName -eq 'Content') + { + $files[$FileName] = @{ 'content' = $Content } + } + + $hashBody = @{ + 'description' = $Description + 'public' = $Public.ToBool() + 'files' = $files + } + + if (-not $PSCmdlet.ShouldProcess('Create new gist')) + { + return + } + + $params = @{ + 'UriFragment' = "gists" + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Method' = 'Post' + 'Description' = "Creating a new gist" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Invoke-GHRestMethod @params | Add-GitHubGistAdditionalProperties) + } } -function Set-GitHubGist +filter Set-GitHubGist { <# .SYNOPSIS @@ -748,7 +819,7 @@ function Set-GitHubGist fileName - Specify a new name here if you want to rename the file. filePath - Specify a path to a file on disk if you wish to update the contents of the file in the gist with the contents of the specified file. - Should not be specified if you use 'content' (below) + Should not be specified if you use 'content' (below) content - Directly specify the raw content that the file in the gist should be updated with. Should not be used if you use 'filePath' (above). @@ -795,10 +866,15 @@ function Set-GitHubGist #> [CmdletBinding( SupportsShouldProcess, - DefaultParameterSetName='Content')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + DefaultParameterSetName='Content', + PositionalBinding = $false)] + [OutputType({$script:GitHubGistTypeName})] param( - [Parameter(Mandatory)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] [string] $Id, [hashtable] $Update, @@ -873,6 +949,11 @@ function Set-GitHubGist if (-not [String]::IsNullOrWhiteSpace($Description)) { $hashBody['description'] = $Description } if ($files.Keys.count -gt 0) { $hashBody['files'] = $files } + if (-not $PSCmdlet.ShouldProcess($Id, 'Update gist')) + { + return + } + $params = @{ 'UriFragment' = "gists/$Id" 'Body' = (ConvertTo-Json -InputObject $hashBody) @@ -886,7 +967,7 @@ function Set-GitHubGist try { - return Invoke-GHRestMethod @params + return (Invoke-GHRestMethod @params | Add-GitHubGistAdditionalProperties) } catch { @@ -900,7 +981,6 @@ function Set-GitHubGist } } - filter Add-GitHubGistAdditionalProperties { <# diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1 new file mode 100644 index 00000000..9d97110b --- /dev/null +++ b/Tests/GitHubGists.tests.ps1 @@ -0,0 +1,33 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +<# +.Synopsis + Tests for GitHubGists.ps1 module +#> + +[CmdletBinding()] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', + Justification='Suppress false positives in Pester code blocks')] +param() + +# This is common test code setup logic for all Pester test files +$moduleRootPath = Split-Path -Path $PSScriptRoot -Parent +. (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1') + +try +{ + Describe 'New-GitHubGist' { + Context 'By files - with parameters' { + } + } +} +finally +{ + if (Test-Path -Path $script:originalConfigFile -PathType Leaf) + { + # Restore the user's configuration to its pre-test state + Restore-GitHubConfiguration -Path $script:originalConfigFile + $script:originalConfigFile = $null + } +} From a73cdb7186c3024c47833115748f8ea91db599b0 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sat, 11 Jul 2020 17:11:00 -0700 Subject: [PATCH 04/15] Adding support for the additional Gist types --- Formatters/GitHubGists.Format.ps1xml | 161 +++++++++++++++++++++- GitHubGists.ps1 | 192 +++++++++++++++++++++++---- Tests/GitHubGists.tests.ps1 | 30 ++++- 3 files changed, 355 insertions(+), 28 deletions(-) diff --git a/Formatters/GitHubGists.Format.ps1xml b/Formatters/GitHubGists.Format.ps1xml index ed79b631..bb002f06 100644 --- a/Formatters/GitHubGists.Format.ps1xml +++ b/Formatters/GitHubGists.Format.ps1xml @@ -1,7 +1,7 @@ - + GitHub.Gist @@ -12,6 +12,9 @@ + + + @@ -34,6 +37,11 @@ id + + + $_.owner.login + + description @@ -58,5 +66,156 @@ + + + GitHub.GistCommit + + GitHub.GistCommit + + + + + + + + + + + + + + + + + + + + + GistId + + + version + + + + ($_.user.login) + + + + committed_at + + + + + + + + + GitHub.GistDetail + + GitHub.GistDetail + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id + + + description + + + public + + + + ($_.files | + Get-Member -MemberType NoteProperty | + Select-Object -ExpandProperty Name) -join ', ' + + + + + ($_.forks.Count) + + + + created_at + + + updated_at + + + + + + + + + GitHub.GistFork + + GitHub.GistFork + + + + + + + + + + + + + + + + + + + + + id + + + + ($_.owner.login) + + + + created_at + + + updated_at + + + + + + diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 index 4014c5eb..d31627f0 100644 --- a/GitHubGists.ps1 +++ b/GitHubGists.ps1 @@ -3,6 +3,9 @@ @{ GitHubGistTypeName = 'GitHub.Gist' + GitHubGistCommitTypeName = 'GitHub.GistCommit' + GitHubGistDetailTypeName = 'GitHub.GistDetail' + GitHubGistForkTypeName = 'GitHub.GistFork' }.GetEnumerator() | ForEach-Object { Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value } @@ -58,9 +61,15 @@ filter Get-GitHubGist .INPUTS GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork .OUTPUTS GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork .EXAMPLE Get-GitHubGist -Starred @@ -81,6 +90,9 @@ filter Get-GitHubGist DefaultParameterSetName='Current', PositionalBinding = $false)] [OutputType({$script:GitHubGistTypeName})] + [OutputType({$script:GitHubGistCommitTypeName})] + [OutputType({$script:GitHubGistDetailTypeName})] + [OutputType({$script:GitHubGistForkTypeName})] param( [Parameter( Mandatory, @@ -88,9 +100,11 @@ filter Get-GitHubGist ParameterSetName='Id', Position = 1)] [Alias('GistId')] - [int64] $Id, + [ValidateNotNullOrEmpty()] + [string] $Id, [Parameter(ParameterSetName='Id')] + [ValidateNotNullOrEmpty()] [string] $Sha, [Parameter(ParameterSetName='Id')] @@ -100,6 +114,7 @@ filter Get-GitHubGist [switch] $Commits, [Parameter(ParameterSetName='User')] + [ValidateNotNullOrEmpty()] [string] $UserName, [Parameter(ParameterSetName='Current')] @@ -127,30 +142,13 @@ filter Get-GitHubGist $uriFragment = [String]::Empty $description = [String]::Empty + $outputType = $script:GitHubGistTypeName if ($PSCmdlet.ParameterSetName -eq 'Id') { $telemetryProperties['ById'] = $true - if ([String]::IsNullOrWhiteSpace($Sha)) - { - if ($Forks) - { - $uriFragment = "gists/$Id/forks" - $description = "Getting forks of gist $Id" - } - elseif ($Commits) - { - $uriFragment = "gists/$Id/commits" - $description = "Getting commits of gist $Id" - } - else - { - $uriFragment = "gists/$Id" - $description = "Getting gist $Id" - } - } - else + if ($PSBoundParameters.ContainsKey('Sha')) { if ($Forks -or $Commits) { @@ -163,6 +161,25 @@ filter Get-GitHubGist $uriFragment = "gists/$Id/$Sha" $description = "Getting gist $Id with specified Sha" + $outputType = $script:GitHubGistDetailTypeName + } + elseif ($Forks) + { + $uriFragment = "gists/$Id/forks" + $description = "Getting forks of gist $Id" + $outputType = $script:GitHubGistForkTypeName + } + elseif ($Commits) + { + $uriFragment = "gists/$Id/commits" + $description = "Getting commits of gist $Id" + $outputType = $script:GitHubGistCommitTypeName + } + else + { + $uriFragment = "gists/$Id" + $description = "Getting gist $Id" + $outputType = $script:GitHubGistDetailTypeName } } elseif ($PSCmdlet.ParameterSetName -eq 'User') @@ -171,10 +188,12 @@ filter Get-GitHubGist $uriFragment = "users/$UserName/gists" $description = "Getting public gists for $UserName" + $outputType = $script:GitHubGistTypeName } elseif ($PSCmdlet.ParameterSetName -eq 'Current') { $telemetryProperties['CurrentUser'] = $true + $outputType = $script:GitHubGistTypeName if (Test-GitHubAuthenticationConfigured) { @@ -204,6 +223,7 @@ filter Get-GitHubGist elseif ($PSCmdlet.ParameterSetName -eq 'Public') { $telemetryProperties['Public'] = $true + $outputType = $script:GitHubGistTypeName $uriFragment = "gists/public" $description = 'Getting public gists' @@ -240,7 +260,7 @@ than 10 Mb, you''ll need to clone the gist via the URL provided by git_pull_url. Write-Log -Message $message -Level Warning } - return ($result | Add-GitHubGistAdditionalProperties) + return ($result | Add-GitHubGistAdditionalProperties -TypeName $outputType) } filter Remove-GitHubGist @@ -269,6 +289,9 @@ filter Remove-GitHubGist .INPUTS GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork .EXAMPLE Remove-GitHubGist -Id 6cad326836d38bd3a7ae @@ -347,6 +370,9 @@ filter Copy-GitHubGist .INPUTS GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork .OUTPUTS GitHub.Gist @@ -428,6 +454,9 @@ filter Add-GitHubGistStar .INPUTS GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork .EXAMPLE Add-GitHubGistStar -Id 6cad326836d38bd3a7ae @@ -505,6 +534,9 @@ filter Remove-GitHubGistStar .INPUTS GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork .EXAMPLE Remove-GitHubGistStar -Id 6cad326836d38bd3a7ae @@ -584,6 +616,9 @@ filter Test-GitHubGistStar .INPUTS GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork .OUTPUTS Boolean indicating if the gist was both found and determined to be starred. @@ -677,6 +712,12 @@ filter New-GitHubGist the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + String - Filename(s) of file(s) that should be the content of the gist. + + .OUTPUTS + GitHub.GitDetail + .EXAMPLE New-GitHubGist -Content 'Body of my file.' -FileName 'sample.txt' -Description 'This is my gist!' -Public @@ -698,13 +739,14 @@ filter New-GitHubGist SupportsShouldProcess, DefaultParameterSetName='FileRef', PositionalBinding = $false)] - [OutputType({$script:GitHubGistTypeName})] + [OutputType({$script:GitHubGistDetailTypeName})] param( [Parameter( Mandatory, ValueFromPipeline, ParameterSetName='FileRef', Position = 1)] + [ValidateNotNullOrEmpty()] [string[]] $File, [Parameter( @@ -794,7 +836,8 @@ filter New-GitHubGist 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return (Invoke-GHRestMethod @params | Add-GitHubGistAdditionalProperties) + return (Invoke-GHRestMethod @params | + Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistDetailTypeName) } } @@ -839,6 +882,15 @@ filter Set-GitHubGist the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork + + .OUTPUTS + GitHub.GistDetail + .EXAMPLE Set-GitHubGist -Id 6cad326836d38bd3a7ae -Description 'This is my newer description' @@ -868,13 +920,14 @@ filter Set-GitHubGist SupportsShouldProcess, DefaultParameterSetName='Content', PositionalBinding = $false)] - [OutputType({$script:GitHubGistTypeName})] + [OutputType({$script:GitHubGistDetailTypeName})] param( [Parameter( Mandatory, ValueFromPipelineByPropertyName, Position = 1)] [Alias('GistId')] + [ValidateNotNullOrEmpty()] [string] $Id, [hashtable] $Update, @@ -967,7 +1020,8 @@ filter Set-GitHubGist try { - return (Invoke-GHRestMethod @params | Add-GitHubGistAdditionalProperties) + return (Invoke-GHRestMethod @params | + Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistDetailTypeName) } catch { @@ -998,8 +1052,14 @@ filter Add-GitHubGistAdditionalProperties .OUTPUTS GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork #> [CmdletBinding()] + [OutputType({$script:GitHubGistypeName})] + [OutputType({$script:GitHubGistDetailTypeName})] + [OutputType({$script:GitHubGistFormTypeName})] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] param( [Parameter( @@ -1013,6 +1073,11 @@ filter Add-GitHubGistAdditionalProperties [string] $TypeName = $script:GitHubGistTypeName ) + if ($TypeName -eq $script:GitHubGistCommitTypeName) + { + return Add-GitHubGistCommitAdditionalProperties -InputObject $InputObject + } + foreach ($item in $InputObject) { $item.PSObject.TypeNames.Insert(0, $TypeName) @@ -1020,14 +1085,89 @@ filter Add-GitHubGistAdditionalProperties if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) { Add-Member -InputObject $item -Name 'GistId' -Value $item.id -MemberType NoteProperty -Force - $null = Add-GitHubUserAdditionalProperties -InputObject $item.owner + + @('user', 'owner') | + ForEach-Object { + if ($null -ne $item.$_) + { + $null = Add-GitHubUserAdditionalProperties -InputObject $item.$_ + } + } + foreach ($fork in $item.forks) { Add-Member -InputObject $fork -Name 'GistId' -Value $fork.id -MemberType NoteProperty -Force $null = Add-GitHubUserAdditionalProperties -InputObject $fork.user } + + foreach ($entry in $item.history) + { + $null = Add-GitHubGistCommitAdditionalProperties -InputObject $entry + } } Write-Output $item } } + +filter Add-GitHubGistCommitAdditionalProperties +{ +<# + .SYNOPSIS + Adds type name and additional properties to ease pipelining to GitHub GistCommit objects. + + .PARAMETER InputObject + The GitHub object to add additional properties to. + + .PARAMETER TypeName + The type that should be assigned to the object. + + .INPUTS + [PSCustomObject] + + .OUTPUTS + GitHub.GistCommit +#> + [CmdletBinding()] + [OutputType({$script:GitHubGistCommitTypeName})] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] + param( + [Parameter( + Mandatory, + ValueFromPipeline)] + [AllowNull()] + [AllowEmptyCollection()] + [PSCustomObject[]] $InputObject, + + [ValidateNotNullOrEmpty()] + [string] $TypeName = $script:GitHubGistCommitTypeName + ) + + foreach ($item in $InputObject) + { + $item.PSObject.TypeNames.Insert(0, $TypeName) + + if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) + { + $hostName = $(Get-GitHubConfiguration -Name 'ApiHostName') + if ($item.uri -match "^https?://(?:www\.|api\.|)$hostName/gists/([^/]+)/(.+)$") + { + $id = $Matches[1] + $sha = $Matches[2] + + if ($sha -ne $item.version) + { + $message = "The gist commit url no longer follows the expected pattern. Please contact the PowerShellForGitHubTeam: $item.uri" + Write-Log -Message $message -Level Warning + } + } + + Add-Member -InputObject $item -Name 'GistId' -Value $id -MemberType NoteProperty -Force + Add-Member -InputObject $item -Name 'Sha' -Value $item.version -MemberType NoteProperty -Force + + $null = Add-GitHubUserAdditionalProperties -InputObject $item.user + } + + Write-Output $item + } +} \ No newline at end of file diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1 index 9d97110b..0dd02f97 100644 --- a/Tests/GitHubGists.tests.ps1 +++ b/Tests/GitHubGists.tests.ps1 @@ -18,7 +18,35 @@ $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent try { Describe 'New-GitHubGist' { - Context 'By files - with parameters' { + Context 'By files' { + BeforeAll { + $tempFile = New-TemporaryFile + $fileA = "$($tempFile.FullName).ps1" + Move-Item -Path $tempFile -Destination $fileA + Out-File -FilePath $fileA -InputObject "fileA content" -Encoding utf8 + + $tempFile = New-TemporaryFile + $fileB = "$($tempFile.FullName).txt" + Move-Item -Path $tempFile -Destination $fileB + Out-File -FilePath $fileB -InputObject "fileB content" -Encoding utf8 + + $description = 'my description' + } + + AfterAll { + @($fileA, $fileB) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + $gist = New-GitHubGist -File $fileA -Description $description -Public + It 'Should have the expected result' { + + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } } } } From 46f9aecb0a07091a82b9ed07333ea4f3788fffec Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sun, 12 Jul 2020 09:44:58 -0700 Subject: [PATCH 05/15] Update gist Comments to properly support pipeline --- Formatters/GitHubGistComments.Format.ps1xml | 54 ++++ GitHubGistComments.ps1 | 274 +++++++++++++++----- GitHubGists.ps1 | 25 +- PowerShellForGitHub.psd1 | 1 + Tests/GitHubGistComments.tests.ps1 | 62 +++++ 5 files changed, 351 insertions(+), 65 deletions(-) create mode 100644 Formatters/GitHubGistComments.Format.ps1xml create mode 100644 Tests/GitHubGistComments.tests.ps1 diff --git a/Formatters/GitHubGistComments.Format.ps1xml b/Formatters/GitHubGistComments.Format.ps1xml new file mode 100644 index 00000000..b2035fca --- /dev/null +++ b/Formatters/GitHubGistComments.Format.ps1xml @@ -0,0 +1,54 @@ + + + + + + GitHub.GistComment + + GitHub.GistComment + + + + + + + + + + + + + + + + + + + + + + + + id + + + + $_.user.login + + + + body + + + created_at + + + updated_at + + + + + + + + diff --git a/GitHubGistComments.ps1 b/GitHubGistComments.ps1 index 6640d36b..1cadaf9c 100644 --- a/GitHubGistComments.ps1 +++ b/GitHubGistComments.ps1 @@ -1,7 +1,13 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -function Get-GitHubGistComment +@{ + GitHubGistCommentTypeName = 'GitHub.GistComment' + }.GetEnumerator() | ForEach-Object { + Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value + } + +filter Get-GitHubGistComment { <# .SYNOPSIS @@ -12,7 +18,7 @@ function Get-GitHubGistComment The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER GistId The ID of the specific gist that you wish to retrieve the comments for. .PARAMETER CommentId @@ -36,23 +42,34 @@ function Get-GitHubGistComment the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.GistComment + + .OUTPUTS + GitHub.GistComment + .EXAMPLE - Get-GitHubGistComment -Id 6cad326836d38bd3a7ae + Get-GitHubGistComment -GistId 6cad326836d38bd3a7ae Gets all comments on octocat's "hello_world.rb" gist. .EXAMPLE - Get-GitHubGistComment -Id 6cad326836d38bd3a7ae -CommentId 1507813 + Get-GitHubGistComment -GistId 6cad326836d38bd3a7ae -CommentId 1507813 Gets comment 1507813 from octocat's "hello_world.rb" gist. #> - [CmdletBinding(SupportsShouldProcess)] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + [CmdletBinding(PositionalBinding = $false)] + [OutputType({$script:GitHubGistCommentTypeName})] param( - [Parameter(Mandatory)] - [Alias('GistId')] - [string] $Id, - + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [string] $GistId, + + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('GistCommentId')] + [ValidateNotNullOrEmpty()] [string] $CommentId, [ValidateSet('Raw', 'Text', 'Html', 'Full')] @@ -72,15 +89,15 @@ function Get-GitHubGistComment if ([String]::IsNullOrWhiteSpace($CommentId)) { - $uriFragment = "gists/$Id/comments" - $description = "Getting comments for gist $Id" + $uriFragment = "gists/$GistId/comments" + $description = "Getting comments for gist $GistId" } else { $telemetryProperties['SpecifiedCommentId'] = $true - $uriFragment = "gists/$Id/comments/$CommentId" - $description = "Getting comment $CommentId for gist $Id" + $uriFragment = "gists/$GistId/comments/$CommentId" + $description = "Getting comment $CommentId for gist $GistId" } $params = @{ @@ -93,12 +110,11 @@ function Get-GitHubGistComment 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - $result = Invoke-GHRestMethodMultipleResult @params - - return $result + return (Invoke-GHRestMethodMultipleResult @params | + Add-GitHubGistCommentAdditionalProperties -GistId $GistId) } -function Remove-GitHubGistComment +filter Remove-GitHubGistComment { <# .SYNOPSIS @@ -109,12 +125,15 @@ function Remove-GitHubGistComment The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER GistId The ID of the specific gist that you wish to remove the comment from. .PARAMETER CommentId The ID of the comment to remove from the gist. + .PARAMETER Force + If this switch is specified, you will not be prompted for confirmation of command execution. + .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. @@ -125,32 +144,52 @@ function Remove-GitHubGistComment the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.GistComment + .EXAMPLE - Remove-GitHubGist -Id 6cad326836d38bd3a7ae + Remove-GitHubGist -GistId 6cad326836d38bd3a7ae -CommentId 12324567 - Removes octocat's "hello_world.rb" gist (assuming you have permission). + Removes the specified comment from octocat's "hello_world.rb" gist + (assuming you have permission). .EXAMPLE - Remove-GitHubGist -Id 6cad326836d38bd3a7ae -Confirm:$false + Remove-GitHubGist -GistId 6cad326836d38bd3a7ae -CommentId 12324567 -Confirm:$false - Removes octocat's "hello_world.rb" gist (assuming you have permission). + Removes the specified comment from octocat's "hello_world.rb" gist + (assuming you have permission). Will not prompt for confirmation, as -Confirm:$false was specified. + + .EXAMPLE + Remove-GitHubGist -GistId 6cad326836d38bd3a7ae -CommentId 12324567 -Force + + Removes the specified comment from octocat's "hello_world.rb" gist + (assuming you have permission). + Will not prompt for confirmation, as -Force was specified. #> [CmdletBinding( SupportsShouldProcess, + PositionalBinding = $false, ConfirmImpact="High")] [Alias('Delete-GitHubGist')] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] param( - [Parameter(Mandatory)] - [Alias('GistId')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $GistId, - [Parameter(Mandatory)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('GistCommentId')] [ValidateNotNullOrEmpty()] [string] $CommentId, + [switch] $Force, + [string] $AccessToken, [switch] $NoStatus @@ -158,24 +197,31 @@ function Remove-GitHubGistComment Write-InvocationLog -Invocation $MyInvocation - if ($PSCmdlet.ShouldProcess($CommentId, "Delete comment from gist $Id")) + if ($Force -and (-not $Confirm)) { - $telemetryProperties = @{} - $params = @{ - 'UriFragment' = "gists/$Id/comments/$CommentId" - 'Method' = 'Delete' - 'Description' = "Removing comment $CommentId from gist $Id" - 'AccessToken' = $AccessToken - 'TelemetryEventName' = $MyInvocation.MyCommand.Name - 'TelemetryProperties' = $telemetryProperties - 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) - } + $ConfirmPreference = 'None' + } + + if (-not $PSCmdlet.ShouldProcess($CommentId, "Delete comment from gist $GistId")) + { + return + } - return Invoke-GHRestMethod @params + $telemetryProperties = @{} + $params = @{ + 'UriFragment' = "gists/$GistId/comments/$CommentId" + 'Method' = 'Delete' + 'Description' = "Removing comment $CommentId from gist $GistId" + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } + + return Invoke-GHRestMethod @params } -function New-GitHubGistComment +filter New-GitHubGistComment { <# .SYNOPSIS @@ -186,7 +232,7 @@ function New-GitHubGistComment The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER GistId The ID of the specific gist that you wish to add the comment to. .PARAMETER Comment @@ -202,20 +248,32 @@ function New-GitHubGistComment the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.GistComment + + .OUTPUTS + GitHub.GistComment + .EXAMPLE - New-GitHubGistComment -Id 6cad326836d38bd3a7ae -Comment 'Hello World' + New-GitHubGistComment -GistId 6cad326836d38bd3a7ae -Comment 'Hello World' Adds a new comment of "Hello World" to octocat's "hello_world.rb" gist. #> - [CmdletBinding(SupportsShouldProcess)] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false)] + [OutputType({$script:GitHubGistCommentTypeName})] param( - [Parameter(Mandatory)] - [Alias('GistId')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $GistId, - [Parameter(Mandatory)] + [Parameter( + Mandatory, + Position = 2)] [ValidateNotNullOrEmpty()] [string] $Comment, @@ -230,22 +288,27 @@ function New-GitHubGistComment 'body' = $Comment } + if (-not $PSCmdlet.ShouldProcess($GistId, "Create new comment for gist")) + { + return + } + $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$Id/comments" + 'UriFragment' = "gists/$GistId/comments" 'Body' = (ConvertTo-Json -InputObject $hashBody) 'Method' = 'Post' - 'Description' = "Creating new comment on gist $Id" + 'Description' = "Creating new comment on gist $GistId" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return Invoke-GHRestMethod @params + return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties -GistId $GistId) } -function Set-GitHubGistComment +filter Set-GitHubGistComment { <# .SYNOPSIS @@ -256,7 +319,7 @@ function Set-GitHubGistComment The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER GistId The ID of the gist that the comment is on. .PARAMETER CommentId @@ -275,24 +338,40 @@ function Set-GitHubGistComment the background, enabling the command prompt to provide status information. If not supplied here, the DefaultNoStatus configuration property value will be used. + .INPUTS + GitHub.GistComment + + .OUTPUTS + GitHub.GistComment + .EXAMPLE New-GitHubGistComment -Id 6cad326836d38bd3a7ae -Comment 'Hello World' Adds a new comment of "Hello World" to octocat's "hello_world.rb" gist. #> - [CmdletBinding(SupportsShouldProcess)] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification = "Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")] + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false)] + [OutputType({$script:GitHubGistCommentTypeName})] param( - [Parameter(Mandatory)] - [Alias('GistId')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $GistId, - [Parameter(Mandatory)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('GistCommentId')] [ValidateNotNullOrEmpty()] [string] $CommentId, - [Parameter(Mandatory)] + [Parameter( + Mandatory, + Position = 3)] [ValidateNotNullOrEmpty()] [string] $Comment, @@ -307,17 +386,84 @@ function Set-GitHubGistComment 'body' = $Comment } + if (-not $PSCmdlet.ShouldProcess($CommentId, "Update gist comment on gist $GistId")) + { + return + } + $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$Id/comments/$CommentId" + 'UriFragment' = "gists/$GistId/comments/$CommentId" 'Body' = (ConvertTo-Json -InputObject $hashBody) 'Method' = 'Patch' - 'Description' = "Creating new comment on gist $Id" + 'Description' = "Creating new comment on gist $GistId" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return Invoke-GHRestMethod @params + return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties -GistId $GistId) +} + +filter Add-GitHubGistCommentAdditionalProperties +{ +<# + .SYNOPSIS + Adds type name and additional properties to ease pipelining to GitHub Gist Comment objects. + + .PARAMETER InputObject + The GitHub object to add additional properties to. + + .PARAMETER TypeName + The type that should be assigned to the object. + + .PARAMETER GistId + The ID of the gist that the comment is for. + + .INPUTS + [PSCustomObject] + + .OUTPUTS + GitHub.GistComment +#> + [CmdletBinding()] + [OutputType({$script:GitHubGisCommentTypeName})] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] + param( + [Parameter( + Mandatory, + ValueFromPipeline)] + [AllowNull()] + [AllowEmptyCollection()] + [PSCustomObject[]] $InputObject, + + [ValidateNotNullOrEmpty()] + [string] $TypeName = $script:GitHubGistCommentTypeName, + + [ValidateNotNullOrEmpty()] + [string] $GistId + ) + + foreach ($item in $InputObject) + { + $item.PSObject.TypeNames.Insert(0, $TypeName) + + if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) + { + Add-Member -InputObject $item -Name 'GistCommentId' -Value $item.id -MemberType NoteProperty -Force + + if ($PSBoundParameters.ContainsKey('GistId')) + { + Add-Member -InputObject $item -Name 'GistId' -Value $GistId -MemberType NoteProperty -Force + } + + if ($null -ne $item.user) + { + $null = Add-GitHubUserAdditionalProperties -InputObject $item.user + } + } + + Write-Output $item + } } diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 index d31627f0..18e43418 100644 --- a/GitHubGists.ps1 +++ b/GitHubGists.ps1 @@ -61,6 +61,7 @@ filter Get-GitHubGist .INPUTS GitHub.Gist + GitHub.GistComment GitHub.GistCommit GitHub.GistDetail GitHub.GistFork @@ -277,6 +278,9 @@ filter Remove-GitHubGist .PARAMETER Id The ID of the specific gist that you wish to retrieve. + .PARAMETER Force + If this switch is specified, you will not be prompted for confirmation of command execution. + .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. @@ -289,6 +293,7 @@ filter Remove-GitHubGist .INPUTS GitHub.Gist + GitHub.GistComment GitHub.GistCommit GitHub.GistDetail GitHub.GistFork @@ -303,6 +308,12 @@ filter Remove-GitHubGist Removes octocat's "hello_world.rb" gist (assuming you have permission). Will not prompt for confirmation, as -Confirm:$false was specified. + + .EXAMPLE + Remove-GitHubGist -Id 6cad326836d38bd3a7ae -Force + + Removes octocat's "hello_world.rb" gist (assuming you have permission). + Will not prompt for confirmation, as -Force was specified. #> [CmdletBinding( SupportsShouldProcess, @@ -318,6 +329,8 @@ filter Remove-GitHubGist [ValidateNotNullOrEmpty()] [string] $Id, + [switch] $Force, + [string] $AccessToken, [switch] $NoStatus @@ -325,6 +338,11 @@ filter Remove-GitHubGist Write-InvocationLog -Invocation $MyInvocation + if ($Force -and (-not $Confirm)) + { + $ConfirmPreference = 'None' + } + if (-not $PSCmdlet.ShouldProcess($Id, "Delete gist")) { return @@ -370,6 +388,7 @@ filter Copy-GitHubGist .INPUTS GitHub.Gist + GitHub.GistComment GitHub.GistCommit GitHub.GistDetail GitHub.GistFork @@ -454,6 +473,7 @@ filter Add-GitHubGistStar .INPUTS GitHub.Gist + GitHub.GistComment GitHub.GistCommit GitHub.GistDetail GitHub.GistFork @@ -534,6 +554,7 @@ filter Remove-GitHubGistStar .INPUTS GitHub.Gist + GitHub.GistComment GitHub.GistCommit GitHub.GistDetail GitHub.GistFork @@ -616,6 +637,7 @@ filter Test-GitHubGistStar .INPUTS GitHub.Gist + GitHub.GistComment GitHub.GistCommit GitHub.GistDetail GitHub.GistFork @@ -884,6 +906,7 @@ filter Set-GitHubGist .INPUTS GitHub.Gist + GitHub.GistComment GitHub.GistCommit GitHub.GistDetail GitHub.GistFork @@ -1057,7 +1080,7 @@ filter Add-GitHubGistAdditionalProperties GitHub.GistFork #> [CmdletBinding()] - [OutputType({$script:GitHubGistypeName})] + [OutputType({$script:GitHubGistTypeName})] [OutputType({$script:GitHubGistDetailTypeName})] [OutputType({$script:GitHubGistFormTypeName})] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index f35151e9..f948e041 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -15,6 +15,7 @@ # Format files (.ps1xml) to be loaded when importing this module FormatsToProcess = @( + 'Formatters/GitHubGistComments.Format.ps1xml', 'Formatters/GitHubGists.Format.ps1xml', 'Formatters/GitHubReleases.Format.ps1xml' 'Formatters/GitHubRepositories.Format.ps1xml' diff --git a/Tests/GitHubGistComments.tests.ps1 b/Tests/GitHubGistComments.tests.ps1 new file mode 100644 index 00000000..6dd8bbb1 --- /dev/null +++ b/Tests/GitHubGistComments.tests.ps1 @@ -0,0 +1,62 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +<# +.Synopsis + Tests for GitHubGistCommentss.ps1 module +#> + +[CmdletBinding()] +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', + Justification='Suppress false positives in Pester code blocks')] +param() + +# This is common test code setup logic for all Pester test files +$moduleRootPath = Split-Path -Path $PSScriptRoot -Parent +. (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1') + +try +{ + Describe 'New-GitHubGistComment' { + Context 'By parameters' { + BeforeAll { + $tempFile = New-TemporaryFile + $fileA = "$($tempFile.FullName).ps1" + Move-Item -Path $tempFile -Destination $fileA + Out-File -FilePath $fileA -InputObject "fileA content" -Encoding utf8 + + $tempFile = New-TemporaryFile + $fileB = "$($tempFile.FullName).txt" + Move-Item -Path $tempFile -Destination $fileB + Out-File -FilePath $fileB -InputObject "fileB content" -Encoding utf8 + + $description = 'my description' + } + + AfterAll { + @($fileA, $fileB) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + $gist = New-GitHubGist -File $fileA -Description $description -Public + It 'Should have the expected result' { + + } + + It 'Should have the expected type and additional properties' { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + } +} +finally +{ + if (Test-Path -Path $script:originalConfigFile -PathType Leaf) + { + # Restore the user's configuration to its pre-test state + Restore-GitHubConfiguration -Path $script:originalConfigFile + $script:originalConfigFile = $null + } +} From 7286c5371c86ee43e4365cc1f4f731b54b68c933 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sun, 12 Jul 2020 14:51:44 -0700 Subject: [PATCH 06/15] Fix parameter naming --- GitHubGistComments.ps1 | 101 +++++++++++++++++++------------------ GitHubGists.ps1 | 110 ++++++++++++++++++++--------------------- 2 files changed, 108 insertions(+), 103 deletions(-) diff --git a/GitHubGistComments.ps1 b/GitHubGistComments.ps1 index 1cadaf9c..4204421e 100644 --- a/GitHubGistComments.ps1 +++ b/GitHubGistComments.ps1 @@ -18,10 +18,10 @@ filter Get-GitHubGistComment The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER GistId + .PARAMETER Gist The ID of the specific gist that you wish to retrieve the comments for. - .PARAMETER CommentId + .PARAMETER Comment The ID of the specific comment on the gist that you wish to retrieve. .PARAMETER MediaType @@ -49,12 +49,12 @@ filter Get-GitHubGistComment GitHub.GistComment .EXAMPLE - Get-GitHubGistComment -GistId 6cad326836d38bd3a7ae + Get-GitHubGistComment -Gist 6cad326836d38bd3a7ae Gets all comments on octocat's "hello_world.rb" gist. .EXAMPLE - Get-GitHubGistComment -GistId 6cad326836d38bd3a7ae -CommentId 1507813 + Get-GitHubGistComment -Gist 6cad326836d38bd3a7ae -Comment 1507813 Gets comment 1507813 from octocat's "hello_world.rb" gist. #> @@ -65,12 +65,13 @@ filter Get-GitHubGistComment Mandatory, ValueFromPipelineByPropertyName, Position = 1)] - [string] $GistId, + [Alias('GistId')] + [string] $Gist, [Parameter(ValueFromPipelineByPropertyName)] [Alias('GistCommentId')] [ValidateNotNullOrEmpty()] - [string] $CommentId, + [string] $Comment, [ValidateSet('Raw', 'Text', 'Html', 'Full')] [string] $MediaType = 'Raw', @@ -87,17 +88,17 @@ filter Get-GitHubGistComment $uriFragment = [String]::Empty $description = [String]::Empty - if ([String]::IsNullOrWhiteSpace($CommentId)) + if ($PSBoundParameters.ContainsKey('Comment')) { - $uriFragment = "gists/$GistId/comments" - $description = "Getting comments for gist $GistId" + $telemetryProperties['SpecifiedComment'] = $true + + $uriFragment = "gists/$Gist/comments/$Comment" + $description = "Getting comment $Comment for gist $Gist" } else { - $telemetryProperties['SpecifiedCommentId'] = $true - - $uriFragment = "gists/$GistId/comments/$CommentId" - $description = "Getting comment $CommentId for gist $GistId" + $uriFragment = "gists/$Gist/comments" + $description = "Getting comments for gist $Gist" } $params = @{ @@ -111,7 +112,7 @@ filter Get-GitHubGistComment } return (Invoke-GHRestMethodMultipleResult @params | - Add-GitHubGistCommentAdditionalProperties -GistId $GistId) + Add-GitHubGistCommentAdditionalProperties -GistId $Gist) } filter Remove-GitHubGistComment @@ -125,10 +126,10 @@ filter Remove-GitHubGistComment The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER GistId + .PARAMETER Gist The ID of the specific gist that you wish to remove the comment from. - .PARAMETER CommentId + .PARAMETER Comment The ID of the comment to remove from the gist. .PARAMETER Force @@ -148,20 +149,20 @@ filter Remove-GitHubGistComment GitHub.GistComment .EXAMPLE - Remove-GitHubGist -GistId 6cad326836d38bd3a7ae -CommentId 12324567 + Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Comment 12324567 Removes the specified comment from octocat's "hello_world.rb" gist (assuming you have permission). .EXAMPLE - Remove-GitHubGist -GistId 6cad326836d38bd3a7ae -CommentId 12324567 -Confirm:$false + Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Comment 12324567 -Confirm:$false Removes the specified comment from octocat's "hello_world.rb" gist (assuming you have permission). Will not prompt for confirmation, as -Confirm:$false was specified. .EXAMPLE - Remove-GitHubGist -GistId 6cad326836d38bd3a7ae -CommentId 12324567 -Force + Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Comment 12324567 -Force Removes the specified comment from octocat's "hello_world.rb" gist (assuming you have permission). @@ -177,8 +178,9 @@ filter Remove-GitHubGistComment Mandatory, ValueFromPipelineByPropertyName, Position = 1)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $GistId, + [string] $Gist, [Parameter( Mandatory, @@ -186,7 +188,7 @@ filter Remove-GitHubGistComment Position = 2)] [Alias('GistCommentId')] [ValidateNotNullOrEmpty()] - [string] $CommentId, + [string] $Comment, [switch] $Force, @@ -202,16 +204,16 @@ filter Remove-GitHubGistComment $ConfirmPreference = 'None' } - if (-not $PSCmdlet.ShouldProcess($CommentId, "Delete comment from gist $GistId")) + if (-not $PSCmdlet.ShouldProcess($Comment, "Delete comment from gist $Gist")) { return } $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$GistId/comments/$CommentId" + 'UriFragment' = "gists/$Gist/comments/$Comment" 'Method' = 'Delete' - 'Description' = "Removing comment $CommentId from gist $GistId" + 'Description' = "Removing comment $Comment from gist $Gist" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties @@ -232,11 +234,11 @@ filter New-GitHubGistComment The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER GistId + .PARAMETER Gist The ID of the specific gist that you wish to add the comment to. - .PARAMETER Comment - The text of the comment that you wish to leave on the gist. + .PARAMETER Body + The body of the comment that you wish to leave on the gist. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the @@ -255,7 +257,7 @@ filter New-GitHubGistComment GitHub.GistComment .EXAMPLE - New-GitHubGistComment -GistId 6cad326836d38bd3a7ae -Comment 'Hello World' + New-GitHubGistComment -Gist 6cad326836d38bd3a7ae -Body 'Hello World' Adds a new comment of "Hello World" to octocat's "hello_world.rb" gist. #> @@ -268,14 +270,15 @@ filter New-GitHubGistComment Mandatory, ValueFromPipelineByPropertyName, Position = 1)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $GistId, + [string] $Gist, [Parameter( Mandatory, Position = 2)] [ValidateNotNullOrEmpty()] - [string] $Comment, + [string] $Body, [string] $AccessToken, @@ -285,27 +288,27 @@ filter New-GitHubGistComment Write-InvocationLog -Invocation $MyInvocation $hashBody = @{ - 'body' = $Comment + 'body' = $Body } - if (-not $PSCmdlet.ShouldProcess($GistId, "Create new comment for gist")) + if (-not $PSCmdlet.ShouldProcess($Gist, "Create new comment for gist")) { return } $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$GistId/comments" + 'UriFragment' = "gists/$Gist/comments" 'Body' = (ConvertTo-Json -InputObject $hashBody) 'Method' = 'Post' - 'Description' = "Creating new comment on gist $GistId" + 'Description' = "Creating new comment on gist $Gist" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties -GistId $GistId) + return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties -GistId $Gist) } filter Set-GitHubGistComment @@ -319,13 +322,13 @@ filter Set-GitHubGistComment The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER GistId + .PARAMETER Gist The ID of the gist that the comment is on. - .PARAMETER CommentId + .PARAMETER Comment The ID of the comment that you wish to edit. - .PARAMETER Comment + .PARAMETER Body The new text of the comment that you wish to leave on the gist. .PARAMETER AccessToken @@ -345,9 +348,10 @@ filter Set-GitHubGistComment GitHub.GistComment .EXAMPLE - New-GitHubGistComment -Id 6cad326836d38bd3a7ae -Comment 'Hello World' + New-GitHubGistComment -Gist 6cad326836d38bd3a7ae -Comment 1232456 -Body 'Hello World' - Adds a new comment of "Hello World" to octocat's "hello_world.rb" gist. + Updates the body of the comment with ID 1232456 octocat's "hello_world.rb" gist to be + "Hello World". #> [CmdletBinding( SupportsShouldProcess, @@ -358,8 +362,9 @@ filter Set-GitHubGistComment Mandatory, ValueFromPipelineByPropertyName, Position = 1)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $GistId, + [string] $Gist, [Parameter( Mandatory, @@ -367,13 +372,13 @@ filter Set-GitHubGistComment Position = 2)] [Alias('GistCommentId')] [ValidateNotNullOrEmpty()] - [string] $CommentId, + [string] $Comment, [Parameter( Mandatory, Position = 3)] [ValidateNotNullOrEmpty()] - [string] $Comment, + [string] $Body, [string] $AccessToken, @@ -383,27 +388,27 @@ filter Set-GitHubGistComment Write-InvocationLog -Invocation $MyInvocation $hashBody = @{ - 'body' = $Comment + 'body' = $Body } - if (-not $PSCmdlet.ShouldProcess($CommentId, "Update gist comment on gist $GistId")) + if (-not $PSCmdlet.ShouldProcess($Comment, "Update gist comment on gist $Gist")) { return } $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$GistId/comments/$CommentId" + 'UriFragment' = "gists/$Gist/comments/$Comment" 'Body' = (ConvertTo-Json -InputObject $hashBody) 'Method' = 'Patch' - 'Description' = "Creating new comment on gist $GistId" + 'Description' = "Creating new comment on gist $Gist" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties -GistId $GistId) + return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties -GistId $Gist) } filter Add-GitHubGistCommentAdditionalProperties diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 index 18e43418..d36db759 100644 --- a/GitHubGists.ps1 +++ b/GitHubGists.ps1 @@ -21,7 +21,7 @@ filter Get-GitHubGist The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER Gist The ID of the specific gist that you wish to retrieve. .PARAMETER Sha @@ -83,7 +83,7 @@ filter Get-GitHubGist Gets all public gists that have been updated within the past two days. .EXAMPLE - Get-GitHubGist -Id 6cad326836d38bd3a7ae + Get-GitHubGist -Gist 6cad326836d38bd3a7ae Gets octocat's "hello_world.rb" gist. #> @@ -102,7 +102,7 @@ filter Get-GitHubGist Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $Gist, [Parameter(ParameterSetName='Id')] [ValidateNotNullOrEmpty()] @@ -160,26 +160,26 @@ filter Get-GitHubGist $telemetryProperties['SpecifiedSha'] = $true - $uriFragment = "gists/$Id/$Sha" - $description = "Getting gist $Id with specified Sha" + $uriFragment = "gists/$Gist/$Sha" + $description = "Getting gist $Gist with specified Sha" $outputType = $script:GitHubGistDetailTypeName } elseif ($Forks) { - $uriFragment = "gists/$Id/forks" - $description = "Getting forks of gist $Id" + $uriFragment = "gists/$Gist/forks" + $description = "Getting forks of gist $Gist" $outputType = $script:GitHubGistForkTypeName } elseif ($Commits) { - $uriFragment = "gists/$Id/commits" - $description = "Getting commits of gist $Id" + $uriFragment = "gists/$Gist/commits" + $description = "Getting commits of gist $Gist" $outputType = $script:GitHubGistCommitTypeName } else { - $uriFragment = "gists/$Id" - $description = "Getting gist $Id" + $uriFragment = "gists/$Gist" + $description = "Getting gist $Gist" $outputType = $script:GitHubGistDetailTypeName } } @@ -275,7 +275,7 @@ filter Remove-GitHubGist The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER Gist The ID of the specific gist that you wish to retrieve. .PARAMETER Force @@ -299,18 +299,18 @@ filter Remove-GitHubGist GitHub.GistFork .EXAMPLE - Remove-GitHubGist -Id 6cad326836d38bd3a7ae + Remove-GitHubGist -Gist 6cad326836d38bd3a7ae Removes octocat's "hello_world.rb" gist (assuming you have permission). .EXAMPLE - Remove-GitHubGist -Id 6cad326836d38bd3a7ae -Confirm:$false + Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Confirm:$false Removes octocat's "hello_world.rb" gist (assuming you have permission). Will not prompt for confirmation, as -Confirm:$false was specified. .EXAMPLE - Remove-GitHubGist -Id 6cad326836d38bd3a7ae -Force + Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Force Removes octocat's "hello_world.rb" gist (assuming you have permission). Will not prompt for confirmation, as -Force was specified. @@ -327,7 +327,7 @@ filter Remove-GitHubGist Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $Gist, [switch] $Force, @@ -343,16 +343,16 @@ filter Remove-GitHubGist $ConfirmPreference = 'None' } - if (-not $PSCmdlet.ShouldProcess($Id, "Delete gist")) + if (-not $PSCmdlet.ShouldProcess($Gist, "Delete gist")) { return } $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$Id" + 'UriFragment' = "gists/$Gist" 'Method' = 'Delete' - 'Description' = "Removing gist $Id" + 'Description' = "Removing gist $Gist" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties @@ -373,7 +373,7 @@ filter Copy-GitHubGist The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER Gist The ID of the specific gist that you wish to fork. .PARAMETER AccessToken @@ -397,12 +397,12 @@ filter Copy-GitHubGist GitHub.Gist .EXAMPLE - Copy-GitHubGist -Id 6cad326836d38bd3a7ae + Copy-GitHubGist -Gist 6cad326836d38bd3a7ae Forks octocat's "hello_world.rb" gist. .EXAMPLE - Fork-GitHubGist -Id 6cad326836d38bd3a7ae + Fork-GitHubGist -Gist 6cad326836d38bd3a7ae Forks octocat's "hello_world.rb" gist. This is using the alias for the command. The result is the same whether you use Copy-GitHubGist or Fork-GitHubGist. @@ -419,7 +419,7 @@ filter Copy-GitHubGist Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $Gist, [string] $AccessToken, @@ -428,16 +428,16 @@ filter Copy-GitHubGist Write-InvocationLog -Invocation $MyInvocation - if (-not $PSCmdlet.ShouldProcess($Id, "Forking gist")) + if (-not $PSCmdlet.ShouldProcess($Gist, "Forking gist")) { return } $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$Id/forks" + 'UriFragment' = "gists/$Gist/forks" 'Method' = 'Post' - 'Description' = "Forking gist $Id" + 'Description' = "Forking gist $Gist" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties @@ -458,7 +458,7 @@ filter Add-GitHubGistStar The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER Gist The ID of the specific Gist that you wish to star. .PARAMETER AccessToken @@ -479,12 +479,12 @@ filter Add-GitHubGistStar GitHub.GistFork .EXAMPLE - Add-GitHubGistStar -Id 6cad326836d38bd3a7ae + Add-GitHubGistStar -Gist 6cad326836d38bd3a7ae STars octocat's "hello_world.rb" gist. .EXAMPLE - Star-GitHubGist -Id 6cad326836d38bd3a7ae + Star-GitHubGist -Gist 6cad326836d38bd3a7ae Stars octocat's "hello_world.rb" gist. This is using the alias for the command. The result is the same whether you use Add-GitHubGistStar or Star-GitHubGist. @@ -500,7 +500,7 @@ filter Add-GitHubGistStar Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $Gist, [string] $AccessToken, @@ -509,16 +509,16 @@ filter Add-GitHubGistStar Write-InvocationLog -Invocation $MyInvocation - if (-not $PSCmdlet.ShouldProcess($Id, "Starring gist")) + if (-not $PSCmdlet.ShouldProcess($Gist, "Starring gist")) { return } $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$Id/star" + 'UriFragment' = "gists/$Gist/star" 'Method' = 'Put' - 'Description' = "Starring gist $Id" + 'Description' = "Starring gist $Gist" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties @@ -539,7 +539,7 @@ filter Remove-GitHubGistStar The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER Gist The ID of the specific gist that you wish to unstar. .PARAMETER AccessToken @@ -560,12 +560,12 @@ filter Remove-GitHubGistStar GitHub.GistFork .EXAMPLE - Remove-GitHubGistStar -Id 6cad326836d38bd3a7ae + Remove-GitHubGistStar -Gist 6cad326836d38bd3a7ae Unstars octocat's "hello_world.rb" gist. .EXAMPLE - Unstar-GitHubGist -Id 6cad326836d38bd3a7ae + Unstar-GitHubGist -Gist 6cad326836d38bd3a7ae Unstars octocat's "hello_world.rb" gist. This is using the alias for the command. The result is the same whether you use Remove-GitHubGistStar or Unstar-GitHubGist. @@ -581,7 +581,7 @@ filter Remove-GitHubGistStar Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $Gist, [string] $AccessToken, @@ -590,16 +590,16 @@ filter Remove-GitHubGistStar Write-InvocationLog -Invocation $MyInvocation - if (-not $PSCmdlet.ShouldProcess($Id, "Unstarring gist")) + if (-not $PSCmdlet.ShouldProcess($Gist, "Unstarring gist")) { return } $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$Id/star" + 'UriFragment' = "gists/$Gist/star" 'Method' = 'Delete' - 'Description' = "Unstarring gist $Id" + 'Description' = "Unstarring gist $Gist" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties @@ -622,7 +622,7 @@ filter Test-GitHubGistStar The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER Gist The ID of the specific gist that you wish to check. .PARAMETER AccessToken @@ -646,7 +646,7 @@ filter Test-GitHubGistStar Boolean indicating if the gist was both found and determined to be starred. .EXAMPLE - Test-GitHubGistStar -Id 6cad326836d38bd3a7ae + Test-GitHubGistStar -Gist 6cad326836d38bd3a7ae Returns $true if the gist is starred, or $false if isn't starred or couldn't be checked (due to permissions or non-existence). @@ -664,7 +664,7 @@ filter Test-GitHubGistStar Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $Gist, [string] $AccessToken, @@ -675,9 +675,9 @@ filter Test-GitHubGistStar $telemetryProperties = @{} $params = @{ - 'UriFragment' = "gists/$Id/star" + 'UriFragment' = "gists/$Gist/star" 'Method' = 'Get' - 'Description' = "Checking if gist $Id is starred" + 'Description' = "Checking if gist $Gist is starred" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties @@ -874,7 +874,7 @@ filter Set-GitHubGist The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .PARAMETER Id + .PARAMETER Gist The ID for the gist to update. .PARAMETER Update @@ -915,27 +915,27 @@ filter Set-GitHubGist GitHub.GistDetail .EXAMPLE - Set-GitHubGist -Id 6cad326836d38bd3a7ae -Description 'This is my newer description' + Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Description 'This is my newer description' Updates the description for the specified gist. .EXAMPLE - Set-GitHubGist -Id 6cad326836d38bd3a7ae -Delete 'hello_world.rb' + Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Delete 'hello_world.rb' Deletes the 'hello_world.rb' file from the specified gist. .EXAMPLE - Set-GitHubGist -Id 6cad326836d38bd3a7ae -Delete 'hello_world.rb' -Description 'This is my newer description' + Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Delete 'hello_world.rb' -Description 'This is my newer description' Deletes the 'hello_world.rb' file from the specified gist and updates the description. .EXAMPLE - Set-GitHubGist -Id 6cad326836d38bd3a7ae -Update @{'hello_world.rb' = @{ 'fileName' = 'hello_universe.rb' }} + Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Update @{'hello_world.rb' = @{ 'fileName' = 'hello_universe.rb' }} Renames the 'hello_world.rb' file in the specified gist to be 'hello_universe.rb'. .EXAMPLE - Set-GitHubGist -Id 6cad326836d38bd3a7ae -Update @{'hello_world.rb' = @{ 'fileName' = 'hello_universe.rb' }} + Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Update @{'hello_world.rb' = @{ 'fileName' = 'hello_universe.rb' }} Renames the 'hello_world.rb' file in the specified gist to be 'hello_universe.rb'. #> @@ -951,7 +951,7 @@ filter Set-GitHubGist Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $Id, + [string] $Gist, [hashtable] $Update, @@ -1025,16 +1025,16 @@ filter Set-GitHubGist if (-not [String]::IsNullOrWhiteSpace($Description)) { $hashBody['description'] = $Description } if ($files.Keys.count -gt 0) { $hashBody['files'] = $files } - if (-not $PSCmdlet.ShouldProcess($Id, 'Update gist')) + if (-not $PSCmdlet.ShouldProcess($Gist, 'Update gist')) { return } $params = @{ - 'UriFragment' = "gists/$Id" + 'UriFragment' = "gists/$Gist" 'Body' = (ConvertTo-Json -InputObject $hashBody) 'Method' = 'Patch' - 'Description' = "Updating gist $Id" + 'Description' = "Updating gist $Gist" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties From ecc68abd63d54496e30d8298a1ffe4ff5d250e29 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sun, 12 Jul 2020 15:36:20 -0700 Subject: [PATCH 07/15] Complete work for gist comments --- GitHubGistComments.ps1 | 29 +-- PowerShellForGitHub.psd1 | 1 + Tests/GitHubGistComments.tests.ps1 | 297 +++++++++++++++++++++++++++-- 3 files changed, 303 insertions(+), 24 deletions(-) diff --git a/GitHubGistComments.ps1 b/GitHubGistComments.ps1 index 4204421e..08b069f6 100644 --- a/GitHubGistComments.ps1 +++ b/GitHubGistComments.ps1 @@ -111,8 +111,7 @@ filter Get-GitHubGistComment 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return (Invoke-GHRestMethodMultipleResult @params | - Add-GitHubGistCommentAdditionalProperties -GistId $Gist) + return (Invoke-GHRestMethodMultipleResult @params | Add-GitHubGistCommentAdditionalProperties) } filter Remove-GitHubGistComment @@ -308,7 +307,7 @@ filter New-GitHubGistComment 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties -GistId $Gist) + return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties) } filter Set-GitHubGistComment @@ -408,7 +407,7 @@ filter Set-GitHubGistComment 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties -GistId $Gist) + return (Invoke-GHRestMethod @params | Add-GitHubGistCommentAdditionalProperties) } filter Add-GitHubGistCommentAdditionalProperties @@ -444,10 +443,7 @@ filter Add-GitHubGistCommentAdditionalProperties [PSCustomObject[]] $InputObject, [ValidateNotNullOrEmpty()] - [string] $TypeName = $script:GitHubGistCommentTypeName, - - [ValidateNotNullOrEmpty()] - [string] $GistId + [string] $TypeName = $script:GitHubGistCommentTypeName ) foreach ($item in $InputObject) @@ -456,13 +452,22 @@ filter Add-GitHubGistCommentAdditionalProperties if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) { - Add-Member -InputObject $item -Name 'GistCommentId' -Value $item.id -MemberType NoteProperty -Force - - if ($PSBoundParameters.ContainsKey('GistId')) + $hostName = $(Get-GitHubConfiguration -Name 'ApiHostName') + if ($item.url -match "^https?://(?:www\.|api\.|)$hostName/gists/([^/]+)/comments/(.+)$") { - Add-Member -InputObject $item -Name 'GistId' -Value $GistId -MemberType NoteProperty -Force + $gistId = $Matches[1] + $commentId = $Matches[2] + + if ($commentId -ne $item.id) + { + $message = "The gist comment url no longer follows the expected pattern. Please contact the PowerShellForGitHubTeam: $item.url" + Write-Log -Message $message -Level Warning + } } + Add-Member -InputObject $item -Name 'GistCommentId' -Value $item.id -MemberType NoteProperty -Force + Add-Member -InputObject $item -Name 'GistId' -Value $gistId -MemberType NoteProperty -Force + if ($null -ne $item.user) { $null = Add-GitHubUserAdditionalProperties -InputObject $item.user diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index f948e041..79e83386 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -124,6 +124,7 @@ 'Move-GitHubProjectColumn', 'Move-GitHubRepositoryOwnership', 'New-GitHubGist', + 'New-GitHubGistComment', 'New-GitHubIssue', 'New-GitHubIssueComment', 'New-GitHubLabel', diff --git a/Tests/GitHubGistComments.tests.ps1 b/Tests/GitHubGistComments.tests.ps1 index 6dd8bbb1..de64cd3c 100644 --- a/Tests/GitHubGistComments.tests.ps1 +++ b/Tests/GitHubGistComments.tests.ps1 @@ -17,29 +17,264 @@ $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent try { - Describe 'New-GitHubGistComment' { + Describe 'Get-GitHubGistComment' { + BeforeAll { + $body = 'Comment body' + } + Context 'By parameters' { BeforeAll { - $tempFile = New-TemporaryFile - $fileA = "$($tempFile.FullName).ps1" - Move-Item -Path $tempFile -Destination $fileA - Out-File -FilePath $fileA -InputObject "fileA content" -Encoding utf8 + $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $body = 'Comment body' + } + + AfterAll { + $gist | Remove-GitHubGist -Force + } + + $comments = @(Get-GitHubGistComment -Gist $gist.id -MediaType 'Raw') + It 'Should have no comments so far' { + $comments.Count | Should -Be 0 + } + + $firstComment = New-GitHubGistComment -Gist $gist.id -Body $body + $comments = @(Get-GitHubGistComment -Gist $gist.id -MediaType 'Text') + It 'Should have one comments so far' { + $comments.Count | Should -Be 1 + $comments[0].id | Should -Be $firstComment.id + $comments[0].body | Should -BeNullOrEmpty + $comments[0].body_html | Should -BeNullOrEmpty + $comments[0].body_text | Should -Not -BeNullOrEmpty + } + + It 'Should have the expected type and additional properties' { + $comments[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comments[0].GistCommentId | Should -Be $comments[0].id + $comments[0].GistId | Should -Be $gist.id + $comments[0].user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $null = New-GitHubGistComment -Gist $gist.id -Body $body + $comments = @(Get-GitHubGistComment -Gist $gist.id -MediaType 'Html') + It 'Should have one comments so far' { + $comments.Count | Should -Be 2 + foreach ($comment in $comments) + { + $comment.body | Should -BeNullOrEmpty + $comment.body_html | Should -Not -BeNullOrEmpty + $comment.body_text | Should -BeNullOrEmpty + } + } + + It 'Should have the expected type and additional properties' { + foreach ($comment in $comments) + { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + $comment = Get-GitHubGistComment -Gist $gist.id -Comment $firstComment.id -MediaType 'Html' + It 'Should retrieve the specific comment' { + $comment.id | Should -Be $firstComment.id + $comment.body | Should -BeNullOrEmpty + $comment.body_html | Should -Not -BeNullOrEmpty + $comment.body_text | Should -BeNullOrEmpty + } - $tempFile = New-TemporaryFile - $fileB = "$($tempFile.FullName).txt" - Move-Item -Path $tempFile -Destination $fileB - Out-File -FilePath $fileB -InputObject "fileB content" -Encoding utf8 + It 'Should have the expected type and additional properties' { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } - $description = 'my description' + Context 'Gist on the pipeline' { + BeforeAll { + $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $body = 'Comment body' } AfterAll { - @($fileA, $fileB) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + $gist | Remove-GitHubGist -Force + } + + $comments = @(Get-GitHubGistComment -Gist $gist.id -MediaType 'Text') + It 'Should have no comments so far' { + $comments.Count | Should -Be 0 + } + + $firstComment = $gist | New-GitHubGistComment -Body $body + $comments = @($gist | Get-GitHubGistComment -MediaType 'Raw') + It 'Should have one comments so far' { + $comments.Count | Should -Be 1 + $comments[0].id | Should -Be $firstComment.id + $comments[0].body | Should -Not -BeNullOrEmpty + $comments[0].body_html | Should -BeNullOrEmpty + $comments[0].body_text | Should -BeNullOrEmpty + } + + It 'Should have the expected type and additional properties' { + $comments[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comments[0].GistCommentId | Should -Be $comments[0].id + $comments[0].GistId | Should -Be $gist.id + $comments[0].user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $null = $gist | New-GitHubGistComment -Body $body + $comments = @($gist | Get-GitHubGistComment -MediaType 'Full') + It 'Should have one comments so far' { + $comments.Count | Should -Be 2 + foreach ($comment in $comments) + { + $comment.body | Should -Not -BeNullOrEmpty + $comment.body_html | Should -Not -BeNullOrEmpty + $comment.body_text | Should -Not -BeNullOrEmpty + } + } + + It 'Should have the expected type and additional properties' { + foreach ($comment in $comments) + { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + $comment = Get-GitHubGistComment -Gist $gist.id -Comment $firstComment.id -MediaType 'Html' + It 'Should retrieve the specific comment' { + $comment.id | Should -Be $firstComment.id + $comment.body | Should -BeNullOrEmpty + $comment.body_html | Should -Not -BeNullOrEmpty + $comment.body_text | Should -BeNullOrEmpty + } + + It 'Should have the expected type and additional properties' { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $comment = $firstComment | Get-GitHubGistComment -MediaType 'Html' + It 'Should retrieve the specific comment with the comment on the pipeline' { + $comment.id | Should -Be $firstComment.id + $comment.body | Should -BeNullOrEmpty + $comment.body_html | Should -Not -BeNullOrEmpty + $comment.body_text | Should -BeNullOrEmpty + } + + It 'Should have the expected type and additional properties' { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + } + + Describe 'New-GitHubGistComment' { + BeforeAll { + $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $body = 'Comment body' + } + + AfterAll { + $gist | Remove-GitHubGist -Force + } + + Context 'By parameters' { + $comment = New-GitHubGistComment -Gist $gist.id -Body $body + It 'Should have the expected result' { + $comment.body | Should -Be $body + } + + It 'Should have the expected type and additional properties' { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + Context 'Gist on the pipeline' { + $comment = $gist | New-GitHubGistComment -Body $body + It 'Should have the expected result' { + $comment.body | Should -Be $body + } + + It 'Should have the expected type and additional properties' { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + } + + Describe 'New-GitHubGistComment' { + BeforeAll { + $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $body = 'Comment body' + $updatedBody = 'Updated comment body' + } + + AfterAll { + $gist | Remove-GitHubGist -Force + } + + Context 'By parameters' { + $comment = New-GitHubGistComment -Gist $gist.id -Body $body + It 'Should have the expected result' { + $comment.body | Should -Be $body + } + + $comment = Set-GitHubGistComment -Gist $gist.id -Comment $comment.id -Body $updatedBody + It 'Should have the expected result' { + $comment.body | Should -Be $updatedBody + } + + It 'Should have the expected type and additional properties' { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + Context 'Gist on the pipeline' { + $comment = $gist | New-GitHubGistComment -Body $body + It 'Should have the expected result' { + $comment.body | Should -Be $body + } + + $comment = $gist | Set-GitHubGistComment -Comment $comment.id -Body $updatedBody + It 'Should have the expected result' { + $comment.body | Should -Be $updatedBody + } + + It 'Should have the expected type and additional properties' { + $comment.PSObject.TypeNames[0] | Should -Be 'GitHub.GistComment' + $comment.GistCommentId | Should -Be $comment.id + $comment.GistId | Should -Be $gist.id + $comment.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } + } - $gist = New-GitHubGist -File $fileA -Description $description -Public + Context 'Gist Comment on the pipeline' { + $comment = $gist | New-GitHubGistComment -Body $body It 'Should have the expected result' { + $comment.body | Should -Be $body + } + $comment = $comment | Set-GitHubGistComment -Body $updatedBody + It 'Should have the expected result' { + $comment.body | Should -Be $updatedBody } It 'Should have the expected type and additional properties' { @@ -50,6 +285,44 @@ try } } } + + Describe 'Remove-GitHubGistComment' { + BeforeAll { + $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $body = 'Comment body' + } + + AfterAll { + $gist | Remove-GitHubGist -Force + } + + Context 'By parameters' { + $comment = New-GitHubGistComment -Gist $gist.id -Body $body + + Remove-GitHubGistComment -Gist $gist.id -Comment $comment.id -Force + It 'Should be gone' { + { Get-GitHubGistComment -Gist $gist.id -Comment $comment.id } | Should -Throw + } + } + + Context 'Gist on the pipeline' { + $comment = $gist | New-GitHubGistComment -Body $body + + $gist | Remove-GitHubGistComment -Comment $comment.id -Force + It 'Should be gone' { + { $gist | Get-GitHubGistComment -Comment $comment.id } | Should -Throw + } + } + + Context 'Gist Comment on the pipeline' { + $comment = $gist | New-GitHubGistComment -Body $body + + $comment | Remove-GitHubGistComment -Force + It 'Should be gone' { + { $comment | Get-GitHubGistComment } | Should -Throw + } + } + } } finally { From b9b71c5aba47e61d363a85fe9e8fce4fd670f1b5 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sun, 12 Jul 2020 16:11:26 -0700 Subject: [PATCH 08/15] Working on tests for gists --- GitHubGists.ps1 | 8 ++- Tests/GitHubGists.tests.ps1 | 136 +++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 4 deletions(-) diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 index d36db759..2441b119 100644 --- a/GitHubGists.ps1 +++ b/GitHubGists.ps1 @@ -196,7 +196,7 @@ filter Get-GitHubGist $telemetryProperties['CurrentUser'] = $true $outputType = $script:GitHubGistTypeName - if (Test-GitHubAuthenticationConfigured) + if (Test-GitHubAuthenticationConfigured -or (-not [String]::IsNullOrEmpty($AccessToken))) { if ($Starred) { @@ -218,7 +218,9 @@ filter Get-GitHubGist throw $message } - $description = 'Getting public gists' + $message = 'Specified -Current, but not currently authenticated. Either call Set-GitHubAuthentication first, or provide a value for the AccessToken parameter.' + Write-Log -Message $message -Level Error + throw $message } } elseif ($PSCmdlet.ParameterSetName -eq 'Public') @@ -256,7 +258,7 @@ Response has been truncated. The API will only return the first 3000 gist resul the first 300 files within an individual gist, and the first 1 Mb of an individual file. If the file has been truncated, you can call (Invoke-WebRequest -UseBasicParsing -Method Get -Uri ).Content) where is the value of raw_url for the file in question. Be aware that for files larger -than 10 Mb, you''ll need to clone the gist via the URL provided by git_pull_url. +than 10 Mb, you'll need to clone the gist via the URL provided by git_pull_url. "@ Write-Log -Message $message -Level Warning } diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1 index 0dd02f97..beea1e0d 100644 --- a/Tests/GitHubGists.tests.ps1 +++ b/Tests/GitHubGists.tests.ps1 @@ -17,7 +17,41 @@ $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent try { - Describe 'New-GitHubGist' { + Describe 'Get-GitHubGist' { + Context 'Specific Gist' { + } + + Context 'Specific Gist with Sha' { + } + + Context 'Forks' { + # Make sure you check for error when Sha specified + } + + Context 'Commits' { + # Make sure you check for error when Sha specified + } + + Context 'All gists for a specific user' { + } + + Context 'All starred gists for a specific user' { + } + + Context 'All gists for the current authenticated user' { + } + + Context 'All gists for the current authenticated user, but not authenticated' { + } + + Context 'All starred gists for the current authenticated user, but not authenticated' { + } + + Context 'All public gists' { + } + } + + Describe 'Get-GitHubGist' { Context 'By files' { BeforeAll { $tempFile = New-TemporaryFile @@ -49,6 +83,106 @@ try } } } + + Describe 'Remove-GitHubGist' { + Context 'By files' { + BeforeAll { + } + + AfterAll { + } + } + } + + Describe 'Copy-GitHubGist' { + Context 'By files' { + BeforeAll { + } + + AfterAll { + } + } + } + + Describe 'Add/Remove/Test-GitHubGistStar' { + Context 'By files' { + BeforeAll { + $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + } + + AfterAll { + $gist | Remove-GitHubGist -Force + } + + Context 'With parameters' { + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should not be starred yet' { + $starred | Should -BeFalse + } + + Add-GitHubGistStar -Gist $gist.id + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should now be starred yet' { + $starred | Should -BeTrue + } + + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should not be starred yet' { + $starred | Should -BeTrue + } + + Remove-GitHubGistStar -Gist $gist.id + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should no longer be starred yet' { + $starred | Should -BeFalse + } + } + + Context 'With the gist on the pipeline' { + $starred = $gist | Test-GitHubGistStar + It 'Should not be starred yet' { + $starred | Should -BeFalse + } + + $gist | Add-GitHubGistStar + $starred = $gist | Test-GitHubGistStar + It 'Should now be starred yet' { + $starred | Should -BeTrue + } + + $starred = $gist | Test-GitHubGistStar + It 'Should not be starred yet' { + $starred | Should -BeTrue + } + + $gist | Remove-GitHubGistStar + $starred = $gist | Test-GitHubGistStar + It 'Should no longer be starred yet' { + $starred | Should -BeFalse + } + } + } + } + + Describe 'New-GitHubGist' { + Context 'By files' { + BeforeAll { + } + + AfterAll { + } + } + } + + Describe 'Set-GitHubGist' { + Context 'By files' { + BeforeAll { + } + + AfterAll { + } + } + } } finally { From de107a92baef935552dc080cca91ed31cbb2f0b0 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sun, 12 Jul 2020 20:08:46 -0700 Subject: [PATCH 09/15] Adding Copy-GitHubGist tests --- Tests/GitHubGists.tests.ps1 | 138 +++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 48 deletions(-) diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1 index beea1e0d..852152e3 100644 --- a/Tests/GitHubGists.tests.ps1 +++ b/Tests/GitHubGists.tests.ps1 @@ -95,71 +95,113 @@ try } Describe 'Copy-GitHubGist' { - Context 'By files' { - BeforeAll { + BeforeAll { + $originalGist = Get-GitHubGist -Gist '1169852' # octocat/test.cs + } + + Context 'By parameters' { + $gist = Copy-GitHubGist -Gist $originalGist.id + It 'Should have been forked' { + $gist.files.Count | Should -Be $originalGist.files.Count + foreach ($file in $gist.files) + { + $originalFile = $originalGist.files | + Where-Object { $_.filename -eq $file.filename } + $file.filename | Should -Be $originalFile.filename + $file.size | Should -Be $originalFile.size + } } - AfterAll { + It 'Should have the expected additional type and properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + It 'Should be removed' { + { Remove-GitHubGist -Gist $gist.id -Force } | Should -Not -Throw } } - } - Describe 'Add/Remove/Test-GitHubGistStar' { - Context 'By files' { - BeforeAll { - $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + Context 'Gist on the pipeline' { + $gist = $originalGist | Copy-GitHubGist + It 'Should have been forked' { + $gist.files.Count | Should -Be $originalGist.files.Count + foreach ($file in $gist.files) + { + $originalFile = $originalGist.files | + Where-Object { $_.filename -eq $file.filename } + $file.filename | Should -Be $originalFile.filename + $file.size | Should -Be $originalFile.size + } } - AfterAll { - $gist | Remove-GitHubGist -Force + It 'Should have the expected additional type and properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } - Context 'With parameters' { - $starred = Test-GitHubGistStar -Gist $gist.id - It 'Should not be starred yet' { - $starred | Should -BeFalse - } + It 'Should be removed' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + } + } - Add-GitHubGistStar -Gist $gist.id - $starred = Test-GitHubGistStar -Gist $gist.id - It 'Should now be starred yet' { - $starred | Should -BeTrue - } + Describe 'Add/Remove/Test-GitHubGistStar' { + BeforeAll { + $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + } - $starred = Test-GitHubGistStar -Gist $gist.id - It 'Should not be starred yet' { - $starred | Should -BeTrue - } + AfterAll { + $gist | Remove-GitHubGist -Force + } - Remove-GitHubGistStar -Gist $gist.id - $starred = Test-GitHubGistStar -Gist $gist.id - It 'Should no longer be starred yet' { - $starred | Should -BeFalse - } + Context 'With parameters' { + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should not be starred yet' { + $starred | Should -BeFalse } - Context 'With the gist on the pipeline' { - $starred = $gist | Test-GitHubGistStar - It 'Should not be starred yet' { - $starred | Should -BeFalse - } + Add-GitHubGistStar -Gist $gist.id + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should now be starred yet' { + $starred | Should -BeTrue + } - $gist | Add-GitHubGistStar - $starred = $gist | Test-GitHubGistStar - It 'Should now be starred yet' { - $starred | Should -BeTrue - } + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should not be starred yet' { + $starred | Should -BeTrue + } - $starred = $gist | Test-GitHubGistStar - It 'Should not be starred yet' { - $starred | Should -BeTrue - } + Remove-GitHubGistStar -Gist $gist.id + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should no longer be starred yet' { + $starred | Should -BeFalse + } + } - $gist | Remove-GitHubGistStar - $starred = $gist | Test-GitHubGistStar - It 'Should no longer be starred yet' { - $starred | Should -BeFalse - } + Context 'With the gist on the pipeline' { + $starred = $gist | Test-GitHubGistStar + It 'Should not be starred yet' { + $starred | Should -BeFalse + } + + $gist | Add-GitHubGistStar + $starred = $gist | Test-GitHubGistStar + It 'Should now be starred yet' { + $starred | Should -BeTrue + } + + $starred = $gist | Test-GitHubGistStar + It 'Should not be starred yet' { + $starred | Should -BeTrue + } + + $gist | Remove-GitHubGistStar + $starred = $gist | Test-GitHubGistStar + It 'Should no longer be starred yet' { + $starred | Should -BeFalse } } } From 7fb4b81bc2919bb773009307f315695587dcf4db Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Tue, 14 Jul 2020 15:46:27 -0700 Subject: [PATCH 10/15] Completed all UT's Also: Add abilility to download gists Add Set-GitHubGistStar helper Re-order Content/FileName parameters Switch to [System.IO.File]::ReadAllText() for reading files Add gistfile detection/error handling Add confirmation for removing gist files Add helpers: Remove-GitHubGistFile Set-GitHubGistFile Rename-GitHubGistFile --- Formatters/GitHubGists.Format.ps1xml | 22 +- GitHubGists.ps1 | 819 +++++++++++++++++++-- PowerShellForGitHub.psd1 | 6 + Tests/GitHubGistComments.tests.ps1 | 10 +- Tests/GitHubGists.tests.ps1 | 1017 +++++++++++++++++++++++++- 5 files changed, 1768 insertions(+), 106 deletions(-) diff --git a/Formatters/GitHubGists.Format.ps1xml b/Formatters/GitHubGists.Format.ps1xml index bb002f06..3e02fa85 100644 --- a/Formatters/GitHubGists.Format.ps1xml +++ b/Formatters/GitHubGists.Format.ps1xml @@ -120,6 +120,9 @@ + + + @@ -145,6 +148,11 @@ id + + + ($_.owner.login) + + description @@ -203,7 +211,19 @@ - ($_.owner.login) + # There appears to be a bug in the GitHub API. + # Documentation says that the property should alway be "user", + # but it switches between "owner" and "user" depending on if it's a property + # of a gist, or the direct result from a gist forks query. + # https://github.community/t/gist-api-v3-documentation-incorrect-for-forks/122545 + if ($null -eq $_.user) + { + $_.owner.login + } + else + { + $_.user.login + } diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 index 2441b119..854c1354 100644 --- a/GitHubGists.ps1 +++ b/GitHubGists.ps1 @@ -36,6 +36,12 @@ filter Get-GitHubGist .PARAMETER UserName Gets public gists for the specified user. + .PARAMETER Path + Download the files that are part of the specified gist to this path. + + .PARAMETER Force + If downloading files, this will overwrite any files with the same name in the provided path. + .PARAMETER Current Gets the authenticated user's gists. @@ -100,11 +106,17 @@ filter Get-GitHubGist ValueFromPipelineByPropertyName, ParameterSetName='Id', Position = 1)] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='Download', + Position = 1)] [Alias('GistId')] [ValidateNotNullOrEmpty()] [string] $Gist, [Parameter(ParameterSetName='Id')] + [Parameter(ParameterSetName='Download')] [ValidateNotNullOrEmpty()] [string] $Sha, @@ -114,10 +126,22 @@ filter Get-GitHubGist [Parameter(ParameterSetName='Id')] [switch] $Commits, - [Parameter(ParameterSetName='User')] + [Parameter( + Mandatory, + ParameterSetName='User')] [ValidateNotNullOrEmpty()] [string] $UserName, + [Parameter( + Mandatory, + ParameterSetName='Download', + Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $Path, + + [Parameter(ParameterSetName='Download')] + [switch] $Force, + [Parameter(ParameterSetName='Current')] [switch] $Current, @@ -145,7 +169,7 @@ filter Get-GitHubGist $description = [String]::Empty $outputType = $script:GitHubGistTypeName - if ($PSCmdlet.ParameterSetName -eq 'Id') + if ($PSCmdlet.ParameterSetName -in ('Id', 'Download')) { $telemetryProperties['ById'] = $true @@ -196,7 +220,7 @@ filter Get-GitHubGist $telemetryProperties['CurrentUser'] = $true $outputType = $script:GitHubGistTypeName - if (Test-GitHubAuthenticationConfigured -or (-not [String]::IsNullOrEmpty($AccessToken))) + if ((Test-GitHubAuthenticationConfigured) -or (-not [String]::IsNullOrEmpty($AccessToken))) { if ($Starred) { @@ -249,21 +273,156 @@ filter Get-GitHubGist 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - $result = Invoke-GHRestMethodMultipleResult @params + $result = (Invoke-GHRestMethodMultipleResult @params | + Add-GitHubGistAdditionalProperties -TypeName $outputType) + + if ($PSCmdlet.ParameterSetName -eq 'Download') + { + Save-GitHubGist -GistObject $result -Path $Path -Force:$Force + } + else + { + if ($result.truncated -eq $true) + { + $message = @( + 'Response has been truncated. The API will only return the first 3000 gist results', + 'the first 300 files within the gist, and the first 1 Mb of an individual', + 'file. If the file has been truncated, you can call', + '(Invoke-WebRequest -UseBasicParsing -Method Get -Uri ).Content)', + 'where is the value of raw_url for the file in question. Be aware that', + 'for files larger than 10 Mb, you''ll need to clone the gist via the URL provided', + 'by git_pull_url.') + + Write-Log -Message ($message -join ' ') -Level Warning + } + + return $result + } +} + +function Save-GitHubGist +{ +<# + .SYNOPSIS + Downloads the contents of a gist to the specified file path. + + .DESCRIPTION + Downloads the contents of a gist to the specified file path. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER GistObject + The Gist PSCustomObject + + .PARAMETER Path + Download the files that are part of the specified gist to this path. + + .PARAMETER Force + If downloading files, this will overwrite any files with the same name in the provided path. + + .NOTES + Internal-only helper +#> + [CmdletBinding(PositionalBinding = $false)] + param( + [Parameter(Mandatory)] + [PSCustomObject] $GistObject, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $Path, + + [switch] $Force + ) + + # First, check to see if the response is missing files. + if ($GistObject.truncated) + { + $message = @( + 'Gist response has been truncated. The API will only return information on', + 'the first 300 files within a gist. To download this entire gist,', + 'you''ll need to clone it via the URL provided by git_pull_url', + "[$($GistObject.git_pull_url)].") + + Write-Log -Message ($message -join ' ') -Level Error + throw $message + } - if ($result.truncated -eq $true) + # Then check to see if there are files we won't be able to download + $files = $GistObject.files | Get-Member -Type NoteProperty | Select-Object -ExpandProperty Name + foreach ($fileName in $files) { - $message = @" -Response has been truncated. The API will only return the first 3000 gist results, -the first 300 files within an individual gist, and the first 1 Mb of an individual file. -If the file has been truncated, you can call (Invoke-WebRequest -UseBasicParsing -Method Get -Uri ).Content) -where is the value of raw_url for the file in question. Be aware that for files larger -than 10 Mb, you'll need to clone the gist via the URL provided by git_pull_url. -"@ - Write-Log -Message $message -Level Warning + if ($GistObject.files.$fileName.truncated -and + ($GistObject.files.$fileName.size -gt 10mb)) + { + $message = @( + "At least one file ($fileName) in this gist is larger than 10mb.", + 'In order to download this gist, you''ll need to clone it via the URL', + "provided by git_pull_url [$($GistObject.git_pull_url)].") + + Write-Log -Message ($message -join ' ') -Level Error + throw $message + } } - return ($result | Add-GitHubGistAdditionalProperties -TypeName $outputType) + # Finally, we're ready to directly save the non-truncated files, + # and download the ones that are between 1 - 10mb. + $originalSecurityProtocol = [Net.ServicePointManager]::SecurityProtocol + [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12 + try + { + $headers = @{} + $AccessToken = Get-AccessToken -AccessToken $AccessToken + if (-not [String]::IsNullOrEmpty($AccessToken)) + { + $headers['Authorization'] = "token $AccessToken" + } + + $Path = Resolve-UnverifiedPath -Path $Path + $null = New-Item -Path $Path -ItemType Directory -Force + foreach ($fileName in $files) + { + $filePath = Join-Path -Path $Path -ChildPath $fileName + if ((Test-Path -Path $filePath -PathType Leaf) -and (-not $Force)) + { + $message = "File already exists at path [$filePath]. Choose a different path or specify -Force" + Write-Log -Message $message -Level Error + throw $message + } + + if ($GistObject.files.$fileName.truncated) + { + # Disable Progress Bar in function scope during Invoke-WebRequest + $ProgressPreference = 'SilentlyContinue' + + $webRequestParams = @{ + UseBasicParsing = $true + Method = 'Get' + Headers = $headers + Uri = $GistObject.files.$fileName.raw_url + OutFile = $filePath + } + + Invoke-WebRequest @webRequestParams + } + else + { + $stream = New-Object -TypeName System.IO.StreamWriter -ArgumentList ($filePath) + try + { + $stream.Write($GistObject.files.$fileName.content) + } + finally + { + $stream.Close() + } + } + } + } + finally + { + [Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocol + } } filter Remove-GitHubGist @@ -449,6 +608,90 @@ filter Copy-GitHubGist return (Invoke-GHRestMethod @params | Add-GitHubGistAdditionalProperties) } +filter Set-GitHubGistStar +{ +<# + .SYNOPSIS + Changes the starred state of a gist on GitHub for the current authenticated user. + + .DESCRIPTION + Changes the starred state of a gist on GitHub for the current authenticated user. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Gist + The ID of the specific Gist that you wish to change the starred state for. + + .PARAMETER Star + Include this switch to star the gist. Exclude the switch (or use -Star:$false) to + remove the star. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .INPUTS + GitHub.Gist + GitHub.GistComment + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork + + .EXAMPLE + Set-GitHubGistStar -Gist 6cad326836d38bd3a7ae -Star + + Stars octocat's "hello_world.rb" gist. + + .EXAMPLE + Set-GitHubGistStar -Gist 6cad326836d38bd3a7ae + + Unstars octocat's "hello_world.rb" gist. + + .EXAMPLE + Get-GitHubGist -Gist 6cad326836d38bd3a7ae | Set-GitHubGistStar -Star:$false + + Unstars octocat's "hello_world.rb" gist. + +#> + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false)] + param( + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] + [ValidateNotNullOrEmpty()] + [string] $Gist, + + [switch] $Star, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + Set-TelemetryEvent -EventName $MyInvocation.MyCommand.Name + + $PSBoundParameters.Remove('Star') + if ($Star) + { + return Add-GitHubGistStar @PSBoundParameters + } + else + { + return Remove-GitHubGistStar @PSBoundParameters + } +} + filter Add-GitHubGistStar { <# @@ -483,7 +726,7 @@ filter Add-GitHubGistStar .EXAMPLE Add-GitHubGistStar -Gist 6cad326836d38bd3a7ae - STars octocat's "hello_world.rb" gist. + Stars octocat's "hello_world.rb" gist. .EXAMPLE Star-GitHubGist -Gist 6cad326836d38bd3a7ae @@ -652,10 +895,6 @@ filter Test-GitHubGistStar Returns $true if the gist is starred, or $false if isn't starred or couldn't be checked (due to permissions or non-existence). - - .NOTES - For some reason, this does not currently seem to be working correctly - (even though it matches the spec: https://developer.github.com/v3/gists/#check-if-a-gist-is-starred). #> [CmdletBinding(PositionalBinding = $false)] [OutputType([bool])] @@ -714,12 +953,12 @@ filter New-GitHubGist Use this when you have multiple files that should be part of a gist, or when you simply want to reference an existing file on disk. - .PARAMETER Content - The content of a single file that should be part of the gist. - .PARAMETER FileName The name of the file that Content should be stored in within the newly created gist. + .PARAMETER Content + The content of a single file that should be part of the gist. + .PARAMETER Description A descriptive name for this gist. @@ -743,7 +982,7 @@ filter New-GitHubGist GitHub.GitDetail .EXAMPLE - New-GitHubGist -Content 'Body of my file.' -FileName 'sample.txt' -Description 'This is my gist!' -Public + New-GitHubGist -FileName 'sample.txt' -Content 'Body of my file.' -Description 'This is my gist!' -Public Creates a new public gist with a single file named 'sample.txt' that has the body of "Body of my file." @@ -778,14 +1017,14 @@ filter New-GitHubGist ParameterSetName='Content', Position = 1)] [ValidateNotNullOrEmpty()] - [string] $Content, + [string] $FileName, [Parameter( Mandatory, ParameterSetName='Content', Position = 2)] [ValidateNotNullOrEmpty()] - [string] $FileName, + [string] $Content, [string] $Description, @@ -806,14 +1045,14 @@ filter New-GitHubGist foreach ($path in $File) { $path = Resolve-UnverifiedPath -Path $path - if (-not (Test-Path -Path $path)) + if (-not (Test-Path -Path $path -PathType Leaf)) { $message = "Specified file [$path] could not be found or was inaccessible." Write-Log -Message $message -Level Error throw $message } - $content = Get-Content -Path $path -Raw -Encoding UTF8 + $content = [System.IO.File]::ReadAllText($path) $fileName = (Get-Item -Path $path).Name if ($files.ContainsKey($fileName)) @@ -838,6 +1077,13 @@ filter New-GitHubGist $files[$FileName] = @{ 'content' = $Content } } + if (($files.Keys.StartsWith('gistfile') | Where-Object { $_ -eq $true }).Count -gt 0) + { + $message = "Don't name your files starting with 'gistfile'. This is the format of the automatic naming scheme that Gist uses internally." + Write-Log -Message $message -Level Error + throw $message + } + $hashBody = @{ 'description' = $Description 'public' = $Public.ToBool() @@ -896,6 +1142,9 @@ filter Set-GitHubGist .PARAMETER Description New description for this gist. + .PARAMETER Force + If this switch is specified, you will not be prompted for confirmation of command execution. + .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. @@ -922,9 +1171,9 @@ filter Set-GitHubGist Updates the description for the specified gist. .EXAMPLE - Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Delete 'hello_world.rb' + Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Delete 'hello_world.rb' -Force - Deletes the 'hello_world.rb' file from the specified gist. + Deletes the 'hello_world.rb' file from the specified gist without prompting for confirmation. .EXAMPLE Set-GitHubGist -Gist 6cad326836d38bd3a7ae -Delete 'hello_world.rb' -Description 'This is my newer description' @@ -961,6 +1210,8 @@ filter Set-GitHubGist [string] $Description, + [switch] $Force, + [string] $AccessToken, [switch] $NoStatus @@ -972,10 +1223,18 @@ filter Set-GitHubGist $files = @{} + $shouldProcessMessage = 'Update gist' + # Mark the files that should be deleted. - foreach ($toDelete in $Delete) + if ($Delete.Count -gt 0) { - $files[$toDelete] = $null + $ConfirmPreference = 'Low' + $shouldProcessMessage = 'Update gist (and remove files)' + + foreach ($toDelete in $Delete) + { + $files[$toDelete] = $null + } } # Then figure out which ones need content updates and/or file renames @@ -998,20 +1257,20 @@ filter Set-GitHubGist { if (-not [String]::IsNullOrWhiteSpace($providedContent)) { - $message = "When updating a file [$currentFileName], you cannot provide both a path to a file [$providedPath] and the raw content." + $message = "When updating a file [$currentFileName], you cannot provide both a path to a file [$providedFilePath] and the raw content." Write-Log -Message $message -Level Error throw $message } - $providedPath = Resolve-Path -Path $providedPath - if (-not (Test-Path -Path $providedPath)) + $providedFilePath = Resolve-Path -Path $providedFilePath + if (-not (Test-Path -Path $providedFilePath -PathType Leaf)) { - $message = "Specified file [$providedPath] could not be found or was inaccessible." + $message = "Specified file [$providedFilePath] could not be found or was inaccessible." Write-Log -Message $message -Level Error throw $message } - $newContent = Get-Content -Path $providedFilePath -Raw -Encoding UTF8 + $newContent = [System.IO.File]::ReadAllText($providedFilePath) $files[$currentFileName] = @{ 'content' = $newContent } } @@ -1027,11 +1286,17 @@ filter Set-GitHubGist if (-not [String]::IsNullOrWhiteSpace($Description)) { $hashBody['description'] = $Description } if ($files.Keys.count -gt 0) { $hashBody['files'] = $files } - if (-not $PSCmdlet.ShouldProcess($Gist, 'Update gist')) + if ($Force -and (-not $Confirm)) + { + $ConfirmPreference = 'None' + } + + if (-not $PSCmdlet.ShouldProcess($Gist, $shouldProcessMessage)) { return } + $ConfirmPreference = 'None' $params = @{ 'UriFragment' = "gists/$Gist" 'Body' = (ConvertTo-Json -InputObject $hashBody) @@ -1060,48 +1325,413 @@ filter Set-GitHubGist } } -filter Add-GitHubGistAdditionalProperties +function Set-GitHubGistFile { <# .SYNOPSIS - Adds type name and additional properties to ease pipelining to GitHub Gist objects. + Updates content of file(s) in an existing gist on GitHub, + or adds them if they aren't already part of the gist. - .PARAMETER InputObject - The GitHub object to add additional properties to. + .DESCRIPTION + Updates content of file(s) in an existing gist on GitHub, + or adds them if they aren't already part of the gist. - .PARAMETER TypeName - The type that should be assigned to the object. + This is a helper function built on top of Set-GitHubGist. - .INPUTS - [PSCustomObject] + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub - .OUTPUTS + .PARAMETER Gist + The ID for the gist to update. + + .PARAMETER File + An array of filepaths that should be part of this gist. + Use this when you have multiple files that should be part of a gist, or when you simply + want to reference an existing file on disk. + + .PARAMETER FileName + The name of the file that Content should be stored in within the newly created gist. + + .PARAMETER Content + The content of a single file that should be part of the gist. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .INPUTS GitHub.Gist + GitHub.GistComment GitHub.GistCommit GitHub.GistDetail GitHub.GistFork + + .OUTPUTS + GitHub.GistDetail + + .EXAMPLE + Set-GitHubGistFile -Gist 1234567 -Content 'Body of my file.' -FileName 'sample.txt' + + Adds a file named 'sample.txt' that has the body of "Body of my file." to the existing + specified gist, or updates the contents of 'sample.txt' in the gist if is already there. + + .EXAMPLE + Set-GitHubGistFile -Gist 1234567 -File 'c:\files\foo.txt' + + Adds the file 'foo.txt' to the existing specified gist, or updates its content if it + is already there. + + .EXAMPLE + Set-GitHubGistFile -Gist 1234567 -File ('c:\files\foo.txt', 'c:\other\bar.txt', 'c:\octocat.ps1') + + Adds all three files to the existing specified gist, or updates the contents of the files + in the gist if they are already there. #> - [CmdletBinding()] - [OutputType({$script:GitHubGistTypeName})] + [CmdletBinding( + SupportsShouldProcess, + DefaultParameterSetName='Content', + PositionalBinding = $false)] [OutputType({$script:GitHubGistDetailTypeName})] - [OutputType({$script:GitHubGistFormTypeName})] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] + [Alias('Add-GitHubGistFile')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")] param( [Parameter( Mandatory, - ValueFromPipeline)] - [AllowNull()] - [AllowEmptyCollection()] - [PSCustomObject[]] $InputObject, - + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] [ValidateNotNullOrEmpty()] - [string] $TypeName = $script:GitHubGistTypeName - ) + [string] $Gist, - if ($TypeName -eq $script:GitHubGistCommitTypeName) - { - return Add-GitHubGistCommitAdditionalProperties -InputObject $InputObject - } + [Parameter( + Mandatory, + ValueFromPipeline, + ParameterSetName='FileRef', + Position = 2)] + [ValidateNotNullOrEmpty()] + [string[]] $File, + + [Parameter( + Mandatory, + ParameterSetName='Content', + Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $FileName, + + [Parameter( + Mandatory, + ParameterSetName='Content', + Position = 3)] + [ValidateNotNullOrEmpty()] + [string] $Content, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + begin + { + $files = @{} + } + + process + { + foreach ($path in $File) + { + $path = Resolve-UnverifiedPath -Path $path + if (-not (Test-Path -Path $path -PathType Leaf)) + { + $message = "Specified file [$path] could not be found or was inaccessible." + Write-Log -Message $message -Level Error + throw $message + } + + $fileName = (Get-Item -Path $path).Name + $files[$fileName] = @{ 'filePath' = $path } + } + } + + end + { + Write-InvocationLog -Invocation $MyInvocation + Set-TelemetryEvent -EventName $MyInvocation.MyCommand.Name + + if ($PSCmdlet.ParameterSetName -eq 'Content') + { + $files[$FileName] = @{ 'content' = $Content } + } + + $params = @{ + 'Gist' = $Gist + 'Update' = $files + 'AccessToken' = $AccessToken + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Set-GitHubGist @params) + } +} + +function Remove-GitHubGistFile +{ +<# + .SYNOPSIS + Removes one or more files from an existing gist on GitHub. + + .DESCRIPTION + Removes one or more files from an existing gist on GitHub. + + This is a helper function built on top of Set-GitHubGist. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Gist + The ID for the gist to update. + + .PARAMETER FileName + An array of filenames (no paths, just names) to remove from the gist. + + .PARAMETER Force + If this switch is specified, you will not be prompted for confirmation of command execution. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .INPUTS + GitHub.Gist + GitHub.GistComment + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork + + .OUTPUTS + GitHub.GistDetail + + .EXAMPLE + Remove-GitHubGistFile -Gist 1234567 -FileName ('foo.txt') + + Removes the file 'foo.txt' from the specified gist. + + .EXAMPLE + Remove-GitHubGistFile -Gist 1234567 -FileName ('foo.txt') -Force + + Removes the file 'foo.txt' from the specified gist without prompting for confirmation. + + .EXAMPLE + @('foo.txt', 'bar.txt') | Remove-GitHubGistFile -Gist 1234567 + + Removes the files 'foo.txt' and 'bar.txt' from the specified gist. +#> + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false)] + [OutputType({$script:GitHubGistDetailTypeName})] + [Alias('Delete-GitHubGistFile')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")] + param( + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] + [ValidateNotNullOrEmpty()] + [string] $Gist, + + [Parameter( + Mandatory, + ValueFromPipeline, + Position = 2)] + [ValidateNotNullOrEmpty()] + [string[]] $FileName, + + [switch] $Force, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + begin + { + $files = @() + } + + process + { + foreach ($name in $FileName) + { + $files += $name + } + } + + end + { + Write-InvocationLog -Invocation $MyInvocation + Set-TelemetryEvent -EventName $MyInvocation.MyCommand.Name + + $params = @{ + 'Gist' = $Gist + 'Delete' = $files + 'Force' = $Force + 'Confirm' = ($Confirm -eq $true) + 'AccessToken' = $AccessToken + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Set-GitHubGist @params) + } +} + +filter Rename-GitHubGistFile +{ +<# + .SYNOPSIS + Renames a file in a gist on GitHub. + + .DESCRIPTION + Renames a file in a gist on GitHub. + + This is a helper function built on top of Set-GitHubGist. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER Gist + The ID for the gist to update. + + .PARAMETER FileName + The current file in the gist to be renamed. + + .PARAMETER NewName + The new name of the file for the gist. + + .PARAMETER AccessToken + If provided, this will be used as the AccessToken for authentication with the + REST Api. Otherwise, will attempt to use the configured value or will run unauthenticated. + + .PARAMETER NoStatus + If this switch is specified, long-running commands will run on the main thread + with no commandline status update. When not specified, those commands run in + the background, enabling the command prompt to provide status information. + If not supplied here, the DefaultNoStatus configuration property value will be used. + + .INPUTS + GitHub.Gist + GitHub.GistComment + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork + + .OUTPUTS + GitHub.GistDetail + + .EXAMPLE + Rename-GitHubGistFile -Gist 1234567 -FileName 'foo.txt' -NewName 'bar.txt' + + Renames the file 'foo.txt' to 'bar.txt' in the specified gist. +#> + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false)] + [OutputType({$script:GitHubGistDetailTypeName})] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")] + param( + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('GistId')] + [ValidateNotNullOrEmpty()] + [string] $Gist, + + [Parameter( + Mandatory, + Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $FileName, + + [Parameter( + Mandatory, + Position = 3)] + [ValidateNotNullOrEmpty()] + [string] $NewName, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog -Invocation $MyInvocation + Set-TelemetryEvent -EventName $MyInvocation.MyCommand.Name + + $params = @{ + 'Gist' = $Gist + 'Update' = @{$FileName = @{ 'fileName' = $NewName }} + 'AccessToken' = $AccessToken + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Set-GitHubGist @params) +} + +filter Add-GitHubGistAdditionalProperties +{ +<# + .SYNOPSIS + Adds type name and additional properties to ease pipelining to GitHub Gist objects. + + .PARAMETER InputObject + The GitHub object to add additional properties to. + + .PARAMETER TypeName + The type that should be assigned to the object. + + .INPUTS + [PSCustomObject] + + .OUTPUTS + GitHub.Gist + GitHub.GistCommit + GitHub.GistDetail + GitHub.GistFork +#> + [CmdletBinding()] + [OutputType({$script:GitHubGistTypeName})] + [OutputType({$script:GitHubGistDetailTypeName})] + [OutputType({$script:GitHubGistFormTypeName})] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] + param( + [Parameter( + Mandatory, + ValueFromPipeline)] + [AllowNull()] + [AllowEmptyCollection()] + [PSCustomObject[]] $InputObject, + + [ValidateNotNullOrEmpty()] + [string] $TypeName = $script:GitHubGistTypeName + ) + + if ($TypeName -eq $script:GitHubGistCommitTypeName) + { + return Add-GitHubGistCommitAdditionalProperties -InputObject $InputObject + } + elseif ($TypeName -eq $script:GitHubGistForkTypeName) + { + return Add-GitHubGistForkAdditionalProperties -InputObject $InputObject + } foreach ($item in $InputObject) { @@ -1119,15 +1749,14 @@ filter Add-GitHubGistAdditionalProperties } } - foreach ($fork in $item.forks) + if ($null -ne $item.forks) { - Add-Member -InputObject $fork -Name 'GistId' -Value $fork.id -MemberType NoteProperty -Force - $null = Add-GitHubUserAdditionalProperties -InputObject $fork.user + $item.forks = Add-GitHubGistForkAdditionalProperties -InputObject $item.forks } - foreach ($entry in $item.history) + if ($null -ne $item.history) { - $null = Add-GitHubGistCommitAdditionalProperties -InputObject $entry + $item.history = Add-GitHubGistCommitAdditionalProperties -InputObject $item.history } } @@ -1175,7 +1804,7 @@ filter Add-GitHubGistCommitAdditionalProperties if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) { $hostName = $(Get-GitHubConfiguration -Name 'ApiHostName') - if ($item.uri -match "^https?://(?:www\.|api\.|)$hostName/gists/([^/]+)/(.+)$") + if ($item.url -match "^https?://(?:www\.|api\.|)$hostName/gists/([^/]+)/(.+)$") { $id = $Matches[1] $sha = $Matches[2] @@ -1193,6 +1822,62 @@ filter Add-GitHubGistCommitAdditionalProperties $null = Add-GitHubUserAdditionalProperties -InputObject $item.user } + Write-Output $item + } +} + +filter Add-GitHubGistForkAdditionalProperties +{ +<# + .SYNOPSIS + Adds type name and additional properties to ease pipelining to GitHub Gist Fork objects. + + .PARAMETER InputObject + The GitHub object to add additional properties to. + + .PARAMETER TypeName + The type that should be assigned to the object. + + .INPUTS + [PSCustomObject] + + .OUTPUTS + GitHub.GistFork +#> + [CmdletBinding()] + [OutputType({$script:GitHubGistForkTypeName})] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] + param( + [Parameter( + Mandatory, + ValueFromPipeline)] + [AllowNull()] + [AllowEmptyCollection()] + [PSCustomObject[]] $InputObject, + + [ValidateNotNullOrEmpty()] + [string] $TypeName = $script:GitHubGistForkTypeName + ) + + foreach ($item in $InputObject) + { + $item.PSObject.TypeNames.Insert(0, $TypeName) + + if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) + { + Add-Member -InputObject $item -Name 'GistId' -Value $item.id -MemberType NoteProperty -Force + + # See here for why we need to work with both 'user' _and_ 'owner': + # https://github.community/t/gist-api-v3-documentation-incorrect-for-forks/122545 + @('user', 'owner') | + ForEach-Object { + if ($null -ne $item.$_) + { + $null = Add-GitHubUserAdditionalProperties -InputObject $item.$_ + } + } + } + Write-Output $item } } \ No newline at end of file diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 79e83386..5cbc5e48 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -143,6 +143,7 @@ 'Remove-GitHubComment', 'Remove-GitHubGist', 'Remove-GitHubGistComment', + 'Remove-GitHubGistFile', 'Remove-GitHubGistStar', 'Remove-GitHubIssueComment', 'Remove-GitHubIssueLabel', @@ -156,6 +157,7 @@ 'Remove-GitHubReleaseAsset', 'Remove-GitHubRepository', 'Remove-GitHubRepositoryBranch' + 'Rename-GitHubGistFile', 'Rename-GitHubRepository', 'Reset-GitHubConfiguration', 'Restore-GitHubConfiguration', @@ -164,6 +166,8 @@ 'Set-GitHubContent', 'Set-GitHubGist', 'Set-GitHubGistComment', + 'Set-GitHubGistFile', + 'Set-GitHubGistStar', 'Set-GitHubIssue', 'Set-GitHubIssueComment', 'Set-GitHubIssueLabel', @@ -188,11 +192,13 @@ ) AliasesToExport = @( + 'Add-GitHubGistFile', 'Delete-GitHubAsset', 'Delete-GitHubBranch', 'Delete-GitHubComment', 'Delete-GitHubGist', 'Delete-GitHubGistComment', + 'Delete-GitHubGistFile', 'Delete-GitHubIssueComment', 'Delete-GitHubLabel', 'Delete-GitHubMilestone', diff --git a/Tests/GitHubGistComments.tests.ps1 b/Tests/GitHubGistComments.tests.ps1 index de64cd3c..ab14b510 100644 --- a/Tests/GitHubGistComments.tests.ps1 +++ b/Tests/GitHubGistComments.tests.ps1 @@ -24,7 +24,7 @@ try Context 'By parameters' { BeforeAll { - $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text' $body = 'Comment body' } @@ -94,7 +94,7 @@ try Context 'Gist on the pipeline' { BeforeAll { - $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text' $body = 'Comment body' } @@ -180,7 +180,7 @@ try Describe 'New-GitHubGistComment' { BeforeAll { - $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text' $body = 'Comment body' } @@ -219,7 +219,7 @@ try Describe 'New-GitHubGistComment' { BeforeAll { - $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $gist = New-GitHubGist -Filename 'sample.txt' -Content 'Sample text' $body = 'Comment body' $updatedBody = 'Updated comment body' } @@ -288,7 +288,7 @@ try Describe 'Remove-GitHubGistComment' { BeforeAll { - $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text' $body = 'Comment body' } diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1 index 852152e3..cc5df85d 100644 --- a/Tests/GitHubGists.tests.ps1 +++ b/Tests/GitHubGists.tests.ps1 @@ -15,81 +15,438 @@ param() $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent . (Join-Path -Path $moduleRootPath -ChildPath 'Tests\Common.ps1') +filter New-LargeFile +{ +<# + .SYNOPSIS + Creates a large dummy file with random conntent + + .DESCRIPTION + Creates a large dummy file with random conntent + Credits for the random content creation logic goes to Robert Robelo + + .PARAMETER Path + The full path to the file to create. + + .PARAMETER SizeMB + The size of the random file to be genrated. Default is one MB + + .PARAMETER Type + The type of file should be created. + + .PARAMETER Force + Will allow this to overwrite the target file if it already exists. + + .EXAMPLE + New-LargeFile -Path C:\Temp\LF\bigfile.txt -SizeMB 10 +#> + + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(ValueFromPipeline)] + [String] $Path, + + [ValidateRange(1, 5120)] + [UInt16] $SizeMB = 1, + + [ValidateSet('Text', 'Binary')] + [string] $Type = 'Text', + + [switch] $Force + ) + + $tempFile = New-TemporaryFile + + if ($Type -eq 'Text') + { + $streamWriter = New-Object -TypeName IO.StreamWriter -ArgumentList ($tempFile) + try + { + # get a 64 element Char[]; I added the - and \n to have 64 chars + [char[]]$chars = 'azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789-\n' + 1..$SizeMB | ForEach-Object { + # get 1MB of chars from 4 256KB strings + 1..4 | ForEach-Object { + $randomizedChars = $chars | Get-Random -Count $chars.Count + + # repeat random string 4096 times to get a 256KB string + $output = (-join $randomizedChars) * 4kb + + # write 256KB string to file + $streamWriter.Write($output) + + # release resources + Clear-Variable -Name @('randomizedChars', 'output') + } + } + } + catch + { + Remove-File -Path $tempFile -ErrorAction SilentlyContinue + } + finally + { + $streamWriter.Close() + $streamWriter.Dispose() + + # Force the immediate garbage collection of allocated resources + [GC]::Collect() + } + } + else + { + $content = New-Object -TypeName Byte[] -ArgumentList ($SizeMB * 1mb) + (New-Object -TypeName Random).NextBytes($content) + [IO.File]::WriteAllBytes($tempFile, $content) + } + + try + { + if ($PSBoundParameters.ContainsKey('Path')) + { + return (Move-Item -Path $tempFile -Destination $Path -Force:$Force) + } + else + { + return (Get-Item -Path $tempFile) + } + } + catch + { + Remove-File -Path $tempFile -ErrorAction SilentlyContinue + } +} + try { Describe 'Get-GitHubGist' { Context 'Specific Gist' { + $id = '0831f3fbd83ac4d46451' # octocat/git-author-rewrite.sh + $gist = Get-GitHubGist -Gist $id + It 'Should be the expected gist' { + $gist.id | Should -Be $id + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + $gist.history[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistCommit' + $gist.forks[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistFork' + } + + $gist = $gist | Get-GitHubGist + It 'Should be the expected gist with the gist on the pipeline' { + $gist.id | Should -Be $id + } } - Context 'Specific Gist with Sha' { + Context 'Commits and specific Gist with Sha' { + $id = '0831f3fbd83ac4d46451' # octocat/git-author-rewrite.sh + + $gist = Get-GitHubGist -Gist $id + $commits = Get-GitHubGist -Gist $gist.id -Commits + + It 'Should have multiple commits' { + $commits.Count | Should -BeGreaterThan 1 + } + + It 'Should have the expected type and additional properties' { + foreach ($commit in $commits) + { + $commit.PSObject.TypeNames[0] | Should -Be 'GitHub.GistCommit' + $commit.GistId | Should -Be $gist.id + $commit.Sha | Should -Be $commit.version + $commit.user.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + $oldestSha = $commits | Sort-Object -Property 'committed_at' | Select-Object -First 1 + + $firstGistCommit = Get-GitHubGist -Gist $gist.id -Sha $oldestSha.version + It 'Should be the expected commit' { + $firstGistCommit.created_at | Should -Be $oldestSha.committed_at + } + + It 'Should have the expected type and additional properties' { + $firstGistCommit.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $firstGistCommit.GistId | Should -Be $firstGistCommit.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + $gist.history[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistCommit' + $gist.forks[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistFork' + } + + It 'Should fail if we specify Sha _and_ Commits' { + { Get-GitHubGist -Gist $gist.id -Commits -Sha $oldestSha.version } | Should -Throw + } + + It 'Should fail if we specify Sha _and_ Forks' { + { Get-GitHubGist -Gist $gist.id -Forks -Sha $oldestSha.version } | Should -Throw + } + + $firstGistCommit = $gist | Get-GitHubGist -Sha $oldestSha.version + It 'Should be the expected gist commit with the gist on the pipeline' { + $firstGistCommit.created_at | Should -Be $oldestSha.committed_at + } + + $firstGistCommit = $firstGistCommit | Get-GitHubGist + It 'Should be the expected gist commit with the gist commit on the pipeline' { + $firstGistCommit.created_at | Should -Be $oldestSha.committed_at + } } Context 'Forks' { - # Make sure you check for error when Sha specified - } + $id = '0831f3fbd83ac4d46451' # octocat/git-author-rewrite.sh + + $gist = Get-GitHubGist -Gist $id + $forks = Get-GitHubGist -Gist $gist.id -Forks + + It 'Should have multiple forks' { + $forks.Count | Should -BeGreaterThan 1 + } + + It 'Should have the expected type and additional properties' { + foreach ($fork in $forks) + { + $fork.PSObject.TypeNames[0] | Should -Be 'GitHub.GistFork' + $fork.GistId | Should -Be $fork.id + $fork.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + $forks = $gist | Get-GitHubGist -Forks - Context 'Commits' { - # Make sure you check for error when Sha specified + It 'Should have multiple forks when gist is on the pipeline' { + $forks.Count | Should -BeGreaterThan 1 + } } Context 'All gists for a specific user' { - } + $username = 'octocat' + $gists = Get-GitHubGist -UserName $username - Context 'All starred gists for a specific user' { + It 'Should have multiple gists' { + $gists.Count | Should -BeGreaterThan 1 + } + + It 'Should have the expected type and additional properties' { + foreach ($gist in $gists) + { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + $since = (Get-Date -Date '01/01/2016') + $sinceGists = Get-GitHubGist -UserName $username -Since $since + It 'Should have fewer results with using the since parameter' { + $sinceGists.Count | Should -BeGreaterThan 0 + $sinceGists.Count | Should -BeLessThan $gists.Count + } } Context 'All gists for the current authenticated user' { + $gist = New-GitHubGist -Filename 'sample.txt' -Content 'Sample text' + $gists = @(Get-GitHubGist) + It 'Should at least one gist including the one just created' { + $gists.Count | Should -BeGreaterOrEqual 1 + $gists.id | Should -Contain $gist.id + } + + It 'Should have the expected type and additional properties' { + foreach ($gist in $gists) + { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + It 'Should be removed' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } } Context 'All gists for the current authenticated user, but not authenticated' { + # This would just be testing that an exception is thrown. + # There's no easy way to cover unauthenticated sessions in the UT's, + # so we'll just accept the lower code coverage here. + } + + Context 'All starred gists for the current authenticated user' { + $id = '0831f3fbd83ac4d46451' # octocat/git-author-rewrite.sh + Add-GitHubGistStar -Gist $id + + $gists = @(Get-GitHubGist -Starred) + It 'Should include the one we just starred' { + $gists.Count | Should -BeGreaterOrEqual 1 + $gists.id | Should -Contain $id + } + + Remove-GitHubGistStar -Gist $id } Context 'All starred gists for the current authenticated user, but not authenticated' { + # This would just be testing that an exception is thrown. + # There's no easy way to cover unauthenticated sessions in the UT's, + # so we'll just accept the lower code coverage here. } Context 'All public gists' { + # This would require 100 queries, taking over 2 minutes. + # Given the limited additional value that we'd get from this additional test relative + # to the time it would take to execute, we'll just accept the lower code coverage here. } } - Describe 'Get-GitHubGist' { - Context 'By files' { + Describe 'Get-GitHubGist/Download' { + BeforeAll { + # To get access to New-TemporaryDirectory + $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent + . (Join-Path -Path $moduleRootPath -ChildPath 'Helpers.ps1') + $tempPath = New-TemporaryDirectory + } + + AfterAll { + Remove-Item -Path $tempPath -Recurse -ErrorAction SilentlyContinue -Force + } + + Context 'Download gist content' { BeforeAll { $tempFile = New-TemporaryFile $fileA = "$($tempFile.FullName).ps1" Move-Item -Path $tempFile -Destination $fileA - Out-File -FilePath $fileA -InputObject "fileA content" -Encoding utf8 + $fileAName = (Get-Item -Path $fileA).Name + $fileAContent = 'fileA content' + Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8 $tempFile = New-TemporaryFile $fileB = "$($tempFile.FullName).txt" Move-Item -Path $tempFile -Destination $fileB - Out-File -FilePath $fileB -InputObject "fileB content" -Encoding utf8 + $fileBName = (Get-Item -Path $fileB).Name + $fileBContent = 'fileB content' + Out-File -FilePath $fileB -InputObject $fileBContent -Encoding utf8 - $description = 'my description' + $tempFile = New-LargeFile -SizeMB 1 + $twoMegFile = "$($tempFile.FullName).bin" + Move-Item -Path $tempFile -Destination $twoMegFile + $twoMegFileName = (Get-Item -Path $twoMegFile).Name + + $gist = @($fileA, $fileB, $twoMegFile) | New-GitHubGist } AfterAll { - @($fileA, $fileB) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + $gist | Remove-GitHubGist -Force + @($fileA, $fileB, $twoMegFile) | + Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null } - $gist = New-GitHubGist -File $fileA -Description $description -Public - It 'Should have the expected result' { + It 'Should have no files at the download path' { + @(Get-ChildItem -Path $tempPath).Count | Should -Be 0 + } + Get-GitHubGist -Gist $gist.id -Path $tempPath + It 'Should download all of the files' { + @(Get-ChildItem -Path $tempPath).Count | Should -Be 3 + [System.IO.File]::ReadAllText($fileA).Trim() | + Should -Be ([System.IO.File]::ReadAllText((Join-Path -Path $tempPath -ChildPath $fileAName)).Trim()) + [System.IO.File]::ReadAllText($fileB).Trim() | + Should -Be ([System.IO.File]::ReadAllText((Join-Path -Path $tempPath -ChildPath $fileBName)).Trim()) + (Get-FileHash -Path $twoMegFile).Hash | + Should -Be (Get-FileHash -Path (Join-Path -Path $tempPath -ChildPath $twoMegFileName)).Hash } - It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' - $gist.GistId | Should -Be $gist.id - $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + $gist | Get-GitHubGist -Path $tempPath -Force + It 'Should download all of the files with the gist on the pipeline and -Force' { + @(Get-ChildItem -Path $tempPath).Count | Should -Be 3 + [System.IO.File]::ReadAllText($fileA).Trim() | + Should -Be ([System.IO.File]::ReadAllText((Join-Path -Path $tempPath -ChildPath $fileAName)).Trim()) + [System.IO.File]::ReadAllText($fileB).Trim() | + Should -Be ([System.IO.File]::ReadAllText((Join-Path -Path $tempPath -ChildPath $fileBName)).Trim()) + (Get-FileHash -Path $twoMegFile).Hash | + Should -Be (Get-FileHash -Path (Join-Path -Path $tempPath -ChildPath $twoMegFileName)).Hash } } - } - Describe 'Remove-GitHubGist' { - Context 'By files' { + Context 'More than 300 files' { BeforeAll { + $files = @() + 1..301 | ForEach-Object { + $tempFile = New-TemporaryFile + $file = "$($tempFile.FullName)-$_.ps1" + Move-Item -Path $tempFile -Destination $file + $fileContent = "file-$_ content" + Out-File -FilePath $file -InputObject $fileContent -Encoding utf8 + $files += $file + } } AfterAll { + $files | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + # Marking this test to skip. It works just fine, but takes 26 second to execute. + # Not worth it for the moderate improvement to code coverage. + It 'Should throw an exception because there are too many files' -Skip:(-not ([string]::IsNullOrEmpty($env:ciAccessToken))) { + $gist = $files | New-GitHubGist + { $gist | Get-GitHubGist -Path $tempPath -Force } | Should -Throw + $gist | Remove-GitHubGist -Force + } + + } + + Context 'Download gist content' { + BeforeAll { + $tempFile = New-LargeFile -SizeMB 10 + $tenMegFile = "$($tempFile.FullName).bin" + Move-Item -Path $tempFile -Destination $tenMegFile + $tenMegFileName = (Get-Item -Path $tenMegFile).Name + } + + AfterAll { + @($tenMegFile) | + Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + # Marking this test to skip. It works just fine, but takes 82 second to execute. + # Not worth it for the moderate improvement to code coverage. + It 'Should throw an exception because the file is too large to download' -Skip:(-not ([string]::IsNullOrEmpty($env:ciAccessToken))) { + $gist = $tenMegFile | New-GitHubGist + { $gist | Get-GitHubGist -Path $tempPath -Force } | Should -Throw + $gist | Remove-GitHubGist -Force + } + } + } + + Describe 'Remove-GitHubGist' { + Context 'With parameters' { + $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text' + It 'Should be there' { + { Get-GitHubGist -Gist $gist.id } | Should -Not -Throw + } + + It 'Should remove the gist successfully' { + { Remove-GitHubGist -Gist $gist.id -Force } | Should -Not -Throw + } + + It 'Should be removed' { + { Get-GitHubGist -Gist $gist.id } | Should -Throw + } + } + + Context 'With the gist on the pipeline' { + $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text' + It 'Should be there' { + { $gist | Get-GitHubGist } | Should -Not -Throw + } + + It 'Should remove the gist successfully' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + + It 'Should be removed' { + { $gist | Get-GitHubGist } | Should -Throw } } } @@ -148,9 +505,9 @@ try } } - Describe 'Add/Remove/Test-GitHubGistStar' { + Describe 'Add/Remove/Set/Test-GitHubGistStar' { BeforeAll { - $gist = New-GitHubGist -Content 'Sample text' -Filename 'sample.txt' + $gist = New-GitHubGist -FileName 'sample.txt' -Content 'Sample text' } AfterAll { @@ -165,18 +522,25 @@ try Add-GitHubGistStar -Gist $gist.id $starred = Test-GitHubGistStar -Gist $gist.id - It 'Should now be starred yet' { + It 'Should now be starred' { $starred | Should -BeTrue } + Remove-GitHubGistStar -Gist $gist.id $starred = Test-GitHubGistStar -Gist $gist.id - It 'Should not be starred yet' { + It 'Should no longer be starred' { + $starred | Should -BeFalse + } + + Set-GitHubGistStar -Gist $gist.id -Star + $starred = Test-GitHubGistStar -Gist $gist.id + It 'Should now be starred' { $starred | Should -BeTrue } - Remove-GitHubGistStar -Gist $gist.id + Set-GitHubGistStar -Gist $gist.id $starred = Test-GitHubGistStar -Gist $gist.id - It 'Should no longer be starred yet' { + It 'Should no longer be starred' { $starred | Should -BeFalse } } @@ -189,39 +553,626 @@ try $gist | Add-GitHubGistStar $starred = $gist | Test-GitHubGistStar - It 'Should now be starred yet' { + It 'Should now be starred' { $starred | Should -BeTrue } + $gist | Remove-GitHubGistStar + $starred = $gist | Test-GitHubGistStar + It 'Should no longer be starred' { + $starred | Should -BeFalse + } + + $gist | Set-GitHubGistStar -Star $starred = $gist | Test-GitHubGistStar - It 'Should not be starred yet' { + It 'Should now be starred' { $starred | Should -BeTrue } - $gist | Remove-GitHubGistStar + $gist | Set-GitHubGistStar $starred = $gist | Test-GitHubGistStar - It 'Should no longer be starred yet' { + It 'Should no longer be starred' { $starred | Should -BeFalse } } } Describe 'New-GitHubGist' { + Context 'By content' { + BeforeAll { + $content = 'This is my content' + $filename = 'sample.txt' + $description = 'my description' + } + + $gist = New-GitHubGist -FileName $filename -Content $content -Public + It 'Should have the expected result' { + $gist.public | Should -BeTrue + $gist.description | Should -BeNullOrEmpty + $gist.files.$filename.content | Should -Be $content + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + It 'Should be removed' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + + $gist = New-GitHubGist -FileName $filename -Content $content -Description $description -Public:$false + It 'Should have the expected result' { + $gist.public | Should -BeFalse + $gist.description | Should -Be $description + $gist.files.$filename.content | Should -Be $content + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + It 'Should error if file starts with "gistfile"' { + { New-GitHubGist -FileName 'gistfile1' -Content $content } | Should -Throw + } + + It 'Should be removed' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + } + Context 'By files' { BeforeAll { + $tempFile = New-TemporaryFile + $fileA = "$($tempFile.FullName).ps1" + Move-Item -Path $tempFile -Destination $fileA + $fileAName = (Get-Item -Path $fileA).Name + $fileAContent = 'fileA content' + Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8 + + $tempFile = New-TemporaryFile + $fileB = "$($tempFile.FullName).txt" + Move-Item -Path $tempFile -Destination $fileB + $fileBName = (Get-Item -Path $fileB).Name + $fileBContent = 'fileB content' + Out-File -FilePath $fileB -InputObject $fileBContent -Encoding utf8 + + $description = 'my description' } AfterAll { + @($fileA, $fileB) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + $gist = New-GitHubGist -File @($fileA, $fileB) -Public + It 'Should have the expected result' { + $gist.public | Should -BeTrue + $gist.description | Should -BeNullOrEmpty + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent + $gist.files.$fileBName.content.Trim() | Should -Be $fileBContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + It 'Should be removed' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + + $gist = New-GitHubGist -File @($fileA, $fileB) -Description $description -Public:$false + It 'Should have the expected result' { + $gist.public | Should -BeFalse + $gist.description | Should -Be $description + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent + $gist.files.$fileBName.content.Trim() | Should -Be $fileBContent + } + + It 'Should be removed' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + + $gist = @($fileA, $fileB) | New-GitHubGist -Description $description -Public:$false + It 'Should have the expected result with the files on the pipeline' { + $gist.public | Should -BeFalse + $gist.description | Should -Be $description + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent + $gist.files.$fileBName.content.Trim() | Should -Be $fileBContent } } } Describe 'Set-GitHubGist' { - Context 'By files' { + BeforeAll { + $fileAName = 'foo.txt' + $fileAContent = 'foo content' + $fileAUpdatedContent = 'foo updated content' + $fileANewName = 'gamma.txt' + + $fileBName = 'bar.txt' + $fileBContent = 'bar content' + $fileBUpdatedContent = 'bar updated content' + + $fileCName = 'alpha.txt' + $fileCContent = 'alpha content' + $fileCUpdatedContent = 'alpha updated content' + $fileCNewName = 'gamma.txt' + + $tempFile = New-TemporaryFile + $fileD = "$($tempFile.FullName).txt" + Move-Item -Path $tempFile -Destination $fileD + $fileDName = (Get-Item -Path $fileD).Name + $fileDContent = 'fileD content' + Out-File -FilePath $fileD -InputObject $fileDContent -Encoding utf8 + $fileDUpdatedContent = 'fileD updated content' + + $description = 'my description' + $updatedDescription = 'updated description' + } + + AfterAll { + @($fileD) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + Context 'With parameters' { + BeforeAll { + $gist = New-GitHubGist -FileName $fileAName -Content $fileAContent -Description $description + } + + AfterAll { + $gist | Remove-GitHubGist -Force + } + + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $fileBName -Content $fileBContent + It 'Should be in the expected, original state' { + $gist.description | Should -Be $description + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$fileAName.content | Should -Be $fileAContent + $gist.files.$fileBName.content | Should -Be $fileBContent + } + + $setParams = @{ + Gist = $gist.id + Description = $updatedDescription + Delete = @($fileBName) + Update = @{ + $fileAName = @{ + fileName = $fileANewName + content = $fileAUpdatedContent + } + $fileCName = @{ content = $fileCContent } + $fileDName = @{ filePath = $fileD } + } + } + + $gist = Set-GitHubGist @setParams -Force + It 'Should have been properly updated' { + $gist.description | Should -Be $updatedDescription + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 3 + $gist.files.$fileAName | Should -BeNullOrEmpty + $gist.files.$fileANewName.content | Should -Be $fileAContent + $gist.files.$fileBName | Should -BeNullOrEmpty + $gist.files.$fileCName.content | Should -Be $fileCContent + $gist.files.$fileDName.content.Trim() | Should -Be $fileDContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $setParams = @{ + Gist = $gist.id + Update = @{ + $fileDName = @{ + content = 'updated content' + filePath = $fileD + } + } + } + + It 'Should throw if updating a file with both a filePath and content' { + { $gist = Set-GitHubGist @setParams } | Should -Throw + } + } + + Context 'With the gist on the pipeline' { + BeforeAll { + $gist = New-GitHubGist -FileName $fileAName -Content $fileAContent -Description $description + } + + AfterAll { + $gist | Remove-GitHubGist -Force + } + + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $fileBName -Content $fileBContent + It 'Should be in the expected, original state' { + $gist.description | Should -Be $description + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$fileAName.content | Should -Be $fileAContent + $gist.files.$fileBName.content | Should -Be $fileBContent + } + + $setParams = @{ + Description = $updatedDescription + Delete = @($fileBName) + Update = @{ + $fileAName = @{ + fileName = $fileANewName + content = $fileAUpdatedContent + } + $fileCName = @{ content = $fileCContent } + $fileDName = @{ filePath = $fileD } + } + } + + $gist = $gist | Set-GitHubGist @setParams -Confirm:$false + It 'Should have been properly updated' { + $gist.description | Should -Be $updatedDescription + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 3 + $gist.files.$fileAName | Should -BeNullOrEmpty + $gist.files.$fileANewName.content | Should -Be $fileAContent + $gist.files.$fileBName | Should -BeNullOrEmpty + $gist.files.$fileCName.content | Should -Be $fileCContent + $gist.files.$fileDName.content.Trim() | Should -Be $fileDContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $setParams = @{ + Update = @{ + $fileDName = @{ + content = 'updated content' + filePath = $fileD + } + } + } + + It 'Should throw if updating a file with both a filePath and content' { + { $gist = $gist | Set-GitHubGist @setParams } | Should -Throw + } + } + } + + Describe 'Set-GitHubGistFile' { + BeforeAll { + $origFileName = 'foo.txt' + $origContent = 'original content' + $updatedOrigContent = 'updated content' + + $newFileName = 'bar.txt' + $newContent = 'new content' + + $gist = New-GitHubGist -FileName $origFileName -Content $origContent + } + + AfterAll { + $gist | Remove-GitHubGist -Force + } + + Context 'By content with parameters' { + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $updatedOrigContent + It 'Should have the expected result' { + $gist.files.$origFileName.content | Should -Be $updatedOrigContent + $gist.files.$newFileName | Should -BeNullOrEmpty + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $newFileName -Content $newContent + It 'Should have the expected result' { + $gist.files.$origFileName.content | Should -Be $updatedOrigContent + $gist.files.$newFileName.content | Should -Be $newContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent + It 'Should remove the new file' { + { $gist | Remove-GitHubGistFile -FileName $newFileName -Force } | Should -Not -Throw + } + } + + Context 'By content with the gist on the pipeline' { + $gist = $gist | Set-GitHubGistFile -FileName $origFileName -Content $updatedOrigContent + It 'Should have the expected result' { + $gist.files.$origFileName.content | Should -Be $updatedOrigContent + $gist.files.$newFileName | Should -BeNullOrEmpty + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $gist = $gist | Set-GitHubGistFile -FileName $newFileName -Content $newContent + It 'Should have the expected result' { + $gist.files.$origFileName.content | Should -Be $updatedOrigContent + $gist.files.$newFileName.content | Should -Be $newContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent + It 'Should remove the new file' { + { $gist | Remove-GitHubGistFile -FileName $newFileName -Force } | Should -Not -Throw + } + } + + Context 'By files with parameters' { + BeforeAll { + $tempFile = New-TemporaryFile + $fileA = "$($tempFile.FullName).txt" + Move-Item -Path $tempFile -Destination $fileA + $fileAName = (Get-Item -Path $fileA).Name + $fileAContent = 'fileA content' + Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8 + $fileAUpdatedContent = 'fileA content updated' + } + + AfterAll { + @($fileA) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + $gist = Set-GitHubGistFile -Gist $gist.id -File $fileA + It 'Should have the expected result' { + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$origFileName.content | Should -Be $origContent + $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + Out-File -FilePath $fileA -InputObject $fileAUpdatedContent -Encoding utf8 + $gist = Set-GitHubGistFile -Gist $gist.id -File $fileA + It 'Should have the expected result' { + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$origFileName.content | Should -Be $origContent + $gist.files.$fileAName.content.Trim() | Should -Be $fileAUpdatedContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent + It 'Should remove the new file' { + { $gist | Remove-GitHubGistFile -FileName $fileAName -Force } | Should -Not -Throw + } + } + + Context 'By files with the gist on the pipeline' { + BeforeAll { + $tempFile = New-TemporaryFile + $fileA = "$($tempFile.FullName).txt" + Move-Item -Path $tempFile -Destination $fileA + $fileAName = (Get-Item -Path $fileA).Name + $fileAContent = 'fileA content' + Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8 + $fileAUpdatedContent = 'fileA content updated' + } + + AfterAll { + @($fileA) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + $gist = $gist | Set-GitHubGistFile -File $fileA + It 'Should have the expected result' { + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$origFileName.content | Should -Be $origContent + $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + Out-File -FilePath $fileA -InputObject $fileAUpdatedContent -Encoding utf8 + $gist = $gist | Set-GitHubGistFile -File $fileA + It 'Should have the expected result' { + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$origFileName.content | Should -Be $origContent + $gist.files.$fileAName.content.Trim() | Should -Be $fileAUpdatedContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent + It 'Should remove the new file' { + { $gist | Remove-GitHubGistFile -FileName $fileAName -Force } | Should -Not -Throw + } + } + + Context 'By files with the file on the pipeline' { BeforeAll { + $tempFile = New-TemporaryFile + $fileA = "$($tempFile.FullName).txt" + Move-Item -Path $tempFile -Destination $fileA + $fileAName = (Get-Item -Path $fileA).Name + $fileAContent = 'fileA content' + Out-File -FilePath $fileA -InputObject $fileAContent -Encoding utf8 + $fileAUpdatedContent = 'fileA content updated' } AfterAll { + @($fileA) | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null + } + + $gist = $fileA | Set-GitHubGistFile -Gist $gist.id + It 'Should have the expected result' { + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$origFileName.content | Should -Be $origContent + $gist.files.$fileAName.content.Trim() | Should -Be $fileAContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + Out-File -FilePath $fileA -InputObject $fileAUpdatedContent -Encoding utf8 + $gist = $fileA | Set-GitHubGistFile -Gist $gist.id + It 'Should have the expected result' { + ($gist.files | Get-Member -Type NoteProperty).Count | Should -Be 2 + $gist.files.$origFileName.content | Should -Be $origContent + $gist.files.$fileAName.content.Trim() | Should -Be $fileAUpdatedContent + } + + It 'Should have the expected type and additional properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + $gist = Set-GitHubGistFile -Gist $gist.id -FileName $origFileName -Content $origContent + It 'Should remove the new file' { + { $gist | Remove-GitHubGistFile -FileName $fileAName -Force } | Should -Not -Throw + } + } + } + + Describe 'Rename-GitHubGistFile' { + BeforeAll { + $originalName = 'foo.txt' + $newName = 'bar.txt' + $content = 'sample content' + } + + Context 'With parameters' { + $gist = New-GitHubGist -FileName $originalName -Content $content + It 'Should have the expected file' { + $gist.files.$originalName.content | Should -Be $content + $gist.files.$newName | Should -BeNullOrEmpty + } + + $gist = Rename-GitHubGistFile -Gist $gist.id -FileName $originalName -NewName $newName + It 'Should have been renamed' { + $gist.files.$originalName | Should -BeNullOrEmpty + $gist.files.$newName.content | Should -Be $content + } + + It 'Should have the expected additional type and properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + It 'Should successfully remove the gist' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + } + + Context 'With the gist on the pipeline' { + $gist = New-GitHubGist -FileName $originalName -Content $content + It 'Should have the expected file' { + $gist.files.$originalName.content | Should -Be $content + $gist.files.$newName | Should -BeNullOrEmpty + } + + $gist = $gist | Rename-GitHubGistFile -FileName $originalName -NewName $newName + It 'Should have been renamed' { + $gist.files.$originalName | Should -BeNullOrEmpty + $gist.files.$newName.content | Should -Be $content + } + + It 'Should have the expected additional type and properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + It 'Should successfully remove the gist' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + } + } + + Describe 'Remove-GitHubGistFile' { + BeforeAll { + $fileName = 'sample.txt' + $content = 'sample' + } + + Context 'With parameters' { + $gist = New-GitHubGist -FileName $fileName -Content $content + It 'Should have the expected file' { + $gist.files.$fileName | Should -Not -BeNullOrEmpty + } + + $gist = Remove-GitHubGistFile -Gist $gist.id -FileName $fileName -Force + It 'Should have been removed' { + $gist.files.$fileName | Should -BeNullOrEmpty + } + + It 'Should have the expected additional type and properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + It 'Should successfully remove the gist' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw + } + } + + Context 'With the gist on the pipeline' { + $gist = New-GitHubGist -FileName $fileName -Content $content + It 'Should have the expected file' { + $gist.files.$fileName | Should -Not -BeNullOrEmpty + } + + $gist = $gist | Remove-GitHubGistFile -FileName $fileName -Confirm:$false + It 'Should have been removed' { + $gist.files.$fileName | Should -BeNullOrEmpty + } + + It 'Should have the expected additional type and properties' { + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.GistId | Should -Be $gist.id + $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + + It 'Should successfully remove the gist' { + { $gist | Remove-GitHubGist -Force } | Should -Not -Throw } } } From 1f3ad37fee1b4dc3cbff1843a342c98f00741870 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Tue, 14 Jul 2020 16:57:43 -0700 Subject: [PATCH 11/15] Unskipping tests, fixing CommentId type --- GitHubGistComments.ps1 | 8 ++++---- Tests/GitHubGists.tests.ps1 | 14 ++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/GitHubGistComments.ps1 b/GitHubGistComments.ps1 index 08b069f6..283b10a3 100644 --- a/GitHubGistComments.ps1 +++ b/GitHubGistComments.ps1 @@ -71,10 +71,10 @@ filter Get-GitHubGistComment [Parameter(ValueFromPipelineByPropertyName)] [Alias('GistCommentId')] [ValidateNotNullOrEmpty()] - [string] $Comment, + [int64] $Comment, [ValidateSet('Raw', 'Text', 'Html', 'Full')] - [string] $MediaType = 'Raw', + [string] $MediaType = 'Full', [string] $AccessToken, @@ -187,7 +187,7 @@ filter Remove-GitHubGistComment Position = 2)] [Alias('GistCommentId')] [ValidateNotNullOrEmpty()] - [string] $Comment, + [int64] $Comment, [switch] $Force, @@ -371,7 +371,7 @@ filter Set-GitHubGistComment Position = 2)] [Alias('GistCommentId')] [ValidateNotNullOrEmpty()] - [string] $Comment, + [int64] $Comment, [Parameter( Mandatory, diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1 index cc5df85d..a1ac628e 100644 --- a/Tests/GitHubGists.tests.ps1 +++ b/Tests/GitHubGists.tests.ps1 @@ -386,9 +386,10 @@ try $files | Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null } - # Marking this test to skip. It works just fine, but takes 26 second to execute. - # Not worth it for the moderate improvement to code coverage. - It 'Should throw an exception because there are too many files' -Skip:(-not ([string]::IsNullOrEmpty($env:ciAccessToken))) { + # May want to consider skipping this test. + # It works just fine, but takes 26 second to execute. + # (May not be worth it for the moderate improvement to code coverage.) + It 'Should throw an exception because there are too many files' { $gist = $files | New-GitHubGist { $gist | Get-GitHubGist -Path $tempPath -Force } | Should -Throw $gist | Remove-GitHubGist -Force @@ -409,9 +410,10 @@ try Remove-Item -Force -ErrorAction SilentlyContinue | Out-Null } - # Marking this test to skip. It works just fine, but takes 82 second to execute. - # Not worth it for the moderate improvement to code coverage. - It 'Should throw an exception because the file is too large to download' -Skip:(-not ([string]::IsNullOrEmpty($env:ciAccessToken))) { + # May want to consider skipping this test. + # It works just fine, but takes 26 second to execute. + # (May not be worth it for the moderate improvement to code coverage.) + It 'Should throw an exception because the file is too large to download' { $gist = $tenMegFile | New-GitHubGist { $gist | Get-GitHubGist -Path $tempPath -Force } | Should -Throw $gist | Remove-GitHubGist -Force From 2fd05402a7d5b6b9763e3b40dd71dc4dc96009dd Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Tue, 14 Jul 2020 17:13:42 -0700 Subject: [PATCH 12/15] Add USAGE documentation --- USAGE.md | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/USAGE.md b/USAGE.md index 8e93a1c5..456c0186 100644 --- a/USAGE.md +++ b/USAGE.md @@ -97,6 +97,18 @@ * [Create a release asset](#create-a-release-asset) * [Update a release asset](#update-a-release-asset) * [Remove a release asset](#remove-a-release-asset) + * [Gists](#gists) + * [Getting gists](#getting-gists) + * [Download a gist](#download-a-gist) + * [Fork a gist](#fork-a-gist) + * [Creating a gist](#creating-a-gist) + * [Removing a gist](#removing-a-gist) + * [Updating a gist](#updating-a-gist) + * [Starring a gist](#starring-a-gist) + * [Getting gist comments](#getting-gist-comments) + * [Adding a gist comment](#adding-a-gist-comment) + * [Changing a gist comment](#changing-a-gist-comment) + * [Removing a gist comment](#removing-a-gist-comment) * [Advanced](#advanced) * [Migrating blog comments to GitHub issues](#migrating-blog-comments-to-github-issues) @@ -869,6 +881,169 @@ or with pipelining... ```powershell $asset | Remove-GitHubReleaseAsset -force + +---------- + +### Gists + +#### Getting gists +```powershell +# There are many options here: + +# 1. Getting all gists for the current authenticated user: +Get-GitHubGist + +# 1b. Getting all gists for the current authenticated user that were updated in the past 6 days. +Get-GitHubGist -Since ((Get-Date).AddDays(-6)) + +# 2. Get all starred gists for the current authenticated user +Get-GitHubGist -Starred + +# 3. Get all public gists for a specific user +Get-GitHubGist -UserName 'octocat' + +# 4. Get all public gists (well, the first 3000): +Get-GitHubGist -Public + +# 5. Get a specific gist +Get-GitHubGist -Gist '6cad326836d38bd3a7ae' + +# 5a. List all commits for a specific gist +Get-GitHubGist -Gist '6cad326836d38bd3a7ae' -Commits + +# 5b. Get a gist at a specific commit (Sha) +Get-GitHubGist -Gist '6cad326836d38bd3a7ae' -Sha 'de5b9b59d1f28206e8d646c7c8025e9809d0ed73' + +# 5c. Get all of the forks for a gist +Get-GitHubGist -Gist '6cad326836d38bd3a7ae' -Forks +``` + +#### Download a gist +```powershell +Get-GitHubGist -Gist '6cad326836d38bd3a7ae' -Path 'c:\users\octocat\downloads\gist\' +``` + +#### Fork a gist +```powershell +Fork-GitHubGist -Gist '6cad326836d38bd3a7ae' +``` + +#### Creating a gist +```powershell +# You can create a gist by specifying a single file's content in-line... +New-GitHubGist -FileName 'foo.txt' -Content 'foo content' + +# or by providing one or more files that should be part of the gist +New-GitHubGist -File @('c:\files\foo.txt', 'c:\files\bar.txt') +@('c:\files\foo.txt', 'c:\files\bar.txt') | New-GitHubGist +``` + +#### Removing a gist +```powershell +Remove-GitHubGist -Gist '6cad326836d38bd3a7ae' +``` + +#### Updating a gist +```powershell +$gist = New-GitHubGist -FileName 'foo.txt' -Content 'content' + +# The main method to use is Set-GitHubGist, however it is quite complicated. +$params = @{ + Description = 'new description' # modifies the description of the gist + Update = @{ + 'foo.txt' = @{ + fileName = 'alpha.txt' # Will rename foo.txt -> alpha.txt + content = 'updated content' # and will also update its content + } + 'bar.txt' = @{ + filePath = 'c:\files\bar.txt' # Will upload the content of bar.txt to the gist. + } + } + Delete = @('bar.txt') + Force = $true # avoid confirmation prompting due to the deletion +} + +Set-GitHubGist -Gist $gist.id @params + +# Therefore, you can use simpler helper methods to accomplish atomic tasks +Set-GistHubGistFile -Gist $gist.id -FileName 'foo.txt' -Content 'updated content' + +# This will update the text in the existing file 'foo.txt' and add the file 'bar.txt' +$gist | Set-GitHubGistFile -File ('c:\files\foo.txt', 'c:\files\bar.txt') + +Rename-GistHubGistFile -Gist $gist.id -FileName 'foo.txt' -NewName 'bar.txt' + +$gist | Remove-GitHubGistFile -FileName 'bar.txt' -Force + +``` + +#### Starring a gist +```powershell +$gistId = '6cad326836d38bd3a7ae' + +# All of these options will star the same gist +Star-GitHubGist -Gist $gistId +Add-GitHubGistStar -Gist $gistId +Set-GitHubGistStar -Gist $gistId -Star +Get-GitHubGist -Gist $gistId | Star-GitHubGist + +# All of these options will unstar the same gist +Unstar-GitHubGist -Gist $gistId +Remove-GitHubGistStar -Gist $gistId +Set-GitHubGistStar -Gist $gistId +Set-GitHubGistStar -Gist $gistId -Star:$false +Get-GitHubGist -Gist $gistId | Unstar-GitHubGist + +# All of these options will tell you if you have starred a gist +Test-GitHubGistStar -Gist $gistId +Get-GitHubGist -Gist $gistId | Test-GitHubGistStar +``` + +#### Getting gist comments +```powershell +$gistId = '6cad326836d38bd3a7ae' +$commentId = 1507813 + +# You can get all comments for a gist with any of these options: +Get-GitHubGistComment -Gist $gistId +Get-GitHubGist -Gist $gistId | Get-GitHubGistComment + +# You can retrieve an individual comment like this: +Get-GitHubGistComment -Gist $gistId -Comment $commentId +``` + +#### Adding a gist comment +```powershell +$gistId = '6cad326836d38bd3a7ae' + +New-GitHubGistComment -Gist $gistId -Body 'Hello World' + +# or with the pipeline +Get-GitHubGist -Gist $gistId | New-GitHubGistComment -Body 'Hello World' +``` + +#### Changing a gist comment +```powershell +$gistId = '6cad326836d38bd3a7ae' +$commentId = 1507813 + +Set-GitHubGistComment -Gist $gistId -Comment $commentId -Body 'Updated comment' + +# or with the pipeline +Get-GitHubGist -Gist $gistId -Comment $commentId | Set-GitHubGistComment -Body 'Updated comment' +``` + +#### Removing a gist comment +```powershell +$gistId = '6cad326836d38bd3a7ae' +$commentId = 1507813 + +# If you don't specify -Force, it will prompt for confirmation before it will delete the comment + +Remove-GitHubGistComment -Gist $gistId -Comment $commentId -Force + +# or with the pipeline +Get-GitHubGist -Gist $gistId -Comment $commentId | Remove-GitHubGistComment -Force ``` ---------- From bbef392971d38b45caab2b5df7054081905ad521 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sat, 18 Jul 2020 12:25:38 -0700 Subject: [PATCH 13/15] Change typenames: GitHub.Gist/GistDetail -> GistHub.GistSummary/Gist --- GitHubGistComments.ps1 | 16 ++++++++ GitHubGists.ps1 | 73 +++++++++++++++++++------------------ Tests/GitHubGists.tests.ps1 | 50 ++++++++++++------------- 3 files changed, 78 insertions(+), 61 deletions(-) diff --git a/GitHubGistComments.ps1 b/GitHubGistComments.ps1 index 283b10a3..b8d43b31 100644 --- a/GitHubGistComments.ps1 +++ b/GitHubGistComments.ps1 @@ -43,7 +43,11 @@ filter Get-GitHubGistComment If not supplied here, the DefaultNoStatus configuration property value will be used. .INPUTS + GitHub.Gist GitHub.GistComment + GitHub.GistCommit + GitHub.GistFork + GitHub.GistSummary .OUTPUTS GitHub.GistComment @@ -145,7 +149,11 @@ filter Remove-GitHubGistComment If not supplied here, the DefaultNoStatus configuration property value will be used. .INPUTS + GitHub.Gist GitHub.GistComment + GitHub.GistCommit + GitHub.GistFork + GitHub.GistSummary .EXAMPLE Remove-GitHubGist -Gist 6cad326836d38bd3a7ae -Comment 12324567 @@ -250,7 +258,11 @@ filter New-GitHubGistComment If not supplied here, the DefaultNoStatus configuration property value will be used. .INPUTS + GitHub.Gist GitHub.GistComment + GitHub.GistCommit + GitHub.GistFork + GitHub.GistSummary .OUTPUTS GitHub.GistComment @@ -341,7 +353,11 @@ filter Set-GitHubGistComment If not supplied here, the DefaultNoStatus configuration property value will be used. .INPUTS + GitHub.Gist GitHub.GistComment + GitHub.GistCommit + GitHub.GistFork + GitHub.GistSummary .OUTPUTS GitHub.GistComment diff --git a/GitHubGists.ps1 b/GitHubGists.ps1 index 854c1354..d357bc49 100644 --- a/GitHubGists.ps1 +++ b/GitHubGists.ps1 @@ -4,8 +4,8 @@ @{ GitHubGistTypeName = 'GitHub.Gist' GitHubGistCommitTypeName = 'GitHub.GistCommit' - GitHubGistDetailTypeName = 'GitHub.GistDetail' GitHubGistForkTypeName = 'GitHub.GistFork' + GitHubGistSummaryTypeName = 'GitHub.GistSummary' }.GetEnumerator() | ForEach-Object { Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value } @@ -69,14 +69,14 @@ filter Get-GitHubGist GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .OUTPUTS GitHub.Gist GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .EXAMPLE Get-GitHubGist -Starred @@ -98,8 +98,8 @@ filter Get-GitHubGist PositionalBinding = $false)] [OutputType({$script:GitHubGistTypeName})] [OutputType({$script:GitHubGistCommitTypeName})] - [OutputType({$script:GitHubGistDetailTypeName})] [OutputType({$script:GitHubGistForkTypeName})] + [OutputType({$script:GitHubGistSummaryTypeName})] param( [Parameter( Mandatory, @@ -167,7 +167,7 @@ filter Get-GitHubGist $uriFragment = [String]::Empty $description = [String]::Empty - $outputType = $script:GitHubGistTypeName + $outputType = $script:GitHubGistSummaryTypeName if ($PSCmdlet.ParameterSetName -in ('Id', 'Download')) { @@ -186,7 +186,7 @@ filter Get-GitHubGist $uriFragment = "gists/$Gist/$Sha" $description = "Getting gist $Gist with specified Sha" - $outputType = $script:GitHubGistDetailTypeName + $outputType = $script:GitHubGistTypeName } elseif ($Forks) { @@ -204,7 +204,7 @@ filter Get-GitHubGist { $uriFragment = "gists/$Gist" $description = "Getting gist $Gist" - $outputType = $script:GitHubGistDetailTypeName + $outputType = $script:GitHubGistTypeName } } elseif ($PSCmdlet.ParameterSetName -eq 'User') @@ -213,12 +213,12 @@ filter Get-GitHubGist $uriFragment = "users/$UserName/gists" $description = "Getting public gists for $UserName" - $outputType = $script:GitHubGistTypeName + $outputType = $script:GitHubGistSummaryTypeName } elseif ($PSCmdlet.ParameterSetName -eq 'Current') { $telemetryProperties['CurrentUser'] = $true - $outputType = $script:GitHubGistTypeName + $outputType = $script:GitHubGistSummaryTypeName if ((Test-GitHubAuthenticationConfigured) -or (-not [String]::IsNullOrEmpty($AccessToken))) { @@ -250,7 +250,7 @@ filter Get-GitHubGist elseif ($PSCmdlet.ParameterSetName -eq 'Public') { $telemetryProperties['Public'] = $true - $outputType = $script:GitHubGistTypeName + $outputType = $script:GitHubGistSummaryTypeName $uriFragment = "gists/public" $description = 'Getting public gists' @@ -456,8 +456,8 @@ filter Remove-GitHubGist GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .EXAMPLE Remove-GitHubGist -Gist 6cad326836d38bd3a7ae @@ -551,11 +551,11 @@ filter Copy-GitHubGist GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .OUTPUTS - GitHub.Gist + GitHub.GistSummary .EXAMPLE Copy-GitHubGist -Gist 6cad326836d38bd3a7ae @@ -571,7 +571,7 @@ filter Copy-GitHubGist [CmdletBinding( SupportsShouldProcess, PositionalBinding = $false)] - [OutputType({$script:GitHubGistTypeName})] + [OutputType({$script:GitHubGistSummaryTypeName})] [Alias('Fork-GitHubGist')] param( [Parameter( @@ -605,7 +605,8 @@ filter Copy-GitHubGist 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -BoundParameters $PSBoundParameters -Name NoStatus -ConfigValueName DefaultNoStatus) } - return (Invoke-GHRestMethod @params | Add-GitHubGistAdditionalProperties) + return (Invoke-GHRestMethod @params | + Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistSummaryTypeName) } filter Set-GitHubGistStar @@ -640,8 +641,8 @@ filter Set-GitHubGistStar GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .EXAMPLE Set-GitHubGistStar -Gist 6cad326836d38bd3a7ae -Star @@ -720,8 +721,8 @@ filter Add-GitHubGistStar GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .EXAMPLE Add-GitHubGistStar -Gist 6cad326836d38bd3a7ae @@ -801,8 +802,8 @@ filter Remove-GitHubGistStar GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .EXAMPLE Remove-GitHubGistStar -Gist 6cad326836d38bd3a7ae @@ -884,8 +885,8 @@ filter Test-GitHubGistStar GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .OUTPUTS Boolean indicating if the gist was both found and determined to be starred. @@ -1002,7 +1003,7 @@ filter New-GitHubGist SupportsShouldProcess, DefaultParameterSetName='FileRef', PositionalBinding = $false)] - [OutputType({$script:GitHubGistDetailTypeName})] + [OutputType({$script:GitHubGistTypeName})] param( [Parameter( Mandatory, @@ -1107,7 +1108,7 @@ filter New-GitHubGist } return (Invoke-GHRestMethod @params | - Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistDetailTypeName) + Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistTypeName) } } @@ -1159,8 +1160,8 @@ filter Set-GitHubGist GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .OUTPUTS GitHub.GistDetail @@ -1194,7 +1195,7 @@ filter Set-GitHubGist SupportsShouldProcess, DefaultParameterSetName='Content', PositionalBinding = $false)] - [OutputType({$script:GitHubGistDetailTypeName})] + [OutputType({$script:GitHubGistTypeName})] param( [Parameter( Mandatory, @@ -1311,7 +1312,7 @@ filter Set-GitHubGist try { return (Invoke-GHRestMethod @params | - Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistDetailTypeName) + Add-GitHubGistAdditionalProperties -TypeName $script:GitHubGistTypeName) } catch { @@ -1368,11 +1369,11 @@ function Set-GitHubGistFile GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .OUTPUTS - GitHub.GistDetail + GitHub.Gist .EXAMPLE Set-GitHubGistFile -Gist 1234567 -Content 'Body of my file.' -FileName 'sample.txt' @@ -1396,7 +1397,7 @@ function Set-GitHubGistFile SupportsShouldProcess, DefaultParameterSetName='Content', PositionalBinding = $false)] - [OutputType({$script:GitHubGistDetailTypeName})] + [OutputType({$script:GitHubGistTypeName})] [Alias('Add-GitHubGistFile')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")] param( @@ -1514,11 +1515,11 @@ function Remove-GitHubGistFile GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .OUTPUTS - GitHub.GistDetail + GitHub.Gist .EXAMPLE Remove-GitHubGistFile -Gist 1234567 -FileName ('foo.txt') @@ -1538,7 +1539,7 @@ function Remove-GitHubGistFile [CmdletBinding( SupportsShouldProcess, PositionalBinding = $false)] - [OutputType({$script:GitHubGistDetailTypeName})] + [OutputType({$script:GitHubGistTypeName})] [Alias('Delete-GitHubGistFile')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")] param( @@ -1631,11 +1632,11 @@ filter Rename-GitHubGistFile GitHub.Gist GitHub.GistComment GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary .OUTPUTS - GitHub.GistDetail + GitHub.Gist .EXAMPLE Rename-GitHubGistFile -Gist 1234567 -FileName 'foo.txt' -NewName 'bar.txt' @@ -1645,7 +1646,7 @@ filter Rename-GitHubGistFile [CmdletBinding( SupportsShouldProcess, PositionalBinding = $false)] - [OutputType({$script:GitHubGistDetailTypeName})] + [OutputType({$script:GitHubGistTypeName})] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="This is a helper method for Set-GitHubGist which will handle ShouldProcess.")] param( [Parameter( @@ -1704,13 +1705,13 @@ filter Add-GitHubGistAdditionalProperties .OUTPUTS GitHub.Gist GitHub.GistCommit - GitHub.GistDetail GitHub.GistFork + GitHub.GistSummary #> [CmdletBinding()] [OutputType({$script:GitHubGistTypeName})] - [OutputType({$script:GitHubGistDetailTypeName})] [OutputType({$script:GitHubGistFormTypeName})] + [OutputType({$script:GitHubGistSummaryTypeName})] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification="Internal helper that is definitely adding more than one property.")] param( [Parameter( @@ -1721,7 +1722,7 @@ filter Add-GitHubGistAdditionalProperties [PSCustomObject[]] $InputObject, [ValidateNotNullOrEmpty()] - [string] $TypeName = $script:GitHubGistTypeName + [string] $TypeName = $script:GitHubGistSummaryTypeName ) if ($TypeName -eq $script:GitHubGistCommitTypeName) diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1 index a1ac628e..bc59b974 100644 --- a/Tests/GitHubGists.tests.ps1 +++ b/Tests/GitHubGists.tests.ps1 @@ -128,7 +128,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' $gist.history[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistCommit' @@ -169,7 +169,7 @@ try } It 'Should have the expected type and additional properties' { - $firstGistCommit.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $firstGistCommit.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $firstGistCommit.GistId | Should -Be $firstGistCommit.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' $gist.history[0].PSObject.TypeNames[0] | Should -Be 'GitHub.GistCommit' @@ -232,7 +232,7 @@ try It 'Should have the expected type and additional properties' { foreach ($gist in $gists) { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistSummary' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -257,7 +257,7 @@ try It 'Should have the expected type and additional properties' { foreach ($gist in $gists) { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistSummary' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -472,7 +472,7 @@ try } It 'Should have the expected additional type and properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistSummary' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -496,7 +496,7 @@ try } It 'Should have the expected additional type and properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistSummary' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -595,7 +595,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -612,7 +612,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -659,7 +659,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -767,7 +767,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -829,7 +829,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -873,7 +873,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -885,7 +885,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -904,7 +904,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -916,7 +916,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -950,7 +950,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -964,7 +964,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -998,7 +998,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -1012,7 +1012,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -1046,7 +1046,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -1060,7 +1060,7 @@ try } It 'Should have the expected type and additional properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -1093,7 +1093,7 @@ try } It 'Should have the expected additional type and properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -1117,7 +1117,7 @@ try } It 'Should have the expected additional type and properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -1146,7 +1146,7 @@ try } It 'Should have the expected additional type and properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } @@ -1168,7 +1168,7 @@ try } It 'Should have the expected additional type and properties' { - $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.GistDetail' + $gist.PSObject.TypeNames[0] | Should -Be 'GitHub.Gist' $gist.GistId | Should -Be $gist.id $gist.owner.PSObject.TypeNames[0] | Should -Be 'GitHub.User' } From d8517c6fdba74b9dde45654f8a46844751ee2f1d Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sat, 18 Jul 2020 16:24:35 -0700 Subject: [PATCH 14/15] Minor UT fixes --- Tests/GitHubGists.tests.ps1 | 5 ++++- Tests/GitHubRepositories.tests.ps1 | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Tests/GitHubGists.tests.ps1 b/Tests/GitHubGists.tests.ps1 index bc59b974..67e06ccf 100644 --- a/Tests/GitHubGists.tests.ps1 +++ b/Tests/GitHubGists.tests.ps1 @@ -309,7 +309,10 @@ try } AfterAll { - Remove-Item -Path $tempPath -Recurse -ErrorAction SilentlyContinue -Force + if (Get-Variable -Name tempPath -ErrorAction SilentlyContinue) + { + Remove-Item -Path $tempPath -Recurse -ErrorAction SilentlyContinue -Force + } } Context 'Download gist content' { diff --git a/Tests/GitHubRepositories.tests.ps1 b/Tests/GitHubRepositories.tests.ps1 index eb4bc666..74599da4 100644 --- a/Tests/GitHubRepositories.tests.ps1 +++ b/Tests/GitHubRepositories.tests.ps1 @@ -1271,6 +1271,11 @@ try Describe 'GitHubRepositories\Disable-GitHubRepositoryVulnerabilityAlert' { BeforeAll { $repo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) + + # The CI build has been unreliable with this test. + # Adding a short sleep to ensure successive queries reflect updated state. + Start-Sleep -Seconds $script:defaultSleepSecondsForReliability + Enable-GitHubRepositoryVulnerabilityAlert -Uri $repo.svn_url } @@ -1306,6 +1311,11 @@ try Describe 'GitHubRepositories\Disable-GitHubRepositorySecurityFix' { BeforeAll { $repo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) + + # The CI build has been unreliable with this test. + # Adding a short sleep to ensure successive queries reflect updated state. + Start-Sleep -Seconds $script:defaultSleepSecondsForReliability + Enable-GitHubRepositorySecurityFix -Uri $repo.svn_url } From 2fe6ca233ce73e5203e636626dcab9e29d2d04cc Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Sun, 19 Jul 2020 11:37:06 -0700 Subject: [PATCH 15/15] Remove added sleeps in lieu of new relibability design from #268 --- Tests/GitHubRepositories.tests.ps1 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Tests/GitHubRepositories.tests.ps1 b/Tests/GitHubRepositories.tests.ps1 index 74599da4..eb4bc666 100644 --- a/Tests/GitHubRepositories.tests.ps1 +++ b/Tests/GitHubRepositories.tests.ps1 @@ -1271,11 +1271,6 @@ try Describe 'GitHubRepositories\Disable-GitHubRepositoryVulnerabilityAlert' { BeforeAll { $repo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) - - # The CI build has been unreliable with this test. - # Adding a short sleep to ensure successive queries reflect updated state. - Start-Sleep -Seconds $script:defaultSleepSecondsForReliability - Enable-GitHubRepositoryVulnerabilityAlert -Uri $repo.svn_url } @@ -1311,11 +1306,6 @@ try Describe 'GitHubRepositories\Disable-GitHubRepositorySecurityFix' { BeforeAll { $repo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) - - # The CI build has been unreliable with this test. - # Adding a short sleep to ensure successive queries reflect updated state. - Start-Sleep -Seconds $script:defaultSleepSecondsForReliability - Enable-GitHubRepositorySecurityFix -Uri $repo.svn_url }