From 9ef3c2b5670fc7b640a47a33d0aa725c63319839 Mon Sep 17 00:00:00 2001 From: Howard Wolosky Date: Fri, 14 Aug 2020 16:41:20 -0700 Subject: [PATCH] Improvements to GitHub Team API's (#275) #257 did a fantastic job closing the gap on missing functionality in the module related to GitHub Teams. This PR just adds onto that work by providing options that will reduce the need for additional queries during common operations. * `Get-GitHubTeam`: **Breaking Change** Looking up a team by its `ID` has been deprecated per GitHub documentation. Removed that functionality and added the ability to look up by `slug` instead. This also means that you can now pipe in a team and get back the specific result without needing to filter through all org results. * `Get-GitHubTeamMember`: Updated to use the `slug` instead of the team `ID`. * `New-GitHubTeam`: Added ability to pass in the `ParentTeamId` (also via the pipeline) to avoid the need to query through all org teams. * `Set-GitHubTeam`: Added ability to pass in the team `slug` (also via the pipeline) to avoid the need to query through all org teams. Similar to `New-GitHubTeam`, also added the ability to pass-in the `ParentTeamId` to avoid the full org team lookup. * `Remove-GitHubTeam`: Added ability to pass in the team `slug` (also via the pipeline) to avoid the need to query through all org teams. * Added `Rename-GitHubTeam` as a helper/wrapper on top of `Set-GitHubTeam` * Added additional pipeline tests for existing functions * Added new tests for `Rename-GitHubTeam` and `Get-GitHubTeamMember` * Small update to formatters to simplify the display of the team parent References: [GitHub Teams API](https://developer.github.com/v3/teams/) --- Formatters/GitHubTeams.Format.ps1xml | 22 +- GitHubTeams.ps1 | 320 +++++++++++++++++---- PowerShellForGitHub.psd1 | 1 + Tests/GitHubTeams.tests.ps1 | 399 +++++++++++++++++++++++---- 4 files changed, 632 insertions(+), 110 deletions(-) diff --git a/Formatters/GitHubTeams.Format.ps1xml b/Formatters/GitHubTeams.Format.ps1xml index 7b08c7d6..449db6b5 100644 --- a/Formatters/GitHubTeams.Format.ps1xml +++ b/Formatters/GitHubTeams.Format.ps1xml @@ -8,6 +8,23 @@ GitHub.TeamSummary + + + + + + + + + + + + + + + + + @@ -57,7 +74,7 @@ created_at - updated_at + created_at members_count @@ -66,7 +83,8 @@ repos_count - parent + + $_.parent.name OrganizationName diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 94af89ec..ecf9475d 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -33,13 +33,15 @@ filter Get-GitHubTeam them individually. .PARAMETER OrganizationName - The name of the organization + The name of the organization. .PARAMETER TeamName - The name of the specific team to retrieve + The name of the specific team to retrieve. + Note: This will be slower than querying by TeamSlug since it requires retrieving + all teams first. - .PARAMETER TeamId - The ID of the specific team to retrieve + .PARAMETER TeamSlug + The slug (a unique key based on the team name) of the specific team to retrieve. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the @@ -78,15 +80,20 @@ filter Get-GitHubTeam param ( [Parameter(ParameterSetName='Elements')] + [Parameter(ParameterSetName='TeamName')] [string] $OwnerName, [Parameter(ParameterSetName='Elements')] + [Parameter(ParameterSetName='TeamName')] [string] $RepositoryName, [Parameter( Mandatory, ValueFromPipelineByPropertyName, ParameterSetName='Uri')] + [Parameter( + ValueFromPipelineByPropertyName, + ParameterSetName='TeamName')] [Alias('RepositoryUrl')] [string] $Uri, @@ -94,20 +101,28 @@ filter Get-GitHubTeam Mandatory, ValueFromPipelineByPropertyName, ParameterSetName='Organization')] + [Parameter( + ValueFromPipelineByPropertyName, + ParameterSetName='TeamName')] + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TeamSlug')] [ValidateNotNullOrEmpty()] [string] $OrganizationName, - [Parameter(ParameterSetName='Organization')] - [Parameter(ParameterSetName='Elements')] - [Parameter(ParameterSetName='Uri')] + [Parameter( + Mandatory, + ParameterSetName='TeamName')] + [ValidateNotNullOrEmpty()] [string] $TeamName, [Parameter( Mandatory, ValueFromPipelineByPropertyName, - ParameterSetName='Single')] + ParameterSetName='TeamSlug')] [ValidateNotNullOrEmpty()] - [string] $TeamId, + [string] $TeamSlug, [string] $AccessToken ) @@ -119,12 +134,18 @@ filter Get-GitHubTeam $uriFragment = [String]::Empty $description = [String]::Empty $teamType = [String]::Empty - if ($PSCmdlet.ParameterSetName -in ('Elements', 'Uri')) + + if ($PSBoundParameters.ContainsKey('TeamName') -and + (-not $PSBoundParameters.ContainsKey('OrganizationName'))) { $elements = Resolve-RepositoryElements $OwnerName = $elements.ownerName $RepositoryName = $elements.repositoryName + } + if ((-not [String]::IsNullOrEmpty($OwnerName)) -and + (-not [String]::IsNullOrEmpty($RepositoryName))) + { $telemetryProperties['OwnerName'] = Get-PiiSafeString -PlainText $OwnerName $telemetryProperties['RepositoryName'] = Get-PiiSafeString -PlainText $RepositoryName @@ -132,21 +153,21 @@ filter Get-GitHubTeam $description = "Getting teams for $RepositoryName" $teamType = $script:GitHubTeamSummaryTypeName } - elseif ($PSCmdlet.ParameterSetName -eq 'Organization') + elseif ($PSCmdlet.ParameterSetName -eq 'TeamSlug') { - $telemetryProperties['OrganizationName'] = Get-PiiSafeString -PlainText $OrganizationName + $telemetryProperties['TeamSlug'] = Get-PiiSafeString -PlainText $TeamSlug - $uriFragment = "/orgs/$OrganizationName/teams" - $description = "Getting teams in $OrganizationName" - $teamType = $script:GitHubTeamSummaryTypeName + $uriFragment = "/orgs/$OrganizationName/teams/$TeamSlug" + $description = "Getting team $TeamSlug" + $teamType = $script:GitHubTeamTypeName } else { - $telemetryProperties['TeamId'] = Get-PiiSafeString -PlainText $TeamId + $telemetryProperties['OrganizationName'] = Get-PiiSafeString -PlainText $OrganizationName - $uriFragment = "/teams/$TeamId" - $description = "Getting team $TeamId" - $teamType = $script:GitHubTeamTypeName + $uriFragment = "/orgs/$OrganizationName/teams" + $description = "Getting teams in $OrganizationName" + $teamType = $script:GitHubTeamSummaryTypeName } $params = @{ @@ -204,13 +225,13 @@ filter Get-GitHubTeamMember The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub .PARAMETER OrganizationName - The name of the organization + The name of the organization. .PARAMETER TeamName - The name of the team in the organization + The name of the team in the organization. - .PARAMETER TeamId - The ID of the team in the organization + .PARAMETER TeamSlug + The slug (a unique key based on the team name) of the team in the organization. .PARAMETER AccessToken If provided, this will be used as the AccessToken for authentication with the @@ -239,7 +260,7 @@ filter Get-GitHubTeamMember .EXAMPLE $members = Get-GitHubTeamMember -Organization PowerShell -TeamName Everybody #> - [CmdletBinding(DefaultParameterSetName = 'ID')] + [CmdletBinding(DefaultParameterSetName = 'Slug')] [OutputType({$script:GitHubUserTypeName})] param ( @@ -259,8 +280,8 @@ filter Get-GitHubTeamMember [Parameter( Mandatory, ValueFromPipelineByPropertyName, - ParameterSetName='ID')] - [int64] $TeamId, + ParameterSetName='Slug')] + [string] $TeamSlug, [string] $AccessToken ) @@ -278,18 +299,18 @@ filter Get-GitHubTeamMember throw $message } - $TeamId = $team.id + $TeamSlug = $team.slug } $telemetryProperties = @{ 'OrganizationName' = (Get-PiiSafeString -PlainText $OrganizationName) 'TeamName' = (Get-PiiSafeString -PlainText $TeamName) - 'TeamId' = (Get-PiiSafeString -PlainText $TeamId) + 'TeamSlug' = (Get-PiiSafeString -PlainText $TeamSlug) } $params = @{ - 'UriFragment' = "teams/$TeamId/members" - 'Description' = "Getting members of team $TeamId" + 'UriFragment' = "orgs/$OrganizationName/teams/$TeamSlug/members" + 'Description' = "Getting members of team $TeamSlug" 'AccessToken' = $AccessToken 'TelemetryEventName' = $MyInvocation.MyCommand.Name 'TelemetryProperties' = $telemetryProperties @@ -330,6 +351,9 @@ function New-GitHubTeam .PARAMETER ParentTeamName The name of a team to set as the parent team. + .PARAMETER ParentTeamId + The ID of the team to set as the parent team. + .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. @@ -361,7 +385,8 @@ function New-GitHubTeam #> [CmdletBinding( SupportsShouldProcess, - PositionalBinding = $false + PositionalBinding = $false, + DefaultParameterSetName = 'ParentId' )] [OutputType({$script:GitHubTeamTypeName})] param @@ -391,8 +416,15 @@ function New-GitHubTeam [ValidateSet('Secret', 'Closed')] [string] $Privacy, + [Parameter(ParameterSetName='ParentName')] [string] $ParentTeamName, + [Parameter( + ValueFromPipelineByPropertyName, + ParameterSetName='ParentId')] + [Alias('TeamId')] + [int64] $ParentTeamId, + [string] $AccessToken ) @@ -451,8 +483,12 @@ function New-GitHubTeam } $team = Get-GitHubTeam @getGitHubTeamParms + $ParentTeamId = $team.id + } - $hashBody['parent_team_id'] = $team.id + if ($ParentTeamId -gt 0) + { + $hashBody['parent_team_id'] = $ParentTeamId } if (-not $PSCmdlet.ShouldProcess($TeamName, 'Create GitHub Team')) @@ -491,6 +527,14 @@ filter Set-GitHubTeam .PARAMETER TeamName The name of the team. + When TeamSlug is specified, specifying a name here that is different from the existing + name will cause the team to be renamed. TeamSlug and TeamName are specified for you + automatically when piping in a GitHub.Team object, so a rename would only occur if + intentionally specify this parameter and provide a different name. + + .PARAMETER TeamSlug + The slug (a unique key based on the team name) of the team to update. + .PARAMETER Description The description for the team. @@ -500,6 +544,9 @@ filter Set-GitHubTeam .PARAMETER ParentTeamName The name of a team to set as the parent team. + .PARAMETER ParentTeamId + The ID of the team to set as the parent team. + .PARAMETER PassThru Returns the updated GitHub Team. By default, this cmdlet does not generate any output. You can use "Set-GitHubConfiguration -DefaultPassThru" to control the default behavior @@ -529,7 +576,8 @@ filter Set-GitHubTeam #> [CmdletBinding( SupportsShouldProcess, - PositionalBinding = $false + PositionalBinding = $false, + DefaultParameterSetName = 'ParentName' )] [OutputType( { $script:GitHubTeamTypeName } )] param @@ -548,13 +596,21 @@ filter Set-GitHubTeam [ValidateNotNullOrEmpty()] [string] $TeamName, + [Parameter(ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [string] $TeamSlug, + [string] $Description, [ValidateSet('Secret','Closed')] [string] $Privacy, + [Parameter(ParameterSetName='ParentTeamName')] [string] $ParentTeamName, + [Parameter(ParameterSetName='ParentTeamId')] + [int64] $ParentTeamId, + [switch] $PassThru, [string] $AccessToken @@ -564,22 +620,31 @@ filter Set-GitHubTeam $telemetryProperties = @{ OrganizationName = (Get-PiiSafeString -PlainText $OrganizationName) + TeamSlug = (Get-PiiSafeString -PlainText $TeamSlug) TeamName = (Get-PiiSafeString -PlainText $TeamName) } - $getGitHubTeamParms = @{ - OrganizationName = $OrganizationName - } - if ($PSBoundParameters.ContainsKey('AccessToken')) + if ((-not $PSBoundParameters.ContainsKey('TeamSlug')) -or + $PSBoundParameters.ContainsKey('ParentTeamName')) { - $getGitHubTeamParms['AccessToken'] = $AccessToken - } + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + } + if ($PSBoundParameters.ContainsKey('AccessToken')) + { + $getGitHubTeamParms['AccessToken'] = $AccessToken + } - $orgTeams = Get-GitHubTeam @getGitHubTeamParms + $orgTeams = Get-GitHubTeam @getGitHubTeamParms - $team = $orgTeams | Where-Object -Property name -eq $TeamName + if ($PSBoundParameters.ContainsKey('TeamName')) + { + $team = $orgTeams | Where-Object -Property name -eq $TeamName + $TeamSlug = $team.slug + } + } - $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" + $uriFragment = "/orgs/$OrganizationName/teams/$TeamSlug" $hashBody = @{ name = $TeamName @@ -590,11 +655,21 @@ filter Set-GitHubTeam if ($PSBoundParameters.ContainsKey('ParentTeamName')) { $parentTeam = $orgTeams | Where-Object -Property name -eq $ParentTeamName - $hashBody['parent_team_id'] = $parentTeam.id } + elseif ($PSBoundParameters.ContainsKey('ParentTeamId')) + { + if ($ParentTeamId -gt 0) + { + $hashBody['parent_team_id'] = $ParentTeamId + } + else + { + $hashBody['parent_team_id'] = $null + } + } - if (-not $PSCmdlet.ShouldProcess($TeamName, 'Set GitHub Team')) + if (-not $PSCmdlet.ShouldProcess($TeamSlug, 'Set GitHub Team')) { return } @@ -616,6 +691,118 @@ filter Set-GitHubTeam } } +filter Rename-GitHubTeam +{ +<# + .SYNOPSIS + Renames a team within an organization on GitHub. + + .DESCRIPTION + Renames a team within an organization on GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER OrganizationName + The name of the team's organization. + + .PARAMETER TeamName + The existing name of the team. + + .PARAMETER TeamSlug + The slug (a unique key based on the team name) of the team to update. + + .PARAMETER NewTeamName + The new name for the team. + + .PARAMETER PassThru + Returns the updated GitHub Team. By default, this cmdlet does not generate any output. + You can use "Set-GitHubConfiguration -DefaultPassThru" to control the default behavior + of this switch. + + .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. + + .INPUTS + GitHub.Organization + GitHub.Team + + .OUTPUTS + GitHub.Team + + .EXAMPLE + Rename-GitHubTeam -OrganizationName PowerShell -TeamName Developers -NewTeamName DeveloperTeam + + Renames the 'Developers' GitHub team in the 'PowerShell' organization to be 'DeveloperTeam'. + + .EXAMPLE + $team = Get-GitHubTeam -OrganizationName PowerShell -TeamName Developers + $team | Rename-GitHubTeam -NewTeamName 'DeveloperTeam' + + You can also pipe in a GitHub team that was returned from a previous command. + + .NOTES + This is a helper/wrapper for Set-GitHubTeam which can also rename a GitHub Team. +#> + [CmdletBinding( + PositionalBinding = $false, + DefaultParameterSetName = 'TeamSlug')] + [OutputType( { $script:GitHubTeamTypeName } )] + param + ( + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [ValidateNotNullOrEmpty()] + [string] $OrganizationName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 2, + ParameterSetName='TeamName')] + [ValidateNotNullOrEmpty()] + [string] $TeamName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TeamSlug')] + [ValidateNotNullOrEmpty()] + [string] $TeamSlug, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 3)] + [ValidateNotNullOrEmpty()] + [string] $NewTeamName, + + [switch] $PassThru, + + [string] $AccessToken + ) + + Write-InvocationLog + + if (-not $PSBoundParameters.ContainsKey('TeamSlug')) + { + $team = Get-GitHubTeam -OrganizationName $OrganizationName -TeamName $TeamName -AccessToken:$AccessToken + $TeamSlug = $team.slug + } + + $params = @{ + OrganizationName = $OrganizationName + TeamSlug = $TeamSlug + TeamName = $NewTeamName + PassThru = (Resolve-ParameterWithDefaultConfigurationValue -Name PassThru -ConfigValueName DefaultPassThru) + AccessToken = $AccessToken + } + + return Set-GitHubTeam @params +} + filter Remove-GitHubTeam { <# @@ -631,7 +818,10 @@ filter Remove-GitHubTeam The name of the organization the team is in. .PARAMETER TeamName - The name of the team. + The name of the team to remove. + + .PARAMETER TeamSlug + The slug (a unique key based on the team name) of the team to remove. .PARAMETER Force If this switch is specified, you will not be prompted for confirmation of command execution. @@ -666,8 +856,8 @@ filter Remove-GitHubTeam [CmdletBinding( SupportsShouldProcess, PositionalBinding = $false, - ConfirmImpact = 'High' - )] + ConfirmImpact = 'High', + DefaultParameterSetName = 'TeamSlug')] [Alias('Delete-GitHubTeam')] param ( @@ -683,10 +873,18 @@ filter Remove-GitHubTeam Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, - Position = 2)] + Position = 2, + ParameterSetName='TeamName')] [ValidateNotNullOrEmpty()] [string] $TeamName, + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + ParameterSetName='TeamSlug')] + [ValidateNotNullOrEmpty()] + [string] $TeamSlug, + [switch] $Force, [string] $AccessToken @@ -696,21 +894,26 @@ filter Remove-GitHubTeam $telemetryProperties = @{ OrganizationName = (Get-PiiSafeString -PlainText $RepositoryName) + TeamSlug = (Get-PiiSafeString -PlainText $TeamSlug) TeamName = (Get-PiiSafeString -PlainText $TeamName) } - $getGitHubTeamParms = @{ - OrganizationName = $OrganizationName - TeamName = $TeamName - } - if ($PSBoundParameters.ContainsKey('AccessToken')) + if ($PSBoundParameters.ContainsKey('TeamName')) { - $getGitHubTeamParms['AccessToken'] = $AccessToken - } + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + TeamName = $TeamName + } + if ($PSBoundParameters.ContainsKey('AccessToken')) + { + $getGitHubTeamParms['AccessToken'] = $AccessToken + } - $team = Get-GitHubTeam @getGitHubTeamParms + $team = Get-GitHubTeam @getGitHubTeamParms + $TeamSlug = $team.slug + } - $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" + $uriFragment = "/orgs/$OrganizationName/teams/$TeamSlug" if ($Force -and (-not $Confirm)) { @@ -725,7 +928,7 @@ filter Remove-GitHubTeam $params = @{ UriFragment = $uriFragment Method = 'Delete' - Description = "Deleting $TeamName" + Description = "Deleting $TeamSlug" AccessToken = $AccessToken TelemetryEventName = $MyInvocation.MyCommand.Name TelemetryProperties = $telemetryProperties @@ -774,6 +977,7 @@ filter Add-GitHubTeamAdditionalProperties { Add-Member -InputObject $item -Name 'TeamName' -Value $item.name -MemberType NoteProperty -Force Add-Member -InputObject $item -Name 'TeamId' -Value $item.id -MemberType NoteProperty -Force + Add-Member -InputObject $item -Name 'TeamSlug' -Value $item.slug -MemberType NoteProperty -Force $organizationName = [String]::Empty if ($item.organization) diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 10944b72..a17a3e7d 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -165,6 +165,7 @@ 'Remove-GitHubTeam', 'Rename-GitHubGistFile', 'Rename-GitHubRepository', + 'Rename-GitHubTeam', 'Reset-GitHubConfiguration', 'Restore-GitHubConfiguration', 'Set-GitHubAuthentication', diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index f6d4dda6..03035d7c 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -59,7 +59,7 @@ try $team.description | Should -Be $description $team.parent | Should -BeNullOrEmpty $team.privacy | Should -Be $privacy - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -79,25 +79,25 @@ try $team.updated_at | Should -Not -BeNullOrEmpty $team.members_count | Should -Be 1 $team.repos_count | Should -Be 0 - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } } - Context 'When specifying the "OrganizationName" parameter through the pipeline' { + Context 'When specifying the "OrganizationName" and "TeamSlug" through the pipeline' { BeforeAll { $orgTeams = $team | Get-GitHubTeam $team = $orgTeams | Where-Object -Property name -eq $teamName } It 'Should have the expected type and additional properties' { - $team.PSObject.TypeNames[0] | Should -Be 'GitHub.TeamSummary' + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' $team.name | Should -Be $teamName $team.description | Should -Be $description $team.parent | Should -BeNullOrEmpty $team.privacy | Should -Be $privacy - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -141,7 +141,7 @@ try $team.description | Should -Be $description $team.parent | Should -BeNullOrEmpty $team.privacy | Should -Be $privacy - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -167,7 +167,7 @@ try $team.updated_at | Should -Not -BeNullOrEmpty $team.members_count | Should -Be 1 $team.repos_count | Should -Be 1 - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -190,7 +190,7 @@ try $team.members_count | Should -Be 1 $team.repos_count | Should -Be 1 $team.privacy | Should -Be $privacy - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -209,7 +209,7 @@ try } } - Context 'When getting a GitHub Team by TeamId' { + Context 'When getting a GitHub Team by TeamSlug' { BeforeAll { $teamName = [Guid]::NewGuid().Guid $description = 'Team Description' @@ -225,11 +225,27 @@ try } $newTeam = New-GitHubTeam @newGithubTeamParms + } - $team = Get-GitHubTeam -TeamId $newTeam.id + It 'Should have the expected type and additional properties as a parameter' { + $team = Get-GitHubTeam -OrganizationName $script:organizationName -TeamSlug $newTeam.slug + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $team.name | Should -Be $teamName + $team.description | Should -Be $description + $team.organization.login | Should -Be $organizationName + $team.parent | Should -BeNullOrEmpty + $team.created_at | Should -Not -BeNullOrEmpty + $team.updated_at | Should -Not -BeNullOrEmpty + $team.members_count | Should -Be 1 + $team.repos_count | Should -Be 0 + $team.privacy | Should -Be $privacy + $team.TeamName | Should -Be $team.name + $team.TeamId | Should -Be $team.id + $team.OrganizationName | Should -Be $organizationName } - It 'Should have the expected type and additional properties' { + It 'Should have the expected type and additional properties via the pipeline' { + $team = $newTeam | Get-GitHubTeam $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' $team.name | Should -Be $teamName $team.description | Should -Be $description @@ -240,15 +256,15 @@ try $team.members_count | Should -Be 1 $team.repos_count | Should -Be 0 $team.privacy | Should -Be $privacy - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } AfterAll { - if (Get-Variable -Name team -ErrorAction SilentlyContinue) + if (Get-Variable -Name newTeam -ErrorAction SilentlyContinue) { - $team | Remove-GitHubTeam -Force + $newTeam | Remove-GitHubTeam -Force } } } @@ -278,7 +294,7 @@ try $team.parent | Should -BeNullOrEmpty $team.members_count | Should -Be 1 $team.repos_count | Should -Be 0 - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -329,7 +345,7 @@ try $team.members_count | Should -Be 1 $team.repos_count | Should -Be 1 $team.privacy | Should -Be $privacy - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -347,7 +363,7 @@ try } } - Context 'When creating a child GitHub team' { + Context 'When creating a child GitHub team using the Parent TeamName' { BeforeAll { $parentTeamName = [Guid]::NewGuid().Guid $privacy = 'Closed' @@ -378,7 +394,7 @@ try $childTeam.organization.login | Should -Be $organizationName $childTeam.parent.name | Should -Be $parentTeamName $childTeam.privacy | Should -Be $privacy - $childTeam.TeamName | Should -Be $childTeamName + $childTeam.TeamName | Should -Be $childTeam.name $childTeam.TeamId | Should -Be $childTeam.id $childTeam.OrganizationName | Should -Be $organizationName } @@ -396,44 +412,98 @@ try } } - Context 'When specifying the "Organization" parameter through the pipeline' { + Context 'When creating a child GitHub team using the Parent TeamId' { BeforeAll { - $teamName1 = [Guid]::NewGuid().Guid - $teamName2 = [Guid]::NewGuid().Guid + $parentTeamName = [Guid]::NewGuid().Guid + $privacy = 'Closed' $newGithubTeamParms = @{ OrganizationName = $organizationName - TeamName = $teamName1 + TeamName = $parentTeamName + Privacy = $privacy } - $team1 = New-GitHubTeam @newGithubTeamParms + $parentTeam = New-GitHubTeam @newGithubTeamParms - $team2 = $team1 | New-GitHubTeam -TeamName $teamName2 + $childTeamName = [Guid]::NewGuid().Guid + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $childTeamName + ParentTeamId = $parentTeam.id + Privacy = $privacy + } + + $childTeam = New-GitHubTeam @newGithubTeamParms } It 'Should have the expected type and additional properties' { - $team2.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' - $team2.name | Should -Be $teamName2 - $team2.organization.login | Should -Be $organizationName - $team2.parent | Should -BeNullOrEmpty - $team2.created_at | Should -Not -BeNullOrEmpty - $team2.updated_at | Should -Not -BeNullOrEmpty - $team2.members_count | Should -Be 1 - $team2.repos_count | Should -Be 0 - $team2.TeamName | Should -Be $teamName2 - $team2.TeamId | Should -Be $team2.id - $team2.OrganizationName | Should -Be $organizationName + $childTeam.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $childTeam.name | Should -Be $childTeamName + $childTeam.organization.login | Should -Be $organizationName + $childTeam.parent.name | Should -Be $parentTeamName + $childTeam.privacy | Should -Be $privacy + $childTeam.TeamName | Should -Be $childTeam.name + $childTeam.TeamId | Should -Be $childTeam.id + $childTeam.OrganizationName | Should -Be $organizationName } AfterAll { - if (Get-Variable -Name team1 -ErrorAction SilentlyContinue) + if (Get-Variable -Name childTeam -ErrorAction SilentlyContinue) { - $team1 | Remove-GitHubTeam -Force + $childTeam | Remove-GitHubTeam -Force } - if (Get-Variable -Name team2 -ErrorAction SilentlyContinue) + if (Get-Variable -Name parentTeam -ErrorAction SilentlyContinue) { - $team2 | Remove-GitHubTeam -Force + $parentTeam | Remove-GitHubTeam -Force + } + } + } + + Context 'When creating a child GitHub team using the Parent TeamId on the pipeline' { + BeforeAll { + $parentTeamName = [Guid]::NewGuid().Guid + $privacy = 'Closed' + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $parentTeamName + Privacy = $privacy + } + + $parentTeam = New-GitHubTeam @newGithubTeamParms + + $childTeamName = [Guid]::NewGuid().Guid + + $newGithubTeamParms = @{ + TeamName = $childTeamName + Privacy = $privacy + } + + $childTeam = $parentTeam | New-GitHubTeam @newGithubTeamParms + } + + It 'Should have the expected type and additional properties' { + $childTeam.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $childTeam.name | Should -Be $childTeamName + $childTeam.organization.login | Should -Be $organizationName + $childTeam.parent.name | Should -Be $parentTeamName + $childTeam.privacy | Should -Be $privacy + $childTeam.TeamName | Should -Be $childTeam.name + $childTeam.TeamId | Should -Be $childTeam.id + $childTeam.OrganizationName | Should -Be $organizationName + } + + AfterAll { + if (Get-Variable -Name childTeam -ErrorAction SilentlyContinue) + { + $childTeam | Remove-GitHubTeam -Force + } + + if (Get-Variable -Name parentTeam -ErrorAction SilentlyContinue) + { + $parentTeam | Remove-GitHubTeam -Force } } } @@ -454,7 +524,7 @@ try $team.updated_at | Should -Not -BeNullOrEmpty $team.members_count | Should -Be 1 $team.repos_count | Should -Be 0 - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -484,7 +554,7 @@ try $team.updated_at | Should -Not -BeNullOrEmpty $team.members_count | Should -Be 1 $team.repos_count | Should -Be 0 - $team.TeamName | Should -Be $teamName + $team.TeamName | Should -Be $team.name $team.TeamId | Should -Be $team.id $team.OrganizationName | Should -Be $organizationName } @@ -544,7 +614,7 @@ try $updatedTeam.description | Should -Be $description $updatedTeam.parent.name | Should -Be $parentTeamName $updatedTeam.privacy | Should -Be $privacy - $updatedTeam.TeamName | Should -Be $teamName + $updatedTeam.TeamName | Should -Be $team.name $updatedTeam.TeamId | Should -Be $team.id $updatedTeam.OrganizationName | Should -Be $organizationName } @@ -597,7 +667,7 @@ try $updatedTeam.updated_at | Should -Not -BeNullOrEmpty $updatedTeam.members_count | Should -Be 1 $updatedTeam.repos_count | Should -Be 0 - $updatedTeam.TeamName | Should -Be $teamName + $updatedTeam.TeamName | Should -Be $team.name $updatedTeam.TeamId | Should -Be $team.id $updatedTeam.OrganizationName | Should -Be $organizationName } @@ -610,6 +680,65 @@ try } } + Context 'When updating a GitHub team to be a child using the Parent TeamId' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $parentTeamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'Closed' + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $parentTeamName + Privacy = $privacy + } + + $parentTeam = New-GitHubTeam @newGithubTeamParms + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + Privacy = $privacy + } + + $team = New-GitHubTeam @newGithubTeamParms + + $updateGitHubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + Description = $description + Privacy = $privacy + ParentTeamId = $parentTeam.id + } + + $updatedTeam = Set-GitHubTeam @updateGitHubTeamParms -PassThru + } + + It 'Should have the expected type and additional properties' { + $updatedTeam.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $updatedTeam.name | Should -Be $teamName + $updatedTeam.organization.login | Should -Be $organizationName + $updatedTeam.description | Should -Be $description + $updatedTeam.parent.name | Should -Be $parentTeamName + $updatedTeam.privacy | Should -Be $privacy + $updatedTeam.TeamName | Should -Be $team.name + $updatedTeam.TeamId | Should -Be $team.id + $updatedTeam.OrganizationName | Should -Be $organizationName + } + + AfterAll { + if (Get-Variable -Name team -ErrorAction SilentlyContinue) + { + $team | Remove-GitHubTeam -Force + } + + if (Get-Variable -Name parentTeam -ErrorAction SilentlyContinue) + { + $parentTeam | Remove-GitHubTeam -Force + } + } + } + Context 'When specifying the "Organization" and "TeamName" parameters through the pipeline' { BeforeAll { $teamName = [Guid]::NewGuid().Guid @@ -620,7 +749,7 @@ try TeamName = $teamName } - $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + $team = New-GitHubTeam @newGithubTeamParms $updatedTeam = $team | Set-GitHubTeam -Description $description -PassThru } @@ -635,7 +764,7 @@ try $updatedTeam.updated_at | Should -Not -BeNullOrEmpty $updatedTeam.members_count | Should -Be 1 $updatedTeam.repos_count | Should -Be 0 - $updatedTeam.TeamName | Should -Be $teamName + $updatedTeam.TeamName | Should -Be $team.name $updatedTeam.TeamId | Should -Be $updatedTeam.id $updatedTeam.OrganizationName | Should -Be $organizationName } @@ -649,12 +778,113 @@ try } } + Describe 'GitHubTeams\Rename-GitHubTeam' { + BeforeAll { + $organizationName = $script:organizationName + $teamName = [Guid]::NewGuid().Guid + $newTeamName = [Guid]::NewGuid().Guid + } + + Context 'When renaming a GitHub team with the TeamName' { + BeforeAll { + $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + } + + $updatedTeam = Rename-GitHubTeam -OrganizationName $organizationName -TeamName $teamName -NewTeamName $newTeamName -PassThru + It 'Should have the expected type and additional properties' { + $updatedTeam.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $updatedTeam.name | Should -Be $newTeamName + $updatedTeam.organization.login | Should -Be $OrganizationName + $updatedTeam.description | Should -BeNullOrEmpty + $updatedTeam.parent.name | Should -BeNullOrEmpty + $updatedTeam.created_at | Should -Not -BeNullOrEmpty + $updatedTeam.updated_at | Should -Not -BeNullOrEmpty + $updatedTeam.members_count | Should -Be 1 + $updatedTeam.repos_count | Should -Be 0 + $updatedTeam.TeamName | Should -Be $updatedTeam.name + $updatedTeam.TeamId | Should -Be $updatedTeam.id + $updatedTeam.OrganizationName | Should -Be $organizationName + } + + It 'Should find the renamed team' { + { Get-GitHubTeam -OrganizationName $organizationName -TeamName $newTeamName } | + Should -Not -Throw + } + + AfterAll { + Remove-GitHubTeam -OrganizationName $organizationName -TeamName $newTeamName -Force + } + } + + Context 'When renaming a GitHub team with the TeamSlug' { + BeforeAll { + $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + } + + $updatedTeam = Rename-GitHubTeam -OrganizationName $organizationName -TeamSlug $team.slug -NewTeamName $newTeamName -PassThru + It 'Should have the expected type and additional properties' { + $updatedTeam.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $updatedTeam.name | Should -Be $newTeamName + $updatedTeam.organization.login | Should -Be $OrganizationName + $updatedTeam.description | Should -BeNullOrEmpty + $updatedTeam.parent.name | Should -BeNullOrEmpty + $updatedTeam.created_at | Should -Not -BeNullOrEmpty + $updatedTeam.updated_at | Should -Not -BeNullOrEmpty + $updatedTeam.members_count | Should -Be 1 + $updatedTeam.repos_count | Should -Be 0 + $updatedTeam.TeamName | Should -Be $updatedTeam.name + $updatedTeam.TeamId | Should -Be $updatedTeam.id + $updatedTeam.OrganizationName | Should -Be $organizationName + } + + It 'Should find the renamed team' { + { Get-GitHubTeam -OrganizationName $organizationName -TeamName $newTeamName } | + Should -Not -Throw + } + + AfterAll { + Remove-GitHubTeam -OrganizationName $organizationName -TeamName $newTeamName -Force + } + } + + Context 'When renaming a GitHub team with the TeamSlug on the pipeline' { + BeforeAll { + $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + } + + $updatedTeam = $team | Rename-GitHubTeam -NewTeamName $newTeamName -PassThru + It 'Should have the expected type and additional properties' { + $updatedTeam.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $updatedTeam.name | Should -Be $newTeamName + $updatedTeam.organization.login | Should -Be $OrganizationName + $updatedTeam.description | Should -BeNullOrEmpty + $updatedTeam.parent.name | Should -BeNullOrEmpty + $updatedTeam.created_at | Should -Not -BeNullOrEmpty + $updatedTeam.updated_at | Should -Not -BeNullOrEmpty + $updatedTeam.members_count | Should -Be 1 + $updatedTeam.repos_count | Should -Be 0 + $updatedTeam.TeamName | Should -Be $updatedTeam.name + $updatedTeam.TeamId | Should -Be $updatedTeam.id + $updatedTeam.OrganizationName | Should -Be $organizationName + } + + It 'Should find the renamed team' { + { Get-GitHubTeam -OrganizationName $organizationName -TeamName $newTeamName } | + Should -Not -Throw + } + + AfterAll { + Remove-GitHubTeam -OrganizationName $organizationName -TeamName $newTeamName -Force + } + } + } + Describe 'GitHubTeams\Remove-GitHubTeam' { BeforeAll { $organizationName = $script:organizationName } - Context 'When removing a GitHub team' { + Context 'When removing a GitHub team with the TeamName' { BeforeAll { $teamName = [Guid]::NewGuid().Guid @@ -677,23 +907,92 @@ try } } - Context 'When specifying the "Organization" and "TeamName" parameters through the pipeline' { + Context 'When removing a GitHub team with the TeamSlug' { BeforeAll { $teamName = [Guid]::NewGuid().Guid - $description = 'Team Description' $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName } It 'Should not throw an exception' { - { $team |Remove-GitHubTeam -Force } | Should -Not -Throw + $removeGitHubTeamParms = @{ + OrganizationName = $organizationName + TeamSlug = $team.slug + Confirm = $false + } + + { Remove-GitHubTeam @RemoveGitHubTeamParms } | Should -Not -Throw } It 'Should have removed the team' { - { Get-GitHubTeam -OrganizationName $organizationName -TeamName $teamName } | + { Get-GitHubTeam -OrganizationName $organizationName -TeamSlug $team.slug } | Should -Throw } } + + Context 'When removing a GitHub team with the TeamSlug on the pipeline' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + + $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + } + + It 'Should not throw an exception' { + { $team | Remove-GitHubTeam -Force } | Should -Not -Throw + } + + It 'Should have removed the team' { + { $team | Get-GitHubTeam } | Should -Throw + } + } + } + + Describe 'GitHubTeams\Get-GitHubTeamMember' { + BeforeAll { + $organizationName = $script:organizationName + $teamName = [Guid]::NewGuid().Guid + $team = New-GitHubTeam -OrganizationName $organizationName -TeamName $teamName + } + + AfterAll { + $team | Remove-GitHubTeam -Force + } + + Context 'Getting team members using TeamName' { + $members = @(Get-GitHubTeamMember -OrganizationName $organizationName -TeamName $teamName) + + It 'Should have the expected type number of members' { + $members.Count | Should -Be 1 + } + + It 'Should have the expected type and additional properties' { + $members[0].PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + Context 'Getting team members using TeamSlug' { + $members = @(Get-GitHubTeamMember -OrganizationName $organizationName -TeamSlug $team.slug) + + It 'Should have the expected type number of members' { + $members.Count | Should -Be 1 + } + + It 'Should have the expected type and additional properties' { + $members[0].PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } + + Context 'Getting team members using TeamSlug on the pipeline' { + $members = @($team | Get-GitHubTeamMember) + + It 'Should have the expected type number of members' { + $members.Count | Should -Be 1 + } + + It 'Should have the expected type and additional properties' { + $members[0].PSObject.TypeNames[0] | Should -Be 'GitHub.User' + } + } } } finally