diff --git a/GitHubReferences.ps1 b/GitHubReferences.ps1 new file mode 100644 index 00000000..5dc6cecf --- /dev/null +++ b/GitHubReferences.ps1 @@ -0,0 +1,837 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +@{ + GitHubReferenceTypeName = 'GitHub.Reference' + }.GetEnumerator() | ForEach-Object { + Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value + } + +filter Get-GitHubReference +{ +<# + .SYNOPSIS + Retrieve a reference from a given GitHub repository. + + .DESCRIPTION + Retrieve a reference from a given GitHub repository. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER OwnerName + Owner of the repository. + If not supplied here, the DefaultOwnerName configuration property value will be used. + + .PARAMETER RepositoryName + Name of the repository. + If not supplied here, the DefaultRepositoryName configuration property value will be used. + + .PARAMETER Uri + Uri for the repository. + The OwnerName and RepositoryName will be extracted from here instead of needing to provide + them individually. + + .PARAMETER TagName + The name of the Tag to be retrieved. + + .PARAMETER BranchName + The name of the Branch to be retrieved. + + .PARAMETER MatchPrefix + If provided, this will return matching preferences for the given branch/tag name in case an exact match is not found + + .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.Branch + GitHub.Content + GitHub.Event + GitHub.Issue + GitHub.IssueComment + GitHub.Label + GitHub.Milestone + GitHub.PullRequest + GitHub.Project + GitHub.ProjectCard + GitHub.ProjectColumn + GitHub.Reaction + GitHub.Release + GitHub.Repository + + .OUTPUTS + GitHub.Reference + Details of the git reference in the given repository + + .EXAMPLE + Get-GitHubReference -OwnerName microsoft -RepositoryName PowerShellForGitHub -TagName powershellTagV1 + + .EXAMPLE + Get-GitHubReference -OwnerName microsoft -RepositoryName PowerShellForGitHub -BranchName master + + .EXAMPLE + Get-GitHubReference -OwnerName microsoft -RepositoryName PowerShellForGitHub -BranchName powershell -MatchPrefix + + Get the branch 'powershell' and if it doesn't exist, get all branches beginning with 'powershell' + + .EXAMPLE + $repo = Get-GitHubRepository -OwnerName microsoft -RepositoryName PowerShellForGitHub + $repo | Get-GitHubReference -BranchName powershell + + Get details of the "powershell" branch in the repository + +#> + [CmdletBinding( + SupportsShouldProcess, + DefaultParameterSetName='Uri')] + [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='BranchElements')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [Parameter( + Mandatory, + ParameterSetName='Elements')] + [string] $OwnerName, + + [Parameter( + Mandatory, + ParameterSetName='BranchElements')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [Parameter( + Mandatory, + ParameterSetName='Elements')] + [string] $RepositoryName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='Uri')] + [Alias('RepositoryUrl')] + [string] $Uri, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagElements')] + [string] $TagName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchElements')] + [string] $BranchName, + + [Parameter(ParameterSetName='BranchUri')] + [Parameter(ParameterSetName='BranchElements')] + [Parameter(ParameterSetName='TagUri')] + [Parameter(ParameterSetName='TagElements')] + [switch] $MatchPrefix, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $elements = Resolve-RepositoryElements -BoundParameters $PSBoundParameters + $OwnerName = $elements.ownerName + $RepositoryName = $elements.repositoryName + + $telemetryProperties = @{ + 'OwnerName' = (Get-PiiSafeString -PlainText $OwnerName) + 'RepositoryName' = (Get-PiiSafeString -PlainText $RepositoryName) + } + + $uriFragment = "repos/$OwnerName/$RepositoryName/git" + $reference = Resolve-GitHubReference -TagName $TagName -BranchName $BranchName + + if ([String]::IsNullOrEmpty($reference)) + { + # Add a slash at the end as Invoke-GHRestMethod removes the last trailing slash. Calling this API without the slash causes a 404 + $uriFragment = $uriFragment + "/matching-refs//" + $description = "Getting all references for $RepositoryName" + } + else + { + if ($MatchPrefix) + { + $uriFragment = $uriFragment + "/matching-refs/$reference" + $description = "Getting references matching $reference for $RepositoryName" + } + else + { + # We want to return an exact match, call the 'get single reference' API + $uriFragment = $uriFragment + "/ref/$reference" + $description = "Getting reference $reference for $RepositoryName" + } + } + + $params = @{ + 'UriFragment' = $uriFragment + 'Description' = $description + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Invoke-GHRestMethodMultipleResult @params | Add-GitHubBranchAdditionalProperties) +} + +filter New-GitHubReference +{ + <# + .SYNOPSIS + Create a reference in a given GitHub repository. + + .DESCRIPTION + Create a reference in a given GitHub repository. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER OwnerName + Owner of the repository. + If not supplied here, the DefaultOwnerName configuration property value will be used. + + .PARAMETER RepositoryName + Name of the repository. + If not supplied here, the DefaultRepositoryName configuration property value will be used. + + .PARAMETER Uri + Uri for the repository. + The OwnerName and RepositoryName will be extracted from here instead of needing to provide + them individually. + + .PARAMETER TagName + The name of the Tag to be created. + + .PARAMETER BranchName + The name of the Branch to be created. + + .PARAMETER Sha + The SHA1 value for the reference to be created + + .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.Branch + GitHub.Content + GitHub.Event + GitHub.Issue + GitHub.IssueComment + GitHub.Label + GitHub.Milestone + GitHub.PullRequest + GitHub.Project + GitHub.ProjectCard + GitHub.ProjectColumn + GitHub.Reaction + GitHub.Release + GitHub.Repository + + .OUTPUTS + GitHub.Reference + Details of the git reference created. Throws an Exception if the reference already exists + + .EXAMPLE + New-GitHubReference -OwnerName microsoft -RepositoryName PowerShellForGitHub -TagName powershellTagV1 -Sha aa218f56b14c9653891f9e74264a383fa43fefbd + + .EXAMPLE + New-GitHubReference -Uri https://github.com/You/YourRepo -BranchName master -Sha aa218f56b14c9653891f9e74264a383fa43fefbd + + .EXAMPLE + $repo = Get-GitHubRepository -OwnerName microsoft -RepositoryName PowerShellForGitHub + $repo | New-GitHubReference -BranchName powershell -Sha aa218f56b14c9653891f9e74264a383fa43fefbd + + Create a new branch named "powershell" in the given repository + #> + [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, + ParameterSetName='BranchElements')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [string] $OwnerName, + + [Parameter( + Mandatory, + ParameterSetName='BranchElements')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [string] $RepositoryName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagUri')] + [Alias('RepositoryUrl')] + [string] $Uri, + + [Parameter( + Mandatory, + ParameterSetName='TagUri')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [string] $TagName, + + [Parameter( + Mandatory, + ParameterSetName='BranchUri')] + [Parameter( + Mandatory, + ParameterSetName='BranchElements')] + [string] $BranchName, + + [Parameter(Mandatory)] + [string] $Sha, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $elements = Resolve-RepositoryElements -BoundParameters $PSBoundParameters + $OwnerName = $elements.ownerName + $RepositoryName = $elements.repositoryName + + $telemetryProperties = @{ + 'OwnerName' = (Get-PiiSafeString -PlainText $OwnerName) + 'RepositoryName' = (Get-PiiSafeString -PlainText $RepositoryName) + } + + $reference = Resolve-GitHubReference -TagName $TagName -BranchName $BranchName + + $uriFragment = "repos/$OwnerName/$RepositoryName/git/refs" + $description = "Creating Reference $reference for $RepositoryName from SHA $Sha" + + $hashBody = @{ + 'ref' = "refs/" + $reference + 'sha' = $Sha + } + + $params = @{ + 'UriFragment' = $uriFragment + 'Method' = 'Post' + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Description' = $description + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Invoke-GHRestMethod @params | Add-GitHubBranchAdditionalProperties) +} + +filter Set-GithubReference +{ + <# + .SYNOPSIS + Update a reference in a given GitHub repository. + + .DESCRIPTION + Update a reference in a given GitHub repository. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER OwnerName + Owner of the repository. + If not supplied here, the DefaultOwnerName configuration property value will be used. + + .PARAMETER RepositoryName + Name of the repository. + If not supplied here, the DefaultRepositoryName configuration property value will be used. + + .PARAMETER Uri + Uri for the repository. + The OwnerName and RepositoryName will be extracted from here instead of needing to provide + them individually. + + .PARAMETER TagName + The name of the tag to be updated to the given SHA. + + .PARAMETER BranchName + The name of the branch to be updated to the given SHA. + + .PARAMETER Sha + The updated SHA1 value to be set for this reference. + + .PARAMETER Force + If not set, the update will only occur if it is a fast-forward update. + Not specifying this (or setting it to $false) will make sure you're not overwriting work. + + .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.Branch + GitHub.Content + GitHub.Event + GitHub.Issue + GitHub.IssueComment + GitHub.Label + GitHub.Milestone + GitHub.PullRequest + GitHub.Project + GitHub.ProjectCard + GitHub.ProjectColumn + GitHub.Release + Github.Reference + GitHub.Repository + + .OUTPUTS + GitHub.Reference + + .EXAMPLE + Set-GithubReference -OwnerName microsoft -RepositoryName PowerShellForGitHub -BranchName myBranch -Sha aa218f56b14c9653891f9e74264a383fa43fefbd + + .EXAMPLE + Set-GithubReference -Uri https://github.com/You/YourRepo -TagName myTag -Sha aa218f56b14c9653891f9e74264a383fa43fefbd + + .EXAMPLE + Set-GithubReference -Uri https://github.com/You/YourRepo -TagName myTag -Sha aa218f56b14c9653891f9e74264a383fa43fefbd -Force + + Force an update even if it is not a fast-forward update + + .EXAMPLE + $repo = Get-GitHubRepository -OwnerName microsoft -RepositoryName PowerShellForGitHub + $ref = $repo | Get-GitHubReference -BranchName powershell + $ref | Set-GithubReference -Sha aa218f56b14c9653891f9e74264a383fa43fefbd + + Get the "powershell" branch from the given repo and update its SHA + #> + [CmdletBinding( + SupportsShouldProcess, + DefaultParametersetName='Uri')] + [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='BranchElements')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [string] $OwnerName, + + [Parameter( + Mandatory, + ParameterSetName='BranchElements')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [string] $RepositoryName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagUri')] + [Alias('RepositoryUrl')] + [string] $Uri, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagElements')] + [string] $TagName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchElements')] + [string] $BranchName, + + [Parameter(Mandatory)] + [string] $Sha, + + [switch] $Force, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $elements = Resolve-RepositoryElements -BoundParameters $PSBoundParameters + $OwnerName = $elements.ownerName + $RepositoryName = $elements.repositoryName + + $telemetryProperties = @{ + 'OwnerName' = (Get-PiiSafeString -PlainText $OwnerName) + 'RepositoryName' = (Get-PiiSafeString -PlainText $RepositoryName) + } + + $reference = Resolve-GitHubReference -TagName $TagName -BranchName $BranchName + + $uriFragment = "repos/$OwnerName/$RepositoryName/git/refs/$reference" + $description = "Updating SHA for Reference $reference in $RepositoryName to $Sha" + + $hashBody = @{ + 'force' = $Force.IsPresent + 'sha' = $Sha + } + + $params = @{ + 'UriFragment' = $uriFragment + 'Method' = 'Patch' + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Description' = $description + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Invoke-GHRestMethod @params | Add-GitHubBranchAdditionalProperties) +} + +filter Remove-GitHubReference +{ + <# + .SYNOPSIS + Delete a reference in a given GitHub repository. + + .DESCRIPTION + Delete a reference in a given GitHub repository. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER OwnerName + Owner of the repository. + If not supplied here, the DefaultOwnerName configuration property value will be used. + + .PARAMETER RepositoryName + Name of the repository. + If not supplied here, the DefaultRepositoryName configuration property value will be used. + + .PARAMETER Uri + Uri for the repository. + The OwnerName and RepositoryName will be extracted from here instead of needing to provide + them individually. + + .PARAMETER TagName + The name of the tag to be deleted. + + .PARAMETER BranchName + The name of the branch to be deleted. + + .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.Branch + GitHub.Content + GitHub.Event + GitHub.Issue + GitHub.IssueComment + GitHub.Label + GitHub.Milestone + GitHub.PullRequest + GitHub.Project + GitHub.ProjectCard + GitHub.ProjectColumn + GitHub.Release + Github.Reference + GitHub.Repository + + .OUTPUTS + None + + .EXAMPLE + Remove-GitHubReference -OwnerName microsoft -RepositoryName PowerShellForGitHub -TagName powershellTagV1 + + .EXAMPLE + Remove-GitHubReference -Uri https://github.com/You/YourRepo -BranchName master + + .EXAMPLE + Remove-GitHubReference -OwnerName microsoft -RepositoryName PowerShellForGitHub -TagName milestone1 -Confirm:$false + Remove the tag milestone1 without prompting for confirmation + + .EXAMPLE + Remove-GitHubReference -OwnerName microsoft -RepositoryName PowerShellForGitHub -TagName milestone1 -Force + Remove the tag milestone1 without prompting for confirmation + + .EXAMPLE + $repo = Get-GitHubRepository -OwnerName microsoft -RepositoryName PowerShellForGitHub + $ref = $repo | Get-GitHubReference -TagName powershellV1 + $ref | Remove-GithubReference + + Get a reference to the "powershellV1" tag using Get-GithubReference on the repository. Pass it to this method in order to remove it + #> + [CmdletBinding( + SupportsShouldProcess, + ConfirmImpact="High")] + [Alias('Delete-GitHubReference')] + [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='BranchElements')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [string] $OwnerName, + + [Parameter( + Mandatory, + ParameterSetName='BranchElements')] + [Parameter( + Mandatory, + ParameterSetName='TagElements')] + [string] $RepositoryName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagUri')] + [Alias('RepositoryUrl')] + [string] $Uri, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TagElements')] + [string] $TagName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchUri')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='BranchElements')] + [string] $BranchName, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + $repositoryInfoForDisplayMessage = if ($PSCmdlet.ParameterSetName -eq "Uri") { $Uri } else { $OwnerName, $RepositoryName -join "/" } + $reference = Resolve-GitHubReference -TagName $TagName -BranchName $BranchName + if ($Force -and (-not $Confirm)) + { + $ConfirmPreference = 'None' + } + if ($PSCmdlet.ShouldProcess($repositoryInfoForDisplayMessage, "Remove reference: $reference")) + { + Write-InvocationLog + + $elements = Resolve-RepositoryElements -BoundParameters $PSBoundParameters + $OwnerName = $elements.ownerName + $RepositoryName = $elements.repositoryName + + $telemetryProperties = @{ + 'OwnerName' = (Get-PiiSafeString -PlainText $OwnerName) + 'RepositoryName' = (Get-PiiSafeString -PlainText $RepositoryName) + } + + $uriFragment = "repos/$OwnerName/$RepositoryName/git/refs/$reference" + $description = "Deleting Reference $reference from repository $RepositoryName" + + $params = @{ + 'UriFragment' = $uriFragment + 'Method' = 'Delete' + 'Body' = (ConvertTo-Json -InputObject $hashBody) + 'Description' = $description + 'AccessToken' = $AccessToken + 'TelemetryEventName' = $MyInvocation.MyCommand.Name + 'TelemetryProperties' = $telemetryProperties + 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return Invoke-GHRestMethod @params + } +} + +filter Add-GitHubBranchAdditionalProperties +{ +<# + .SYNOPSIS + Adds type name and additional properties to ease pipelining to GitHub Branch 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.Reference +#> + [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:GitHubReferenceTypeName + ) + + foreach ($item in $InputObject) + { + $item.PSObject.TypeNames.Insert(0, $TypeName) + + if (-not (Get-GitHubConfiguration -Name DisablePipelineSupport)) + { + if ($null -ne $item.url) + { + $elements = Split-GitHubUri -Uri $item.url + } + else + { + $elements = Split-GitHubUri -Uri $item.commit.url + } + $repositoryUrl = Join-GitHubUri @elements + + Add-Member -InputObject $item -Name 'RepositoryUrl' -Value $repositoryUrl -MemberType NoteProperty -Force + + if ($item.ref.StartsWith('refs/heads/')) + { + $branchName = $item.ref -replace ('refs/heads/', '') + Add-Member -InputObject $item -Name 'BranchName' -Value $branchName -MemberType NoteProperty -Force + } + if ($item.ref.StartsWith('refs/tags')) + { + $tagName = $item.ref -replace ('refs/tags/', '') + Add-Member -InputObject $item -Name 'TagName' -Value $tagName -MemberType NoteProperty -Force + } + } + + Write-Output $item + } +} + +filter Resolve-GitHubReference +{ + <# + .SYNOPSIS + Get the given tag or branch in the form of a Github reference + + .DESCRIPTION + Get the given tag or branch in the form of a Github reference i.e. tags/ for a tag and heads/ for a branch + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER TagName + The tag for which we need the reference string + + .PARAMETER BranchName + The branch for which we need the reference string + + .EXAMPLE + Resolve-GitHubReference -TagName powershellTag + + .EXAMPLE + Resolve-GitHubReference -BranchName powershellBranch + #> + param( + [string] $TagName, + [string] $BranchName + ) + + if (-not [String]::IsNullOrEmpty($TagName)) + { + return "tags/$TagName" + } + elseif (-not [String]::IsNullOrEmpty($BranchName)) + { + return "heads/$BranchName" + } + return [String]::Empty +} \ No newline at end of file diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 4be54289..675b5239 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -43,6 +43,7 @@ 'GitHubPullRequests.ps1', 'GitHubReactions.ps1', 'GitHubReleases.ps1', + 'GitHubReferences.ps1', 'GitHubRepositories.ps1', 'GitHubRepositoryForks.ps1', 'GitHubRepositoryTraffic.ps1', @@ -89,6 +90,7 @@ 'Get-GitHubReaction', 'Get-GitHubReferrerTraffic', 'Get-GitHubRelease', + 'Get-GitHubReference', 'Get-GitHubRepository', 'Get-GitHubRepositoryBranch', 'Get-GitHubRepositoryCollaborator', @@ -121,6 +123,7 @@ 'New-GitHubProjectCard', 'New-GitHubProjectColumn', 'New-GitHubPullRequest', + 'New-GitHubReference', 'New-GitHubRepository', 'New-GitHubRepositoryFromTemplate', 'New-GitHubRepositoryBranch', @@ -134,6 +137,7 @@ 'Remove-GitHubProjectCard', 'Remove-GitHubProjectColumn', 'Remove-GitHubReaction', + 'Remove-GitHubReference', 'Remove-GitHubRepository', 'Remove-GitHubRepositoryBranch' 'Rename-GitHubRepository', @@ -159,7 +163,12 @@ 'Test-GitHubAuthenticationConfigured', 'Test-GitHubOrganizationMember', 'Test-GitHubRepositoryVulnerabilityAlert', - 'Unlock-GitHubIssue' + 'Unlock-GitHubIssue', + 'Update-GitHubCurrentUser', + 'Update-GitHubIssue', + 'Update-GitHubLabel', + 'Set-GithubReference', + 'Update-GitHubRepository' ) AliasesToExport = @( @@ -172,6 +181,7 @@ 'Delete-GitHubProjectCard', 'Delete-GitHubProjectColumn', 'Delete-GitHubReaction', + 'Delete-GitHubReference', 'Delete-GitHubRepository', 'Delete-GitHubRepositoryBranch', 'Get-GitHubBranch', diff --git a/Tests/GitHubReferences.Tests.ps1 b/Tests/GitHubReferences.Tests.ps1 new file mode 100644 index 00000000..977f43c4 --- /dev/null +++ b/Tests/GitHubReferences.Tests.ps1 @@ -0,0 +1,817 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +<# +.Synopsis + Tests for GitHubReferences.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 +{ + # Script-scoped, hidden, readonly variables. + @{ + repoGuid = [Guid]::NewGuid().Guid + masterBranchName = "master" + branchName = [Guid]::NewGuid().ToString() + tagName = [Guid]::NewGuid().ToString() + }.GetEnumerator() | ForEach-Object { + Set-Variable -Force -Scope Script -Option ReadOnly -Visibility Private -Name $_.Key -Value $_.Value + } + + Describe 'Create a new branch in repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $masterBranchName + $sha = $existingref.object.sha + } + + AfterAll { + Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On creating a new branch in a repository from a valid SHA' { + $branch = [Guid]::NewGuid().ToString() + $reference = New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branch -Sha $sha + + It 'Should successfully create the new branch and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.BranchName | Should -Be $branch + } + + It 'Should throw an Exception when trying to create it again' { + { New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branch -Sha $sha } | + Should -Throw + } + } + + Context 'On creating a new branch in a repository (specified by Uri) from a valid SHA' { + $branch = [Guid]::NewGuid().ToString() + + $reference = New-GitHubReference -Uri $repo.svn_url -BranchName $branch -Sha $sha + + It 'Should successfully create the new branch and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.BranchName | Should -Be $branch + } + + It 'Should throw an exception when trying to create it again' { + { New-GitHubReference -Uri $repo.svn_url -BranchName $branch -Sha $sha } | Should -Throw + } + } + + Context 'On creating a new branch in a repository with the repo on the pipeline' { + $branch = [Guid]::NewGuid().ToString() + + $reference = $repo | New-GitHubReference -BranchName $branch -Sha $sha + + It 'Should successfully create the new branch and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.BranchName | Should -Be $branch + } + + It 'Should throw an exception when trying to create it again' { + { $repo | New-GitHubReference -BranchName $branch -Sha $sha } | Should -Throw + } + } + } + + Describe 'Create a new tag in a repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $masterBranchName + $sha = $existingref.object.sha + } + + AfterAll { + Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On creating a new tag in a repository referring to a given SHA' { + $tag = [Guid]::NewGuid().ToString() + $reference = New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag -Sha $sha + + It 'Should successfully create the new tag and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.TagName | Should -Be $tag + } + + It 'Should throw an Exception when trying to create it again' { + { New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag -Sha $sha } | Should -Throw + } + } + + Context 'On creating a new tag in a repository (specified by Uri) from a given SHA' { + $tag = [Guid]::NewGuid().ToString() + + $reference = New-GitHubReference -Uri $repo.svn_url -TagName $tag -Sha $sha + + It 'Should successfully create the new tag and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.TagName | Should -Be $tag + } + + It 'Should throw an exception when trying to create it again' { + { New-GitHubReference -Uri $repo.svn_url -TagName $tag -Sha $sha } | Should -Throw + } + } + + Context 'On creating a new tag in a repository with the repo on the pipeline' { + $tag = [Guid]::NewGuid().ToString() + + $reference = $repo | New-GitHubReference -TagName $tag -Sha $sha + + It 'Should successfully create the new tag and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.TagName | Should -Be $tag + } + + It 'Should throw an exception when trying to create it again' { + { $repo | New-GitHubReference -TagName $tag -Sha $sha } | Should -Throw + } + } + } + + Describe 'Getting branch(es) from repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $masterBranchName + $sha = $existingref.object.sha + $randomBranchName = [Guid]::NewGuid() + } + + AfterAll { + Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On getting an existing branch from a repository' { + $reference = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $masterBranchName + + It 'Should return details for that branch and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.BranchName | Should -Be $masterBranchName + } + } + + Context 'On getting an non-existent branch from a repository' { + It 'Should throw an exception' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $randomBranchName } | + Should -Throw + } + } + + Context 'On getting an existing branch using Uri from a repository' { + $reference = Get-GitHubReference -Uri $repo.svn_url -BranchName $masterBranchName + + It 'Should return details for that branch and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.BranchName | Should -Be $masterBranchName + } + } + + Context 'On getting an invalid branch using Uri from a repository' { + It 'Should throw an exception' { + { Get-GitHubReference -Uri $repo.svn_url -BranchName $randomBranchName } | + Should -Throw + } + } + + Context 'On getting an existing branch with the repo on the pipeline' { + $reference = $repo | Get-GitHubReference -BranchName $masterBranchName + + It 'Should return details for that branch and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.BranchName | Should -Be $masterBranchName + } + } + + Context 'On getting an invalid branch with the repo on the pipeline' { + It 'Should throw an exception' { + { $repo | Get-GitHubReference -BranchName $randomBranchName } | + Should -Throw + } + } + + Context 'On getting branches by prefix from a repository' { + $branch1 = "elements_A" + $branch2 = "elements_B" + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branch1 -Sha $sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branch2 -Sha $sha + + $references = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "elements" -MatchPrefix + + It 'Should return all branches matching the prefix when an exact match is not found' { + $expected = @($branch1, $branch2) + $references.BranchName | Sort-Object | Should -Be $expected + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + + Context 'On getting branches by prefix using Uri from a repository' { + $branch1 = "uri_A" + $branch2 = "uri_B" + New-GitHubReference -Uri $repo.svn_url -BranchName $branch1 -Sha $sha + New-GitHubReference -Uri $repo.svn_url -BranchName $branch2 -Sha $sha + + $references = Get-GitHubReference -Uri $repo.svn_url -BranchName "uri" -MatchPrefix + + It 'Should return all branches matching the prefix when an exact match is not found' { + $expected = @($branch1, $branch2) + $references.BranchName | Sort-Object | Should -Be $expected + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + + Context 'On getting branches by prefix with the repo on the pipeline' { + $branch1 = "pipeline_A" + $branch2 = "pipeline_B" + $repo | New-GitHubReference -BranchName $branch1 -Sha $sha + $repo | New-GitHubReference -BranchName $branch2 -Sha $sha + + $references = $repo | Get-GitHubReference -BranchName "pipeline" -MatchPrefix + + It 'Should return all branches matching the prefix when an exact match is not found' { + $expected = @($branch1, $branch2) + $references.BranchName | Sort-Object | Should -Be $expected + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + } + + Describe 'Getting tag(s) from repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $masterBranchName + $sha = $existingref.object.sha + $randomTagName = [Guid]::NewGuid() + New-GitHubReference -Uri $repo.svn_url -TagName $tagName -Sha $sha + } + + AfterAll { + Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On getting an existing tag from a repository' { + $reference = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName + + It 'Should return details for that tag and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.TagName | Should -Be $tagName + } + } + + Context 'On getting an non-existent tag from a repository' { + It 'Should throw an exception' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $randomTagName } | + Should -Throw + } + } + + Context 'On getting an existing tag using Uri from a repository' { + $reference = Get-GitHubReference -Uri $repo.svn_url -TagName $tagName + + It 'Should return details for that tag and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.TagName | Should -Be $tagName + } + } + + Context 'On getting an invalid tag using Uri from a repository' { + It 'Should throw an exception' { + { Get-GitHubReference -Uri $repo.svn_url -TagName $randomTagName } | + Should -Throw + } + } + + Context 'On getting an existing tag with the repo on the pipeline' { + $reference = $repo | Get-GitHubReference -TagName $tagName + + It 'Should return details for that tag and have expected additional properties' { + $reference.PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $reference.RepositoryUrl | Should -Be $repo.RepositoryUrl + $reference.TagName | Should -Be $tagName + } + } + + Context 'On getting an invalid tag using Uri from a repository' { + It 'Should throw an exception' { + { $repo | Get-GitHubReference -TagName $randomTagName } | + Should -Throw + } + } + + Context 'On getting tags by prefix from a repository' { + $tag1 = "elements_A" + $tag2 = "elements_B" + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag1 -Sha $sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag2 -Sha $sha + + $references = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName "elements" -MatchPrefix + + It 'Should return all branches matching the prefix when an exact match is not found' { + $expected = @($tag1, $tag2) + $references.TagName | Sort-Object | Should -Be $expected + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + + Context 'On getting tags by prefix from a repository specified By Uri' { + $tag1 = "uri_A" + $tag2 = "uri_B" + New-GitHubReference -Uri $repo.svn_url -TagName $tag1 -Sha $sha + New-GitHubReference -Uri $repo.svn_url -TagName $tag2 -Sha $sha + + $references = Get-GitHubReference -Uri $repo.svn_url -TagName "uri" -MatchPrefix + + It 'Should return all branches matching the prefix when an exact match is not found' { + $expected = @($tag1, $tag2) + $references.TagName | Sort-Object | Should -Be $expected + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + + Context 'On getting tags by prefix with the repo on the pipeline' { + $tag1 = "pipeline_A" + $tag2 = "pipeline_B" + $repo | New-GitHubReference -TagName $tag1 -Sha $sha + $repo | New-GitHubReference -TagName $tag2 -Sha $sha + + $references = Get-GitHubReference -Uri $repo.svn_url -TagName "pipeline" -MatchPrefix + + It 'Should return all branches matching the prefix when an exact match is not found' { + $expected = @($tag1, $tag2) + $references.TagName | Sort-Object | Should -Be $expected + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + } + Describe 'Getting all references from repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $masterBranchName + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Sha $sha + } + + AfterAll { + # Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On getting all references from a repository' { + $references = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name + It 'Should return all branches matching the prefix when an exact match is not found' { + $references.Count | Should -Be 2 + $references.TagName.Contains($tagName) | Should -Be True + $references.BranchName.Contains($masterBranchName) | Should -Be True + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + + Context 'On getting all references using Uri from a repository' { + $references = Get-GitHubReference -Uri $repo.svn_url + + It 'Should return all branches matching the prefix when an exact match is not found' { + $references.Count | Should -Be 2 + $references.TagName.Contains($tagName) | Should -Be True + $references.BranchName.Contains($masterBranchName) | Should -Be True + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + + Context 'On getting all references with repo on pipeline' { + $references = $repo | Get-GitHubReference + + It 'Should return all branches matching the prefix when an exact match is not found' { + $references.Count | Should -Be 2 + $references.TagName.Contains($tagName) | Should -Be True + $references.BranchName.Contains($masterBranchName) | Should -Be True + $references[0].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[1].PSObject.TypeNames[0] | Should -Be 'GitHub.Reference' + $references[0].RepositoryUrl | Should -Be $repo.RepositoryUrl + $references[1].RepositoryUrl | Should -Be $repo.RepositoryUrl + } + } + } + + Describe 'Delete a branch from a repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + } + + AfterAll { + Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On deleting a branch in a repository' { + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "master" + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Sha $sha + Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Confirm:$false + + It 'Should throw an exception when trying to get the deleted branch' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName } | + Should -Throw + } + + It 'Should throw an exception when the same branch is deleted again' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Confirm:$false} | + Should -Throw + } + } + + Context 'On deleting an invalid branch from a repository' { + It 'Should throw an exception' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $([Guid]::NewGuid()) -Confirm:$false} | + Should -Throw + } + } + + Context 'On deleting a branch in a repository specified by Uri' { + $existingref = Get-GitHubReference -Uri $repo.svn_url -BranchName "master" + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Sha $sha + Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Confirm:$false + + It 'Should throw an exception when trying to get the deleted branch' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName} | + Should -Throw + } + + It 'Should throw an exception when the same branch is deleted again' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Confirm:$false} | + Should -Throw + } + } + + Context 'On deleting a branch in a repository with the repo on pipeline' { + $existingref = Get-GitHubReference -Uri $repo.svn_url -BranchName "master" + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Sha $sha + $repo | Remove-GitHubReference -BranchName $branchName -Confirm:$false + + It 'Should throw an exception when trying to get the deleted branch' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName} | + Should -Throw + } + + It 'Should throw an exception when the same branch is deleted again' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Confirm:$false} | + Should -Throw + } + } + + Context 'On deleting a branch in a repository with the branch reference on pipeline' { + $existingref = Get-GitHubReference -Uri $repo.svn_url -BranchName "master" + $sha = $existingref.object.sha + $branchRef = New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Sha $sha + $branchRef | Remove-GitHubReference -Confirm:$false + + It 'Should throw an exception when trying to get the deleted branch' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName} | + Should -Throw + } + + It 'Should throw an exception when the same branch is deleted again' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Confirm:$false} | + Should -Throw + } + } + + Context 'On deleting an invalid branch from a repository specified by Uri' { + It 'Should throw an exception' { + { Remove-GitHubReference -OwnerName -Uri $repo.svn_url -BranchName $([Guid]::NewGuid()) -Confirm:$false } | + Should -Throw + } + } + + } + + Describe 'Delete a Tag from a Repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + } + + AfterAll { + Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On deleting a valid tag in a repository' { + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "master" + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Sha $sha + Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Confirm:$false + + It 'Should throw an exception when trying to get the deleted tag' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName } | + Should -Throw + } + + It 'Should throw an exception when the same tag is deleted again' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Confirm:$false } | + Should -Throw + } + } + + Context 'On deleting an invalid tag from a repository' { + It 'Should throw an exception' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $([Guid]::NewGuid()) -Confirm:$false } | + Should -Throw + } + } + + Context 'On deleting a tag in a repository specified by Uri' { + $existingref = Get-GitHubReference -Uri $repo.svn_url -BranchName "master" + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Sha $sha + Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Confirm:$false + + It 'Should throw an exception when trying to get the deleted tag' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName } | + Should -Throw + } + + It 'Should throw an exception when the same branch is deleted again' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Confirm:$false } | + Should -Throw + } + } + + Context 'On deleting a tag in a repository with repo on pipeline' { + $existingref = Get-GitHubReference -Uri $repo.svn_url -BranchName "master" + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Sha $sha + $repo | Remove-GitHubReference -TagName $tagName -Confirm:$false + + It 'Should throw an exception when trying to get the deleted tag' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName } | + Should -Throw + } + + It 'Should throw an exception when the same branch is deleted again' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Confirm:$false } | + Should -Throw + } + } + + Context 'On deleting a tag in a repository with tag reference on pipeline' { + $existingref = Get-GitHubReference -Uri $repo.svn_url -BranchName "master" + $sha = $existingref.object.sha + $tagRef = New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Sha $sha + $tagRef | Remove-GitHubReference -Confirm:$false + + It 'Should throw an exception when trying to get the deleted tag' { + { Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName } | + Should -Throw + } + + It 'Should throw an exception when the same branch is deleted again' { + { Remove-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tagName -Confirm:$false } | + Should -Throw + } + } + + Context 'On deleting an invalid tag from a repository specified by Uri' { + It 'Should throw an exception' { + { Remove-GitHubReference -OwnerName -Uri $repo.svn_url -TagName $([Guid]::NewGuid()) -Confirm:$false } | + Should -Throw + } + } + + } + + Describe 'Update a branch in a repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $masterBranchName + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Sha $sha + } + + AfterAll { + Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On updating an existing branch to a different SHA' { + It 'Should throw an exception if the SHA is invalid' { + { Set-GithubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Sha "1234" } | + Should -Throw + } + } + + Context 'On updating a branch to a different SHA' { + $setGitHubContentParams = @{ + Path = 'test.txt' + CommitMessage = 'Commit Message' + Branch = $masterBranchName + Content = 'This is the content for test.txt' + Uri = $repo.svn_url + } + + Set-GitHubContent @setGitHubContentParams + + $masterSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "master").object.sha + $oldSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName).object.sha + Set-GithubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName -Sha $masterSHA + + It 'Should return the updated SHA when the reference is queried after update' { + $newSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName).object.sha + $newSHA | Should -Be $masterSHA + $newSHA | Should -Not -Be $oldSHA + } + } + + Context 'On updating a branch to a different SHA with repo on pipeline' { + $setGitHubContentParams = @{ + Path = 'test.txt' + CommitMessage = 'Commit Message' + Branch = $masterBranchName + Content = 'This is the content for test.txt' + Uri = $repo.svn_url + } + + Set-GitHubContent @setGitHubContentParams + + $masterSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "master").object.sha + $oldSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName).object.sha + $repo | Set-GithubReference -BranchName $branchName -Sha $masterSHA + + It 'Should return the updated SHA when the reference is queried after update' { + $newSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName).object.sha + $newSHA | Should -Be $masterSHA + $newSHA | Should -Not -Be $oldSHA + } + } + + Context 'On updating a branch to a different SHA with branch reference on pipeline' { + $setGitHubContentParams = @{ + Path = 'test.txt' + CommitMessage = 'Commit Message' + Branch = $masterBranchName + Content = 'This is the content for test.txt' + Uri = $repo.svn_url + } + + Set-GitHubContent @setGitHubContentParams + + $masterSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "master").object.sha + $branchRef = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName) + $oldSHA = $branchRef.object.sha + $branchRef | Set-GithubReference -Sha $masterSHA + + It 'Should return the updated SHA when the reference is queried after update' { + $newSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $branchName).object.sha + $newSHA | Should -Be $masterSHA + $newSHA | Should -Not -Be $oldSHA + } + } + + } + + Describe 'Update a tag in a repository' { + BeforeAll { + # AutoInit will create a readme with the GUID of the repo name + $repo = New-GitHubRepository -RepositoryName ($repoGuid) -AutoInit + $tag = "myTag" + $existingref = Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName $masterBranchName + $sha = $existingref.object.sha + New-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag -Sha $sha + } + + AfterAll { + Remove-GitHubRepository -Uri $repo.svn_url -Confirm:$false + } + + Context 'On updating an existing tag to a different SHA' { + It 'Should throw an exception if the SHA is invalid' { + { Set-GithubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag -Sha "1234" } | + Should -Throw + } + } + + Context 'On updating a tag to a valid SHA' { + $setGitHubContentParams = @{ + Path = 'test.txt' + CommitMessage = 'Commit Message' + Branch = $masterBranchName + Content = 'This is the content for test.txt' + Uri = $repo.svn_url + } + + Set-GitHubContent @setGitHubContentParams + + $masterSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "master").object.sha + $oldSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag).object.sha + Set-GithubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag -Sha $masterSHA + + It 'Should return the updated SHA when the reference is queried after update' { + $newSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag).object.sha + $newSHA | Should -Be $masterSHA + $newSHA | Should -Not -Be $oldSHA + } + } + + Context 'On updating a tag to a valid SHA with repo on pipeline' { + $setGitHubContentParams = @{ + Path = 'test.txt' + CommitMessage = 'Commit Message' + Branch = $masterBranchName + Content = 'This is the content for test.txt' + Uri = $repo.svn_url + } + + Set-GitHubContent @setGitHubContentParams + + $masterSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "master").object.sha + $oldSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag).object.sha + $repo | Set-GithubReference -TagName $tag -Sha $masterSHA + + It 'Should return the updated SHA when the reference is queried after update' { + $newSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag).object.sha + $newSHA | Should -Be $masterSHA + $newSHA | Should -Not -Be $oldSHA + } + } + + Context 'On updating a tag to a valid SHA with tag reference on pipeline' { + $setGitHubContentParams = @{ + Path = 'test.txt' + CommitMessage = 'Commit Message' + Branch = $masterBranchName + Content = 'This is the content for test.txt' + Uri = $repo.svn_url + } + + Set-GitHubContent @setGitHubContentParams + + $masterSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -BranchName "master").object.sha + $tagRef = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag) + $oldSHA = $tagRef.object.sha + $tagRef | Set-GithubReference -Sha $masterSHA + + It 'Should return the updated SHA when the reference is queried after update' { + $newSHA = $(Get-GitHubReference -OwnerName $script:ownerName -RepositoryName $repo.name -TagName $tag).object.sha + $newSHA | Should -Be $masterSHA + $newSHA | Should -Not -Be $oldSHA + } + } + } +} +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 + } +} \ No newline at end of file