diff --git a/GitHubTeams.ps1 b/GitHubTeams.ps1 index 54b1f809..d3ccbd85 100644 --- a/GitHubTeams.ps1 +++ b/GitHubTeams.ps1 @@ -34,6 +34,9 @@ filter Get-GitHubTeam .PARAMETER OrganizationName The name of the organization + .PARAMETER TeamName + The name of the specific team to retrieve + .PARAMETER TeamId The ID of the specific team to retrieve @@ -98,6 +101,11 @@ filter Get-GitHubTeam [ValidateNotNullOrEmpty()] [string] $OrganizationName, + [Parameter(ParameterSetName='Organization')] + [Parameter(ParameterSetName='Elements')] + [Parameter(ParameterSetName='Uri')] + [string] $TeamName, + [Parameter( Mandatory, ValueFromPipelineByPropertyName, @@ -153,8 +161,39 @@ filter Get-GitHubTeam 'NoStatus' = (Resolve-ParameterWithDefaultConfigurationValue -Name NoStatus -ConfigValueName DefaultNoStatus) } - return (Invoke-GHRestMethodMultipleResult @params | - Add-GitHubTeamAdditionalProperties) + $result = Invoke-GHRestMethodMultipleResult @params | Add-GitHubTeamAdditionalProperties + + if ($PSBoundParameters.ContainsKey('TeamName')) + { + $team = $result | Where-Object -Property name -eq $TeamName + + if ($null -eq $team) + { + $message = "Team '$TeamName' not found" + Write-Log -Message $message -Level Error + throw $message + } + else + { + $uriFragment = "/teams/$($team.id)" + $description = "Getting team $($team.id)" + + $params = @{ + UriFragment = $uriFragment + Description = $description + Method = 'Get' + AccessToken = $AccessToken + TelemetryEventName = $MyInvocation.MyCommand.Name + TelemetryProperties = $telemetryProperties + NoStatus = (Resolve-ParameterWithDefaultConfigurationValue ` + -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + $result = Invoke-GHRestMethod @params | Add-GitHubTeamAdditionalProperties + } + } + + return $result } filter Get-GitHubTeamMember @@ -276,6 +315,488 @@ filter Get-GitHubTeamMember return (Invoke-GHRestMethodMultipleResult @params | Add-GitHubUserAdditionalProperties) } +function New-GitHubTeam +{ +<# + .SYNOPSIS + Creates a team within an organization on GitHub. + + .DESCRIPTION + Creates 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 organization to create the team in. + + .PARAMETER TeamName + The name of the team. + + .PARAMETER Description + The description for the team. + + .PARAMETER MaintainerName + A list of GitHub IDs for organization members who will become team maintainers. + + .PARAMETER RepositoryFullName + The full name (e.g., "organization-name/repository-name") of repositories to add the team to. + + .PARAMETER Privacy + The level of privacy this team should have. + + .PARAMETER ParentTeamName + The name of a 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. + + .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 + System.String + GitHub.User + + .OUTPUTS + GitHub.Team + + .EXAMPLE + New-GitHubTeam -OrganizationName PowerShell -TeamName 'Developers' + + Creates a new GitHub team called 'Developers' in the 'PowerShell' organization. + + .EXAMPLE + $teamName = 'Team1' + $teamName | New-GitHubTeam -OrganizationName PowerShell + + You can also pipe in a team name that was returned from a previous command. + + .EXAMPLE + $users = Get-GitHubUsers -OrganizationName PowerShell + $users | New-GitHubTeam -OrganizationName PowerShell -TeamName 'Team1' + + You can also pipe in a list of GitHub users that were returned from a previous command. +#> + [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.')] + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false + )] + [OutputType({$script:GitHubTeamTypeName})] + param + ( + [Parameter( + Mandatory, + Position = 1)] + [ValidateNotNullOrEmpty()] + [string] $OrganizationName, + + [Parameter( + Mandatory, + ValueFromPipeline, + Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $TeamName, + + [string] $Description, + + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('UserName')] + [string[]] $MaintainerName, + + [string[]] $RepositoryFullName, + + [ValidateSet('Secret', 'Closed')] + [string] $Privacy, + + [string] $ParentTeamName, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + begin + { + $maintainerNames = @() + } + + process + { + foreach ($user in $MaintainerName) + { + $maintainerNames += $user + } + } + + end + { + Write-InvocationLog + + $telemetryProperties = @{ + OrganizationName = (Get-PiiSafeString -PlainText $OrganizationName) + TeamName = (Get-PiiSafeString -PlainText $TeamName) + } + + $uriFragment = "/orgs/$OrganizationName/teams" + + $hashBody = @{ + name = $TeamName + } + + if ($PSBoundParameters.ContainsKey('Description')) { $hashBody['description'] = $Description } + if ($PSBoundParameters.ContainsKey('RepositoryFullName')) { $hashBody['repo_names'] = $RepositoryFullName } + if ($PSBoundParameters.ContainsKey('Privacy')) { $hashBody['privacy'] = $Privacy.ToLower() } + if ($MaintainerName.Count -gt 0) + { + $hashBody['maintainers'] = $maintainerNames + } + if ($PSBoundParameters.ContainsKey('ParentTeamName')) + { + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + TeamName = $ParentTeamName + Whatif = $false + Confirm = $false + } + if ($PSBoundParameters.ContainsKey('AccessToken')) + { + $getGitHubTeamParms['AccessToken'] = $AccessToken + } + if ($PSBoundParameters.ContainsKey('NoStatus')) + { + $getGitHubTeamParms['NoStatus'] = $NoStatus + } + + $team = Get-GitHubTeam @getGitHubTeamParms + + $hashBody['parent_team_id'] = $team.id + } + + $params = @{ + UriFragment = $uriFragment + Body = (ConvertTo-Json -InputObject $hashBody) + Method = 'Post' + Description = "Creating $TeamName" + AccessToken = $AccessToken + TelemetryEventName = $MyInvocation.MyCommand.Name + TelemetryProperties = $telemetryProperties + NoStatus = (Resolve-ParameterWithDefaultConfigurationValue ` + -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Invoke-GHRestMethod @params | Add-GitHubTeamAdditionalProperties) + } +} + +filter Set-GitHubTeam +{ +<# + .SYNOPSIS + Updates a team within an organization on GitHub. + + .DESCRIPTION + Updates 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 name of the team. + + .PARAMETER Description + The description for the team. + + .PARAMETER Privacy + The level of privacy this team should have. + + .PARAMETER ParentTeamName + The name of a 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. + + .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.Team + + .OUTPUTS + GitHub.Team + + .EXAMPLE + Set-GitHubTeam -OrganizationName PowerShell -TeamName Developers -Description 'New Description' + + Updates the description for the 'Developers' GitHub team in the 'PowerShell' organization. + + .EXAMPLE + $team = Get-GitHubTeam -OrganizationName PowerShell -TeamName Developers + $team | Set-GitHubTeam -Description 'New Description' + + You can also pipe in a GitHub team that was returned from a previous command. +#> + [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.')] + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false + )] + [OutputType({$script:GitHubTeamTypeName})] + param + ( + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 1)] + [ValidateNotNullOrEmpty()] + [string] $OrganizationName, + + [Parameter( + Mandatory, + ValueFromPipelineByPropertyName, + Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $TeamName, + + [string] $Description, + + [ValidateSet('Secret','Closed')] + [string] $Privacy, + + [string] $ParentTeamName, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + Write-InvocationLog + + $telemetryProperties = @{ + OrganizationName = (Get-PiiSafeString -PlainText $OrganizationName) + TeamName = (Get-PiiSafeString -PlainText $TeamName) + } + + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + TeamName = $teamName + Whatif = $false + Confirm = $false + } + if ($PSBoundParameters.ContainsKey('AccessToken')) + { + $getGitHubTeamParms['AccessToken'] = $AccessToken + } + if ($PSBoundParameters.ContainsKey('NoStatus')) + { + $getGitHubTeamParms['NoStatus'] = $NoStatus + } + + $team = Get-GitHubTeam @getGitHubTeamParms + + $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" + + $hashBody = @{ + name = $TeamName + } + + if ($PSBoundParameters.ContainsKey('Description')) { $hashBody['description'] = $Description } + if ($PSBoundParameters.ContainsKey('Privacy')) { $hashBody['privacy'] = $Privacy.ToLower() } + if ($PSBoundParameters.ContainsKey('ParentTeamName')) + { + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + TeamName = $ParentTeamName + Whatif = $false + Confirm = $false + } + if ($PSBoundParameters.ContainsKey('AccessToken')) + { + $getGitHubTeamParms['AccessToken'] = $AccessToken + } + if ($PSBoundParameters.ContainsKey('NoStatus')) + { + $getGitHubTeamParms['NoStatus'] = $NoStatus + } + + $team = Get-GitHubTeam @getGitHubTeamParms + + $hashBody['parent_team_id'] = $team.id + } + + $params = @{ + UriFragment = $uriFragment + Body = (ConvertTo-Json -InputObject $hashBody) + Method = 'Patch' + Description = "Updating $TeamName" + AccessToken = $AccessToken + TelemetryEventName = $MyInvocation.MyCommand.Name + TelemetryProperties = $telemetryProperties + NoStatus = (Resolve-ParameterWithDefaultConfigurationValue ` + -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + return (Invoke-GHRestMethod @params | Add-GitHubTeamAdditionalProperties) +} + +filter Remove-GitHubTeam +{ +<# + .SYNOPSIS + Removes a team from an organization on GitHub. + + .DESCRIPTION + Removes a team from an organization on GitHub. + + The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub + + .PARAMETER OrganizationName + The name of the organization the team is in. + + .PARAMETER TeamName + The name of the team. + + .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.Team + + .OUTPUTS + None + + .EXAMPLE + Remove-GitHubTeam -OrganizationName PowerShell -TeamName Developers + + Removes the 'Developers' GitHub team from the 'PowerShell' organization. + + .EXAMPLE + Remove-GitHubTeam -OrganizationName PowerShell -TeamName Developers -Force + + Removes the 'Developers' GitHub team from the 'PowerShell' organization without prompting. + + .EXAMPLE + $team = Get-GitHubTeam -OrganizationName PowerShell -TeamName Developers + $team | Remove-GitHubTeam -Force + + You can also pipe in a GitHub team that was returned from a previous command. +#> + [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.')] + [CmdletBinding( + SupportsShouldProcess, + PositionalBinding = $false, + ConfirmImpact = 'High' + )] + [Alias('Delete-GitHubTeam')] + param + ( + [Parameter( + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [ValidateNotNullOrEmpty()] + [string] $OrganizationName, + + [Parameter( + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [ValidateNotNullOrEmpty()] + [string] $TeamName, + + [switch] $Force, + + [string] $AccessToken, + + [switch] $NoStatus + ) + + $telemetryProperties = @{ + OrganizationName = (Get-PiiSafeString -PlainText $RepositoryName) + TeamName = (Get-PiiSafeString -PlainText $TeamName) + } + + $getGitHubTeamParms = @{ + OrganizationName = $OrganizationName + TeamName = $TeamName + Whatif = $false + Confirm = $false + } + if ($PSBoundParameters.ContainsKey('AccessToken')) + { + $getGitHubTeamParms['AccessToken'] = $AccessToken + } + if ($PSBoundParameters.ContainsKey('NoStatus')) + { + $getGitHubTeamParms['NoStatus'] = $NoStatus + } + + $team = Get-GitHubTeam @getGitHubTeamParms + + $uriFragment = "/orgs/$OrganizationName/teams/$($team.slug)" + + if ($Force -and (-not $Confirm)) + { + $ConfirmPreference = 'None' + } + + if ($PSCmdlet.ShouldProcess($TeamName, "Remove Team")) + { + Write-InvocationLog + + $params = @{ + UriFragment = $uriFragment + Method = 'Delete' + Description = "Deleting $TeamName" + AccessToken = $AccessToken + TelemetryEventName = $MyInvocation.MyCommand.Name + TelemetryProperties = $telemetryProperties + NoStatus = (Resolve-ParameterWithDefaultConfigurationValue ` + -Name NoStatus -ConfigValueName DefaultNoStatus) + } + + Invoke-GHRestMethod @params | Out-Null + } +} + filter Add-GitHubTeamAdditionalProperties { <# @@ -317,6 +838,23 @@ 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 + if ($item.organization) + { + $organizationName = $item.organization.login + } + else + { + $hostName = $(Get-GitHubConfiguration -Name 'ApiHostName') + + $organizationName = [String]::Empty + if ($item.html_url -match "^https?://$hostName/orgs/([^/]+)/.*$") + { + $organizationName = $Matches[1] + } + } + + Add-Member -InputObject $item -Name 'OrganizationName' -value $organizationName -MemberType NoteProperty -Force + # Apply these properties to any embedded parent teams as well. if ($null -ne $item.parent) { diff --git a/PowerShellForGitHub.psd1 b/PowerShellForGitHub.psd1 index 3504bf7c..8fecad29 100644 --- a/PowerShellForGitHub.psd1 +++ b/PowerShellForGitHub.psd1 @@ -116,6 +116,7 @@ 'New-GitHubRepository', 'New-GitHubRepositoryFromTemplate', 'New-GitHubRepositoryFork', + 'New-GitHubTeam', 'Remove-GitHubAssignee', 'Remove-GitHubIssueComment', 'Remove-GitHubIssueLabel', @@ -125,6 +126,7 @@ 'Remove-GitHubProjectCard', 'Remove-GitHubProjectColumn', 'Remove-GitHubRepository', + 'Remove-GitHubTeam', 'Rename-GitHubRepository', 'Reset-GitHubConfiguration', 'Restore-GitHubConfiguration', @@ -139,6 +141,7 @@ 'Set-GitHubProjectCard', 'Set-GitHubProjectColumn', 'Set-GitHubRepositoryTopic', + 'Set-GitHubTeam', 'Split-GitHubUri', 'Test-GitHubAssignee', 'Test-GitHubAuthenticationConfigured', @@ -160,6 +163,7 @@ 'Delete-GitHubProjectCard', 'Delete-GitHubProjectColumn' 'Delete-GitHubRepository', + 'Delete-GitHubTeam', 'Get-GitHubBranch', 'Get-GitHubComment', 'New-GitHubComment', diff --git a/Tests/GitHubTeams.tests.ps1 b/Tests/GitHubTeams.tests.ps1 index 21658992..e9218aa2 100644 --- a/Tests/GitHubTeams.tests.ps1 +++ b/Tests/GitHubTeams.tests.ps1 @@ -17,7 +17,490 @@ $moduleRootPath = Split-Path -Path $PSScriptRoot -Parent try { - # TODO once more capabilities exist in the module's API set + # Define Script-scoped, readonly, hidden variables. + @{ + defaultRepoDesc = "This is a description." + defaultRepoHomePage = "https://www.microsoft.com/" + defaultRepoTopic = "microsoft" + }.GetEnumerator() | ForEach-Object { + Set-Variable -Force -Scope Script -Option ReadOnly -Visibility Private -Name $_.Key -Value $_.Value + } + + Describe 'GitHubTeams\Get-GitHubTeam' { + BeforeAll { + $organizationName = $script:organizationName + } + + Context 'When getting a GitHub Team by organization' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'closed' + $MaintainerName = $script:ownerName + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + Description = $description + Privacy = $privacy + MaintainerName = $MaintainerName + } + + New-GitHubTeam @newGithubTeamParms | Out-Null + + $getGitHubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + } + + $team = Get-GitHubTeam @getGitHubTeamParms + } + + It 'Should have the expected type and additional properties' { + $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.members_count | Should -Be 1 + $team.repos_count | Should -Be 0 + $team.privacy | Should -Be $privacy + $team.TeamName | Should -Be $teamName + $team.TeamId | Should -Be $team.id + $team.OrganizationName | Should -Be $organizationName + } + + It 'Should support pipeline input for the organization parameter' { + { $team | Get-GitHubTeam -WhatIf } | Should -Not -Throw + } + + AfterAll { + if (Get-Variable -Name team -ErrorAction SilentlyContinue) + { + $team | Remove-GitHubTeam -Force + } + } + } + + Context 'When getting a GitHub Team by repository' { + BeforeAll { + $repoName = [Guid]::NewGuid().Guid + + $newGithubRepositoryParms = @{ + RepositoryName = $repoName + OrganizationName = $organizationName + } + + $repo = New-GitHubRepository @newGitHubRepositoryParms + + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'closed' + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + Description = $description + RepositoryFullName = $repo.full_name + Privacy = $privacy + } + + New-GitHubTeam @newGithubTeamParms | Out-Null + + $getGitHubTeamParms = @{ + OwnerName = $organizationName + RepositoryName = $repoName + } + + $team = Get-GitHubTeam @getGitHubTeamParms + } + + It 'Should have the expected type and additional properties' { + $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.TeamId | Should -Be $team.id + $team.OrganizationName | Should -Be $organizationName + } + + It 'Should support pipeline input for the uri parameter' { + { $repo | Get-GitHubTeam -WhatIf } | Should -Not -Throw + } + + AfterAll { + if (Get-Variable -Name repo -ErrorAction SilentlyContinue) + { + $repo | Remove-GitHubRepository -Force + } + + if (Get-Variable -Name team -ErrorAction SilentlyContinue) + { + $team | Remove-GitHubTeam -Force + } + } + } + + Context 'When getting a GitHub Team by TeamId' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'closed' + $MaintainerName = $script:ownerName + + $newGithubTeamParms = @{ + OrganizationName = $script:organizationName + TeamName = $teamName + Description = $description + Privacy = $privacy + MaintainerName = $MaintainerName + } + + $newTeam = New-GitHubTeam @newGithubTeamParms + + $getGitHubTeamParms = @{ + TeamId = $newTeam.id + } + + $team = Get-GitHubTeam @getGitHubTeamParms + } + + It 'Should have the expected type and additional properties' { + $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.members_count | Should -Be 1 + $team.repos_count | Should -Be 0 + $team.privacy | Should -Be $privacy + $team.TeamName | Should -Be $teamName + $team.TeamId | Should -Be $team.id + $team.OrganizationName | Should -Be $organizationName + } + + AfterAll { + if (Get-Variable -Name team -ErrorAction SilentlyContinue) + { + $team | Remove-GitHubTeam -Force + } + } + } + } + + Describe 'GitHubTeams\New-GitHubTeam' { + BeforeAll { + $organizationName = $script:organizationName + } + + Context 'When creating a new GitHub team with default settings' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + } + + $team = New-GitHubTeam @newGithubTeamParms + } + + It 'Should have the expected type and additional properties' { + $team.PSObject.TypeNames[0] | Should -Be 'GitHub.Team' + $team.name | Should -Be $teamName + $team.description | Should -BeNullOrEmpty + $team.organization.login | Should -Be $organizationName + $team.parent | Should -BeNullOrEmpty + $team.members_count | Should -Be 1 + $team.repos_count | Should -Be 0 + $team.TeamName | Should -Be $teamName + $team.TeamId | Should -Be $team.id + $team.OrganizationName | Should -Be $organizationName + } + + It 'Should support pipeline input for the TeamName parameter' { + { $teamName | New-GitHubTeam -OrganizationName $organizationName -WhatIf } | + Should -Not -Throw + } + + AfterAll { + if (Get-Variable -Name team -ErrorAction SilentlyContinue) + { + $team | Remove-GitHubTeam -Force + } + } + } + + Context 'When creating a new GitHub team with all possible settings' { + BeforeAll { + $repoName = [Guid]::NewGuid().Guid + + $newGithubRepositoryParms = @{ + RepositoryName = $repoName + OrganizationName = $organizationName + } + + $repo = New-GitHubRepository @newGitHubRepositoryParms + + $maintainer = Get-GitHubUser -UserName $script:ownerName + + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'closed' + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + Description = $description + RepositoryFullName = $repo.full_name + Privacy = $privacy + MaintainerName = $maintainer.UserName + } + + $team = New-GitHubTeam @newGithubTeamParms + } + + It 'Should have the expected type and additional properties' { + $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.members_count | Should -Be 1 + $team.repos_count | Should -Be 1 + $team.privacy | Should -Be $privacy + $team.TeamName | Should -Be $teamName + $team.TeamId | Should -Be $team.id + $team.OrganizationName | Should -Be $organizationName + } + + It 'Should support pipeline input for the MaintainerName parameter' { + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + } + { $maintainer | New-GitHubTeam @newGithubTeamParms -WhatIf } | + Should -Not -Throw + } + + AfterAll { + if (Get-Variable -Name repo -ErrorAction SilentlyContinue) + { + $repo | Remove-GitHubRepository -Force + } + + if (Get-Variable -Name team -ErrorAction SilentlyContinue) + { + $team | Remove-GitHubTeam -Force + } + } + } + + Context 'When creating a child GitHub team' { + BeforeAll { + $parentTeamName = [Guid]::NewGuid().Guid + $privacy= 'Closed' + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $parentTeamName + Privacy = $privacy + } + + $parentTeam = New-GitHubTeam @newGithubTeamParms + + $childTeamName = [Guid]::NewGuid().Guid + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $childTeamName + ParentTeamName = $parentTeamName + Privacy = $privacy + } + + $childTeam = 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 $childTeamName + $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 + } + } + } + } + + Describe 'GitHubTeams\Set-GitHubTeam' { + BeforeAll { + $organizationName = $script:organizationName + } + + Context 'When updating a Child GitHub team' { + 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 + ParentTeamName = $parentTeamName + } + + $updatedTeam = Set-GitHubTeam @updateGitHubTeamParms + } + + 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 $teamName + $updatedTeam.TeamId | Should -Be $team.id + $updatedTeam.OrganizationName | Should -Be $organizationName + } + + It 'Should support pipeline input for the OrganizationName and TeamName parameters' { + { $team | Set-GitHubTeam -Description $description -WhatIf } | + Should -Not -Throw + } + + 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 updating a non-child GitHub team' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $description = 'Team Description' + $privacy = 'Closed' + + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + Privacy = 'Secret' + } + + $team = New-GitHubTeam @newGithubTeamParms + + $updateGitHubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + Description = $description + Privacy = $privacy + } + + $updatedTeam = Set-GitHubTeam @updateGitHubTeamParms + } + + 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 -BeNullOrEmpty + $updatedTeam.privacy | Should -Be $privacy + $updatedTeam.TeamName | Should -Be $teamName + $updatedTeam.TeamId | Should -Be $team.id + $updatedTeam.OrganizationName | Should -Be $organizationName + } + + AfterAll { + if (Get-Variable -Name team -ErrorAction SilentlyContinue) + { + $team | Remove-GitHubTeam -Force + } + } + } + } + + Describe 'GitHubTeams\Remove-GitHubTeam' { + BeforeAll { + $organizationName = $script:organizationName + } + + Context 'When removing a GitHub team' { + BeforeAll { + $teamName = [Guid]::NewGuid().Guid + $newGithubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + } + + $team = New-GitHubTeam @newGithubTeamParms + } + + It 'Should support pipeline input for the TeamName parameter' { + { $team | Remove-GitHubTeam -Force -WhatIf } | Should -Not -Throw + } + + It 'Should not throw an exception' { + $removeGitHubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + Confirm = $false + } + + { Remove-GitHubTeam @RemoveGitHubTeamParms } | Should -Not -Throw + } + + It 'Should have removed the team' { + $getGitHubTeamParms = @{ + OrganizationName = $organizationName + TeamName = $teamName + } + + { Get-GitHubTeam @getGitHubTeamParms } | Should -Throw + } + } + } } finally { diff --git a/USAGE.md b/USAGE.md index 2b275c61..b1c9758f 100644 --- a/USAGE.md +++ b/USAGE.md @@ -29,6 +29,15 @@ * [Updating the current authenticated user](#updating-the-current-authenticated-user) * [Getting any user](#getting-any-user) * [Getting all users](#getting-all-users) + * [Teams](#teams) + * [Getting teams in an Organization](#Getting-teams-in-an-Organization) + * [Getting teams assigned to a repository](#Getting-teams-assigned-to-a-repository) + * [Getting a team by team name](#Getting-a-team-by-team-name) + * [Getting a team by team id](#Getting-a-team-by-team-id) + * [Creating a team](#Creating-a-team) + * [Creating a child team](#Creating-a-child-team) + * [Updating a team](#Updating-a-team) + * [Removing a team](#Removing-a-team) * [Repositories](#repositories]) * [Create a repository](#Create-a-repository) * [Create a repository in an organization](#Create-a-repository-in-an-organization) @@ -431,6 +440,58 @@ Get-GitHubUser ---------- +### Teams + +#### Getting teams in an Organization + +```powershell +Get-GitHubTeam -OrganizationName microsoft +``` + +#### Getting teams assigned to a repository + +```powershell +Get-GitHubTeam -OwnerName microsoft -RepositoryName PowerShellForGitHub +``` + +#### Getting a team by team name + +```powershell +Get-GitHubTeam -OrganizationName microsoft -TeamName MyTeam +``` + +#### Getting a team by team id + +```powershell +Get-GitHubTeam -OrganizationName microsoft -TeamId 378661 +``` + +#### Creating a team + +```powershell +New-GitHubTeam -OrganizationName microsoft -TeamName MyTeam -Description 'Team Description' +``` + +#### Creating a child team + +```powershell +New-GitHubTeam -OrganizationName microsoft -TeamName MyChildTeam -Description 'Team Description' -ParentTeamName MyTeam +``` + +#### Updating a team + +```powershell +Update-GitHubTeam -OrganizationName microsoft -TeamName MyChildTeam -Description 'Team Description' -ParentTeamName MyTeam +``` + +#### Removing a team + +```powershell +Remove-GitHubTeam -OrganizationName microsoft -TeamName MyTeam +``` + +---------- + ### Repositories #### Create a repository @@ -456,7 +517,8 @@ New-GitHubRepository -RepositoryName TestRepo -OrganizationName MyOrg -TeamId $m ```powershell New-GitHubRepositoryFromTemplate -OwnerName MyOrg -RepositoryName MyNewRepo-TemplateOwnerName MyOrg -TemplateRepositoryName MyTemplateRepo -======= +``` + #### Get repository vulnerability alert status ```powershell @@ -724,3 +786,4 @@ $issue | New-GitHubIssueComment -Body $CommentBody # Close issue $issue | Update-GitHubIssue -State Closed ``` +