Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the behavior of Get-GitHubRepository #179

Merged
merged 1 commit into from
May 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions GitHubCore.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
mediaTypeVersion = 'v3'
squirrelAcceptHeader = 'application/vnd.github.squirrel-girl-preview'
symmetraAcceptHeader = 'application/vnd.github.symmetra-preview+json'
mercyAcceptHeader = 'application/vnd.github.mercy-preview+json'
nebulaAcceptHeader = 'application/vnd.github.nebula-preview+json'
baptisteAcceptHeader = 'application/vnd.github.baptiste-preview+json'
scarletWitchAcceptHeader = 'application/vnd.github.scarlet-witch-preview+json'
dorianAcceptHeader = 'application/vnd.github.dorian-preview+json'
londonAcceptHeader = 'application/vnd.github.london-preview+json'

}.GetEnumerator() | ForEach-Object {
Set-Variable -Scope Script -Option ReadOnly -Name $_.Key -Value $_.Value
Expand Down
169 changes: 138 additions & 31 deletions GitHubRepositories.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,12 @@ function Get-GitHubRepository
.PARAMETER GetAllPublicRepositories
If this is specified with no other parameter, then instead of returning back all
repositories for the current authenticated user, it will instead return back all
public repositories on GitHub.
public repositories on GitHub in the order in which they were created.

.PARAMETER Since
The ID of the last public repository that you have seen. If specified with
-GetAllPublicRepositories, will only return back public repositories created _after_ this
one.

.PARAMETER AccessToken
If provided, this will be used as the AccessToken for authentication with the
Expand All @@ -340,24 +345,30 @@ function Get-GitHubRepository
Gets all public repositories on GitHub.

.EXAMPLE
Get-GitHubRepository -OctoCat OctoCat
Get-GitHubRepository -OwnerName octocat

Gets all of the repositories for the user octocat

.EXAMPLE
Get-GitHubRepository -Uri https://github.com/PowerShell/PowerShellForGitHub
Get-GitHubRepository -Uri https://github.com/microsoft/PowerShellForGitHub

Gets information about the microsoft/PowerShellForGitHub repository.

.EXAMPLE
Get-GitHubRepository -OrganizationName PowerShell

Gets all of the repositories in the PowerShell organization.
#>
[CmdletBinding(
SupportsShouldProcess,
DefaultParameterSetName='Elements')]
DefaultParameterSetName='AuthenticatedUser')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "", Justification="Methods called within here make use of PSShouldProcess, and the switch is passed on to them inherently.")]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "", Justification="One or more parameters (like NoStatus) are only referenced by helper methods which get access to it from the stack via Get-Variable -Scope 1.")]
param(
[Parameter(ParameterSetName='Elements')]
[Parameter(ParameterSetName='ElementsOrUser')]
[string] $OwnerName,

[Parameter(ParameterSetName='Elements')]
[Parameter(ParameterSetName='ElementsOrUser')]
[string] $RepositoryName,

[Parameter(
Expand All @@ -369,21 +380,36 @@ function Get-GitHubRepository
[string] $OrganizationName,

[ValidateSet('All', 'Public', 'Private')]
[Parameter(ParameterSetName='AuthenticatedUser')]
[string] $Visibility,

[Parameter(ParameterSetName='AuthenticatedUser')]
[string[]] $Affiliation,

[Parameter(ParameterSetName='AuthenticatedUser')]
[Parameter(ParameterSetName='ElementsOrUser')]
[Parameter(ParameterSetName='Organization')]
[ValidateSet('All', 'Owner', 'Public', 'Private', 'Member', 'Forks', 'Sources')]
[string] $Type,

[Parameter(ParameterSetName='AuthenticatedUser')]
[Parameter(ParameterSetName='ElementsOrUser')]
[Parameter(ParameterSetName='Organization')]
[ValidateSet('Created', 'Updated', 'Pushed', 'FullName')]
[string] $Sort,

[Parameter(ParameterSetName='AuthenticatedUser')]
[Parameter(ParameterSetName='ElementsOrUser')]
[Parameter(ParameterSetName='Organization')]
[ValidateSet('Ascending', 'Descending')]
[string] $Direction,

[Parameter(ParameterSetName='PublicRepos')]
[switch] $GetAllPublicRepositories,

[Parameter(ParameterSetName='PublicRepos')]
[int64] $Since,

[string] $AccessToken,

[switch] $NoStatus
Expand All @@ -395,36 +421,115 @@ function Get-GitHubRepository
$OwnerName = $elements.ownerName
$RepositoryName = $elements.repositoryName

$telemetryProperties = @{}
$telemetryProperties = @{
'UsageType' = $PSCmdlet.ParameterSetName
}

$uriFragment = [String]::Empty
$description = [String]::Empty
if ((-not [String]::IsNullOrEmpty($OwnerName)) -and (-not [String]::IsNullOrEmpty($RepositoryName)))
switch ($PSCmdlet.ParameterSetName)
{
$telemetryProperties['OwnerName'] = Get-PiiSafeString -PlainText $OwnerName
$telemetryProperties['RepositoryName'] = Get-PiiSafeString -PlainText $RepositoryName
{ ('ElementsOrUser', 'Uri') -contains $_ } {
# This is a little tricky. Ideally we'd have two separate ParameterSets (Elements, User),
# however PowerShell would be unable to disambiguate between the two, so unfortunately
# we need to do some additional work here. And because fallthru doesn't appear to be
# working right, we're combining both of those, along with Uri.

if ([String]::IsNullOrWhiteSpace($OwnerName))
{
$message = 'OwnerName could not be determined.'
Write-Log -Message $message -Level Error
throw $message
}
elseif ([String]::IsNullOrWhiteSpace($RepositoryName))
{
if ($PSCmdlet.ParameterSetName -eq 'ElementsOrUser')
{
$telemetryProperties['UsageType'] = 'User'
$telemetryProperties['OwnerName'] = Get-PiiSafeString -PlainText $OwnerName

$uriFragment = "users/$OwnerName/repos"
$description = "Getting repos for $OwnerName"
}
else
{
$message = 'RepositoryName could not be determined.'
Write-Log -Message $message -Level Error
throw $message
}
}
else
{
if ($PSCmdlet.ParameterSetName -eq 'ElementsOrUser')
{
$telemetryProperties['UsageType'] = 'Elements'

if ($PSBoundParameters.ContainsKey('Type') -or
$PSBoundParameters.ContainsKey('Sort') -or
$PSBoundParameters.ContainsKey('Direction'))
{
$message = 'Unable to specify -Type, -Sort and/or -Direction when retrieving a specific repository.'
Write-Log -Message $message -Level Error
throw $message
}
}

$telemetryProperties['OwnerName'] = Get-PiiSafeString -PlainText $OwnerName
$telemetryProperties['RepositoryName'] = Get-PiiSafeString -PlainText $RepositoryName

$uriFragment = "repos/$OwnerName/$RepositoryName"
$description = "Getting $OwnerName/$RepositoryName"
}

$uriFragment = "repos/$OwnerName/$RepositoryName"
$description = "Getting repo $RepositoryName"
}
elseif ([String]::IsNullOrEmpty($OwnerName) -and [String]::IsNullOrEmpty($OrganizationName))
{
$uriFragment = 'user/repos'
$description = 'Getting repos for current authenticated user'
}
elseif ([String]::IsNullOrEmpty($OwnerName))
{
$telemetryProperties['OrganizationName'] = Get-PiiSafeString -PlainText $OrganizationName
break
}

$uriFragment = "orgs/$OrganizationName/repos"
$description = "Getting repos for $OrganizationName"
}
else
{
$telemetryProperties['OwnerName'] = Get-PiiSafeString -PlainText $OwnerName
'Organization' {

$telemetryProperties['OrganizationName'] = Get-PiiSafeString -PlainText $OrganizationName

$uriFragment = "orgs/$OrganizationName/repos"
$description = "Getting repos for $OrganizationName"

break
}

'User' {
$telemetryProperties['OwnerName'] = Get-PiiSafeString -PlainText $OwnerName

$uriFragment = "users/$OwnerName/repos"
$description = "Getting repos for $OwnerName"

break
}

'AuthenticatedUser' {
if ($PSBoundParameters.ContainsKey('Type') -and
($PSBoundParameters.ContainsKey('Visibility') -or
$PSBoundParameters.ContainsKey('Affiliation')))
{
$message = 'Unable to specify -Type when using -Visibility and/or -Affiliation.'
Write-Log -Message $message -Level Error
throw $message
}

$uriFragment = 'user/repos'
$description = 'Getting repos for current authenticated user'

break
}

'PublicRepos' {
$uriFragment = 'repositories'
$description = "Getting all public repositories"

$uriFragment = "users/$OwnerName/repos"
$description = "Getting repos for $OwnerName"
if ($PSBoundParameters.ContainsKey('Since'))
{
$description += " since $Since"
}

break
}
}

$sortConverter = @{
Expand All @@ -448,10 +553,12 @@ function Get-GitHubRepository
{
$getParams += "affiliation=$($Affiliation -join ',')"
}
if ($PSBoundParameters.ContainsKey('Since')) { $getParams += "since=$Since" }

$params = @{
'UriFragment' = $uriFragment + '?' + ($getParams -join '&')
'Description' = $description
'AcceptHeader' = "$script:nebulaAcceptHeader,$script:baptisteAcceptHeader,$script:mercyAcceptHeader"
'AccessToken' = $AccessToken
'TelemetryEventName' = $MyInvocation.MyCommand.Name
'TelemetryProperties' = $telemetryProperties
Expand Down Expand Up @@ -810,7 +917,7 @@ function Get-GitHubRepositoryTopic
'UriFragment' = "repos/$OwnerName/$RepositoryName/topics"
'Method' = 'Get'
'Description' = "Getting topics for $RepositoryName"
'AcceptHeader' = 'application/vnd.github.mercy-preview+json'
'AcceptHeader' = $script:mercyAcceptHeader
'AccessToken' = $AccessToken
'TelemetryEventName' = $MyInvocation.MyCommand.Name
'TelemetryProperties' = $telemetryProperties
Expand Down Expand Up @@ -933,7 +1040,7 @@ function Set-GitHubRepositoryTopic
'Body' = (ConvertTo-Json -InputObject $hashBody)
'Method' = 'Put'
'Description' = $description
'AcceptHeader' = 'application/vnd.github.mercy-preview+json'
'AcceptHeader' = $script:mercyAcceptHeader
'AccessToken' = $AccessToken
'TelemetryEventName' = $MyInvocation.MyCommand.Name
'TelemetryProperties' = $telemetryProperties
Expand Down
103 changes: 101 additions & 2 deletions Tests/GitHubRepositories.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,107 @@ $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent

try
{
Describe 'Modifying repositories' {
Describe 'Getting repositories' {
Context 'For authenticated user' {
BeforeAll -Scriptblock {
$publicRepo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) -AutoInit
$privateRepo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) -AutoInit -Private

# Avoid PSScriptAnalyzer PSUseDeclaredVarsMoreThanAssignments
$publicRepo = $publicRepo
$privateRepo = $privateRepo
}

$publicRepos = Get-GitHubRepository -Visibility Public
$privateRepos = Get-GitHubRepository -Visibility Private

It "Should have the public repo" {
$publicRepo.Name | Should BeIn $publicRepos.Name
$publicRepo.Name | Should Not BeIn $privateRepos.Name
}

It "Should have the private repo" {
$privateRepo.Name | Should BeIn $privateRepos.Name
$privateRepo.Name | Should Not BeIn $publicRepos.Name
}

It 'Should not permit bad combination of parameters' {
{ Get-GitHubRepository -Type All -Visibility All } | Should Throw
{ Get-GitHubRepository -Type All -Affiliation Owner } | Should Throw
}

AfterAll -ScriptBlock {
Remove-GitHubRepository -Uri $publicRepo.svn_url
Remove-GitHubRepository -Uri $privateRepo.svn_url
}
}

Context 'For any user' {
$repos = Get-GitHubRepository -OwnerName 'octocat' -Type Public

It "Should have results for The Octocat" {
$repos.Count | Should -BeGreaterThan 0
$repos[0].owner.login | Should Be 'octocat'
}
}

Context 'For organizations' {
BeforeAll -Scriptblock {
$repo = New-GitHubRepository -OrganizationName $script:organizationName -RepositoryName ([Guid]::NewGuid().Guid) -AutoInit

# Avoid PSScriptAnalyzer PSUseDeclaredVarsMoreThanAssignments
$repo = $repo
}

$repos = Get-GitHubRepository -OrganizationName $script:organizationName -Type All
It "Should have results for the organization" {
$repo.name | Should BeIn $repos.name
}

AfterAll -ScriptBlock {
Remove-GitHubRepository -Uri $repo.svn_url
}
}

Context 'For public repos' {
# Skipping these tests for now, as it would run for a _very_ long time.
# No obviously good way to verify this.
}

Context 'For a specific repo' {
BeforeAll -Scriptblock {
$repo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) -AutoInit

# Avoid PSScriptAnalyzer PSUseDeclaredVarsMoreThanAssignments
$repo = $repo
}

$returned = Get-GitHubRepository -Uri $repo.svn_url
It "Should be a single result using Uri ParameterSet" {
$returned | Should -BeOfType PSCustomObject
}

$returned = Get-GitHubRepository -OwnerName $repo.owner.login -RepositoryName $repo.Name
It "Should be a single result using Elements ParameterSet" {
$returned | Should -BeOfType PSCustomObject
}

It 'Should not permit additional parameters' {
{ Get-GitHubRepository -OwnerName $repo.owner.login -RepositoryName $repo.Name -Type All } | Should Throw
}

It 'Should require both OwnerName and RepositoryName' {
{ Get-GitHubRepository -RepositoryName $repo.Name } | Should Throw
{ Get-GitHubRepository -Uri "https://github.com/$script:ownerName" } | Should Throw
}

AfterAll -ScriptBlock {
Remove-GitHubRepository -Uri $repo.svn_url
}
}
}

Describe 'Modifying repositories' {
Context -Name 'For renaming a repository' -Fixture {
BeforeEach -Scriptblock {
$repo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) -AutoInit
Expand All @@ -35,7 +134,7 @@ try
## cleanup temp testing repository
AfterEach -Scriptblock {
## variables from BeforeEach scriptblock are accessible here, but not variables from It scriptblocks, so need to make URI (instead of being able to use $renamedRepo variable from It scriptblock)
Remove-GitHubRepository -Uri "$($repo.svn_url)$suffixToAddToRepo" -Verbose
Remove-GitHubRepository -Uri "$($repo.svn_url)$suffixToAddToRepo"
}
}
}
Expand Down